Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xdrgen: Implement pass-through lines in specifications

XDR specification files can contain lines prefixed with '%' that
pass through unchanged to generated output. Traditional rpcgen
removes the '%' and emits the remainder verbatim, allowing direct
insertion of C includes, pragma directives, or other language-
specific content into the generated code.

Until now, xdrgen silently discarded these lines during parsing.
This prevented specifications from including necessary headers or
preprocessor directives that might be required for the generated
code to compile correctly.

The grammar now captures pass-through lines instead of ignoring
them. A new AST node type represents pass-through content, and
the AST transformer strips the leading '%' character. Definition
and source generators emit pass-through content in document order,
preserving the original placement within the specification.

This brings xdrgen closer to feature parity with traditional
rpcgen while maintaining the existing document-order processing
model.

Existing generated xdrgen source code has been regenerated.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+116 -20
+10 -1
fs/nfsd/nfs4xdr_gen.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // Generated by xdrgen. Manual edits will be lost. 3 3 // XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x 4 - // XDR specification modification time: Thu Dec 25 13:44:43 2025 4 + // XDR specification modification time: Thu Jan 8 23:11:48 2026 5 5 6 6 #include <linux/sunrpc/svc.h> 7 7 ··· 178 178 return xdrgen_decode_open_arguments4(xdr, ptr); 179 179 } 180 180 181 + /* 182 + * Determine what OPEN supports. 183 + */ 184 + 181 185 bool 182 186 xdrgen_decode_fattr4_time_deleg_access(struct xdr_stream *xdr, fattr4_time_deleg_access *ptr) 183 187 { ··· 193 189 { 194 190 return xdrgen_decode_nfstime4(xdr, ptr); 195 191 } 192 + 193 + /* 194 + * New RECOMMENDED Attribute for 195 + * delegation caching of times 196 + */ 196 197 197 198 static bool __maybe_unused 198 199 xdrgen_decode_open_delegation_type4(struct xdr_stream *xdr, open_delegation_type4 *ptr)
+1 -1
fs/nfsd/nfs4xdr_gen.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* Generated by xdrgen. Manual edits will be lost. */ 3 3 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ 4 - /* XDR specification modification time: Thu Dec 25 13:44:43 2025 */ 4 + /* XDR specification modification time: Thu Jan 8 23:11:48 2026 */ 5 5 6 6 #ifndef _LINUX_XDRGEN_NFS4_1_DECL_H 7 7 #define _LINUX_XDRGEN_NFS4_1_DECL_H
+10 -1
include/linux/sunrpc/xdrgen/nfs4_1.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* Generated by xdrgen. Manual edits will be lost. */ 3 3 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ 4 - /* XDR specification modification time: Thu Dec 25 13:44:43 2025 */ 4 + /* XDR specification modification time: Thu Jan 8 23:11:48 2026 */ 5 5 6 6 #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H 7 7 #define _LINUX_XDRGEN_NFS4_1_DEF_H ··· 87 87 88 88 typedef struct open_arguments4 fattr4_open_arguments; 89 89 90 + /* 91 + * Determine what OPEN supports. 92 + */ 93 + 90 94 enum { FATTR4_OPEN_ARGUMENTS = 86 }; 91 95 92 96 enum { OPEN4_RESULT_NO_OPEN_STATEID = 0x00000010 }; ··· 98 94 typedef struct nfstime4 fattr4_time_deleg_access; 99 95 100 96 typedef struct nfstime4 fattr4_time_deleg_modify; 97 + 98 + /* 99 + * New RECOMMENDED Attribute for 100 + * delegation caching of times 101 + */ 101 102 102 103 enum { FATTR4_TIME_DELEG_ACCESS = 84 }; 103 104
-2
tools/net/sunrpc/xdrgen/README
··· 250 250 Enable something like a #include to dynamically insert the content 251 251 of other specification files 252 252 253 - Properly support line-by-line pass-through via the "%" decorator 254 - 255 253 Build a unit test suite for verifying translation of XDR language 256 254 into compilable code 257 255
+26
tools/net/sunrpc/xdrgen/generators/passthru.py
··· 1 + #!/usr/bin/env python3 2 + # ex: set filetype=python: 3 + 4 + """Generate code for XDR pass-through lines""" 5 + 6 + from generators import SourceGenerator, create_jinja2_environment 7 + from xdr_ast import _XdrPassthru 8 + 9 + 10 + class XdrPassthruGenerator(SourceGenerator): 11 + """Generate source code for XDR pass-through content""" 12 + 13 + def __init__(self, language: str, peer: str): 14 + """Initialize an instance of this class""" 15 + self.environment = create_jinja2_environment(language, "passthru") 16 + self.peer = peer 17 + 18 + def emit_definition(self, node: _XdrPassthru) -> None: 19 + """Emit one pass-through line""" 20 + template = self.environment.get_template("definition.j2") 21 + print(template.render(content=node.content)) 22 + 23 + def emit_decoder(self, node: _XdrPassthru) -> None: 24 + """Emit one pass-through line""" 25 + template = self.environment.get_template("source.j2") 26 + print(template.render(content=node.content))
+4 -2
tools/net/sunrpc/xdrgen/grammars/xdr.lark
··· 78 78 | type_def 79 79 | program_def 80 80 | pragma_def 81 + | passthru_def 82 + 83 + passthru_def : PASSTHRU 81 84 82 85 // 83 86 // RPC program definitions not specified in RFC 4506 ··· 118 115 hexadecimal_constant : /0x([a-f]|[A-F]|[0-9])+/ 119 116 octal_constant : /0[0-7]+/ 120 117 121 - PASSTHRU : "%" | "%" /.+/ 122 - %ignore PASSTHRU 118 + PASSTHRU : /%.*/ 123 119 124 120 %import common.C_COMMENT 125 121 %ignore C_COMMENT
+1 -3
tools/net/sunrpc/xdrgen/subcmds/declarations.py
··· 10 10 from lark import logger 11 11 from lark.exceptions import VisitError 12 12 13 - from generators.constant import XdrConstantGenerator 14 13 from generators.enum import XdrEnumGenerator 15 14 from generators.header_bottom import XdrHeaderBottomGenerator 16 15 from generators.header_top import XdrHeaderTopGenerator ··· 20 21 from generators.union import XdrUnionGenerator 21 22 22 23 from xdr_ast import transform_parse_tree, _RpcProgram, Specification 23 - from xdr_ast import _XdrConstant, _XdrEnum, _XdrPointer 24 - from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion 24 + from xdr_ast import _XdrEnum, _XdrPointer, _XdrTypedef, _XdrStruct, _XdrUnion 25 25 from xdr_parse import xdr_parser, set_xdr_annotate 26 26 from xdr_parse import make_error_handler, XdrParseError 27 27 from xdr_parse import handle_transform_error
+4 -1
tools/net/sunrpc/xdrgen/subcmds/definitions.py
··· 14 14 from generators.enum import XdrEnumGenerator 15 15 from generators.header_bottom import XdrHeaderBottomGenerator 16 16 from generators.header_top import XdrHeaderTopGenerator 17 + from generators.passthru import XdrPassthruGenerator 17 18 from generators.pointer import XdrPointerGenerator 18 19 from generators.program import XdrProgramGenerator 19 20 from generators.typedef import XdrTypedefGenerator ··· 22 21 from generators.union import XdrUnionGenerator 23 22 24 23 from xdr_ast import transform_parse_tree, Specification 25 - from xdr_ast import _RpcProgram, _XdrConstant, _XdrEnum, _XdrPointer 24 + from xdr_ast import _RpcProgram, _XdrConstant, _XdrEnum, _XdrPassthru, _XdrPointer 26 25 from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion 27 26 from xdr_parse import xdr_parser, set_xdr_annotate 28 27 from xdr_parse import make_error_handler, XdrParseError ··· 48 47 gen = XdrStructGenerator(language, peer) 49 48 elif isinstance(definition.value, _XdrUnion): 50 49 gen = XdrUnionGenerator(language, peer) 50 + elif isinstance(definition.value, _XdrPassthru): 51 + gen = XdrPassthruGenerator(language, peer) 51 52 else: 52 53 continue 53 54 gen.emit_definition(definition.value)
+17 -7
tools/net/sunrpc/xdrgen/subcmds/source.py
··· 12 12 13 13 from generators.source_top import XdrSourceTopGenerator 14 14 from generators.enum import XdrEnumGenerator 15 + from generators.passthru import XdrPassthruGenerator 15 16 from generators.pointer import XdrPointerGenerator 16 17 from generators.program import XdrProgramGenerator 17 18 from generators.typedef import XdrTypedefGenerator ··· 20 19 from generators.union import XdrUnionGenerator 21 20 22 21 from xdr_ast import transform_parse_tree, _RpcProgram, Specification 23 - from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer 22 + from xdr_ast import _XdrAst, _XdrEnum, _XdrPassthru, _XdrPointer 24 23 from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion 25 24 26 25 from xdr_parse import xdr_parser, set_xdr_annotate, set_xdr_enum_validation ··· 75 74 gen.emit_source(filename, root) 76 75 77 76 for definition in root.definitions: 78 - emit_source_decoder(definition.value, language, "server") 77 + if isinstance(definition.value, _XdrPassthru): 78 + passthru_gen = XdrPassthruGenerator(language, "server") 79 + passthru_gen.emit_decoder(definition.value) 80 + else: 81 + emit_source_decoder(definition.value, language, "server") 79 82 for definition in root.definitions: 80 - emit_source_encoder(definition.value, language, "server") 83 + if not isinstance(definition.value, _XdrPassthru): 84 + emit_source_encoder(definition.value, language, "server") 81 85 82 86 83 87 def generate_client_source(filename: str, root: Specification, language: str) -> None: 84 - """Generate server-side source code""" 88 + """Generate client-side source code""" 85 89 86 90 gen = XdrSourceTopGenerator(language, "client") 87 91 gen.emit_source(filename, root) 88 92 89 - print("") 90 93 for definition in root.definitions: 91 - emit_source_encoder(definition.value, language, "client") 94 + if isinstance(definition.value, _XdrPassthru): 95 + passthru_gen = XdrPassthruGenerator(language, "client") 96 + passthru_gen.emit_decoder(definition.value) 97 + else: 98 + emit_source_encoder(definition.value, language, "client") 92 99 for definition in root.definitions: 93 - emit_source_decoder(definition.value, language, "client") 100 + if not isinstance(definition.value, _XdrPassthru): 101 + emit_source_decoder(definition.value, language, "client") 94 102 95 103 # cel: todo: client needs PROC macros 96 104
+3
tools/net/sunrpc/xdrgen/templates/C/passthru/definition.j2
··· 1 + {# SPDX-License-Identifier: GPL-2.0 #} 2 + 3 + {{ content }}
+3
tools/net/sunrpc/xdrgen/templates/C/passthru/source.j2
··· 1 + {# SPDX-License-Identifier: GPL-2.0 #} 2 + 3 + {{ content }}
+37 -2
tools/net/sunrpc/xdrgen/xdr_ast.py
··· 517 517 518 518 519 519 @dataclass 520 + class _XdrPassthru(_XdrAst): 521 + """Passthrough line to emit verbatim in output""" 522 + 523 + content: str 524 + 525 + 526 + @dataclass 520 527 class Definition(_XdrAst, ast_utils.WithMeta): 521 528 """Corresponds to 'definition' in the grammar""" 522 529 ··· 745 738 raise NotImplementedError("Directive not supported") 746 739 return _Pragma() 747 740 741 + def passthru_def(self, children): 742 + """Instantiate one _XdrPassthru object""" 743 + token = children[0] 744 + content = token.value[1:] 745 + return _XdrPassthru(content) 746 + 748 747 749 748 transformer = ast_utils.create_transformer(this_module, ParseToAst()) 750 749 751 750 751 + def _merge_consecutive_passthru(definitions: List[Definition]) -> List[Definition]: 752 + """Merge consecutive passthru definitions into single nodes""" 753 + result = [] 754 + i = 0 755 + while i < len(definitions): 756 + if isinstance(definitions[i].value, _XdrPassthru): 757 + lines = [definitions[i].value.content] 758 + meta = definitions[i].meta 759 + j = i + 1 760 + while j < len(definitions) and isinstance(definitions[j].value, _XdrPassthru): 761 + lines.append(definitions[j].value.content) 762 + j += 1 763 + merged = _XdrPassthru("\n".join(lines)) 764 + result.append(Definition(meta, merged)) 765 + i = j 766 + else: 767 + result.append(definitions[i]) 768 + i += 1 769 + return result 770 + 771 + 752 772 def transform_parse_tree(parse_tree): 753 773 """Transform productions into an abstract syntax tree""" 754 - 755 - return transformer.transform(parse_tree) 774 + ast = transformer.transform(parse_tree) 775 + ast.definitions = _merge_consecutive_passthru(ast.definitions) 776 + return ast 756 777 757 778 758 779 def get_header_name() -> str: