]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ovl: narrow locking on ovl_remove_and_whiteout()
authorNeilBrown <neil@brown.name>
Wed, 16 Jul 2025 00:44:27 +0000 (10:44 +1000)
committerChristian Brauner <brauner@kernel.org>
Fri, 18 Jul 2025 09:10:42 +0000 (11:10 +0200)
This code:
  performs a lookup_upper
  creates a whiteout object
  renames the whiteout over the result of the lookup

The create and the rename must be locked separately for proposed
directory locking changes.  This patch takes a first step of moving the
lookup out of the locked region.  A subsequent patch will separate the
create from the rename.

Signed-off-by: NeilBrown <neil@brown.name>
Link: https://lore.kernel.org/20250716004725.1206467-17-neil@brown.name
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/overlayfs/dir.c

index e81be60f112558f504d89e4342a36df8e2dec661..340f8679b6e7fe5179b7f9cc69f3a38b358b365f 100644 (file)
@@ -770,15 +770,11 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
                        goto out;
        }
 
-       err = ovl_lock_rename_workdir(workdir, NULL, upperdir, NULL);
-       if (err)
-               goto out_dput;
-
-       upper = ovl_lookup_upper(ofs, dentry->d_name.name, upperdir,
-                                dentry->d_name.len);
+       upper = ovl_lookup_upper_unlocked(ofs, dentry->d_name.name, upperdir,
+                                         dentry->d_name.len);
        err = PTR_ERR(upper);
        if (IS_ERR(upper))
-               goto out_unlock;
+               goto out_dput;
 
        err = -ESTALE;
        if ((opaquedir && upper != opaquedir) ||
@@ -787,17 +783,18 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
                goto out_dput_upper;
        }
 
-       err = ovl_cleanup_and_whiteout(ofs, upperdir, upper);
+       err = ovl_lock_rename_workdir(workdir, NULL, upperdir, upper);
        if (err)
-               goto out_d_drop;
+               goto out_dput_upper;
+
+       err = ovl_cleanup_and_whiteout(ofs, upperdir, upper);
+       if (!err)
+               ovl_dir_modified(dentry->d_parent, true);
 
-       ovl_dir_modified(dentry->d_parent, true);
-out_d_drop:
        d_drop(dentry);
+       unlock_rename(workdir, upperdir);
 out_dput_upper:
        dput(upper);
-out_unlock:
-       unlock_rename(workdir, upperdir);
 out_dput:
        dput(opaquedir);
 out: