summaryrefslogtreecommitdiff
path: root/fs/ntfs3
diff options
context:
space:
mode:
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>2022-10-07 20:16:15 +0300
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>2022-11-14 19:50:45 +0300
commit0ad9dfcb8d3fd6ef91983ccb93fafbf9e3115796 (patch)
tree1ad9831f401b4a34c1a46cab7da90d5eef8afde1 /fs/ntfs3
parentad26a9c84510af7252e582e811de970433a9758f (diff)
downloadlwn-0ad9dfcb8d3fd6ef91983ccb93fafbf9e3115796.tar.gz
lwn-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.c4
-rw-r--r--fs/ntfs3/ntfs_fs.h6
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);