WIP: update tizen_qemu_defconfig
[platform/kernel/linux-starfive.git] / fs / namei.c
index 9155ecb..5b3865a 100644 (file)
@@ -3007,8 +3007,8 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
                return p;
        }
 
-       inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
-       inode_lock_nested(p2->d_inode, I_MUTEX_PARENT2);
+       lock_two_inodes(p1->d_inode, p2->d_inode,
+                       I_MUTEX_PARENT, I_MUTEX_PARENT2);
        return NULL;
 }
 EXPORT_SYMBOL(lock_rename);
@@ -4661,7 +4661,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname
  *        sb->s_vfs_rename_mutex. We might be more accurate, but that's another
  *        story.
  *     c) we have to lock _four_ objects - parents and victim (if it exists),
- *        and source (if it is not a directory).
+ *        and source.
  *        And that - after we got ->i_mutex on parents (until then we don't know
  *        whether the target exists).  Solution: try to be smart with locking
  *        order for inodes.  We rely on the fact that tree topology may change
@@ -4745,10 +4745,16 @@ int vfs_rename(struct renamedata *rd)
 
        take_dentry_name_snapshot(&old_name, old_dentry);
        dget(new_dentry);
-       if (!is_dir || (flags & RENAME_EXCHANGE))
-               lock_two_nondirectories(source, target);
-       else if (target)
-               inode_lock(target);
+       /*
+        * Lock all moved children. Moved directories may need to change parent
+        * pointer so they need the lock to prevent against concurrent
+        * directory changes moving parent pointer. For regular files we've
+        * historically always done this. The lockdep locking subclasses are
+        * somewhat arbitrary but RENAME_EXCHANGE in particular can swap
+        * regular files and directories so it's difficult to tell which
+        * subclasses to use.
+        */
+       lock_two_inodes(source, target, I_MUTEX_NORMAL, I_MUTEX_NONDIR2);
 
        error = -EPERM;
        if (IS_SWAPFILE(source) || (target && IS_SWAPFILE(target)))
@@ -4796,9 +4802,8 @@ int vfs_rename(struct renamedata *rd)
                        d_exchange(old_dentry, new_dentry);
        }
 out:
-       if (!is_dir || (flags & RENAME_EXCHANGE))
-               unlock_two_nondirectories(source, target);
-       else if (target)
+       inode_unlock(source);
+       if (target)
                inode_unlock(target);
        dput(new_dentry);
        if (!error) {