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 06/13] NFSD: Implement NFS-ACL v3 ACL encoding and decoding with xdrgen
Date: Sun, 25 Oct 2026 11:16:15 -0400 [thread overview]
Message-ID: <20261025151622.141025-7-cel@kernel.org> (raw)
In-Reply-To: <20261025151622.141025-1-cel@kernel.org>
The NFS-ACL v3 GETACL result encoder and SETACL argument decoder
cannot be generated the way the other procedures' codecs are: the
wire secattr is a Solaris projection of the kernel's struct
posix_acl, and the per-entry transformation between them -- tag and
id mapping, the canonical four-entry expansion that Solaris VxFS
interoperability requires, and counts gated by the request mask --
is application logic that xdrgen cannot synthesize. Keeping those two
codecs hand-rolled would force the generated NFSv3 types they call,
nfs_fh3, fattr3, and post_op_attr, to keep external linkage, and
those symbols would collide at link time with the public
definitions that nfs3xdr_gen.c already emits for NFSv3 proper.
Supply the nfsd side of xdrgen's hook-driven aggregate codec
mechanism. "pragma aggregate" markers on secattr's two aclent<>
members select the streaming codec, whose generated framing owns
the wire representation and drives per-element application hooks. The
hooks hold the posix_acl logic factored from
nfs_stream_encode_acl() and nfs_stream_decode_acl(); both arrays
share one hook set, with the cursor's member_id distinguishing the
access list from the default list. Wrapper structures pair each
generated argument or result type with the legacy application state
(svc_fh, posix_acl pointers, kstat), placing the generated type at
offset zero so rq_argp or rq_resp addresses both the generated type
the codec fills and the wrapper the hooks read. The hooks reach
that wrapper by way of the svc_rqst, which svcxdr_init_decode() and
svcxdr_init_encode() leave in the xdr_stream's application-private
pointer.
On decode, the begin hook validates the declared count and the
request mask, allocates the posix_acl at its known size, and
publishes it into the argument wrapper before any fallible
per-entry decode runs, so a mid-list failure leaves the ACL
reachable by pc_release rather than leaked. A zero-length published
default list stays NULL, which set_posix_acl() treats as ACL
removal.
A well-formed request that is nonetheless invalid -- an undefined
request mask bit, an empty access ACL, a perm bit outside rwx, an
undefined entry type, a user or group id with no kernel mapping, a
list whose declared count differs from its length, or more entries
than NFS_ACL_MAX_ENTRIES -- instead marks the argument wrapper and
lets the decode succeed, so nfsd3_proc_setacl() can report
ACL3ERR_INVAL rather than GARBAGE_ARGS (draft-ietf-nfsv4-nfs-acl
Section 3.4.4.2). The pre-conversion decoder rejected most of these
cases with GARBAGE_ARGS. It accepted an empty access ACL as a request
to remove the object's access ACL, an operation the protocol does not
define, and it cleared perm bits outside rwx in an NA_CLASS_OBJ entry
without complaint because Solaris clients were seen to set them. The
draft makes both invalid, so the NFS_ACLv3 server now reports
ACL3ERR_INVAL for them as well. These are deliberate, minor changes to
the SETACL wire behavior.
Because the containing codecs are fully generated, the NFSv3 types
the ACL specification re-declares stay static in nfs_acl3xdr_gen.c,
and no public pragma is needed.
Subsequent patches convert the GETACL and SETACL procedures to the
generated codecs.
Signed-off-by: Chuck Lever <cel@kernel.org>
---
Documentation/sunrpc/xdr/nfs_acl3.x | 2 +
fs/nfsd/nfs3acl.c | 271 +++++++++++++++++++++++++
fs/nfsd/nfs_acl3xdr_gen.c | 138 ++++++++++---
fs/nfsd/nfs_acl3xdr_gen.h | 14 +-
include/linux/sunrpc/xdrgen/nfs_acl3.h | 2 +-
5 files changed, 400 insertions(+), 27 deletions(-)
diff --git a/Documentation/sunrpc/xdr/nfs_acl3.x b/Documentation/sunrpc/xdr/nfs_acl3.x
index b355705bf970..931a7d629603 100644
--- a/Documentation/sunrpc/xdr/nfs_acl3.x
+++ b/Documentation/sunrpc/xdr/nfs_acl3.x
@@ -91,6 +91,8 @@ struct secattr {
int dfaclcnt;
aclent dfaclent<NFS_ACL_MAX_ENTRIES>;
};
+pragma aggregate secattr aclent;
+pragma aggregate secattr dfaclent;
/*
* The values for the mask element of the secattr struct as well
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 048046af15c0..1fb9d265bc03 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -18,6 +18,52 @@
#define NFS_ACL_MASK (NA_ACL | NA_ACLCNT | NA_DFACL | NA_DFACLCNT)
+/*
+ * Wrapper structures combine xdrgen types with legacy structures.
+ * The xdrgen field must be first so the structure can be cast
+ * to its XDR type for the RPC dispatch layer.
+ */
+struct GETACL3args_wrapper {
+ struct GETACL3args xdrgen;
+ struct svc_fh fh;
+};
+
+static_assert(offsetof(struct GETACL3args_wrapper, xdrgen) == 0);
+
+/*
+ * The ACL is encoded from the posix_acl fields below, so the
+ * generated secattr (xdrgen.u.resok.acl) is left unused.
+ */
+struct GETACL3res_wrapper {
+ struct GETACL3res xdrgen;
+ int mask;
+ struct posix_acl *acl_access;
+ struct posix_acl *acl_default;
+ struct kstat stat;
+};
+
+static_assert(offsetof(struct GETACL3res_wrapper, xdrgen) == 0);
+
+/*
+ * The ACLs are decoded by hand into the posix_acl fields below, so
+ * the generated aclent arrays (xdrgen.acl) are left unused.
+ */
+struct SETACL3args_wrapper {
+ struct SETACL3args xdrgen;
+ struct svc_fh fh;
+ struct posix_acl *acl_access;
+ struct posix_acl *acl_default;
+ /*
+ * Set when the wire ACL is well-formed XDR but semantically
+ * invalid. The decoder accepts the request so that
+ * nfsd3_proc_setacl can return ACL3ERR_INVAL rather than RPC
+ * GARBAGE_ARGS. See draft-ietf-nfsv4-nfs-acl Section 3.4.4.2.
+ */
+ bool invalid;
+};
+
+static_assert(offsetof(struct SETACL3args_wrapper, xdrgen) == 0);
+
struct nfsd3_getaclargs {
struct svc_fh fh;
__u32 mask;
@@ -110,6 +156,19 @@ static __be32 nfsd3_map_status(__be32 status)
return status;
}
+/*
+ * A minimal (three-entry) ACL travels as four wire entries: the
+ * POSIX entries plus a synthesized NA_CLASS_OBJ mask. The wire
+ * element count is thus max(a_count, 4) when the ACL has at least
+ * three entries, and zero otherwise. An ACL with fewer than three
+ * entries has no minimal set to expand, so it travels as empty.
+ * See draft-ietf-nfsv4-nfs-acl Section 3.4.4.2.
+ */
+static u32 nfs3acl_acl_entries(const struct posix_acl *acl)
+{
+ return (acl && acl->a_count >= 3) ? max_t(int, acl->a_count, 4) : 0;
+}
+
/**
* nfsd3_proc_null - NULL: Do nothing
* @rqstp: RPC transaction context
@@ -318,6 +377,218 @@ nfs3svc_encode_setaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh);
}
+/*
+ * Aggregate codec hooks for the generated secattr codec.
+ *
+ * The generated codec owns the wire framing and drives these hooks
+ * once per element; the hooks hold all posix_acl application logic. The
+ * application context (@c->ctx) is the svc_rqst, bound to the stream by
+ * svcxdr_init_{decode,encode}(); each hook reaches the proc's arg or
+ * result wrapper through rq_{argp,resp}.
+ * The cursor's member_id selects the member: it is
+ * NFS_ACL3_SECATTR_ACLENT or NFS_ACL3_SECATTR_DFACLENT.
+ */
+
+/* GETACL reply: stream the wire entries out of the source posix_acl. */
+
+bool nfs_acl3_secattr_encode_begin(struct xdrgen_aggregate_cursor *c)
+{
+ struct svc_rqst *rqstp = c->ctx;
+ struct GETACL3res_wrapper *resp = rqstp->rq_resp;
+ bool dfacl = c->member_id == NFS_ACL3_SECATTR_DFACLENT;
+ struct posix_acl *acl = dfacl ? resp->acl_default : resp->acl_access;
+ int gate = dfacl ? (resp->mask & NA_DFACL) : (resp->mask & NA_ACL);
+
+ c->count = gate ? nfs3acl_acl_entries(acl) : 0;
+ return true;
+}
+
+bool nfs_acl3_secattr_encode(struct xdrgen_aggregate_cursor *c,
+ struct aclent *out)
+{
+ struct svc_rqst *rqstp = c->ctx;
+ struct GETACL3res_wrapper *resp = rqstp->rq_resp;
+ bool dfacl = c->member_id == NFS_ACL3_SECATTR_DFACLENT;
+ struct posix_acl *acl = dfacl ? resp->acl_default : resp->acl_access;
+ int typeflag = dfacl ? NA_ACL_DEFAULT : 0;
+ const struct posix_acl_entry *entry;
+ int tag;
+
+ /*
+ * A three-entry ACL expands to four wire entries in ascending
+ * type order (USER_OBJ, GROUP_OBJ, a NA_CLASS_OBJ mask cloned
+ * from GROUP_OBJ, OTHER). Some receivers depend on this ordering.
+ * See draft-ietf-nfsv4-nfs-acl Section 3.4.4.2.
+ */
+ if (acl->a_count == 3) {
+ static const u8 map[4] = { 0, 1, 1, 2 };
+
+ entry = &acl->a_entries[map[c->index]];
+ tag = (c->index == 2) ? ACL_MASK : entry->e_tag;
+ } else {
+ entry = &acl->a_entries[c->index];
+ tag = entry->e_tag;
+ }
+
+ out->type = tag | typeflag;
+ switch (tag) {
+ case ACL_USER_OBJ:
+ out->id = from_kuid(&init_user_ns, resp->stat.uid);
+ break;
+ case ACL_GROUP_OBJ:
+ out->id = from_kgid(&init_user_ns, resp->stat.gid);
+ break;
+ case ACL_USER:
+ out->id = from_kuid(&init_user_ns, entry->e_uid);
+ break;
+ case ACL_GROUP:
+ out->id = from_kgid(&init_user_ns, entry->e_gid);
+ break;
+ default:
+ /*
+ * The id field is undefined for these entry types;
+ * emit zero per draft-ietf-nfsv4-nfs-acl Section 3.4.4.2.
+ */
+ out->id = 0;
+ break;
+ }
+ out->perm = entry->e_perm & (ACL_READ | ACL_WRITE | ACL_EXECUTE);
+ return true;
+}
+
+bool nfs_acl3_secattr_encode_end(struct xdrgen_aggregate_cursor *c, bool ok)
+{
+ return true;
+}
+
+/* SETACL args: consume the decoded wire entries into the target posix_acl. */
+
+bool nfs_acl3_secattr_decode_begin(struct xdrgen_aggregate_cursor *c)
+{
+ struct svc_rqst *rqstp = c->ctx;
+ struct SETACL3args_wrapper *argp = rqstp->rq_argp;
+ bool dfacl = c->member_id == NFS_ACL3_SECATTR_DFACLENT;
+ struct posix_acl **pacl = dfacl ? &argp->acl_default : &argp->acl_access;
+ u32 mask = argp->xdrgen.acl.mask;
+ u32 declared = dfacl ? (u32)argp->xdrgen.acl.dfaclcnt :
+ (u32)argp->xdrgen.acl.aclcnt;
+ int gate = dfacl ? (mask & NA_DFACL) : (mask & NA_ACL);
+
+ /* Already rejected: consume the list. */
+ if (argp->invalid)
+ return true;
+ /* The access list is decoded first, so the mask is checked once. */
+ if (!dfacl && (mask & ~NFS_ACL_MASK)) {
+ argp->invalid = true;
+ return true;
+ }
+ /* Too many ACEs is an invalid ACL, not a malformed request. */
+ if (declared > NFS_ACL_MAX_ENTRIES) {
+ argp->invalid = true;
+ return true;
+ }
+
+ if (gate) {
+ /*
+ * A published list whose declared count differs from its
+ * length is an invalid ACL, not a malformed request.
+ */
+ if (c->count != declared) {
+ argp->invalid = true;
+ return true;
+ }
+ if (!dfacl && !c->count) {
+ argp->invalid = true;
+ return true;
+ }
+ /* An empty default list publishes NULL: default ACL removal. */
+ if (c->count) {
+ *pacl = posix_acl_alloc(c->count, GFP_KERNEL);
+ if (!*pacl)
+ return false;
+ }
+ } else if (c->count > declared) {
+ argp->invalid = true;
+ return true;
+ }
+ return true;
+}
+
+bool nfs_acl3_secattr_decode(struct xdrgen_aggregate_cursor *c,
+ const struct aclent *in)
+{
+ struct svc_rqst *rqstp = c->ctx;
+ struct SETACL3args_wrapper *argp = rqstp->rq_argp;
+ bool dfacl = c->member_id == NFS_ACL3_SECATTR_DFACLENT;
+ struct posix_acl *acl = dfacl ? argp->acl_default : argp->acl_access;
+ struct posix_acl_entry *entry;
+
+ /* Already rejected, or list gated out by mask: consume it. */
+ if (argp->invalid || !acl)
+ return true;
+
+ /* A perm bit outside rwx makes the ACL invalid. */
+ if (in->perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) {
+ argp->invalid = true;
+ return true;
+ }
+
+ /* A type bit the protocol does not define makes the ACL invalid. */
+ if (in->type & ~(NA_USER_OBJ | NA_USER | NA_GROUP_OBJ | NA_GROUP |
+ NA_CLASS_OBJ | NA_OTHER_OBJ | NA_ACL_DEFAULT)) {
+ argp->invalid = true;
+ return true;
+ }
+
+ entry = &acl->a_entries[c->index];
+ entry->e_tag = in->type & ~NA_ACL_DEFAULT;
+ entry->e_perm = in->perm;
+ switch (entry->e_tag) {
+ case ACL_USER:
+ /* An id with no kernel mapping makes the ACL invalid. */
+ entry->e_uid = make_kuid(&init_user_ns, in->id);
+ if (!uid_valid(entry->e_uid)) {
+ argp->invalid = true;
+ return true;
+ }
+ break;
+ case ACL_GROUP:
+ entry->e_gid = make_kgid(&init_user_ns, in->id);
+ if (!gid_valid(entry->e_gid)) {
+ argp->invalid = true;
+ return true;
+ }
+ break;
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ case ACL_MASK:
+ break;
+ default:
+ /* An undefined entry type makes the ACL invalid. */
+ argp->invalid = true;
+ return true;
+ }
+
+ return true;
+}
+
+bool nfs_acl3_secattr_decode_end(struct xdrgen_aggregate_cursor *c, bool ok)
+{
+ struct svc_rqst *rqstp = c->ctx;
+ struct SETACL3args_wrapper *argp = rqstp->rq_argp;
+ bool dfacl = c->member_id == NFS_ACL3_SECATTR_DFACLENT;
+ struct posix_acl *acl = dfacl ? argp->acl_default : argp->acl_access;
+
+ /*
+ * On failure the published ACL stays reachable through the arg
+ * wrapper and is freed by pc_release; nothing to do here.
+ */
+ if (!ok || argp->invalid)
+ return true;
+ return posix_acl_from_nfsacl(acl) == 0;
+}
+
/*
* XDR release functions
*/
diff --git a/fs/nfsd/nfs_acl3xdr_gen.c b/fs/nfsd/nfs_acl3xdr_gen.c
index 05e35653a0fc..bbd8bb7d79d3 100644
--- a/fs/nfsd/nfs_acl3xdr_gen.c
+++ b/fs/nfsd/nfs_acl3xdr_gen.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Generated by xdrgen. Manual edits will be lost.
// XDR specification file: ../../Documentation/sunrpc/xdr/nfs_acl3.x
-// XDR specification modification time: Fri Jul 10 20:12:08 2026
+// XDR specification modification time: Fri Jul 10 20:12:44 2026
#include <linux/sunrpc/svc.h>
@@ -38,22 +38,66 @@ xdrgen_decode_secattr(struct xdr_stream *xdr, struct secattr *ptr)
return false;
if (!xdrgen_decode_int(xdr, &ptr->aclcnt))
return false;
- if (xdr_stream_decode_u32(xdr, &ptr->aclent.count) < 0)
- return false;
- if (ptr->aclent.count > NFS_ACL_MAX_ENTRIES)
- return false;
- for (u32 i = 0; i < ptr->aclent.count; i++)
- if (!xdrgen_decode_aclent(xdr, &ptr->aclent.element[i]))
+ {
+ struct xdrgen_aggregate_cursor cursor = {
+ .xdr = xdr,
+ .member_id = NFS_ACL3_SECATTR_ACLENT,
+ .ctx = xdr->xdrgen_ctx,
+ };
+ bool ok = true;
+
+ if (xdr_stream_decode_u32(xdr, &cursor.count) < 0)
return false;
+ if (cursor.count > NFS_ACL_MAX_ENTRIES)
+ return false;
+ if (!nfs_acl3_secattr_decode_begin(&cursor))
+ return false;
+ for (cursor.index = 0; cursor.index < cursor.count; cursor.index++) {
+ struct aclent element = {};
+
+ if (!xdrgen_decode_aclent(xdr, &element)) {
+ ok = false;
+ break;
+ }
+ if (!nfs_acl3_secattr_decode(&cursor, &element)) {
+ ok = false;
+ break;
+ }
+ }
+ if (!nfs_acl3_secattr_decode_end(&cursor, ok) || !ok)
+ return false;
+ }
if (!xdrgen_decode_int(xdr, &ptr->dfaclcnt))
return false;
- if (xdr_stream_decode_u32(xdr, &ptr->dfaclent.count) < 0)
- return false;
- if (ptr->dfaclent.count > NFS_ACL_MAX_ENTRIES)
- return false;
- for (u32 i = 0; i < ptr->dfaclent.count; i++)
- if (!xdrgen_decode_aclent(xdr, &ptr->dfaclent.element[i]))
+ {
+ struct xdrgen_aggregate_cursor cursor = {
+ .xdr = xdr,
+ .member_id = NFS_ACL3_SECATTR_DFACLENT,
+ .ctx = xdr->xdrgen_ctx,
+ };
+ bool ok = true;
+
+ if (xdr_stream_decode_u32(xdr, &cursor.count) < 0)
return false;
+ if (cursor.count > NFS_ACL_MAX_ENTRIES)
+ return false;
+ if (!nfs_acl3_secattr_decode_begin(&cursor))
+ return false;
+ for (cursor.index = 0; cursor.index < cursor.count; cursor.index++) {
+ struct aclent element = {};
+
+ if (!xdrgen_decode_aclent(xdr, &element)) {
+ ok = false;
+ break;
+ }
+ if (!nfs_acl3_secattr_decode(&cursor, &element)) {
+ ok = false;
+ break;
+ }
+ }
+ if (!nfs_acl3_secattr_decode_end(&cursor, ok) || !ok)
+ return false;
+ }
return true;
}
@@ -431,22 +475,66 @@ xdrgen_encode_secattr(struct xdr_stream *xdr, const struct secattr *value)
return false;
if (!xdrgen_encode_int(xdr, value->aclcnt))
return false;
- if (value->aclent.count > NFS_ACL_MAX_ENTRIES)
- return false;
- if (xdr_stream_encode_u32(xdr, value->aclent.count) != XDR_UNIT)
- return false;
- for (u32 i = 0; i < value->aclent.count; i++)
- if (!xdrgen_encode_aclent(xdr, &value->aclent.element[i]))
+ {
+ struct xdrgen_aggregate_cursor cursor = {
+ .xdr = xdr,
+ .member_id = NFS_ACL3_SECATTR_ACLENT,
+ .ctx = xdr->xdrgen_ctx,
+ };
+ bool ok = true;
+
+ if (!nfs_acl3_secattr_encode_begin(&cursor))
return false;
+ if (cursor.count > NFS_ACL_MAX_ENTRIES)
+ ok = false;
+ if (ok && xdr_stream_encode_u32(xdr, cursor.count) != XDR_UNIT)
+ ok = false;
+ for (cursor.index = 0; ok && cursor.index < cursor.count; cursor.index++) {
+ struct aclent element = {};
+
+ if (!nfs_acl3_secattr_encode(&cursor, &element)) {
+ ok = false;
+ break;
+ }
+ if (!xdrgen_encode_aclent(xdr, &element)) {
+ ok = false;
+ break;
+ }
+ }
+ if (!nfs_acl3_secattr_encode_end(&cursor, ok) || !ok)
+ return false;
+ }
if (!xdrgen_encode_int(xdr, value->dfaclcnt))
return false;
- if (value->dfaclent.count > NFS_ACL_MAX_ENTRIES)
- return false;
- if (xdr_stream_encode_u32(xdr, value->dfaclent.count) != XDR_UNIT)
- return false;
- for (u32 i = 0; i < value->dfaclent.count; i++)
- if (!xdrgen_encode_aclent(xdr, &value->dfaclent.element[i]))
+ {
+ struct xdrgen_aggregate_cursor cursor = {
+ .xdr = xdr,
+ .member_id = NFS_ACL3_SECATTR_DFACLENT,
+ .ctx = xdr->xdrgen_ctx,
+ };
+ bool ok = true;
+
+ if (!nfs_acl3_secattr_encode_begin(&cursor))
return false;
+ if (cursor.count > NFS_ACL_MAX_ENTRIES)
+ ok = false;
+ if (ok && xdr_stream_encode_u32(xdr, cursor.count) != XDR_UNIT)
+ ok = false;
+ for (cursor.index = 0; ok && cursor.index < cursor.count; cursor.index++) {
+ struct aclent element = {};
+
+ if (!nfs_acl3_secattr_encode(&cursor, &element)) {
+ ok = false;
+ break;
+ }
+ if (!xdrgen_encode_aclent(xdr, &element)) {
+ ok = false;
+ break;
+ }
+ }
+ if (!nfs_acl3_secattr_encode_end(&cursor, ok) || !ok)
+ return false;
+ }
return true;
}
diff --git a/fs/nfsd/nfs_acl3xdr_gen.h b/fs/nfsd/nfs_acl3xdr_gen.h
index 8d960c0506db..629a06566ca7 100644
--- a/fs/nfsd/nfs_acl3xdr_gen.h
+++ b/fs/nfsd/nfs_acl3xdr_gen.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs_acl3.x */
-/* XDR specification modification time: Fri Jul 10 20:12:08 2026 */
+/* XDR specification modification time: Fri Jul 10 20:12:44 2026 */
#ifndef _LINUX_XDRGEN_NFS_ACL3_DECL_H
#define _LINUX_XDRGEN_NFS_ACL3_DECL_H
@@ -13,6 +13,18 @@
#include <linux/sunrpc/xdrgen/_builtins.h>
#include <linux/sunrpc/xdrgen/nfs_acl3.h>
+enum {
+ NFS_ACL3_SECATTR_ACLENT,
+ NFS_ACL3_SECATTR_DFACLENT,
+};
+
+bool nfs_acl3_secattr_encode_begin(struct xdrgen_aggregate_cursor *c);
+bool nfs_acl3_secattr_encode(struct xdrgen_aggregate_cursor *c, struct aclent *out);
+bool nfs_acl3_secattr_encode_end(struct xdrgen_aggregate_cursor *c, bool ok);
+bool nfs_acl3_secattr_decode_begin(struct xdrgen_aggregate_cursor *c);
+bool nfs_acl3_secattr_decode(struct xdrgen_aggregate_cursor *c, const struct aclent *in);
+bool nfs_acl3_secattr_decode_end(struct xdrgen_aggregate_cursor *c, bool ok);
+
bool nfs_acl_svc_decode_GETACL3args(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nfs_acl_svc_decode_SETACL3args(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nfs_acl_svc_decode_GETXATTRDIR3args(struct svc_rqst *rqstp, struct xdr_stream *xdr);
diff --git a/include/linux/sunrpc/xdrgen/nfs_acl3.h b/include/linux/sunrpc/xdrgen/nfs_acl3.h
index 4d71e4907261..92c0d1e0b0a8 100644
--- a/include/linux/sunrpc/xdrgen/nfs_acl3.h
+++ b/include/linux/sunrpc/xdrgen/nfs_acl3.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs_acl3.x */
-/* XDR specification modification time: Fri Jul 10 20:12:08 2026 */
+/* XDR specification modification time: Fri Jul 10 20:12:44 2026 */
#ifndef _LINUX_XDRGEN_NFS_ACL3_DEF_H
#define _LINUX_XDRGEN_NFS_ACL3_DEF_H
--
2.56.0
next prev parent reply other threads:[~2026-10-26 21:36 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-25 15:16 [PATCH v1 00/13] Convert server-side NFS_ACLv3 XDR to use xdrgen Chuck Lever
2026-10-25 15:16 ` [PATCH v1 01/13] Documentation: Add the RPC language description of NFS_ACLv3 Chuck Lever
2026-10-25 15:16 ` [PATCH v1 02/13] NFSD: Add infrastructure for generating NFS_ACLv3 XDR encoders and decoders Chuck Lever
2026-10-25 15:16 ` [PATCH v1 03/13] NFSD: Remove '#include "xdr3.h"' from nfs3acl.c Chuck Lever
2026-10-25 15:16 ` [PATCH v1 04/13] NFSD: New NFS_ACLv3 status codes Chuck Lever
2026-10-25 15:16 ` [PATCH v1 05/13] NFSD: Use xdrgen XDR functions for the NFS-ACL v3 NULL procedure Chuck Lever
2026-10-25 15:16 ` Chuck Lever [this message]
2026-10-25 15:16 ` [PATCH v1 07/13] NFSD: Use xdrgen XDR functions for the NFS-ACL v3 GETACL procedure Chuck Lever
2026-10-25 15:16 ` [PATCH v1 08/13] NFSD: Use xdrgen XDR functions for the NFS-ACL v3 SETACL procedure Chuck Lever
2026-10-25 15:16 ` [PATCH v1 09/13] NFSD: Map every NFS_ACLv3 reply status into aclstat3 Chuck Lever
2026-10-25 15:16 ` [PATCH v1 10/13] NFSD: Remove the hand-coded XDR helpers for the NFS_ACLv3 procedures Chuck Lever
2026-10-25 15:16 ` [PATCH v1 11/13] NFS: Move NFSACL_MAXPAGES into fs/nfs/nfs3_fs.h Chuck Lever
2026-10-26 22:50 ` Anna Schumaker
2026-10-25 15:16 ` [PATCH v1 12/13] NFSD: Share the attribute conversion helpers with the NFS_ACL procs Chuck Lever
2026-10-25 15:16 ` [PATCH v1 13/13] nfs_common: Remove the unused NFS ACL stream codecs Chuck Lever
2026-10-27 10:56 ` [PATCH v1 00/13] Convert server-side NFS_ACLv3 XDR to use xdrgen Jeff Layton
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=20261025151622.141025-7-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 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.