From: Horst Birthelmer <horst@birthelmer.de>
To: Amir Goldstein <amir73il@gmail.com>
Cc: Horst Birthelmer <horst@birthelmer.com>,
Miklos Szeredi <miklos@szeredi.hu>,
Bernd Schubert <bschubert@ddn.com>,
Joanne Koong <joannelkoong@gmail.com>,
Luis Henriques <luis@igalia.com>,
linux-kernel@vger.kernel.org, fuse-devel@lists.linux.dev,
Horst Birthelmer <hbirthelmer@ddn.com>
Subject: Re: Re: [PATCH v7 4/4] fuse: add compound command for dentry revalidation
Date: Fri, 5 Jun 2026 10:09:58 +0200 [thread overview]
Message-ID: <aiKD5muCy6iLLnK3@fedora.fritz.box> (raw)
In-Reply-To: <CAOQ4uxh5OzWVVPqJMe2g_jGhXBKLGUgKcEXW-_ShKtfXuTt7bQ@mail.gmail.com>
On Fri, Jun 05, 2026 at 10:06:55AM +0200, Amir Goldstein wrote:
> On Thu, Jun 4, 2026 at 11:51 AM Horst Birthelmer <horst@birthelmer.com> wrote:
> >
> > From: Horst Birthelmer <hbirthelmer@ddn.com>
> >
> > During dentry revalidation the compound LOOKUP+GETATTR
> > will save a round trip to user space.
> >
> > Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
> > ---
> > fs/fuse/dir.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> > 1 file changed, 111 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> > index b3406c33abd2..99800e8ca895 100644
> > --- a/fs/fuse/dir.c
> > +++ b/fs/fuse/dir.c
> > @@ -372,6 +372,101 @@ static void fuse_lookup_init(struct fuse_args *args, u64 nodeid,
> > args->out_args[0].value = outarg;
> > }
> >
> > +/*
> > + * Revalidate a dentry using a compound LOOKUP+GETATTR. Saves a round
> > + * trip when both the entry and the attributes need refreshing.
> > + *
> > + * Returns 1 if valid, 0 if the dentry should be invalidated, or a
> > + * negative errno that the caller should propagate (only -ENOMEM /
> > + * -EINTR; other errors are mapped to invalidate).
> > + */
> > +static int fuse_dentry_revalidate_compound(struct inode *dir,
> > + const struct qstr *name,
> > + struct dentry *entry,
> > + struct inode *inode,
> > + struct fuse_mount *fm,
> > + u64 attr_version)
> > +{
> > + struct fuse_entry_out lookup_out = {};
> > + struct fuse_attr_out getattr_out = {};
> > + struct fuse_getattr_in getattr_in = {};
> > + struct fuse_args lookup_args = {};
> > + struct fuse_args getattr_args = {};
> > + struct fuse_forget_link *forget;
> > + int lookup_err = 0, getattr_err = 0;
> > + struct fuse_compound_op ops[2] = {
> > + { .arg = &lookup_args, .error = &lookup_err,
> > + .dep_index = FUSE_COMPOUND_NO_DEP },
> > + { .arg = &getattr_args, .error = &getattr_err,
> > + .dep_index = 0 /* nodeid comes from lookup */ },
> > + };
> > + struct fuse_inode *fi;
> > + int ret;
> > +
> > + forget = fuse_alloc_forget();
> > + if (!forget)
> > + return -ENOMEM;
> > +
> > + fuse_lookup_init(&lookup_args, get_node_id(dir), name, &lookup_out);
> > + /* nodeid is filled from the lookup result before getattr is sent */
> > + fuse_getattr_args_fill(&getattr_args, 0, &getattr_in, &getattr_out);
> > +
> > + ret = fuse_compound_send(fm, ops, 2);
> > + if (ret == -ENOMEM || ret == -EINTR)
> > + goto out;
> > + /*
> > + * The non-compound revalidate path propagates -ENOMEM / -EINTR
> > + * from the lookup to VFS instead of treating them as "invalidate
> > + * this dentry". Keep that behaviour when the lookup ran inside
> > + * a compound: surface the per-subop error to the caller.
> > + */
> > + if (lookup_err == -ENOMEM || lookup_err == -EINTR) {
> > + ret = lookup_err;
> > + goto out;
> > + }
> > + if (ret < 0 || lookup_err || !lookup_out.nodeid) {
> > + ret = 0;
> > + goto out;
> > + }
> > +
> > + fi = get_fuse_inode(inode);
> > + if (lookup_out.nodeid != get_node_id(inode) ||
> > + (bool)IS_AUTOMOUNT(inode) != (bool)(lookup_out.attr.flags & FUSE_ATTR_SUBMOUNT)) {
> > + fuse_queue_forget(fm->fc, forget, lookup_out.nodeid, 1);
> > + forget = NULL;
> > + ret = 0;
> > + goto out;
> > + }
> > +
> > + spin_lock(&fi->lock);
> > + fi->nlookup++;
> > + spin_unlock(&fi->lock);
> > +
> > + if (fuse_invalid_attr(&lookup_out.attr) ||
> > + fuse_stale_inode(inode, lookup_out.generation, &lookup_out.attr)) {
> > + ret = 0;
> > + goto out;
> > + }
> > +
> > + forget_all_cached_acls(inode);
> > +
> > + if (!getattr_err && !fuse_invalid_attr(&getattr_out.attr))
> > + fuse_change_attributes(inode, &getattr_out.attr, NULL,
> > + ATTR_TIMEOUT(&getattr_out),
> > + attr_version);
> > + else
> > + fuse_change_attributes(inode, &lookup_out.attr, NULL,
> > + ATTR_TIMEOUT(&lookup_out),
> > + attr_version);
> > +
> > + fuse_change_entry_timeout(entry, &lookup_out);
> > + ret = 1;
> > +
> > +out:
> > + kfree(forget);
> > + return ret;
> > +}
> > +
>
> That's duplicating a lot of subtle code.
> I think this calls for some helpers.
OK ... this was a new one (compound I mean), and I valued the compactness of the patch more
than the possible code duplication. You're probably right ...
>
> Thanks,
> Amir.
next prev parent reply other threads:[~2026-06-05 8:16 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-04 9:45 [PATCH v7 0/4] fuse: compound commands Horst Birthelmer
2026-06-04 9:45 ` [PATCH v7 1/4] fuse: add compound command to combine multiple requests Horst Birthelmer
2026-06-05 7:41 ` Amir Goldstein
2026-06-05 8:03 ` Horst Birthelmer
2026-06-06 17:30 ` Horst Birthelmer
2026-06-04 9:45 ` [PATCH v7 2/4] fuse: create helper functions for filling in fuse args for open and getattr Horst Birthelmer
2026-06-05 7:42 ` Amir Goldstein
2026-06-04 9:45 ` [PATCH v7 3/4] fuse: add an implementation of open+getattr Horst Birthelmer
2026-06-05 7:50 ` Amir Goldstein
2026-06-04 9:45 ` [PATCH v7 4/4] fuse: add compound command for dentry revalidation Horst Birthelmer
2026-06-05 8:06 ` Amir Goldstein
2026-06-05 8:09 ` Horst Birthelmer [this message]
2026-06-05 8:12 ` [PATCH v7 0/4] fuse: compound commands Amir Goldstein
2026-06-05 8:49 ` Horst Birthelmer
2026-06-05 9:15 ` Amir Goldstein
2026-06-05 9:28 ` Horst Birthelmer
2026-06-05 10:49 ` Bernd Schubert
2026-06-05 11:26 ` Horst Birthelmer
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=aiKD5muCy6iLLnK3@fedora.fritz.box \
--to=horst@birthelmer.de \
--cc=amir73il@gmail.com \
--cc=bschubert@ddn.com \
--cc=fuse-devel@lists.linux.dev \
--cc=hbirthelmer@ddn.com \
--cc=horst@birthelmer.com \
--cc=joannelkoong@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luis@igalia.com \
--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