Linux NFS development
 help / color / mirror / Atom feed
From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neil@brown.name>, Jeff Layton <jlayton@kernel.org>,
	Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>
Subject: [PATCH v1 16/17] NFSD: Use xdrgen XDR functions for the NFS-ACL v2 ACCESS procedure
Date: Thu, 22 Oct 2026 09:53:40 -0400	[thread overview]
Message-ID: <20261022135341.14265-17-cel@kernel.org> (raw)
In-Reply-To: <20261022135341.14265-1-cel@kernel.org>

Convert the NFS-ACL version 2 ACCESS procedure to xdrgen. As with
the GETATTR conversion, neither direction needs a hand-written XDR
tail: ACCESS2args carries a file handle and an access bitmask, so
the generated nfs_acl_svc_decode_ACCESS2args decodes the argument
in full, and ACCESS2res carries a status word and, on success, the
file attributes and the granted access bits, so the generated
nfs_acl_svc_encode_ACCESS2res emits the entire reply. On an error
status the encoder emits only the status word, matching what the
hand-written encoder produced. Wrapper structures bridge the
generated ACCESS2args and ACCESS2res types and the legacy svc_fh
and scratch kstat that the NFSD VFS layer still uses.

The procedure's pc_argzero is zero because the generated decoder
writes the whole ACCESS2args, making the earlier defensive memset
of the argument buffer unnecessary.

Because nfsacld_proc_access() now fills in the reply attributes and
releases the file handle itself, the fh_getattr() call moves into
the proc function and the separate ->pc_release callback is dropped.
This makes it straightforward to confirm the handle is released on
every flow.

ACCESS was the only remaining user of the file-local struct
nfsd3_accessargs and struct nfsd3_accessres, so this removes those
definitions, the hand-written accessargs decoder and accessres
encoder, and the ST and AT size macros that only the ACCESS entry
still referenced. The svcxdr_decode_fhandle, svcxdr_encode_stat,
and svcxdr_encode_fattr declarations lose their last callers here
and are removed as well.

While rewriting the procedure entry, correct its pc_name from the
stale "SETATTR" to "ACCESS".

Signed-off-by: Chuck Lever <cel@kernel.org>
---
 fs/nfsd/nfs2acl.c | 132 ++++++++++++++++------------------------------
 1 file changed, 45 insertions(+), 87 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index d4261ef076bd..a805d2ac76db 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -95,22 +95,19 @@ struct GETATTR2res_wrapper {
 
 static_assert(offsetof(struct GETATTR2res_wrapper, xdrgen) == 0);
 
-struct nfsd3_accessargs {
+struct ACCESS2args_wrapper {
+	struct ACCESS2args	xdrgen;
 	struct svc_fh		fh;
-	__u32			access;
 };
 
-struct nfsd3_accessres {
-	__be32			status;
-	struct svc_fh		fh;
-	__u32			access;
+static_assert(offsetof(struct ACCESS2args_wrapper, xdrgen) == 0);
+
+struct ACCESS2res_wrapper {
+	struct ACCESS2res	xdrgen;
 	struct kstat		stat;
 };
 
-bool svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp);
-bool svcxdr_encode_stat(struct xdr_stream *xdr, __be32 status);
-bool svcxdr_encode_fattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
-			 const struct svc_fh *fhp, const struct kstat *stat);
+static_assert(offsetof(struct ACCESS2res_wrapper, xdrgen) == 0);
 
 /*
  * These maps are identical to the NFSv3 maps (nfs3proc.c). This enables
@@ -514,28 +511,41 @@ static __be32 nfsacld_proc_getattr(struct svc_rqst *rqstp)
 	return rpc_success;
 }
 
-/*
- * Check file access
+/**
+ * nfsacld_proc_access - ACCESS: Check access permission
+ * @rqstp: RPC transaction context
+ *
+ * Return:
+ *   %rpc_success:		RPC executed successfully
+ *
+ * RPC synopsis:
+ *   ACCESS2res ACLPROC2_ACCESS(ACCESS2args) = 4;
  */
 static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
 {
-	struct nfsd3_accessargs *argp = rqstp->rq_argp;
-	struct nfsd3_accessres *resp = rqstp->rq_resp;
+	struct ACCESS2args_wrapper *argp = rqstp->rq_argp;
+	struct ACCESS2res_wrapper *resp = rqstp->rq_resp;
+	struct svc_fh *fhp = &argp->fh;
 
+	nfsacld_fhandle_to_svc_fh(fhp, &argp->xdrgen.fh);
 	dprintk("nfsd: ACCESS(2acl)   %s 0x%x\n",
-			SVCFH_fmt(&argp->fh),
-			argp->access);
+			SVCFH_fmt(fhp), argp->xdrgen.access);
 
-	fh_copy(&resp->fh, &argp->fh);
-	resp->access = argp->access;
-
-	resp->status = nfsd_access(rqstp, &resp->fh, &nfsd2_access_maps,
-				   &resp->access, NULL);
-	if (resp->status != acl2_ok)
+	resp->xdrgen.status = nfsd_access(rqstp, fhp, &nfsd2_access_maps,
+					  &argp->xdrgen.access, NULL);
+	if (resp->xdrgen.status != acl2_ok)
 		goto out;
-	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	resp->xdrgen.status = fh_getattr(fhp, &resp->stat);
+
 out:
-	resp->status = nfsacld_map_status(resp->status);
+	if (resp->xdrgen.status == acl2_ok) {
+		struct ACCESS2resok *resok = &resp->xdrgen.u.resok;
+
+		resok->access = argp->xdrgen.access;
+		nfsacld_stat_to_fattr(rqstp, &resok->attr, &resp->stat, fhp);
+	}
+	fh_put(fhp);
+	resp->xdrgen.status = nfsacld_map_status(resp->xdrgen.status);
 	return rpc_success;
 }
 
@@ -733,47 +743,6 @@ bool nfs_acl2_secattr_decode_end(struct xdrgen_aggregate_cursor *c, bool ok)
 	return posix_acl_from_nfsacl(acl) == 0;
 }
 
-/*
- * XDR decode functions
- */
-
-static bool
-nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
-	struct nfsd3_accessargs *args = rqstp->rq_argp;
-
-	if (!svcxdr_decode_fhandle(xdr, &args->fh))
-		return false;
-	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
-		return false;
-
-	return true;
-}
-
-/*
- * XDR encode functions
- */
-
-/* ACCESS */
-static bool
-nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
-	struct nfsd3_accessres *resp = rqstp->rq_resp;
-
-	if (!svcxdr_encode_stat(xdr, resp->status))
-		return false;
-	switch (resp->status) {
-	case acl2_ok:
-		if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
-			return false;
-		if (xdr_stream_encode_u32(xdr, resp->access) < 0)
-			return false;
-		break;
-	}
-
-	return true;
-}
-
 /*
  * XDR release functions
  */
@@ -785,13 +754,6 @@ static void nfsaclsvc_release_getacl(struct svc_rqst *rqstp)
 	posix_acl_release(resp->acl_default);
 }
 
-static void nfsaclsvc_release_access(struct svc_rqst *rqstp)
-{
-	struct nfsd3_accessres *resp = rqstp->rq_resp;
-
-	fh_put(&resp->fh);
-}
-
 static void nfsaclsvc_release_setacl(struct svc_rqst *rqstp)
 {
 	struct SETACL2args_wrapper *argp = rqstp->rq_argp;
@@ -800,9 +762,6 @@ static void nfsaclsvc_release_setacl(struct svc_rqst *rqstp)
 	posix_acl_release(argp->acl_default);
 }
 
-#define ST 1		/* status*/
-#define AT 21		/* attributes */
-
 static const struct svc_procedure nfsd_acl_procedures2[5] = {
 	[ACLPROC2_NULL] = {
 		.pc_func	= nfsacld_proc_null,
@@ -851,16 +810,15 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = {
 		.pc_name	= "GETATTR",
 	},
 	[ACLPROC2_ACCESS] = {
-		.pc_func = nfsacld_proc_access,
-		.pc_decode = nfsaclsvc_decode_accessargs,
-		.pc_encode = nfsaclsvc_encode_accessres,
-		.pc_release = nfsaclsvc_release_access,
-		.pc_argsize = sizeof(struct nfsd3_accessargs),
-		.pc_argzero = sizeof(struct nfsd3_accessargs),
-		.pc_ressize = sizeof(struct nfsd3_accessres),
-		.pc_cachetype = RC_NOCACHE,
-		.pc_xdrressize = ST+AT+1,
-		.pc_name = "SETATTR",
+		.pc_func	= nfsacld_proc_access,
+		.pc_decode	= nfs_acl_svc_decode_ACCESS2args,
+		.pc_encode	= nfs_acl_svc_encode_ACCESS2res,
+		.pc_argsize	= sizeof(struct ACCESS2args_wrapper),
+		.pc_argzero	= 0,
+		.pc_ressize	= sizeof(struct ACCESS2res_wrapper),
+		.pc_cachetype	= RC_NOCACHE,
+		.pc_xdrressize	= NFS_ACL2_ACCESS2res_sz,
+		.pc_name	= "ACCESS",
 	},
 };
 
@@ -871,11 +829,11 @@ union nfsd_acl2_xdrstore {
 	struct GETACL2args_wrapper	getaclargs;
 	struct SETACL2args_wrapper	setaclargs;
 	struct GETATTR2args_wrapper	getattrargs;
-	struct nfsd3_accessargs		accessargs;
+	struct ACCESS2args_wrapper	accessargs;
 	struct GETACL2res_wrapper	getaclres;
 	struct SETACL2res_wrapper	setaclres;
 	struct GETATTR2res_wrapper	getattrres;
-	struct nfsd3_accessres		accessres;
+	struct ACCESS2res_wrapper	accessres;
 };
 
 const struct svc_version nfsd_acl_version2 = {
-- 
2.56.0


  parent reply	other threads:[~2026-10-22 13:53 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-22 13:53 [PATCH v1 00/17] Convert server-side NFS_ACLv2 XDR to use xdrgen Chuck Lever
2026-10-22 13:53 ` [PATCH v1 01/17] xdrgen: Reject out-of-range unsigned short values on decode Chuck Lever
2026-10-22 13:53 ` [PATCH v1 02/17] xdrgen: Reject out-of-range " Chuck Lever
2026-10-22 13:53 ` [PATCH v1 03/17] nfs_common: Export posix_acl_from_nfsacl for server ACL codecs Chuck Lever
2026-10-22 13:53 ` [PATCH v1 04/17] NFSD: Remove the unused NFSACL_MAXWORDS macro Chuck Lever
2026-10-22 13:53 ` [PATCH v1 05/17] NFSD: Move the definition of NFS_ACL_MAX_ENTRIES Chuck Lever
2026-10-22 13:53 ` [PATCH v1 06/17] Documentation: Add the RPC language description of NFS_ACLv2 Chuck Lever
2026-10-22 13:53 ` [PATCH v1 07/17] NFSD: Add infrastructure for generating NFS_ACLv2 XDR encoders and decoders Chuck Lever
2026-10-22 13:53 ` [PATCH v1 08/17] NFSD: Remove '#include "xdr3.h"' from nfs2acl.c Chuck Lever
2026-10-22 13:53 ` [PATCH v1 09/17] NFSD: Remove '#include "xdr.h"' " Chuck Lever
2026-10-22 13:53 ` [PATCH v1 10/17] NFSD: Switch to using the NFS_ACLv2 status codes Chuck Lever
2026-10-22 13:53 ` [PATCH v1 11/17] NFSD: Use xdrgen XDR functions for the NFS-ACL v2 NULL procedure Chuck Lever
2026-10-22 13:53 ` [PATCH v1 12/17] NFSD: Implement NFS-ACL v2 ACL encoding and decoding with xdrgen Chuck Lever
2026-10-22 13:53 ` [PATCH v1 13/17] NFSD: Use xdrgen XDR functions for the NFS-ACL v2 GETACL procedure Chuck Lever
2026-10-22 13:53 ` [PATCH v1 14/17] NFSD: Use xdrgen XDR functions for the NFS-ACL v2 SETACL procedure Chuck Lever
2026-10-22 13:53 ` [PATCH v1 15/17] NFSD: Use xdrgen XDR functions for the NFS-ACL v2 GETATTR procedure Chuck Lever
2026-10-22 13:53 ` Chuck Lever [this message]
2026-10-22 13:53 ` [PATCH v1 17/17] NFSD: Map every NFS_ACLv2 reply status into aclstat2 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=20261022135341.14265-17-cel@kernel.org \
    --to=cel@kernel.org \
    --cc=dai.ngo@oracle.com \
    --cc=jlayton@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox