]> git.itanic.dy.fi Git - linux-stable/commitdiff
fs: Restrict lock_two_nondirectories() to non-directory inodes
authorJan Kara <jack@suse.cz>
Thu, 1 Jun 2023 10:58:26 +0000 (12:58 +0200)
committerChristian Brauner <brauner@kernel.org>
Wed, 7 Jun 2023 07:15:11 +0000 (09:15 +0200)
Currently lock_two_nondirectories() is skipping any passed directories.
After vfs_rename() uses lock_two_inodes(), all the remaining four users
of this function pass only regular files to it. So drop the somewhat
unusual "skip directory" logic and instead warn if anybody passes
directory to it. This also allows us to use lock_two_inodes() in
lock_two_nondirectories() to concentrate the lock ordering logic in less
places.

Signed-off-by: Jan Kara <jack@suse.cz>
Message-Id: <20230601105830.13168-6-jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/inode.c

index b9d4980322700257066618563be707fc72bbbceb..53ae3b76d232873be7dd05d85770adea40f8b15e 100644 (file)
@@ -1148,7 +1148,7 @@ void lock_two_inodes(struct inode *inode1, struct inode *inode2,
 /**
  * lock_two_nondirectories - take two i_mutexes on non-directory objects
  *
- * Lock any non-NULL argument that is not a directory.
+ * Lock any non-NULL argument. Passed objects must not be directories.
  * Zero, one or two objects may be locked by this function.
  *
  * @inode1: first inode to lock
@@ -1156,13 +1156,9 @@ void lock_two_inodes(struct inode *inode1, struct inode *inode2,
  */
 void lock_two_nondirectories(struct inode *inode1, struct inode *inode2)
 {
-       if (inode1 > inode2)
-               swap(inode1, inode2);
-
-       if (inode1 && !S_ISDIR(inode1->i_mode))
-               inode_lock(inode1);
-       if (inode2 && !S_ISDIR(inode2->i_mode) && inode2 != inode1)
-               inode_lock_nested(inode2, I_MUTEX_NONDIR2);
+       WARN_ON_ONCE(S_ISDIR(inode1->i_mode));
+       WARN_ON_ONCE(S_ISDIR(inode2->i_mode));
+       lock_two_inodes(inode1, inode2, I_MUTEX_NORMAL, I_MUTEX_NONDIR2);
 }
 EXPORT_SYMBOL(lock_two_nondirectories);
 
@@ -1173,10 +1169,14 @@ EXPORT_SYMBOL(lock_two_nondirectories);
  */
 void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2)
 {
-       if (inode1 && !S_ISDIR(inode1->i_mode))
+       if (inode1) {
+               WARN_ON_ONCE(S_ISDIR(inode1->i_mode));
                inode_unlock(inode1);
-       if (inode2 && !S_ISDIR(inode2->i_mode) && inode2 != inode1)
+       }
+       if (inode2 && inode2 != inode1) {
+               WARN_ON_ONCE(S_ISDIR(inode2->i_mode));
                inode_unlock(inode2);
+       }
 }
 EXPORT_SYMBOL(unlock_two_nondirectories);