summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neil@brown.name>2025-07-16 10:44:30 +1000
committerChristian Brauner <brauner@kernel.org>2025-07-18 11:10:43 +0200
commit09d56cc88c247036da5756fd552f2cb2af8d8c5e (patch)
treeec1b1d3e5d28c55566ada68bdcd2398460062dfb
parent8afa0a736713898f04d52abad69c07caa2c2f227 (diff)
ovl: narrow locking in ovl_check_rename_whiteout()
ovl_check_rename_whiteout() now only holds the directory lock when needed, and takes it again if necessary. This makes way for future changes where locks are taken on individual dentries rather than the whole directory. Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: NeilBrown <neil@brown.name> Link: https://lore.kernel.org/20250716004725.1206467-20-neil@brown.name Signed-off-by: Christian Brauner <brauner@kernel.org>
-rw-r--r--fs/overlayfs/super.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 4c3736bf2db4..0d765aa66bd2 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -556,7 +556,6 @@ out:
static int ovl_check_rename_whiteout(struct ovl_fs *ofs)
{
struct dentry *workdir = ofs->workdir;
- struct inode *dir = d_inode(workdir);
struct dentry *temp;
struct dentry *dest;
struct dentry *whiteout;
@@ -577,19 +576,22 @@ static int ovl_check_rename_whiteout(struct ovl_fs *ofs)
err = PTR_ERR(dest);
if (IS_ERR(dest)) {
dput(temp);
- goto out_unlock;
+ ovl_parent_unlock(workdir);
+ return err;
}
/* Name is inline and stable - using snapshot as a copy helper */
take_dentry_name_snapshot(&name, temp);
err = ovl_do_rename(ofs, workdir, temp, workdir, dest, RENAME_WHITEOUT);
+ ovl_parent_unlock(workdir);
if (err) {
if (err == -EINVAL)
err = 0;
goto cleanup_temp;
}
- whiteout = ovl_lookup_upper(ofs, name.name.name, workdir, name.name.len);
+ whiteout = ovl_lookup_upper_unlocked(ofs, name.name.name,
+ workdir, name.name.len);
err = PTR_ERR(whiteout);
if (IS_ERR(whiteout))
goto cleanup_temp;
@@ -598,18 +600,15 @@ static int ovl_check_rename_whiteout(struct ovl_fs *ofs)
/* Best effort cleanup of whiteout and temp file */
if (err)
- ovl_cleanup(ofs, dir, whiteout);
+ ovl_cleanup_unlocked(ofs, workdir, whiteout);
dput(whiteout);
cleanup_temp:
- ovl_cleanup(ofs, dir, temp);
+ ovl_cleanup_unlocked(ofs, workdir, temp);
release_dentry_name_snapshot(&name);
dput(temp);
dput(dest);
-out_unlock:
- ovl_parent_unlock(workdir);
-
return err;
}