Commit 375e289ea85166c5241c570940e7e7e966c63a9f
Committed by
Al Viro
1 parent
f27c9298fd
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
vfs: pull ext4's double-i_mutex-locking into common code
We want to do this elsewhere as well. Also catch any attempts to use it for directories (where this ordering would conflict with ancestor-first directory ordering in lock_rename). Cc: Andreas Dilger <adilger.kernel@dilger.ca> Cc: Dave Chinner <david@fromorbit.com> Acked-by: Jeff Layton <jlayton@redhat.com> Acked-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 5 changed files with 43 additions and 42 deletions Side-by-side Diff
fs/ext4/ext4.h
... | ... | @@ -2734,8 +2734,6 @@ |
2734 | 2734 | struct inode *second); |
2735 | 2735 | extern void ext4_double_up_write_data_sem(struct inode *orig_inode, |
2736 | 2736 | struct inode *donor_inode); |
2737 | -void ext4_inode_double_lock(struct inode *inode1, struct inode *inode2); | |
2738 | -void ext4_inode_double_unlock(struct inode *inode1, struct inode *inode2); | |
2739 | 2737 | extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, |
2740 | 2738 | __u64 start_orig, __u64 start_donor, |
2741 | 2739 | __u64 len, __u64 *moved_len); |
fs/ext4/ioctl.c
... | ... | @@ -130,7 +130,7 @@ |
130 | 130 | |
131 | 131 | /* Protect orig inodes against a truncate and make sure, |
132 | 132 | * that only 1 swap_inode_boot_loader is running. */ |
133 | - ext4_inode_double_lock(inode, inode_bl); | |
133 | + lock_two_nondirectories(inode, inode_bl); | |
134 | 134 | |
135 | 135 | truncate_inode_pages(&inode->i_data, 0); |
136 | 136 | truncate_inode_pages(&inode_bl->i_data, 0); |
... | ... | @@ -205,7 +205,7 @@ |
205 | 205 | ext4_inode_resume_unlocked_dio(inode); |
206 | 206 | ext4_inode_resume_unlocked_dio(inode_bl); |
207 | 207 | |
208 | - ext4_inode_double_unlock(inode, inode_bl); | |
208 | + unlock_two_nondirectories(inode, inode_bl); | |
209 | 209 | |
210 | 210 | iput(inode_bl); |
211 | 211 |
fs/ext4/move_extent.c
... | ... | @@ -1203,42 +1203,6 @@ |
1203 | 1203 | } |
1204 | 1204 | |
1205 | 1205 | /** |
1206 | - * ext4_inode_double_lock - Lock i_mutex on both @inode1 and @inode2 | |
1207 | - * | |
1208 | - * @inode1: the inode structure | |
1209 | - * @inode2: the inode structure | |
1210 | - * | |
1211 | - * Lock two inodes' i_mutex | |
1212 | - */ | |
1213 | -void | |
1214 | -ext4_inode_double_lock(struct inode *inode1, struct inode *inode2) | |
1215 | -{ | |
1216 | - BUG_ON(inode1 == inode2); | |
1217 | - if (inode1 < inode2) { | |
1218 | - mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | |
1219 | - mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); | |
1220 | - } else { | |
1221 | - mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); | |
1222 | - mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); | |
1223 | - } | |
1224 | -} | |
1225 | - | |
1226 | -/** | |
1227 | - * ext4_inode_double_unlock - Release i_mutex on both @inode1 and @inode2 | |
1228 | - * | |
1229 | - * @inode1: the inode that is released first | |
1230 | - * @inode2: the inode that is released second | |
1231 | - * | |
1232 | - */ | |
1233 | - | |
1234 | -void | |
1235 | -ext4_inode_double_unlock(struct inode *inode1, struct inode *inode2) | |
1236 | -{ | |
1237 | - mutex_unlock(&inode1->i_mutex); | |
1238 | - mutex_unlock(&inode2->i_mutex); | |
1239 | -} | |
1240 | - | |
1241 | -/** | |
1242 | 1206 | * ext4_move_extents - Exchange the specified range of a file |
1243 | 1207 | * |
1244 | 1208 | * @o_filp: file structure of the original file |
... | ... | @@ -1327,7 +1291,7 @@ |
1327 | 1291 | return -EINVAL; |
1328 | 1292 | } |
1329 | 1293 | /* Protect orig and donor inodes against a truncate */ |
1330 | - ext4_inode_double_lock(orig_inode, donor_inode); | |
1294 | + lock_two_nondirectories(orig_inode, donor_inode); | |
1331 | 1295 | |
1332 | 1296 | /* Wait for all existing dio workers */ |
1333 | 1297 | ext4_inode_block_unlocked_dio(orig_inode); |
... | ... | @@ -1535,7 +1499,7 @@ |
1535 | 1499 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
1536 | 1500 | ext4_inode_resume_unlocked_dio(orig_inode); |
1537 | 1501 | ext4_inode_resume_unlocked_dio(donor_inode); |
1538 | - ext4_inode_double_unlock(orig_inode, donor_inode); | |
1502 | + unlock_two_nondirectories(orig_inode, donor_inode); | |
1539 | 1503 | |
1540 | 1504 | return ret; |
1541 | 1505 | } |
fs/inode.c
... | ... | @@ -943,6 +943,42 @@ |
943 | 943 | EXPORT_SYMBOL(unlock_new_inode); |
944 | 944 | |
945 | 945 | /** |
946 | + * lock_two_nondirectories - take two i_mutexes on non-directory objects | |
947 | + * @inode1: first inode to lock | |
948 | + * @inode2: second inode to lock | |
949 | + */ | |
950 | +void lock_two_nondirectories(struct inode *inode1, struct inode *inode2) | |
951 | +{ | |
952 | + WARN_ON_ONCE(S_ISDIR(inode1->i_mode)); | |
953 | + if (inode1 == inode2 || !inode2) { | |
954 | + mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | |
955 | + return; | |
956 | + } | |
957 | + WARN_ON_ONCE(S_ISDIR(inode2->i_mode)); | |
958 | + if (inode1 < inode2) { | |
959 | + mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | |
960 | + mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); | |
961 | + } else { | |
962 | + mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); | |
963 | + mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); | |
964 | + } | |
965 | +} | |
966 | +EXPORT_SYMBOL(lock_two_nondirectories); | |
967 | + | |
968 | +/** | |
969 | + * unlock_two_nondirectories - release locks from lock_two_nondirectories() | |
970 | + * @inode1: first inode to unlock | |
971 | + * @inode2: second inode to unlock | |
972 | + */ | |
973 | +void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2) | |
974 | +{ | |
975 | + mutex_unlock(&inode1->i_mutex); | |
976 | + if (inode2 && inode2 != inode1) | |
977 | + mutex_unlock(&inode2->i_mutex); | |
978 | +} | |
979 | +EXPORT_SYMBOL(unlock_two_nondirectories); | |
980 | + | |
981 | +/** | |
946 | 982 | * iget5_locked - obtain an inode from a mounted file system |
947 | 983 | * @sb: super block of file system |
948 | 984 | * @hashval: hash value (usually inode number) to get |
include/linux/fs.h
... | ... | @@ -637,6 +637,9 @@ |
637 | 637 | I_MUTEX_QUOTA |
638 | 638 | }; |
639 | 639 | |
640 | +void lock_two_nondirectories(struct inode *, struct inode*); | |
641 | +void unlock_two_nondirectories(struct inode *, struct inode*); | |
642 | + | |
640 | 643 | /* |
641 | 644 | * NOTE: in a 32bit arch with a preemptable kernel and |
642 | 645 | * an UP compile the i_size_read/write must be atomic |