Skip to contentSkip to conversation

Minor fixes for xdrgen

PATCH New Chuck Lever 1 participant 6 messages Jul 12

Subsystems (3)
lore
Share & tools
lore

Chuck Lever

author maintainer
#0 lore raw

cover Minor fixes for xdrgen

While working on server-side xdrgen conversion for NFSv2 and NFSv3, I found several unrelated minor issues with the xdrgen tool. They are collected here in this series.

Chuck Lever (5):
xdrgen: Emit a blank line ahead of enum declarations
xdrgen: Share void RPC procedure handlers across programs
xdrgen: Do not declare union XDR functions in the definitions header
xdrgen: Add XDR width macros for short integer types
xdrgen: Fix opaque and string encoders for unbounded members

 fs/lockd/nlm3xdr_gen.c                        | 30 +-------------
 fs/lockd/nlm3xdr_gen.h                        |  4 +-
 fs/lockd/nlm4xdr_gen.c                        | 30 +-------------
 fs/lockd/nlm4xdr_gen.h                        |  4 +-
 fs/lockd/svc4proc.c                           | 40 +++++++++----------
 fs/lockd/svcproc.c                            | 40 +++++++++----------
 fs/nfsd/nfs4xdr_gen.c                         |  2 +-
 fs/nfsd/nfs4xdr_gen.h                         |  5 ++-
 include/linux/sunrpc/xdrgen/_builtins.h       | 32 +++++++++++++++
 include/linux/sunrpc/xdrgen/_defs.h           |  2 +
 include/linux/sunrpc/xdrgen/nfs4_1.h          |  2 +-
 include/linux/sunrpc/xdrgen/nlm3.h            |  2 +-
 include/linux/sunrpc/xdrgen/nlm4.h            |  2 +-
 tools/net/sunrpc/xdrgen/generators/program.py |  8 ++++
 .../templates/C/enum/declaration/enum.j2      |  1 +
 .../templates/C/pointer/encoder/string.j2     |  2 +
 .../pointer/encoder/variable_length_opaque.j2 |  2 +
 .../templates/C/program/decoder/argument.j2   |  4 --
 .../templates/C/program/encoder/result.j2     |  4 --
 .../templates/C/struct/encoder/string.j2      |  2 +
 .../struct/encoder/variable_length_opaque.j2  |  2 +
 .../templates/C/union/definition/close.j2     |  6 ---
 22 files changed, 103 insertions(+), 123 deletions(-)
Signature · 1 line
2.54.0
author maintainer
#1 lore raw

PATCH 1/5 xdrgen: Emit a blank line ahead of enum declarations

Clean up.

The declaration templates for structs, pointers, and typedefs each begin with a blank line, which keeps successive declarations and the include block above them visually separated. The enum declaration template omits that blank line. trim_blocks collapses the template's lone comment line to nothing, so the omission stayed invisible as long as every generated header happened to lead with a non-enum declaration.

Fixes 4329010ad9c3 ("xdrgen: Address some checkpatch whitespace complaints")
---
 fs/lockd/nlm3xdr_gen.c                                       | 2 +-
 fs/lockd/nlm3xdr_gen.h                                       | 2 +-
 fs/lockd/nlm4xdr_gen.c                                       | 2 +-
 fs/lockd/nlm4xdr_gen.h                                       | 2 +-
 fs/nfsd/nfs4xdr_gen.c                                        | 2 +-
 fs/nfsd/nfs4xdr_gen.h                                        | 5 ++++-
 include/linux/sunrpc/xdrgen/nfs4_1.h                         | 2 +-
 include/linux/sunrpc/xdrgen/nlm3.h                           | 2 +-
 include/linux/sunrpc/xdrgen/nlm4.h                           | 2 +-
 tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2 | 1 +
 10 files changed, 13 insertions(+), 9 deletions(-)
fs/lockd/nlm3xdr_gen.c +1 -1
index 352a694ca0f5..df14692ce37f 100644
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 // Generated by xdrgen. Manual edits will be lost.
 // XDR specification file: ../../Documentation/sunrpc/xdr/nlm3.x
-// XDR specification modification time: Mon Jun 29 20:39:34 2026
+// XDR specification modification time: Mon Jun 29 20:42:29 2026
 
 #include <linux/sunrpc/svc.h>
 
fs/lockd/nlm3xdr_gen.h +1 -1
index d24cbb887b7f..3824ffe2aae4 100644
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nlm3.x */
-/* XDR specification modification time: Mon Jun 29 20:39:34 2026 */
+/* XDR specification modification time: Mon Jun 29 20:42:29 2026 */
 
 #ifndef _LINUX_XDRGEN_NLM3_DECL_H
 #define _LINUX_XDRGEN_NLM3_DECL_H
fs/lockd/nlm4xdr_gen.c +1 -1
index 004ea01c689e..5a60aff06714 100644
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 // Generated by xdrgen. Manual edits will be lost.
 // XDR specification file: ../../Documentation/sunrpc/xdr/nlm4.x
-// XDR specification modification time: Mon Jun 29 20:39:36 2026
+// XDR specification modification time: Mon Jun 29 20:42:29 2026
 
 #include <linux/sunrpc/svc.h>
 
fs/lockd/nlm4xdr_gen.h +1 -1
index b5898f0e0689..ce9dda0a052a 100644
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nlm4.x */
-/* XDR specification modification time: Mon Jun 29 20:39:36 2026 */
+/* XDR specification modification time: Mon Jun 29 20:42:29 2026 */
 
 #ifndef _LINUX_XDRGEN_NLM4_DECL_H
 #define _LINUX_XDRGEN_NLM4_DECL_H
fs/nfsd/nfs4xdr_gen.c +1 -1
index e5a6ea4a9349..d77835033a8c 100644
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 // Generated by xdrgen. Manual edits will be lost.
 // XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x
-// XDR specification modification time: Tue Jun 30 11:56:05 2026
+// XDR specification modification time: Tue Jun 30 11:57:21 2026
 
 #include <linux/sunrpc/svc.h>
 
fs/nfsd/nfs4xdr_gen.h +4 -1
index 4092379a9efa..21ca82078615 100644
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Tue Jun 30 11:56:05 2026 */
+/* XDR specification modification time: Tue Jun 30 11:57:21 2026 */
 
 #ifndef _LINUX_XDRGEN_NFS4_1_DECL_H
 #define _LINUX_XDRGEN_NFS4_1_DECL_H
@@ -21,10 +21,13 @@ bool xdrgen_encode_fattr4_time_deleg_access(struct xdr_stream *xdr, const fattr4
 
 bool xdrgen_decode_fattr4_time_deleg_modify(struct xdr_stream *xdr, fattr4_time_deleg_modify *ptr);
 bool xdrgen_encode_fattr4_time_deleg_modify(struct xdr_stream *xdr, const fattr4_time_deleg_modify *value);
+
 bool xdrgen_decode_aclmodel4(struct xdr_stream *xdr, aclmodel4 *ptr);
 bool xdrgen_encode_aclmodel4(struct xdr_stream *xdr, aclmodel4 value);
+
 bool xdrgen_decode_aclscope4(struct xdr_stream *xdr, aclscope4 *ptr);
 bool xdrgen_encode_aclscope4(struct xdr_stream *xdr, aclscope4 value);
+
 bool xdrgen_decode_posixacetag4(struct xdr_stream *xdr, posixacetag4 *ptr);
 bool xdrgen_encode_posixacetag4(struct xdr_stream *xdr, posixacetag4 value);
 
include/linux/sunrpc/xdrgen/nfs4_1.h +1 -1
index 6ff4d727b0d2..bd3289a1d66a 100644
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Tue Jun 30 11:56:05 2026 */
+/* XDR specification modification time: Tue Jun 30 11:57:21 2026 */
 
 #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H
 #define _LINUX_XDRGEN_NFS4_1_DEF_H
include/linux/sunrpc/xdrgen/nlm3.h +1 -1
index 3cc69a09c1c7..0fc627031d8a 100644
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nlm3.x */
-/* XDR specification modification time: Mon Jun 29 20:39:34 2026 */
+/* XDR specification modification time: Mon Jun 29 20:42:29 2026 */
 
 #ifndef _LINUX_XDRGEN_NLM3_DEF_H
 #define _LINUX_XDRGEN_NLM3_DEF_H
include/linux/sunrpc/xdrgen/nlm4.h +1 -1
index 7b6f10ea2838..77860a3d1c1e 100644
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nlm4.x */
-/* XDR specification modification time: Mon Jun 29 20:39:36 2026 */
+/* XDR specification modification time: Mon Jun 29 20:42:29 2026 */
 
 #ifndef _LINUX_XDRGEN_NLM4_DEF_H
 #define _LINUX_XDRGEN_NLM4_DEF_H
tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2 +1 -0
index c7ae506076bb..d1405c7c5354 100644
@@ -1,3 +1,4 @@
 {# SPDX-License-Identifier: GPL-2.0 #}
+
 bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr);
 bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, {{ name }} value);
Signature · 1 line
2.54.0
author maintainer
#2 lore raw

PATCH 2/5 xdrgen: Share void RPC procedure handlers across programs

In reply to Chuck Lever

The generated server-side decoder and encoder for a void procedure argument or result are named after the RPC program (for example, nfs_svc_decode_void). xdrgen derives that prefix from the program name alone, not the version, so two versions of one program built into the same module emit the identical symbol. NFSv2 and NFSv3 both declare program NFS_PROGRAM; once both are converted, fs/nfsd fails to link with multiple definitions of nfs_svc_decode_void and nfs_svc_encode_void.

A void handler carries no program- or version-specific behavior:
each merely forwards to xdrgen_decode_void() or xdrgen_encode_void(). Define one shared pair, xdrgen_svc_decode_void() and xdrgen_svc_encode_void(), in the xdrgen builtins, and stop the program generator from emitting a per-program void handler.

lockd is the one in-tree consumer that already emits per-program void handlers, so regenerate the NLMv3 and NLMv4 XDR code to drop nlm_svc_{decode,encode}_void() and nlm4_svc_{decode,encode}_void() and point both procedure tables at the shared handlers. The shared handlers are identical to the generated ones they replace, so no wire behavior changes.

Only the server (svc) handlers are affected. The client-side void stubs remain static and per-program, so they do not collide.

---
 fs/lockd/nlm3xdr_gen.c                        | 28 -------------
 fs/lockd/nlm3xdr_gen.h                        |  2 -
 fs/lockd/nlm4xdr_gen.c                        | 28 -------------
 fs/lockd/nlm4xdr_gen.h                        |  2 -
 fs/lockd/svc4proc.c                           | 40 +++++++++----------
 fs/lockd/svcproc.c                            | 40 +++++++++----------
 include/linux/sunrpc/xdrgen/_builtins.h       | 32 +++++++++++++++
 tools/net/sunrpc/xdrgen/generators/program.py |  8 ++++
 .../templates/C/program/decoder/argument.j2   |  4 --
 .../templates/C/program/encoder/result.j2     |  4 --
 10 files changed, 80 insertions(+), 108 deletions(-)
fs/lockd/nlm3xdr_gen.c +0 -28
index df14692ce37f..4b6e3ee7a719 100644
@@ -271,20 +271,6 @@ xdrgen_decode_nlm_notifyargs(struct xdr_stream *xdr, struct nlm_notifyargs *ptr)
 	return true;
 }
 
-/**
- * nlm_svc_decode_void - Decode a void argument
- * @rqstp: RPC transaction context
- * @xdr: source XDR data stream
- *
- * Return values:
- *   %true: procedure arguments decoded successfully
- *   %false: decode failed
- */
-bool nlm_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
-	return xdrgen_decode_void(xdr);
-}
-
 /**
  * nlm_svc_decode_nlm_testargs - Decode a nlm_testargs argument
  * @rqstp: RPC transaction context
@@ -651,20 +637,6 @@ xdrgen_encode_nlm_notifyargs(struct xdr_stream *xdr, const struct nlm_notifyargs
 	return true;
 }
 
-/**
- * nlm_svc_encode_void - Encode a void result
- * @rqstp: RPC transaction context
- * @xdr: target XDR data stream
- *
- * Return values:
- *   %true: procedure results encoded successfully
- *   %false: encode failed
- */
-bool nlm_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
-	return xdrgen_encode_void(xdr);
-}
-
 /**
  * nlm_svc_encode_nlm_testres - Encode a nlm_testres result
  * @rqstp: RPC transaction context
fs/lockd/nlm3xdr_gen.h +0 -2
index 3824ffe2aae4..bdbfc26ba0e4 100644
@@ -13,7 +13,6 @@
 #include <linux/sunrpc/xdrgen/_builtins.h>
 #include <linux/sunrpc/xdrgen/nlm3.h>
 
-bool nlm_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_decode_nlm_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_decode_nlm_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_decode_nlm_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
@@ -24,7 +23,6 @@ bool nlm_svc_decode_nlm_notifyargs(struct svc_rqst *rqstp, struct xdr_stream *xd
 bool nlm_svc_decode_nlm_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_decode_nlm_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 
-bool nlm_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_encode_nlm_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_encode_nlm_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm_svc_encode_nlm_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
fs/lockd/nlm4xdr_gen.c +0 -28
index 5a60aff06714..f98d74ee3d41 100644
@@ -300,20 +300,6 @@ xdrgen_decode_nlm4_notifyargs(struct xdr_stream *xdr, struct nlm4_notifyargs *pt
 	return true;
 }
 
-/**
- * nlm4_svc_decode_void - Decode a void argument
- * @rqstp: RPC transaction context
- * @xdr: source XDR data stream
- *
- * Return values:
- *   %true: procedure arguments decoded successfully
- *   %false: decode failed
- */
-bool nlm4_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
-	return xdrgen_decode_void(xdr);
-}
-
 /**
  * nlm4_svc_decode_nlm4_testargs - Decode a nlm4_testargs argument
  * @rqstp: RPC transaction context
@@ -704,20 +690,6 @@ xdrgen_encode_nlm4_notifyargs(struct xdr_stream *xdr, const struct nlm4_notifyar
 	return true;
 }
 
-/**
- * nlm4_svc_encode_void - Encode a void result
- * @rqstp: RPC transaction context
- * @xdr: target XDR data stream
- *
- * Return values:
- *   %true: procedure results encoded successfully
- *   %false: encode failed
- */
-bool nlm4_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
-	return xdrgen_encode_void(xdr);
-}
-
 /**
  * nlm4_svc_encode_nlm4_testres - Encode a nlm4_testres result
  * @rqstp: RPC transaction context
fs/lockd/nlm4xdr_gen.h +0 -2
index ce9dda0a052a..1a72c26ad18a 100644
@@ -13,7 +13,6 @@
 #include <linux/sunrpc/xdrgen/_builtins.h>
 #include <linux/sunrpc/xdrgen/nlm4.h>
 
-bool nlm4_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_decode_nlm4_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_decode_nlm4_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_decode_nlm4_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
@@ -24,7 +23,6 @@ bool nlm4_svc_decode_nlm4_notifyargs(struct svc_rqst *rqstp, struct xdr_stream *
 bool nlm4_svc_decode_nlm4_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_decode_nlm4_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 
-bool nlm4_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_encode_nlm4_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_encode_nlm4_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool nlm4_svc_encode_nlm4_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
fs/lockd/svc4proc.c +20 -20
index d104aab0881a..5a70dbe9c6a4 100644
@@ -1167,8 +1167,8 @@ static __be32 nlm4svc_proc_free_all(struct svc_rqst *rqstp)
 static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_NULL] = {
 		.pc_func	= nlm4svc_proc_null,
-		.pc_decode	= nlm4_svc_decode_void,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= XDR_void,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1228,7 +1228,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_TEST_MSG] = {
 		.pc_func	= nlm4svc_proc_test_msg,
 		.pc_decode	= nlm4_svc_decode_nlm4_testargs,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_testargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1238,7 +1238,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_LOCK_MSG] = {
 		.pc_func	= nlm4svc_proc_lock_msg,
 		.pc_decode	= nlm4_svc_decode_nlm4_lockargs,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_lockargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1248,7 +1248,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_CANCEL_MSG] = {
 		.pc_func	= nlm4svc_proc_cancel_msg,
 		.pc_decode	= nlm4_svc_decode_nlm4_cancargs,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_cancargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1258,7 +1258,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_UNLOCK_MSG] = {
 		.pc_func	= nlm4svc_proc_unlock_msg,
 		.pc_decode	= nlm4_svc_decode_nlm4_unlockargs,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_unlockargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1268,7 +1268,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_GRANTED_MSG] = {
 		.pc_func	= nlm4svc_proc_granted_msg,
 		.pc_decode	= nlm4_svc_decode_nlm4_testargs,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_testargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1278,7 +1278,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_TEST_RES] = {
 		.pc_func	= nlm4svc_proc_null,
 		.pc_decode	= nlm4_svc_decode_nlm4_testres,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_testres),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1288,7 +1288,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_LOCK_RES] = {
 		.pc_func	= nlm4svc_proc_null,
 		.pc_decode	= nlm4_svc_decode_nlm4_res,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_res),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1298,7 +1298,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_CANCEL_RES] = {
 		.pc_func	= nlm4svc_proc_null,
 		.pc_decode	= nlm4_svc_decode_nlm4_res,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_res),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1308,7 +1308,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_UNLOCK_RES] = {
 		.pc_func	= nlm4svc_proc_null,
 		.pc_decode	= nlm4_svc_decode_nlm4_res,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_res),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1318,7 +1318,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_GRANTED_RES] = {
 		.pc_func	= nlm4svc_proc_granted_res,
 		.pc_decode	= nlm4_svc_decode_nlm4_res,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_res_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1328,7 +1328,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_SM_NOTIFY] = {
 		.pc_func	= nlm4svc_proc_sm_notify,
 		.pc_decode	= nlm4_svc_decode_nlm4_notifyargs,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_notifyargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1337,8 +1337,8 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	},
 	[17] = {
 		.pc_func	= nlm4svc_proc_unused,
-		.pc_decode	= nlm4_svc_decode_void,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= 0,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1347,8 +1347,8 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	},
 	[18] = {
 		.pc_func	= nlm4svc_proc_unused,
-		.pc_decode	= nlm4_svc_decode_void,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= 0,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1357,8 +1357,8 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	},
 	[19] = {
 		.pc_func	= nlm4svc_proc_unused,
-		.pc_decode	= nlm4_svc_decode_void,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= 0,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1398,7 +1398,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
 	[NLMPROC4_FREE_ALL] = {
 		.pc_func	= nlm4svc_proc_free_all,
 		.pc_decode	= nlm4_svc_decode_nlm4_notify,
-		.pc_encode	= nlm4_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm4_notify_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
fs/lockd/svcproc.c +20 -20
index a1f9d66c2981..7ba628939cff 100644
@@ -1176,8 +1176,8 @@ static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp)
 static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_NULL] = {
 		.pc_func	= nlmsvc_proc_null,
-		.pc_decode	= nlm_svc_decode_void,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= XDR_void,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1237,7 +1237,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_TEST_MSG] = {
 		.pc_func	= nlmsvc_proc_test_msg,
 		.pc_decode	= nlm_svc_decode_nlm_testargs,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_testargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1247,7 +1247,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_LOCK_MSG] = {
 		.pc_func	= nlmsvc_proc_lock_msg,
 		.pc_decode	= nlm_svc_decode_nlm_lockargs,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_lockargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1257,7 +1257,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_CANCEL_MSG] = {
 		.pc_func	= nlmsvc_proc_cancel_msg,
 		.pc_decode	= nlm_svc_decode_nlm_cancargs,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_cancargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1267,7 +1267,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_UNLOCK_MSG] = {
 		.pc_func	= nlmsvc_proc_unlock_msg,
 		.pc_decode	= nlm_svc_decode_nlm_unlockargs,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_unlockargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1277,7 +1277,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_GRANTED_MSG] = {
 		.pc_func	= nlmsvc_proc_granted_msg,
 		.pc_decode	= nlm_svc_decode_nlm_testargs,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_testargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1287,7 +1287,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_TEST_RES] = {
 		.pc_func	= nlmsvc_proc_null,
 		.pc_decode	= nlm_svc_decode_nlm_testres,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_testres),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1297,7 +1297,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_LOCK_RES] = {
 		.pc_func	= nlmsvc_proc_null,
 		.pc_decode	= nlm_svc_decode_nlm_res,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_res),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1307,7 +1307,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_CANCEL_RES] = {
 		.pc_func	= nlmsvc_proc_null,
 		.pc_decode	= nlm_svc_decode_nlm_res,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_res),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1317,7 +1317,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_UNLOCK_RES] = {
 		.pc_func	= nlmsvc_proc_null,
 		.pc_decode	= nlm_svc_decode_nlm_res,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_res),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1327,7 +1327,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_GRANTED_RES] = {
 		.pc_func	= nlmsvc_proc_granted_res,
 		.pc_decode	= nlm_svc_decode_nlm_res,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_res_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1337,7 +1337,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_SM_NOTIFY] = {
 		.pc_func	= nlmsvc_proc_sm_notify,
 		.pc_decode	= nlm_svc_decode_nlm_notifyargs,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_notifyargs_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1346,8 +1346,8 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	},
 	[17] = {
 		.pc_func	= nlmsvc_proc_unused,
-		.pc_decode	= nlm_svc_decode_void,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= 0,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1356,8 +1356,8 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	},
 	[18] = {
 		.pc_func	= nlmsvc_proc_unused,
-		.pc_decode	= nlm_svc_decode_void,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= 0,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1366,8 +1366,8 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	},
 	[19] = {
 		.pc_func	= nlmsvc_proc_unused,
-		.pc_decode	= nlm_svc_decode_void,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_decode	= xdrgen_svc_decode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= 0,
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
@@ -1407,7 +1407,7 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
 	[NLM_FREE_ALL] = {
 		.pc_func	= nlmsvc_proc_free_all,
 		.pc_decode	= nlm_svc_decode_nlm_notify,
-		.pc_encode	= nlm_svc_encode_void,
+		.pc_encode	= xdrgen_svc_encode_void,
 		.pc_argsize	= sizeof(struct nlm_notify_wrapper),
 		.pc_argzero	= 0,
 		.pc_ressize	= 0,
include/linux/sunrpc/xdrgen/_builtins.h +32 -0
index a723fb1da9c8..c9033eb1c829 100644
@@ -296,4 +296,36 @@ xdrgen_encode_opaque(struct xdr_stream *xdr, opaque val)
 	return true;
 }
 
+struct svc_rqst;
+
+/**
+ * xdrgen_svc_decode_void - Decode a void argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ *   %true: procedure arguments decoded successfully
+ *   %false: decode failed
+ */
+static inline bool
+xdrgen_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	return xdrgen_decode_void(xdr);
+}
+
+/**
+ * xdrgen_svc_encode_void - Encode a void result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ *   %true: procedure results encoded successfully
+ *   %false: encode failed
+ */
+static inline bool
+xdrgen_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	return xdrgen_encode_void(xdr);
+}
+
 #endif /* _SUNRPC_XDRGEN__BUILTINS_H_ */
tools/net/sunrpc/xdrgen/generators/program.py +8 -0
index c0cb3f6d3319..37f9655c83fe 100644
@@ -38,6 +38,8 @@ def emit_version_declarations(
     arguments = dict.fromkeys([])
     for procedure in version.procedures:
         if procedure.name not in excluded_apis:
+            if procedure.argument.type_name == "void":
+                continue
             arguments[procedure.argument.type_name] = None
     if len(arguments) > 0:
         print("")
@@ -48,6 +50,8 @@ def emit_version_declarations(
     results = dict.fromkeys([])
     for procedure in version.procedures:
         if procedure.name not in excluded_apis:
+            if procedure.result.type_name == "void":
+                continue
             results[procedure.result.type_name] = None
     if len(results) > 0:
         print("")
@@ -63,6 +67,8 @@ def emit_version_argument_decoders(
     arguments = dict.fromkeys([])
     for procedure in version.procedures:
         if procedure.name not in excluded_apis:
+            if procedure.argument.type_name == "void":
+                continue
             arguments[procedure.argument.type_name] = None
 
     template = environment.get_template("decoder/argument.j2")
@@ -105,6 +111,8 @@ def emit_version_result_encoders(
     results = dict.fromkeys([])
     for procedure in version.procedures:
         if procedure.name not in excluded_apis:
+            if procedure.result.type_name == "void":
+                continue
             results[procedure.result.type_name] = None
 
     template = environment.get_template("encoder/result.j2")
tools/net/sunrpc/xdrgen/templates/C/program/decoder/argument.j2 +0 -4
index 19b219dd276d..096d553b2a1e 100644
@@ -11,9 +11,6 @@
  */
 bool {{ program }}_svc_decode_{{ argument }}(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 {
-{% if argument == 'void' %}
-	return xdrgen_decode_void(xdr);
-{% else %}
 {% if argument in structs %}
 	struct {{ argument }} *argp = rqstp->rq_argp;
 {% else %}
@@ -21,5 +18,4 @@ bool {{ program }}_svc_decode_{{ argument }}(struct svc_rqst *rqstp, struct xdr_
 {% endif %}
 
 	return xdrgen_decode_{{ argument }}(xdr, argp);
-{% endif %}
 }
tools/net/sunrpc/xdrgen/templates/C/program/encoder/result.j2 +0 -4
index 746592cfda56..4243d91966fd 100644
@@ -11,9 +11,6 @@
  */
 bool {{ program }}_svc_encode_{{ result }}(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 {
-{% if result == 'void' %}
-	return xdrgen_encode_void(xdr);
-{% else %}
 {% if result in structs %}
 	struct {{ result }} *resp = rqstp->rq_resp;
 
@@ -23,5 +20,4 @@ bool {{ program }}_svc_encode_{{ result }}(struct svc_rqst *rqstp, struct xdr_st
 
 	return xdrgen_encode_{{ result }}(xdr, *resp);
 {% endif %}
-{% endif %}
 }
Signature · 1 line
2.54.0
author maintainer
#3 lore raw

PATCH 3/5 xdrgen: Do not declare union XDR functions in the definitions header

In reply to Chuck Lever

Unlike the struct, enum, typedef, and pointer templates, the union definitions template also emits xdrgen_decode_*() and xdrgen_encode_*() prototypes for a public union into that header. Those prototypes name struct xdr_stream, which the definitions header neither includes nor forward-declares, so any translation unit that includes the definitions header without xdr.h already in scope draws -Wvisibility warnings. The same public prototypes are emitted into the declarations header, which does include <linux/sunrpc/xdr.h>, making the definitions-header copies redundant.

Drop the prototype emission from the union definitions template so it matches the other type templates. Public unions keep their encode and decode prototypes through the declarations header.

Fixes 4b132aacb076 ("tools: Add xdrgen")
---
 .../net/sunrpc/xdrgen/templates/C/union/definition/close.j2 | 6 ------
 1 file changed, 6 deletions(-)
tools/net/sunrpc/xdrgen/templates/C/union/definition/close.j2 +0 -6
index 5fc1937ba774..19ee759d70c6 100644
@@ -1,9 +1,3 @@
 {# SPDX-License-Identifier: GPL-2.0 #}
 	} u;
 };
-{%- if name in public_apis %}
-
-
-bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
-bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *ptr);
-{%- endif -%}
Signature · 1 line
2.54.0
author maintainer
#4 lore raw

PATCH 4/5 xdrgen: Add XDR width macros for short integer types

In reply to Chuck Lever

Commit ae78eb497868 ("xdrgen: Implement short (16-bit) integer types") taught the generator to emit XDR_short and XDR_unsigned_short in the computed maxsize macros and added the matching encode and decode primitives to _builtins.h, but it left the two width macros themselves undefined in _defs.h.

Define XDR_short and XDR_unsigned_short, each one XDR unit wide, to match the width the generator's maxsize table assigns them.

Fixes ae78eb497868 ("xdrgen: Implement short (16-bit) integer types")
---
 include/linux/sunrpc/xdrgen/_defs.h | 2 ++
 1 file changed, 2 insertions(+)
include/linux/sunrpc/xdrgen/_defs.h +2 -0
index 20c7270aa64d..8f3776ef3229 100644
@@ -25,6 +25,8 @@ typedef struct {
 
 #define XDR_void		(0)
 #define XDR_bool		(1)
+#define XDR_short		(1)
+#define XDR_unsigned_short	(1)
 #define XDR_int			(1)
 #define XDR_unsigned_int	(1)
 #define XDR_long		(1)
Signature · 1 line
2.54.0
author maintainer
#5 lore raw

PATCH 5/5 xdrgen: Fix opaque and string encoders for unbounded members

In reply to Chuck Lever

The variable-length opaque and string encoder templates emit an unconditional bound check, "if (value->NAME.len > MAXSIZE) return false". XDR represents an unbounded specifier (opaque foo<>, string foo<>) as a maxsize of 0, so for an unbounded member the check degenerates to "len > 0" and the generated encoder refuses every non-empty value.

The decoder does not share this defect. It delegates to xdrgen_decode_opaque() and xdrgen_decode_string(), which treat a maxlen of 0 as unbounded and skip the length check. The sibling variable-length array templates already guard their bound check with maxsize != "0".

Guard the bound check the same way in each affected template -- the struct and pointer forms of both the opaque and string encoders -- so an unbounded member encodes a payload of any length while a bounded member keeps its limit.

An explicit zero-length bound (foo<0>) parses to the same maxsize of 0 and so also skips the check; xdrgen does not distinguish it from the unbounded form, matching the decoder and the array encoders.

Fixes 4b132aacb076 ("tools: Add xdrgen")
---
 tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2   | 2 ++
 .../templates/C/pointer/encoder/variable_length_opaque.j2       | 2 ++
 tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2    | 2 ++
 .../xdrgen/templates/C/struct/encoder/variable_length_opaque.j2 | 2 ++
 4 files changed, 8 insertions(+)
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2 +2 -0
index cf65b71eaef3..7ddc2bf3edac 100644
@@ -2,7 +2,9 @@
 {% if annotate %}
 	/* member {{ name }} (variable-length string) */
 {% endif %}
+{% if maxsize != "0" %}
 	if (value->{{ name }}.len > {{ maxsize }})
 		return false;
+{% endif %}
 	if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
 		return false;
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_opaque.j2 +2 -0
index 1d477c2d197a..5bf00070ae95 100644
@@ -2,7 +2,9 @@
 {% if annotate %}
 	/* member {{ name }} (variable-length opaque) */
 {% endif %}
+{% if maxsize != "0" %}
 	if (value->{{ name }}.len > {{ maxsize }})
 		return false;
+{% endif %}
 	if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
 		return false;
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2 +2 -0
index cf65b71eaef3..7ddc2bf3edac 100644
@@ -2,7 +2,9 @@
 {% if annotate %}
 	/* member {{ name }} (variable-length string) */
 {% endif %}
+{% if maxsize != "0" %}
 	if (value->{{ name }}.len > {{ maxsize }})
 		return false;
+{% endif %}
 	if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
 		return false;
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_opaque.j2 +2 -0
index 1d477c2d197a..5bf00070ae95 100644
@@ -2,7 +2,9 @@
 {% if annotate %}
 	/* member {{ name }} (variable-length opaque) */
 {% endif %}
+{% if maxsize != "0" %}
 	if (value->{{ name }}.len > {{ maxsize }})
 		return false;
+{% endif %}
 	if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
 		return false;
Signature · 1 line
2.54.0