summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/util.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2023-07-20 12:51:21 +0300
committerAmir Goldstein <amir73il@gmail.com>2023-10-31 00:12:57 +0200
commit162d06444070c12827d604a2cb6b6bd98d48cbb0 (patch)
treeaa5ac2ffb3dce2d74c3fb7812b3ea37abca90a99 /fs/overlayfs/util.c
parentd08d3b3c2caf6c482703bbc5efaa7b9ae95dea20 (diff)
downloadlinux-stable-162d06444070c12827d604a2cb6b6bd98d48cbb0.tar.gz
linux-stable-162d06444070c12827d604a2cb6b6bd98d48cbb0.tar.bz2
linux-stable-162d06444070c12827d604a2cb6b6bd98d48cbb0.zip
ovl: reorder ovl_want_write() after ovl_inode_lock()
Make the locking order of ovl_inode_lock() strictly between the two vfs stacked layers, i.e.: - ovl vfs locks: sb_writers, inode_lock, ... - ovl_inode_lock - upper vfs locks: sb_writers, inode_lock, ... To that effect, move ovl_want_write() into the helpers ovl_nlink_start() and ovl_copy_up_start which currently take the ovl_inode_lock() after ovl_want_write(). Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Diffstat (limited to 'fs/overlayfs/util.c')
-rw-r--r--fs/overlayfs/util.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 80f20ca85344..af11c83b7a25 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -676,16 +676,26 @@ int ovl_copy_up_start(struct dentry *dentry, int flags)
int err;
err = ovl_inode_lock_interruptible(inode);
- if (!err && ovl_already_copied_up_locked(dentry, flags)) {
+ if (err)
+ return err;
+
+ if (ovl_already_copied_up_locked(dentry, flags))
err = 1; /* Already copied up */
- ovl_inode_unlock(inode);
- }
+ else
+ err = ovl_want_write(dentry);
+ if (err)
+ goto out_unlock;
+
+ return 0;
+out_unlock:
+ ovl_inode_unlock(inode);
return err;
}
void ovl_copy_up_end(struct dentry *dentry)
{
+ ovl_drop_write(dentry);
ovl_inode_unlock(d_inode(dentry));
}
@@ -1088,8 +1098,12 @@ int ovl_nlink_start(struct dentry *dentry)
if (err)
return err;
+ err = ovl_want_write(dentry);
+ if (err)
+ goto out_unlock;
+
if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, inode))
- goto out;
+ return 0;
old_cred = ovl_override_creds(dentry->d_sb);
/*
@@ -1100,10 +1114,15 @@ int ovl_nlink_start(struct dentry *dentry)
*/
err = ovl_set_nlink_upper(dentry);
revert_creds(old_cred);
-
-out:
if (err)
- ovl_inode_unlock(inode);
+ goto out_drop_write;
+
+ return 0;
+
+out_drop_write:
+ ovl_drop_write(dentry);
+out_unlock:
+ ovl_inode_unlock(inode);
return err;
}
@@ -1120,6 +1139,7 @@ void ovl_nlink_end(struct dentry *dentry)
revert_creds(old_cred);
}
+ ovl_drop_write(dentry);
ovl_inode_unlock(inode);
}