From nobody Tue Sep 29 04:10:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78D52471408; Wed, 12 Aug 2026 18:08:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786558105; cv=none; b=HMTsl7SWpSsA8Pt2ZLKUx8pU5gLSQWQlmEahP0sy7DIeqmzSYb1KlR7KvHOOXB7dOZ4NEdO/g9/0MDwv6gwDEdNdHcmptA+DzTcCxYPPFJ23JER50zicJ3A/2mm0sZ9bDC/5nCD1zFfusCOjGM+ppQsrnDsRlg8tVKzBlMT+gog= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786558105; c=relaxed/simple; bh=h8CS5Q+rkx5ibF6+m98ciIhCHpeeIsV8A9y3QTswmto=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KGYzs968ekeVQTakV+S0bvEkChio6SnXRRFDxWYjga2UsWHPIHI2ApG15zZHWTQ230JhPw6kHGdH9Yq6Tl0e3yfgYPoBzezKgZeOA1R8d7HpAz8sN47+evbI/duGlR1G/8aWNMypfyl/7xMzO/svg/0KXBvNwYykFAsQvdIeZDA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=k3TeWktk; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="k3TeWktk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 95ABD1F00A3A; Wed, 12 Aug 2026 18:08:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786558104; bh=AYGLgNHX2Cxh2ohIRv9ErfRwgVHubviL8bLo7Q9ZaGE=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=k3TeWktkKI3ytyg/sgffixFp1ggJhfH3Mw/cM68d3/5fbt6X1hW63gkMNhwInvUXZ EssyMEHj1rWC/yzMB6lOfthReu3hJ52imYK+HfHpzFaAzLtG/Sbi+2BVBNGHGBizZc ByFRvhU7EehJq66dCKEUaAwUEWLg5R3GiwPQ6BJv/MVHJFlR/2nWoTVVajb5e2SMbk /VETj50/dQaDRF4S3cK719nP1K1U9BygisYdcBagLrwAKF5CE9s/6lOfw/K7RG4aFW ovf7EUBHOCmVU6Ztr1tEVNw8f+2k0M8Q4rE9019Vg3jAhoBjKohSYijjfQgxNbhQSG shRMJAAHmOnmg== From: Jeff Layton Date: Wed, 12 Aug 2026 14:08:14 -0400 Subject: [PATCH 1/2] nfsd: pass caller-provided attrmask storage into nfsd4_setup_notify_entry4() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260812-dir-deleg-v1-1-411faa713068@kernel.org> References: <20260812-dir-deleg-v1-0-411faa713068@kernel.org> In-Reply-To: <20260812-dir-deleg-v1-0-411faa713068@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4988; i=jlayton@kernel.org; h=from:subject:message-id; bh=h8CS5Q+rkx5ibF6+m98ciIhCHpeeIsV8A9y3QTswmto=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqfLaWSnrHoM1dxHDCivZctxslayTejtvG8LQuX 1l+mmHm4AqJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCany2lgAKCRAADmhBGVaC FbAND/4yAM+ZZJn7WyAn0P7YnFfEeD4p/cajuT9hvENY18tVRFySvuRFbLwmHVAhry9CJlf/+Nl OvCh2qtUc2qAmYBZUAzksxTIwZTR4tVH8nJghlyYHT7UTVZmxDbLDSP+8ZGqUez2SAmZziU0+gC ttK3DuBXBtItfZHILKQRlkwi7/z/z5drWHVvKX84UDpdGTLl/vKdL2srCMaGFZnlZ/jYYOEIbMx 0fvfBtjGRCDDZwwMx5O/dZaTSuWi9vJ1dvupv1z/5gCQzQSbSBjHkGm29sETSRTLut5ULxD3Z2O DWr9hCvNKJvP2A5Zusk/KAC+9arPluvPar53OjmwRgg3Gc+/7uXxEUCaDDCDd8fJQR2+JTkIhQP bT6GJEuvjOTiRCxL6K9RzrUfDiOUuFc9hSSe/JD4C8tS9mL0ojREQKqwdUSEJqy4cZjEWROSeut nlHr0RaPlDBVixYUWaO8/9fRDErFmTZR/a3dzFkY45b7q1uRwCpIpRGDxPf6Qr6saWqDQsI65JW X9fYa7ZcPbvN6SBmb9Pl+J77VFXAmsS5ZK8KT3Ooxc87TLyCPUecHQ/Itl8NQnCO78nYug5ePvK Dy25xvPNFh5NsuannqksMRJXJqwClgymSL6g+m0492OR0F3yTdJipxheHHu9mL0pz4g2rcM91u/ Xqg9eCdSde6/d6Q== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 nfsd4_setup_notify_entry4() stole 3 words from the xdr stream via xdr_reserve_space() to hold the host-order bmval[3] attrmask that nfsd4_encode_attr_vals() consumes and ne_attrs.attrmask.element points at. Stashing host-endian scratch in an XDR stream buffer is fragile: the buffer layout is not guaranteed by sunrpc, and it blocks moving the encoder to pages or xdrgen. The attrmask only needs to live until the enclosing encode call serializes the notify_entry4, so hand it caller-provided stack storage instead. The two callers keep the words on the stack: up to three concurrent entries for a rename in nfsd4_encode_notify_event(), one in nfsd4_encode_dir_attr_change(). No wire change: the reserved words were never emitted; attr_vals.data/len are still captured relative to xdr->p. Assisted-by: LLM Signed-off-by: Jeff Layton --- fs/nfsd/nfs4xdr.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index a47eb544b99f..7d1b2d6f57f2 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4378,21 +4378,16 @@ setup_notify_fhandle(struct dentry *dentry, struct = nfs4_delegation *dp, 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) + struct nfsd_file *nf, char *name, u32 namelen, + u32 *attrmask) { struct path path =3D nf->nf_file->f_path; struct nfsd4_fattr_args args =3D { }; const u32 *reqmask; - uint32_t *attrmask; __be32 status; bool parent; int ret; =20 - /* Reserve space for attrmask */ - attrmask =3D xdr_reserve_space(xdr, 3 * sizeof(uint32_t)); - if (!attrmask) - return false; - ne->ne_file.data =3D name; ne->ne_file.len =3D namelen; ne->ne_attrs.attrmask.element =3D attrmask; @@ -4476,6 +4471,7 @@ u8 *nfsd4_encode_notify_event(struct xdr_stream *xdr,= struct nfsd_notify_event * struct nfs4_delegation *dp, struct nfsd_file *nf, u32 *notify_mask) { + u32 attrmask[3][3] =3D { }; u8 *p =3D NULL; =20 *notify_mask =3D 0; @@ -4484,7 +4480,8 @@ u8 *nfsd4_encode_notify_event(struct xdr_stream *xdr,= struct nfsd_notify_event * struct notify_remove4 nr =3D { }; =20 if (!nfsd4_setup_notify_entry4(&nr.nrm_old_entry, xdr, nne->ne_dentry, d= p, - nf, nne->ne_name, nne->ne_namelen)) + nf, nne->ne_name, nne->ne_namelen, + attrmask[0])) goto out_err; p =3D (u8 *)xdr->p; if (!xdrgen_encode_notify_remove4(xdr, &nr)) @@ -4495,14 +4492,16 @@ u8 *nfsd4_encode_notify_event(struct xdr_stream *xd= r, struct nfsd_notify_event * struct notify_remove4 old =3D { }; =20 if (!nfsd4_setup_notify_entry4(&na.nad_new_entry, xdr, nne->ne_dentry, d= p, - nf, nne->ne_name, nne->ne_namelen)) + nf, nne->ne_name, nne->ne_namelen, + attrmask[0])) goto out_err; =20 /* 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)) + nne->ne_name, nne->ne_namelen, + attrmask[1])) goto out_err; na.nad_old_entry.count =3D 1; na.nad_old_entry.element =3D &old; @@ -4521,19 +4520,19 @@ u8 *nfsd4_encode_notify_event(struct xdr_stream *xd= r, struct nfsd_notify_event * /* 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)) + nne->ne_namelen, attrmask[0])) goto out_err; =20 if (!nfsd4_setup_notify_entry4(&nr.nrn_new_entry.nad_new_entry, xdr, nne->ne_dentry, dp, nf, newname, - nne->ne_newnamelen)) + nne->ne_newnamelen, attrmask[1])) goto out_err; =20 /* 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, newname, - nne->ne_newnamelen)) + nne->ne_newnamelen, attrmask[2])) goto out_err; nr.nrn_new_entry.nad_old_entry.count =3D 1; nr.nrn_new_entry.nad_old_entry.element =3D &old; @@ -4569,11 +4568,12 @@ u8 *nfsd4_encode_dir_attr_change(struct xdr_stream = *xdr, struct nfs4_delegation { struct dentry *dentry =3D nf->nf_file->f_path.dentry; struct notify_attr4 na =3D { }; + u32 attrmask[3] =3D { }; u8 *p; =20 /* RFC 8881 s10.4.3: ne_file must be a zero-length string for dir attrs */ if (!nfsd4_setup_notify_entry4(&na.na_changed_entry, xdr, - dentry, dp, nf, "", 0)) + dentry, dp, nf, "", 0, attrmask)) return ERR_PTR(-ENOBUFS); =20 /* No requested attributes to report; omit the event */ --=20 2.55.0 From nobody Tue Sep 29 04:10:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F638481AB0; Wed, 12 Aug 2026 18:08:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786558106; cv=none; b=OztlQK+TSacjHCYErBYszPPJxZdBogNnRVWdfrPaPmkzybSMbH9YeY0IS9/yGtHozagDgkxV0rDutKRJPTHUmSXQiOidea2nPS6KhdAZDtFNRqgQm0KTKH4bZCmNOg9b8vbwqT+hz7pbWGqea50/B80MAtwTDWgMGKeWq7n4dog= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786558106; c=relaxed/simple; bh=UdBXUWJ3qFYYvJ4Rc2yTan11nOfSrINI/dKKW84HkzU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tJl1BCWV1O9Y3Y4U2gp4FlODRaYHrRuYFsDyoLgNfkJE9URDRh3YtC4POyrheEu/iNtuykG9CEwfsSEZ+Wm+YGpSqmnhF5QhTxuM3ohyf1ljYIeNOYLc5mIcDoALozVuX5+7o0k2Fbt/lhNvTyhK+bDsorhQtfi9CbhiHTpROQc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DDvR0LMl; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DDvR0LMl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 681D71F00A3E; Wed, 12 Aug 2026 18:08:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786558105; bh=g9Ieuc7g3+3SRGhj2KYEpURRJen+bO2L/kcR4adJznM=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=DDvR0LMliOByzowuIuf2EBm9HHn/tuAK5o57F1IFRX1j00lCiK6Ze/Oxbyi+AGxVR o6rD1rjqBj+Aun3GhgnxEnnCogrgi/b1HF09j3bHGxPTYU3A6fh7VmS1fVWzNvogor Dee7ZTYvXuJGwVNVPUUZ+/MjcFacE/ciBoUvYceU2+ktDVtJ1+2xoQ2te2cPLLM8Ci OnOMvzaPLJZ07m16SZ3+1WZ6dYeHuDBUAgZIQAqiwjS6YPRiMdFBaPW1vsq+mCT8pQ dF6VUYvc7sc6gTb2KdSqn3c747bkgF9pYzev8xaOxgYej+KyCMGh+CMJee0ryXjFsu ipYovgTrc0wkQ== From: Jeff Layton Date: Wed, 12 Aug 2026 14:08:15 -0400 Subject: [PATCH 2/2] nfsd: back CB_NOTIFY notify_mask words with per-delegation storage Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260812-dir-deleg-v1-2-411faa713068@kernel.org> References: <20260812-dir-deleg-v1-0-411faa713068@kernel.org> In-Reply-To: <20260812-dir-deleg-v1-0-411faa713068@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3627; i=jlayton@kernel.org; h=from:subject:message-id; bh=UdBXUWJ3qFYYvJ4Rc2yTan11nOfSrINI/dKKW84HkzU=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqfLaWLVWKUYA4oKbtpMImENatU4bDBM31D4DLv aYk5L7PVg2JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCany2lgAKCRAADmhBGVaC FW0FEADVqxJeUrfxw07wK36sspoiFGWeUeVpMGaDD87Xc6xncIIWFF8cnPZJF33a32eb+U5v+n/ Tx0TuPzgM2QJmTrtHR5/QVnhhGqH+hUmlV9aGw4vKgpaieDCdTlK6aLQx2I0f4glnSI9Lmim1H3 a/uKLqxdQQ9vwSpB42CZwmLmqlJ+qhx6nHWsYS/D5bcDdmucRXZAjOEAU1zTbKKwLz8ddvpfdA/ lfeA8cE5Ug+vTpaz8ijb1ikH0q/bv+KkWZswMZEgu9s3O/TgGNOaxPpv2/uIOBSqc/wD7zuNsTh 7vdlnWRyk4iD5S7ICyB/mKXv9ySQKLMFSUpkv/GEuQRLBv50L2tFMLdGgK6jASf5siSuhdJR3bq 1q9IfB97lcH+MY3szSt4Yx3Lj9jHVQPqHA/jpGQ3VOxIgVkl3Wl4Qo8muuvkAXPX8iUXSsolaJf CR7hh4G4ANysI7aIt6UiMKCbK7CR11c+62DYtdfmAPpO0lFzO0up1LjIYma9ybfmUtC3n1G1wan asg5dgAuJRWSdwLKXFNYpVk/oyvxRlDAVDGgn7RvC9IUTlY4ZT/9U1IV5w1BAw4KC3yrJb+efdS 9M/G8J7K2eC5JP8AJsLlOgZzzXgX5y0ytEPIDOkJ5kQ+thXvBW7BpByIBesKqBhwiohi+T2Hn3z VcDZFBuaIrRL78Q== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 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 --- 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 *sti= d) for (i =3D 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 =3D 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 =3D kcalloc(NOTIFY4_EVENT_QUEUE_SIZE, sizeof(*ncn->ncn_mas= ks), 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 =3D events[i]; =20 if (!error) { - u32 *maskp =3D (u32 *)xdr_reserve_space(&stream, sizeof(*maskp)); + u32 *maskp =3D &ncn->ncn_masks[i]; u8 *p; =20 - if (!maskp) { - error =3D true; - goto put_event; - } - p =3D 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 =3D (u32 *)xdr_reserve_space(&stream, sizeof(*maskp)); + u32 *maskp =3D &ncn->ncn_masks[count]; u8 *p; =20 - if (maskp) - p =3D nfsd4_encode_dir_attr_change(&stream, dp, nf); - else - p =3D ERR_PTR(-ENOBUFS); + p =3D nfsd4_encode_dir_attr_change(&stream, dp, nf); =20 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 e= vents 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 }; --=20 2.55.0