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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.