mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
xdrgen: Stream optional-data aggregate lists during encode
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. Acked-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260908134234.512312-11-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
This commit is contained in:
parent
9ebc61dfe9
commit
1e7f9d30d5
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -182,7 +182,13 @@ no count: each 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
|
||||
type. 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 fails without consuming the
|
||||
list, so xdrgen also rejects the directive when the struct is
|
||||
reachable from an RPC argument.
|
||||
|
|
@ -208,7 +214,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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user