From: "NeilBrown" <neil@brown.name>
To: "Amir Goldstein" <amir73il@gmail.com>
Cc: "Miklos Szeredi" <miklos@szeredi.hu>,
linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH 08/20] ovl: narrow locking in ovl_rename()
Date: Mon, 14 Jul 2025 11:00:29 +1000 [thread overview]
Message-ID: <175245482902.2234665.10015695984345104010@noble.neil.brown.name> (raw)
In-Reply-To: <CAOQ4uxiRBS14KdZRY4ad_6cOZ+u3dZp+0C+8WYjJ=qmqhjqQTg@mail.gmail.com>
On Fri, 11 Jul 2025, Amir Goldstein wrote:
> On Fri, Jul 11, 2025 at 1:21 AM NeilBrown <neil@brown.name> wrote:
> >
> > Drop the rename lock immediately after the rename, and use
> > ovl_cleanup_unlocked() for cleanup.
> >
> > This makes way for future changes where locks are taken on individual
> > dentries rather than the whole directory.
> >
> > Signed-off-by: NeilBrown <neil@brown.name>
> > ---
> > fs/overlayfs/dir.c | 15 ++++++++++-----
> > 1 file changed, 10 insertions(+), 5 deletions(-)
> >
> > diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> > index 687d5e12289c..d01e83f9d800 100644
> > --- a/fs/overlayfs/dir.c
> > +++ b/fs/overlayfs/dir.c
> > @@ -1262,9 +1262,10 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
> > new_upperdir, newdentry, flags);
> > if (err)
> > goto out_dput;
> > + unlock_rename(new_upperdir, old_upperdir);
> >
> > if (cleanup_whiteout)
> > - ovl_cleanup(ofs, old_upperdir->d_inode, newdentry);
> > + ovl_cleanup_unlocked(ofs, old_upperdir, newdentry);
> >
> > if (overwrite && d_inode(new)) {
> > if (new_is_dir)
> > @@ -1283,12 +1284,8 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
> > if (d_inode(new) && ovl_dentry_upper(new))
> > ovl_copyattr(d_inode(new));
> >
> > -out_dput:
> > dput(newdentry);
> > -out_dput_old:
> > dput(olddentry);
> > -out_unlock:
> > - unlock_rename(new_upperdir, old_upperdir);
> > out_revert_creds:
> > ovl_revert_creds(old_cred);
> > if (update_nlink)
> > @@ -1299,6 +1296,14 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
> > dput(opaquedir);
> > ovl_cache_free(&list);
> > return err;
> > +
> > +out_dput:
> > + dput(newdentry);
> > +out_dput_old:
> > + dput(olddentry);
> > +out_unlock:
> > + unlock_rename(new_upperdir, old_upperdir);
> > + goto out_revert_creds;
> > }
> >
> > static int ovl_create_tmpfile(struct file *file, struct dentry *dentry,
> > --
> > 2.49.0
> >
>
> I think we get end up with fewer and clearer to understand goto labels
> with a relatively simple trick:
>
> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index fe493f3ed6b6..7cddaa7b263e 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -1069,8 +1069,8 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> int err;
> struct dentry *old_upperdir;
> struct dentry *new_upperdir;
> - struct dentry *olddentry;
> - struct dentry *newdentry;
> + struct dentry *olddentry = NULL;
> + struct dentry *newdentry = NULL;
> struct dentry *trap;
> bool old_opaque;
> bool new_opaque;
> @@ -1187,18 +1187,22 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> olddentry = ovl_lookup_upper(ofs, old->d_name.name, old_upperdir,
> old->d_name.len);
> err = PTR_ERR(olddentry);
> - if (IS_ERR(olddentry))
> + if (IS_ERR(olddentry)) {
> + olddentry = NULL;
> goto out_unlock;
> + }
>
> err = -ESTALE;
> if (!ovl_matches_upper(old, olddentry))
> - goto out_dput_old;
> + goto out_unlock;
>
> newdentry = ovl_lookup_upper(ofs, new->d_name.name, new_upperdir,
> new->d_name.len);
> err = PTR_ERR(newdentry);
> - if (IS_ERR(newdentry))
> - goto out_dput_old;
> + if (IS_ERR(newdentry)) {
> + newdentry = NULL;
> + goto out_unlock;
> + }
>
> old_opaque = ovl_dentry_is_opaque(old);
> new_opaque = ovl_dentry_is_opaque(new);
> @@ -1207,28 +1211,28 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> if (d_inode(new) && ovl_dentry_upper(new)) {
> if (opaquedir) {
> if (newdentry != opaquedir)
> - goto out_dput;
> + goto out_unlock;
> } else {
> if (!ovl_matches_upper(new, newdentry))
> - goto out_dput;
> + goto out_unlock;
> }
> } else {
> if (!d_is_negative(newdentry)) {
> if (!new_opaque || !ovl_upper_is_whiteout(ofs,
> newdentry))
> - goto out_dput;
> + goto out_unlock;
> } else {
> if (flags & RENAME_EXCHANGE)
> - goto out_dput;
> + goto out_unlock;
> }
> }
>
> if (olddentry == trap)
> - goto out_dput;
> + goto out_unlock;
> if (newdentry == trap)
> - goto out_dput;
> + goto out_unlock;
>
> if (olddentry->d_inode == newdentry->d_inode)
> - goto out_dput;
> + goto out_unlock;
>
> err = 0;
> if (ovl_type_merge_or_lower(old))
> @@ -1236,7 +1240,7 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> else if (is_dir && !old_opaque && ovl_type_merge(new->d_parent))
> err = ovl_set_opaque_xerr(old, olddentry, -EXDEV);
> if (err)
> - goto out_dput;
> + goto out_unlock;
>
> if (!overwrite && ovl_type_merge_or_lower(new))
> err = ovl_set_redirect(new, samedir);
> @@ -1244,15 +1248,16 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> ovl_type_merge(old->d_parent))
> err = ovl_set_opaque_xerr(new, newdentry, -EXDEV);
> if (err)
> - goto out_dput;
> + goto out_unlock;
>
> err = ovl_do_rename(ofs, old_upperdir->d_inode, olddentry,
> new_upperdir->d_inode, newdentry, flags);
> if (err)
> - goto out_dput;
> + goto out_unlock;
> + unlock_rename(new_upperdir, old_upperdir);
>
> if (cleanup_whiteout)
> - ovl_cleanup(ofs, old_upperdir->d_inode, newdentry);
> + ovl_cleanup_unlocked(ofs, old_upperdir->d_inode, newdentry);
>
> if (overwrite && d_inode(new)) {
> if (new_is_dir)
> @@ -1271,12 +1276,6 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> if (d_inode(new) && ovl_dentry_upper(new))
> ovl_copyattr(d_inode(new));
>
> -out_dput:
> - dput(newdentry);
> -out_dput_old:
> - dput(olddentry);
> -out_unlock:
> - unlock_rename(new_upperdir, old_upperdir);
> out_revert_creds:
> ovl_revert_creds(old_cred);
> if (update_nlink)
> @@ -1284,9 +1283,15 @@ static int ovl_rename(struct mnt_idmap *idmap,
> struct inode *olddir,
> else
> ovl_drop_write(old);
> out:
> + dput(newdentry);
> + dput(olddentry);
> dput(opaquedir);
> ovl_cache_free(&list);
> return err;
> +
> +out_unlock:
> + unlock_rename(new_upperdir, old_upperdir);
> + goto out_revert_creds;
> }
>
I decided to make the goto changed into a separate patch as follows. My
version is slightly different to yours (see new var "de").
Thanks,
NeilBrown
From: NeilBrown <neil@brown.name>
Date: Mon, 14 Jul 2025 10:44:03 +1000
Subject: [PATCH] ovl: simplify gotos in ovl_rename()
Rather than having three separate goto label: out_unlock, out_dput_old,
and out_dput, make use of that fact that dput() happily accepts a NULL
point to reduce this to just one goto label: out_unlock.
olddentry and newdentry are initialised to NULL and only set once a
value dentry is found. They are then put late in the function.
Suggested-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: NeilBrown <neil@brown.name>
---
fs/overlayfs/dir.c | 54 +++++++++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index e094adf9d169..63460bdd71cf 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -1082,9 +1082,9 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
int err;
struct dentry *old_upperdir;
struct dentry *new_upperdir;
- struct dentry *olddentry;
- struct dentry *newdentry;
- struct dentry *trap;
+ struct dentry *olddentry = NULL;
+ struct dentry *newdentry = NULL;
+ struct dentry *trap, *de;
bool old_opaque;
bool new_opaque;
bool cleanup_whiteout = false;
@@ -1197,21 +1197,23 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
goto out_revert_creds;
}
- olddentry = ovl_lookup_upper(ofs, old->d_name.name, old_upperdir,
- old->d_name.len);
- err = PTR_ERR(olddentry);
- if (IS_ERR(olddentry))
+ de = ovl_lookup_upper(ofs, old->d_name.name, old_upperdir,
+ old->d_name.len);
+ err = PTR_ERR(de);
+ if (IS_ERR(de))
goto out_unlock;
+ olddentry = de;
err = -ESTALE;
if (!ovl_matches_upper(old, olddentry))
- goto out_dput_old;
+ goto out_unlock;
- newdentry = ovl_lookup_upper(ofs, new->d_name.name, new_upperdir,
- new->d_name.len);
- err = PTR_ERR(newdentry);
- if (IS_ERR(newdentry))
- goto out_dput_old;
+ de = ovl_lookup_upper(ofs, new->d_name.name, new_upperdir,
+ new->d_name.len);
+ err = PTR_ERR(de);
+ if (IS_ERR(de))
+ goto out_unlock;
+ newdentry = de;
old_opaque = ovl_dentry_is_opaque(old);
new_opaque = ovl_dentry_is_opaque(new);
@@ -1220,28 +1222,28 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
if (d_inode(new) && ovl_dentry_upper(new)) {
if (opaquedir) {
if (newdentry != opaquedir)
- goto out_dput;
+ goto out_unlock;
} else {
if (!ovl_matches_upper(new, newdentry))
- goto out_dput;
+ goto out_unlock;
}
} else {
if (!d_is_negative(newdentry)) {
if (!new_opaque || !ovl_upper_is_whiteout(ofs, newdentry))
- goto out_dput;
+ goto out_unlock;
} else {
if (flags & RENAME_EXCHANGE)
- goto out_dput;
+ goto out_unlock;
}
}
if (olddentry == trap)
- goto out_dput;
+ goto out_unlock;
if (newdentry == trap)
- goto out_dput;
+ goto out_unlock;
if (olddentry->d_inode == newdentry->d_inode)
- goto out_dput;
+ goto out_unlock;
err = 0;
if (ovl_type_merge_or_lower(old))
@@ -1249,7 +1251,7 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
else if (is_dir && !old_opaque && ovl_type_merge(new->d_parent))
err = ovl_set_opaque_xerr(old, olddentry, -EXDEV);
if (err)
- goto out_dput;
+ goto out_unlock;
if (!overwrite && ovl_type_merge_or_lower(new))
err = ovl_set_redirect(new, samedir);
@@ -1257,12 +1259,12 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
ovl_type_merge(old->d_parent))
err = ovl_set_opaque_xerr(new, newdentry, -EXDEV);
if (err)
- goto out_dput;
+ goto out_unlock;
err = ovl_do_rename(ofs, old_upperdir, olddentry,
new_upperdir, newdentry, flags);
if (err)
- goto out_dput;
+ goto out_unlock;
if (cleanup_whiteout)
ovl_cleanup(ofs, old_upperdir->d_inode, newdentry);
@@ -1284,10 +1286,6 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
if (d_inode(new) && ovl_dentry_upper(new))
ovl_copyattr(d_inode(new));
-out_dput:
- dput(newdentry);
-out_dput_old:
- dput(olddentry);
out_unlock:
unlock_rename(new_upperdir, old_upperdir);
out_revert_creds:
@@ -1297,6 +1295,8 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
else
ovl_drop_write(old);
out:
+ dput(newdentry);
+ dput(olddentry);
dput(opaquedir);
ovl_cache_free(&list);
return err;
--
2.49.0
next prev parent reply other threads:[~2025-07-14 1:00 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-10 23:03 [PATCH 00/20 v2] ovl: narrow regions protected by i_rw_sem NeilBrown
2025-07-10 23:03 ` [PATCH 01/20] ovl: simplify an error path in ovl_copy_up_workdir() NeilBrown
2025-07-11 8:25 ` Amir Goldstein
2025-07-11 10:30 ` Amir Goldstein
2025-07-14 0:13 ` NeilBrown
2025-07-14 5:42 ` parent_lock/unlock (Was: [PATCH 01/20] ovl: simplify an error path in ovl_copy_up_workdir()) Amir Goldstein
2025-07-16 3:55 ` NeilBrown
2025-07-10 23:03 ` [PATCH 02/20] ovl: change ovl_create_index() to take write and dir locks NeilBrown
2025-07-11 10:41 ` Amir Goldstein
2025-07-14 0:14 ` NeilBrown
2025-07-10 23:03 ` [PATCH 03/20] ovl: Call ovl_create_temp() without lock held NeilBrown
2025-07-11 11:10 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 04/20] ovl: narrow the locked region in ovl_copy_up_workdir() NeilBrown
2025-07-11 12:03 ` Amir Goldstein
2025-07-14 0:29 ` NeilBrown
2025-07-10 23:03 ` [PATCH 05/20] ovl: narrow locking in ovl_create_upper() NeilBrown
2025-07-11 12:09 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 06/20] ovl: narrow locking in ovl_clear_empty() NeilBrown
2025-07-11 12:27 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 07/20] ovl: narrow locking in ovl_create_over_whiteout() NeilBrown
2025-07-11 12:42 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 08/20] ovl: narrow locking in ovl_rename() NeilBrown
2025-07-11 13:03 ` Amir Goldstein
2025-07-14 1:00 ` NeilBrown [this message]
2025-07-14 5:12 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 09/20] ovl: narrow locking in ovl_cleanup_whiteouts() NeilBrown
2025-07-10 23:03 ` [PATCH 10/20] ovl: narrow locking in ovl_cleanup_index() NeilBrown
2025-07-11 13:12 ` Amir Goldstein
2025-07-14 1:03 ` NeilBrown
2025-07-10 23:03 ` [PATCH 11/20] ovl: narrow locking in ovl_workdir_create() NeilBrown
2025-07-11 13:32 ` Amir Goldstein
2025-07-14 1:08 ` NeilBrown
2025-07-10 23:03 ` [PATCH 12/20] ovl: narrow locking in ovl_indexdir_cleanup() NeilBrown
2025-07-11 13:33 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 13/20] ovl: narrow locking in ovl_workdir_cleanup_recurse() NeilBrown
2025-07-11 13:35 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 14/20] ovl: change ovl_workdir_cleanup() to take dir lock as needed NeilBrown
2025-07-11 13:28 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 15/20] ovl: narrow locking on ovl_remove_and_whiteout() NeilBrown
2025-07-11 13:42 ` Amir Goldstein
2025-07-14 1:35 ` NeilBrown
2025-07-10 23:03 ` [PATCH 16/20] ovl: change ovl_cleanup_and_whiteout() to take rename lock as needed NeilBrown
2025-07-11 13:50 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 17/20] ovl: narrow locking in ovl_whiteout() NeilBrown
2025-07-11 15:19 ` Amir Goldstein
2025-07-14 1:44 ` NeilBrown
2025-07-10 23:03 ` [PATCH 18/20] ovl: narrow locking in ovl_check_rename_whiteout() NeilBrown
2025-07-11 13:54 ` Amir Goldstein
2025-07-10 23:03 ` [PATCH 19/20] ovl: change ovl_create_real() to receive dentry parent NeilBrown
2025-07-10 23:03 ` [PATCH 20/20] ovl: rename ovl_cleanup_unlocked() to ovl_cleanup() NeilBrown
2025-07-11 9:57 ` Amir Goldstein
2025-07-11 16:41 ` [PATCH 00/20 v2] ovl: narrow regions protected by i_rw_sem Amir Goldstein
2025-07-14 5:57 ` Amir Goldstein
2025-07-16 0:13 ` NeilBrown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=175245482902.2234665.10015695984345104010@noble.neil.brown.name \
--to=neil@brown.name \
--cc=amir73il@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).