All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Chuck Lever <cel@kernel.org>, NeilBrown <neil@brown.name>,
	 Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <Dai.Ngo@oracle.com>,  Tom Talpey <tom@talpey.com>
Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Jeff Layton <jlayton@kernel.org>
Subject: [PATCH 2/2] nfsd: back CB_NOTIFY notify_mask words with per-delegation storage
Date: Wed, 12 Aug 2026 14:08:15 -0400	[thread overview]
Message-ID: <20260812-dir-deleg-v1-2-411faa713068@kernel.org> (raw)
In-Reply-To: <20260812-dir-deleg-v1-0-411faa713068@kernel.org>

nfsd4_cb_notify_prepare() reserved a word from the encoding xdr stream
for each notify4's host-order notify_mask, storing the pointer in
ncn_nf[].notify_mask.element. That element must survive until the RPC
encode re-reads ncn_nf, so the host-endian word lived inside the XDR
staging buffer for the whole callback lifetime - the same fragile
pattern as the attrmask, and one that keeps host-order bytes in a
buffer meant to hold big-endian XDR.

ncn_nf is a bounded per-delegation array reused across every CB_NOTIFY,
so give it a parallel ncn_masks array with the same lifetime:

- allocate/free ncn_masks alongside ncn_nf in alloc_init_dir_deleg() /
  nfs4_free_dir_deleg()
- point notify_mask.element at &ncn_masks[i] (events) and
  &ncn_masks[count] (dir attr change)

The mask backing is now pre-allocated, so the per-word NULL checks in
prepare go away. The staging stream holds only encoded XDR.

Assisted-by: LLM
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/nfsd/nfs4state.c | 20 +++++++++-----------
 fs/nfsd/state.h     |  1 +
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 510380b6aa7a..1ba97e3f65eb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1323,6 +1323,7 @@ static void nfs4_free_dir_deleg(struct nfs4_stid *stid)
 	for (i = 0; i < ncn->ncn_evt_cnt; ++i)
 		nfsd_notify_event_put(ncn->ncn_evt[i]);
 	kfree(ncn->ncn_nf);
+	kfree(ncn->ncn_masks);
 	for (i = 0; i < NOTIFY4_PAGE_ARRAY_SIZE; i++) {
 		if (!ncn->ncn_pages[i])
 			break;
@@ -1355,6 +1356,11 @@ alloc_init_dir_deleg(struct nfs4_client *clp, struct nfs4_file *fp)
 		nfs4_put_stid(&dp->dl_stid);
 		return NULL;
 	}
+	ncn->ncn_masks = kcalloc(NOTIFY4_EVENT_QUEUE_SIZE, sizeof(*ncn->ncn_masks), GFP_KERNEL);
+	if (!ncn->ncn_masks) {
+		nfs4_put_stid(&dp->dl_stid);
+		return NULL;
+	}
 	spin_lock_init(&ncn->ncn_lock);
 	nfsd4_init_cb(&ncn->ncn_cb, dp->dl_stid.sc_client,
 			&nfsd4_cb_notify_ops, NFSPROC4_CLNT_CB_NOTIFY);
@@ -3767,14 +3773,9 @@ nfsd4_cb_notify_prepare(struct nfsd4_callback *cb)
 		struct nfsd_notify_event *nne = events[i];
 
 		if (!error) {
-			u32 *maskp = (u32 *)xdr_reserve_space(&stream, sizeof(*maskp));
+			u32 *maskp = &ncn->ncn_masks[i];
 			u8 *p;
 
-			if (!maskp) {
-				error = true;
-				goto put_event;
-			}
-
 			p = nfsd4_encode_notify_event(&stream, nne, dp, nf, maskp);
 			if (!p) {
 				pr_notice("Could not generate CB_NOTIFY from fsnotify mask 0x%x\n",
@@ -3792,13 +3793,10 @@ nfsd4_cb_notify_prepare(struct nfsd4_callback *cb)
 		nfsd_notify_event_put(nne);
 	}
 	if (!error && (dp->dl_notify_mask & BIT(NOTIFY4_CHANGE_DIR_ATTRS))) {
-		u32 *maskp = (u32 *)xdr_reserve_space(&stream, sizeof(*maskp));
+		u32 *maskp = &ncn->ncn_masks[count];
 		u8 *p;
 
-		if (maskp)
-			p = nfsd4_encode_dir_attr_change(&stream, dp, nf);
-		else
-			p = ERR_PTR(-ENOBUFS);
+		p = nfsd4_encode_dir_attr_change(&stream, dp, nf);
 
 		if (IS_ERR(p)) {
 			/*
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index ff1c9fa731aa..c65b604e29f1 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -271,6 +271,7 @@ struct nfsd4_cb_notify {
 	struct nfsd_notify_event	*ncn_evt[NOTIFY4_EVENT_QUEUE_SIZE]; // list of events
 	struct page			*ncn_pages[NOTIFY4_PAGE_ARRAY_SIZE]; // for encoding
 	struct notify4			*ncn_nf;	// array of notify4's to be sent
+	u32				*ncn_masks;	// host-order notify_mask backing for ncn_nf[]
 	bool				ncn_encode_err;	// did encoding fail?
 	struct nfsd4_callback		ncn_cb;		// notify4 callback
 };

-- 
2.55.0


  parent reply	other threads:[~2026-08-12 18:08 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12 18:08 [PATCH 0/2] nfsd: don't use the xdr buf for temporary storage in CB_NOTIFY Jeff Layton
2026-08-12 18:08 ` [PATCH 1/2] nfsd: pass caller-provided attrmask storage into nfsd4_setup_notify_entry4() Jeff Layton
2026-08-12 18:08 ` Jeff Layton [this message]
2026-08-12 18:58 ` [PATCH 0/2] nfsd: don't use the xdr buf for temporary storage in CB_NOTIFY 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=20260812-dir-deleg-v1-2-411faa713068@kernel.org \
    --to=jlayton@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=cel@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=tom@talpey.com \
    /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.