From: "Chuck Lever" <cel@kernel.org>
To: "Jeff Layton" <jlayton@kernel.org>,
"Chuck Lever" <chuck.lever@oracle.com>,
NeilBrown <neil@brown.name>,
"Olga Kornievskaia" <okorniev@redhat.com>,
"Dai Ngo" <Dai.Ngo@oracle.com>, "Tom Talpey" <tom@talpey.com>,
"Trond Myklebust" <trondmy@kernel.org>,
"Anna Schumaker" <anna@kernel.org>,
"Jonathan Corbet" <corbet@lwn.net>,
"Shuah Khan" <skhan@linuxfoundation.org>
Cc: "Steven Rostedt" <rostedt@goodmis.org>,
"Alexander Aring" <alex.aring@gmail.com>,
"Amir Goldstein" <amir73il@gmail.com>, "Jan Kara" <jack@suse.cz>,
"Alexander Viro" <viro@zeniv.linux.org.uk>,
"Christian Brauner" <brauner@kernel.org>,
"Calum Mackay" <calum.mackay@oracle.com>,
linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
linux-nfs@vger.kernel.org
Subject: Re: [PATCH v5 10/21] nfsd: add notification handlers for dir events
Date: Mon, 08 Jun 2026 16:52:12 -0400 [thread overview]
Message-ID: <efdade0b-38f2-4e5e-b6dc-567d9eea97a9@app.fastmail.com> (raw)
In-Reply-To: <20260522-dir-deleg-v5-10-542cddfad576@kernel.org>
On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> Add the necessary parts to accept a fsnotify callback for directory
> change event and create a CB_NOTIFY request for it. When a dir nfsd_file
> is created set a handle_event callback to handle the notification.
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index e17488a911f7..31df04675713 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -4172,6 +4172,127 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp,
> struct xdr_stream *xdr,
> goto out;
> }
>
> +static bool
> +nfsd4_setup_notify_entry4(struct notify_entry4 *ne, struct xdr_stream
> *xdr,
> + struct dentry *dentry, struct nfs4_delegation *dp,
> + struct nfsd_file *nf, char *name, u32 namelen)
> +{
> + uint32_t *attrmask;
> +
> + /* Reserve space for attrmask */
> + attrmask = xdr_reserve_space(xdr, 3 * sizeof(uint32_t));
> + if (!attrmask)
> + return false;
> +
> + ne->ne_file.data = name;
> + ne->ne_file.len = namelen;
> + ne->ne_attrs.attrmask.element = attrmask;
> +
> + attrmask[0] = 0;
> + attrmask[1] = 0;
> + attrmask[2] = 0;
> + ne->ne_attrs.attr_vals.data = NULL;
> + ne->ne_attrs.attr_vals.len = 0;
> + ne->ne_attrs.attrmask.count = 1;
> + return true;
> +}
> +
> +/**
> + * nfsd4_encode_notify_event - encode a notify
> + * @xdr: stream to which to encode the fattr4
> + * @nne: nfsd_notify_event to encode
> + * @dp: delegation where the event occurred
> + * @nf: nfsd_file on which event occurred
> + * @notify_mask: pointer to word where notification mask should be set
> + *
> + * Encode @nne into @xdr. Returns a pointer to the start of the event,
> or NULL if
> + * the event couldn't be encoded. The appropriate bit in the
> notify_mask will also
> + * be set on success.
> + */
> +u8 *nfsd4_encode_notify_event(struct xdr_stream *xdr, struct
> nfsd_notify_event *nne,
> + struct nfs4_delegation *dp, struct nfsd_file *nf,
> + u32 *notify_mask)
> +{
> + u8 *p = NULL;
> +
> + *notify_mask = 0;
> +
> + if (nne->ne_mask & FS_DELETE) {
> + struct notify_remove4 nr = { };
> +
> + if (!nfsd4_setup_notify_entry4(&nr.nrm_old_entry, xdr,
> nne->ne_dentry, dp,
> + nf, nne->ne_name, nne->ne_namelen))
> + goto out_err;
> + p = (u8 *)xdr->p;
> + if (!xdrgen_encode_notify_remove4(xdr, &nr))
> + goto out_err;
> + *notify_mask |= BIT(NOTIFY4_REMOVE_ENTRY);
> + } else if (nne->ne_mask & FS_CREATE) {
> + struct notify_add4 na = { };
> + struct notify_remove4 old = { };
> +
> + if (!nfsd4_setup_notify_entry4(&na.nad_new_entry, xdr,
> nne->ne_dentry, dp,
> + nf, nne->ne_name, nne->ne_namelen))
> + goto out_err;
> +
> + /* If a file was overwritten, report it in nad_old_entry */
> + if (nne->ne_target) {
> + if (!nfsd4_setup_notify_entry4(&old.nrm_old_entry, xdr,
> + NULL, dp, nf,
> + nne->ne_name, nne->ne_namelen))
> + goto out_err;
> + na.nad_old_entry.count = 1;
> + na.nad_old_entry.element = &old;
> + }
> +
> + p = (u8 *)xdr->p;
> + if (!xdrgen_encode_notify_add4(xdr, &na))
> + goto out_err;
> +
> + *notify_mask |= BIT(NOTIFY4_ADD_ENTRY);
> + } else if (nne->ne_mask & FS_RENAME) {
> + struct notify_rename4 nr = { };
> + struct notify_remove4 old = { };
> + struct name_snapshot n;
> + bool ret;
> +
> + /* Don't send any attributes in the old_entry since they're the same
> in new */
> + if (!nfsd4_setup_notify_entry4(&nr.nrn_old_entry.nrm_old_entry, xdr,
> + NULL, dp, nf, nne->ne_name,
> + nne->ne_namelen))
> + goto out_err;
> +
> + take_dentry_name_snapshot(&n, nne->ne_dentry);
> + ret = nfsd4_setup_notify_entry4(&nr.nrn_new_entry.nad_new_entry, xdr,
> + nne->ne_dentry, dp, nf, (char *)n.name.name,
> + n.name.len);
Now once I got all of the previous edits in place, all three LLM
reviewers identified an issue here that might require a significant
rewrite. This is why I stopped the minor editing here and decided
it was time for you to consider restructuring (or not). I haven't
looked at patches 11-21.
I think the new name here has a time-of-use problem.
nrn_old_entry uses nne->ne_name, which alloc_nfsd_notify_event() copied
when fsnotify delivered the rename. nrn_new_entry instead reads the
live dentry via take_dentry_name_snapshot() at callback-prepare time,
which can run long after the event was queued.
CB_NOTIFY is asynchronous: nfsd_handle_dir_event() queues the event on
ncn_evt[] and nothing holds ne_dentry stable until the work runs.
d_move() reuses the same dentry and rewrites d_name in place, so a
second rename of the entry before the queued callback encodes leaves
the dget'd ne_dentry carrying the later name. An A->B event then
encodes as A->C, and a client holding the directory delegation applies
the wrong old->new mapping to its cache. The old name is immune
because it was snapshotted up front; only the new name is read late.
The new name is available at notification time -- fsnotify_move() passes
&moved->d_name as new_name, and ne_dentry is that moved dentry -- so
alloc_nfsd_notify_event() can snapshot it alongside the old name.
What I haven't assessed is whether the suggested restructuring is
now vulnerable to misbehavior during memory exhaustion.
> +
> + /* If a file was overwritten, report it in nad_old_entry */
> + if (ret && nne->ne_target) {
> + ret = nfsd4_setup_notify_entry4(&old.nrm_old_entry, xdr,
> + NULL, dp, nf,
> + (char *)n.name.name, n.name.len);
> + if (ret) {
> + nr.nrn_new_entry.nad_old_entry.count = 1;
> + nr.nrn_new_entry.nad_old_entry.element = &old;
> + }
> + }
> +
> + if (ret) {
> + p = (u8 *)xdr->p;
> + ret = xdrgen_encode_notify_rename4(xdr, &nr);
> + }
> + release_dentry_name_snapshot(&n);
> + if (!ret)
> + goto out_err;
> + *notify_mask |= BIT(NOTIFY4_RENAME_ENTRY);
> + }
> + return p;
> +out_err:
> + pr_warn("nfsd: unable to marshal notify_rename4 to xdr stream\n");
> + return NULL;
> +}
> +
> static void svcxdr_init_encode_from_buffer(struct xdr_stream *xdr,
> struct xdr_buf *buf, __be32 *p, int bytes)
> {
--
Chuck Lever
next prev parent reply other threads:[~2026-06-08 20:52 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-22 19:42 [PATCH v5 00/21] nfsd: add support for CB_NOTIFY callbacks in directory delegations Jeff Layton
2026-05-22 19:42 ` [PATCH v5 01/21] nfsd: check fl_lmops in nfsd_breaker_owns_lease() Jeff Layton
2026-05-22 19:42 ` [PATCH v5 02/21] nfsd: add protocol support for CB_NOTIFY Jeff Layton
2026-05-22 19:42 ` [PATCH v5 03/21] nfs_common: add new NOTIFY4_* flags proposed in RFC8881bis Jeff Layton
2026-05-22 19:42 ` [PATCH v5 04/21] nfsd: allow nfsd to get a dir lease with an ignore mask Jeff Layton
2026-06-08 16:29 ` Chuck Lever
2026-05-22 19:42 ` [PATCH v5 05/21] nfsd: update the fsnotify mark when setting or removing a dir delegation Jeff Layton
2026-06-08 16:38 ` Chuck Lever
2026-06-10 13:49 ` Jeff Layton
2026-06-10 13:55 ` Chuck Lever
2026-05-22 19:42 ` [PATCH v5 06/21] nfsd: make nfsd4_callback_ops->prepare operation bool return Jeff Layton
2026-05-22 19:42 ` [PATCH v5 07/21] nfsd: add callback encoding and decoding linkages for CB_NOTIFY Jeff Layton
2026-06-08 16:52 ` Chuck Lever
2026-06-10 15:19 ` Jeff Layton
2026-06-10 15:25 ` Chuck Lever
2026-05-22 19:42 ` [PATCH v5 08/21] nfsd: use RCU to protect fi_deleg_file Jeff Layton
2026-06-08 17:00 ` Chuck Lever
2026-05-22 19:42 ` [PATCH v5 09/21] nfsd: add data structures for handling CB_NOTIFY Jeff Layton
2026-06-08 20:18 ` Chuck Lever
2026-06-10 15:51 ` Jeff Layton
2026-05-22 19:42 ` [PATCH v5 10/21] nfsd: add notification handlers for dir events Jeff Layton
2026-06-08 20:40 ` Chuck Lever
2026-06-10 18:33 ` Jeff Layton
2026-06-08 20:52 ` Chuck Lever [this message]
2026-06-10 18:38 ` Jeff Layton
2026-05-22 19:42 ` [PATCH v5 11/21] nfsd: add tracepoint to dir_event handler Jeff Layton
2026-05-22 19:42 ` [PATCH v5 12/21] nfsd: apply the notify mask to the delegation when requested Jeff Layton
2026-05-22 19:42 ` [PATCH v5 13/21] nfsd: add helper to marshal a fattr4 from completed args Jeff Layton
2026-05-22 19:42 ` [PATCH v5 14/21] nfsd: allow nfsd4_encode_fattr4_change() to work with no export Jeff Layton
2026-05-22 19:42 ` [PATCH v5 15/21] nfsd: send basic file attributes in CB_NOTIFY Jeff Layton
2026-05-22 19:42 ` [PATCH v5 16/21] nfsd: allow encoding a filehandle into fattr4 without a svc_fh Jeff Layton
2026-05-22 19:42 ` [PATCH v5 17/21] nfsd: add a fi_connectable flag to struct nfs4_file Jeff Layton
2026-05-22 19:42 ` [PATCH v5 18/21] nfsd: add the filehandle to returned attributes in CB_NOTIFY Jeff Layton
2026-05-22 19:42 ` [PATCH v5 19/21] nfsd: properly track requested child attributes Jeff Layton
2026-05-22 19:42 ` [PATCH v5 20/21] nfsd: track requested dir attributes Jeff Layton
2026-05-22 19:42 ` [PATCH v5 21/21] nfsd: add support to CB_NOTIFY for dir attribute changes Jeff Layton
2026-05-23 17:00 ` [PATCH v5 00/21] nfsd: add support for CB_NOTIFY callbacks in directory delegations Chuck Lever
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=efdade0b-38f2-4e5e-b6dc-567d9eea97a9@app.fastmail.com \
--to=cel@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=alex.aring@gmail.com \
--cc=amir73il@gmail.com \
--cc=anna@kernel.org \
--cc=brauner@kernel.org \
--cc=calum.mackay@oracle.com \
--cc=chuck.lever@oracle.com \
--cc=corbet@lwn.net \
--cc=jack@suse.cz \
--cc=jlayton@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=rostedt@goodmis.org \
--cc=skhan@linuxfoundation.org \
--cc=tom@talpey.com \
--cc=trondmy@kernel.org \
--cc=viro@zeniv.linux.org.uk \
/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