]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xdrgen: Emit a max_arg_sz macro
authorChuck Lever <chuck.lever@oracle.com>
Fri, 26 Dec 2025 15:19:34 +0000 (10:19 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 26 Jan 2026 15:10:58 +0000 (10:10 -0500)
struct svc_service has a .vs_xdrsize field that is filled in by
servers for each of their RPC programs. This field is supposed to
contain the size of the largest procedure argument in the RPC
program. This value is also sometimes used to size network
transport buffers.

Currently, server implementations must manually calculate and
hard-code this value, which is error-prone and requires updates
when procedure arguments change.

Update xdrgen to determine which procedure argument structure is
largest, and emit a macro with a well-known name that contains
the size of that structure. Server code then uses this macro when
initializing the .vs_xdrsize field.

For NLM version 4, xdrgen now emits:

    #define NLM4_MAX_ARGS_SZ (NLM4_nlm4_lockargs_sz)

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
tools/net/sunrpc/xdrgen/generators/program.py
tools/net/sunrpc/xdrgen/subcmds/definitions.py
tools/net/sunrpc/xdrgen/templates/C/program/maxsize/max_args.j2 [new file with mode: 0644]

index decb092ef02cdfbd2e2ed7eba4c61ee7818be6e1..c0cb3f6d3319798bff88aba36071b3196b11708a 100644 (file)
@@ -5,8 +5,9 @@
 
 from jinja2 import Environment
 
-from generators import SourceGenerator, create_jinja2_environment
+from generators import SourceGenerator, create_jinja2_environment, get_jinja2_template
 from xdr_ast import _RpcProgram, _RpcVersion, excluded_apis
+from xdr_ast import max_widths, get_header_name
 
 
 def emit_version_definitions(
@@ -169,3 +170,35 @@ class XdrProgramGenerator(SourceGenerator):
                     emit_version_argument_encoders(
                         self.environment, program, version,
                     )
+
+    def emit_maxsize(self, node: _RpcProgram) -> None:
+        """Emit maxsize macro for maximum RPC argument size"""
+        header = get_header_name().upper()
+
+        # Find the largest argument across all versions
+        max_arg_width = 0
+        max_arg_name = None
+        for version in node.versions:
+            for procedure in version.procedures:
+                if procedure.name in excluded_apis:
+                    continue
+                arg_name = procedure.argument.type_name
+                if arg_name == "void":
+                    continue
+                if arg_name not in max_widths:
+                    continue
+                if max_widths[arg_name] > max_arg_width:
+                    max_arg_width = max_widths[arg_name]
+                    max_arg_name = arg_name
+
+        if max_arg_name is None:
+            return
+
+        macro_name = header + "_MAX_ARGS_SZ"
+        template = get_jinja2_template(self.environment, "maxsize", "max_args")
+        print(
+            template.render(
+                macro=macro_name,
+                width=header + "_" + max_arg_name + "_sz",
+            )
+        )
index d6c2dcd6f78fef4b27a85de0826b2c04f73e770e..b17526a03ddaea6d0e12df594a1b2ac1d7de20fb 100644 (file)
@@ -66,6 +66,8 @@ def emit_header_maxsize(root: Specification, language: str, peer: str) -> None:
             gen = XdrStructGenerator(language, peer)
         elif isinstance(definition.value, _XdrUnion):
             gen = XdrUnionGenerator(language, peer)
+        elif isinstance(definition.value, _RpcProgram):
+            gen = XdrProgramGenerator(language, peer)
         else:
             continue
         gen.emit_maxsize(definition.value)
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/maxsize/max_args.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/maxsize/max_args.j2
new file mode 100644 (file)
index 0000000..9f3bfb4
--- /dev/null
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} \
+       ({{ width }})