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 v2 10/10] xdrgen: Stream optional-data aggregate lists during encode
Date: Fri, 4 Sep 2026 12:50:52 -0400 [thread overview]
Message-ID: <20260904165052.153327-11-cel@kernel.org> (raw)
In-Reply-To: <20260904165052.153327-1-cel@kernel.org>
The optional-data aggregate encoder loops cursor.count times, so the
begin hook must report the element count before the first element is
written. A producer that reads its elements while the reply is
encoded -- NFSv2 READDIR streaming directory entries straight into the
send buffer -- does not know that count in advance, and would have to
materialize the whole list just to satisfy the loop bound.
An optional-data list carries no count on the wire, so nothing forces
one on the encoder. Drive it from the item hook instead: a false
return ends the list, and the framing writes the terminator.
The counted-array form and its hook contract are unchanged. No
in-tree spec marks an optional-data member yet, so no generated code
changes here.
Signed-off-by: Chuck Lever <cel@kernel.org>
---
include/linux/sunrpc/xdrgen/_defs.h | 27 ++++++++++++-------
tools/net/sunrpc/xdrgen/README | 11 ++++++--
.../C/struct/encoder/aggregate_optional.j2 | 6 ++---
3 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/include/linux/sunrpc/xdrgen/_defs.h b/include/linux/sunrpc/xdrgen/_defs.h
index f4375d73c5ca..d767206feea4 100644
--- a/include/linux/sunrpc/xdrgen/_defs.h
+++ b/include/linux/sunrpc/xdrgen/_defs.h
@@ -30,15 +30,24 @@ typedef struct {
} 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.
+ * Cursor a hook-driven aggregate codec hands to its begin/item/end
+ * 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 and
+ * @ctx its xdrgen_ctx, the svc_rqst on the server. @index is the
+ * current element; @member_id selects among a type's marked members.
+ * For a counted array @count is the wire length: a decoder fills it
+ * before the begin hook runs, an encoder's begin hook sets it. The
+ * hook contract is under "Pragma aggregate" in
+ * tools/net/sunrpc/xdrgen/README.
+ *
+ * An optional-data list ("type *name") carries no count. Its encoder
+ * pulls elements until the item hook returns false. False ends the
+ * list rather than failing the encode: the framing writes the
+ * value-follows terminator, so a producer that stops early leaves a
+ * valid truncated list on the wire. A producer that stops for a
+ * mid-list error records it in the application state @ctx reaches,
+ * and either returns false from the end hook, which fails the
+ * encode, or reports it in the procedure status.
*/
struct xdrgen_aggregate_cursor {
struct xdr_stream *xdr;
diff --git a/tools/net/sunrpc/xdrgen/README b/tools/net/sunrpc/xdrgen/README
index 15c6f6b0762a..0714808194ed 100644
--- a/tools/net/sunrpc/xdrgen/README
+++ b/tools/net/sunrpc/xdrgen/README
@@ -179,7 +179,14 @@ element is prefixed by a value-follows TRUE and the sequence is
closed by a FALSE, which the framing writes after the last
element. The element type must therefore be a pointer type, whose
codec owns that framing; xdrgen rejects any other element type.
-For the optional-data form xdrgen generates a working
+That form has no count to loop on, so its encoder pulls
+elements until the item hook returns false. False ends the list
+rather than failing the encode: a producer stops when its source
+is exhausted or when a reply budget fills. A producer that stops
+for an error records it in its own state and either fails the
+encode from the end hook or reports it in the procedure status.
+For the optional-data
+form xdrgen generates a working
encoder only; the decoder it emits does not decode the list, so
xdrgen also rejects the directive when the struct is reachable
from an RPC argument.
@@ -205,7 +212,7 @@ member:
For a variable-length array, a decoder fills the cursor's count from
the wire before calling the begin hook, and an encoder's begin hook
sets that count for the framing to bound-check and emit. An
-optional-data list's encoder begin hook sets the count as well; its
+optional-data list's encoder does not read the count and its
decoder never fills it. Once a begin hook
has succeeded its end hook runs, so that it can release what begin
took; the end hook receives the running success flag.
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/aggregate_optional.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/aggregate_optional.j2
index d45b823225f7..4f35b6976109 100644
--- a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/aggregate_optional.j2
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/aggregate_optional.j2
@@ -12,13 +12,11 @@
if (!{{ hook }}_encode_begin(&cursor))
return false;
- for (cursor.index = 0; cursor.index < cursor.count; cursor.index++) {
+ for (cursor.index = 0; ; cursor.index++) {
{{ classifier }}{{ c_type }} element = {};
- if (!{{ hook }}_encode(&cursor, &element)) {
- ok = false;
+ if (!{{ hook }}_encode(&cursor, &element))
break;
- }
if (!xdrgen_encode_{{ type }}(xdr, &element)) {
ok = false;
break;
--
2.55.0
next prev parent reply other threads:[~2026-09-04 16:51 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 16:50 [PATCH v2 00/10] New pragmas for the xdrgen tool Chuck Lever
2026-09-04 16:50 ` [PATCH v2 01/10] SUNRPC: Carry a generated-codec context pointer in struct xdr_stream Chuck Lever
2026-09-04 16:50 ` [PATCH v2 02/10] SUNRPC: Bind the svc_rqst to its XDR streams Chuck Lever
2026-09-04 16:50 ` [PATCH v2 03/10] SUNRPC: Add svcxdr_encode_opaque_payload() Chuck Lever
2026-09-04 16:50 ` [PATCH v2 04/10] xdrgen: Pass the containing struct name to member codec emitters Chuck Lever
2026-09-04 16:50 ` [PATCH v2 05/10] xdrgen: Add a "pragma pages" directive Chuck Lever
2026-09-04 16:50 ` [PATCH v2 06/10] SUNRPC: Add svcxdr_decode_opaque_payload() Chuck Lever
2026-09-04 16:50 ` [PATCH v2 07/10] xdrgen: Extend the pages directive to page-resident arguments Chuck Lever
2026-09-04 16:50 ` [PATCH v2 08/10] xdrgen: Add hook-driven aggregate codec for variable-length arrays Chuck Lever
2026-09-04 16:50 ` [PATCH v2 09/10] xdrgen: Extend the aggregate codec to optional-data list members Chuck Lever
2026-09-04 16:50 ` Chuck Lever [this message]
2026-09-04 17:04 ` [PATCH v2 00/10] New pragmas for the xdrgen tool 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=20260904165052.153327-11-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