summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorChuck Lever <cel@kernel.org>2026-09-08 09:42:32 -0400
committerChuck Lever <cel@kernel.org>2026-10-04 21:15:29 -0400
commit2f5c8429a994e863d30b3eb920edbc5f5b62c2d9 (patch)
treeb1ee61b4836c093bb79857ed4cd23c204832502e /include/linux
parent08989c3e551f2d16f2615c204453b76348dd6bf9 (diff)
xdrgen: Add hook-driven aggregate codec for variable-length arrays
A generated variable-length array codec stages the wire array as a C array and walks it. When the in-kernel object is not that array, building that array is wasted memory traffic. The NFS_ACLv2 secattr aclent<> list is one such case: it is a Solaris wire form of the kernel's posix_acl. The hand-rolled codec that performs that transform forces its containing types to keep external linkage (pragma public), and that linkage collides at link time with the same generated types in a sibling program. Add a per-member "pragma aggregate <struct> <member>" directive. For a marked member the generated code owns only the wire framing and calls hand-written begin, item, and end hooks that handle one element at a time. Interior codec signatures do not change. The framing-owned loop follows xdr_encode_array2(), whose only remaining user is fs/nfs_common/nfsacl.c, and seq_file's start/show/stop, where a guaranteed stop() releases what start() took. Those APIs take an ops vtable because one loop serves consumers chosen at run time. Here the consumer is known at generation time, so the hooks bind by name at link time, as the ASN.1 compiler's actions do. A missing hook is a link error, the emitted prototypes enforce the element type, and no indirect call is added per element. The item hooks return only success or failure, with no early "no more elements" return, so that the same hook contract can later frame the RFC 4506 optional-data idiom, where the application pushes entries into generated framing. The front end resolves each marker against the specification and reports one it cannot honor against its own source position, rather than degrading silently to the array-walking codec or surfacing as a traceback from whichever emitter reached it. Absent the marker the generator emits byte-identical output. Acked-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260908134234.512312-9-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/sunrpc/xdrgen/_defs.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/sunrpc/xdrgen/_defs.h b/include/linux/sunrpc/xdrgen/_defs.h
index 1e183b9d1c1d..f4375d73c5ca 100644
--- a/include/linux/sunrpc/xdrgen/_defs.h
+++ b/include/linux/sunrpc/xdrgen/_defs.h
@@ -29,6 +29,25 @@ typedef struct {
u8 *data;
} opaque;
+/*
+ * Cursor a hook-driven aggregate codec hands to its application hooks,
+ * one element at a time, in place of a materialized C array. The
+ * generated framing owns it. @xdr is the RPC layer's stream; @ctx is
+ * that stream's xdrgen_ctx, the svc_rqst on the server. @index is
+ * the current element and @count the wire array length: a decoder
+ * fills @count from the wire before the begin hook runs, an
+ * encoder's begin hook sets it. @member_id selects among a type's
+ * marked members. The begin/item/end contract is under "Pragma
+ * aggregate" in tools/net/sunrpc/xdrgen/README.
+ */
+struct xdrgen_aggregate_cursor {
+ struct xdr_stream *xdr;
+ u32 index;
+ u32 count;
+ unsigned int member_id;
+ void *ctx;
+};
+
#define XDR_void (0)
#define XDR_bool (1)
#define XDR_short (1)