diff options
author | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2022-10-07 19:16:15 +0200 |
---|---|---|
committer | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2022-11-14 17:50:45 +0100 |
commit | 0ad9dfcb8d3fd6ef91983ccb93fafbf9e3115796 (patch) | |
tree | 1ad9831f401b4a34c1a46cab7da90d5eef8afde1 /fs/ntfs3 | |
parent | fs/ntfs3: Fixing wrong logic in attr_set_size and ntfs_fallocate (diff) | |
download | linux-0ad9dfcb8d3fd6ef91983ccb93fafbf9e3115796.tar.xz linux-0ad9dfcb8d3fd6ef91983ccb93fafbf9e3115796.zip |
fs/ntfs3: Changing locking in ntfs_rename
In some cases we can be in deadlock
because we tried to lock the same dir.
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Diffstat (limited to 'fs/ntfs3')
-rw-r--r-- | fs/ntfs3/namei.c | 4 | ||||
-rw-r--r-- | fs/ntfs3/ntfs_fs.h | 6 |
2 files changed, 10 insertions, 0 deletions
diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c index daff8d0cd63d..0e72d2067804 100644 --- a/fs/ntfs3/namei.c +++ b/fs/ntfs3/namei.c @@ -305,6 +305,8 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir, ni_lock_dir(dir_ni); ni_lock(ni); + if (dir_ni != new_dir_ni) + ni_lock_dir2(new_dir_ni); is_bad = false; err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad); @@ -328,6 +330,8 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir, ntfs_sync_inode(inode); } + if (dir_ni != new_dir_ni) + ni_unlock(new_dir_ni); ni_unlock(ni); ni_unlock(dir_ni); out: diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 5269d4e66685..776993ae498b 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -334,6 +334,7 @@ enum ntfs_inode_mutex_lock_class { NTFS_INODE_MUTEX_REPARSE, NTFS_INODE_MUTEX_NORMAL, NTFS_INODE_MUTEX_PARENT, + NTFS_INODE_MUTEX_PARENT2, }; /* @@ -1121,6 +1122,11 @@ static inline void ni_lock_dir(struct ntfs_inode *ni) mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_PARENT); } +static inline void ni_lock_dir2(struct ntfs_inode *ni) +{ + mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_PARENT2); +} + static inline void ni_unlock(struct ntfs_inode *ni) { mutex_unlock(&ni->ni_lock); |