Commit 375e289ea85166c5241c570940e7e7e966c63a9f

Authored by J. Bruce Fields
Committed by Al Viro
1 parent f27c9298fd

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

... ... @@ -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);
... ... @@ -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 }
... ... @@ -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
... ... @@ -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