]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ovl: narrow locking in ovl_check_rename_whiteout()
authorNeilBrown <neil@brown.name>
Wed, 16 Jul 2025 00:44:30 +0000 (10:44 +1000)
committerChristian Brauner <brauner@kernel.org>
Fri, 18 Jul 2025 09:10:43 +0000 (11:10 +0200)
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>
fs/overlayfs/super.c

index 4c3736bf2db4d3053668df7d67933d8228db5662..0d765aa66bd2a4753348e0f77f92ed42f7943996 100644 (file)
@@ -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;
 }