diff options
| author | Chuck Lever <cel@kernel.org> | 2026-09-08 09:42:32 -0400 |
|---|---|---|
| committer | Chuck Lever <cel@kernel.org> | 2026-10-04 21:15:29 -0400 |
| commit | 2f5c8429a994e863d30b3eb920edbc5f5b62c2d9 (patch) | |
| tree | b1ee61b4836c093bb79857ed4cd23c204832502e /include/linux | |
| parent | 08989c3e551f2d16f2615c204453b76348dd6bf9 (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.h | 19 |
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) |
