Linux NFS development
 help / color / mirror / Atom feed
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 v1 02/13] NFSD: Add infrastructure for generating NFS_ACLv3 XDR encoders and decoders
Date: Sun, 25 Oct 2026 11:16:11 -0400	[thread overview]
Message-ID: <20261025151622.141025-3-cel@kernel.org> (raw)
In-Reply-To: <20261025151622.141025-1-cel@kernel.org>

NFSD's NFS_ACLv3 XDR codecs are hand-maintained; they are being
converted to xdrgen-generated code one RPC procedure at a time.
The first step is to generate and commit the xdrgen C code based on
nfs_acl3.x. The generated code can be refreshed any time nfs_acl3.x
is modified by running "(cd fs/nfsd && make xdrgen)"

Signed-off-by: Chuck Lever <cel@kernel.org>
---
 Documentation/sunrpc/xdr/nfs_acl3.x    |   2 +
 fs/nfsd/Makefile                       |  13 +-
 fs/nfsd/nfs_acl3xdr_gen.c              | 749 +++++++++++++++++++++++++
 fs/nfsd/nfs_acl3xdr_gen.h              |  24 +
 include/linux/sunrpc/xdrgen/nfs_acl3.h | 284 ++++++++++
 5 files changed, 1069 insertions(+), 3 deletions(-)
 create mode 100644 fs/nfsd/nfs_acl3xdr_gen.c
 create mode 100644 fs/nfsd/nfs_acl3xdr_gen.h
 create mode 100644 include/linux/sunrpc/xdrgen/nfs_acl3.h

diff --git a/Documentation/sunrpc/xdr/nfs_acl3.x b/Documentation/sunrpc/xdr/nfs_acl3.x
index 913ecf3a369f..b0e1d2e1fd43 100644
--- a/Documentation/sunrpc/xdr/nfs_acl3.x
+++ b/Documentation/sunrpc/xdr/nfs_acl3.x
@@ -40,6 +40,8 @@
  *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+pragma header nfs_acl3;
+
 const NFS_ACL_MAX_ENTRIES = 1024;
 
 typedef unsigned int uid;
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index 7db3b248e15a..96af6d479731 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -16,7 +16,7 @@ nfsd-y 			+= nfssvc.o nfsctl.o nfsfh.o vfs.o \
 			   nfs3proc.o nfs3xdr.o nfs3xdr_gen.o
 nfsd-$(CONFIG_NFSD_V2) += nfsproc.o nfsxdr.o nfs2xdr_gen.o
 nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o nfs_acl2xdr_gen.o
-nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
+nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o nfs_acl3xdr_gen.o
 nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
 			   nfs4acl.o nfs4callback.o nfs4recover.o nfs4xdr_gen.o
 nfsd-$(CONFIG_NFSD_PNFS) += nfs4layouts.o
@@ -40,11 +40,12 @@ nfsd-$(CONFIG_DEBUG_FS) += debugfs.o
 XDRGEN_DEFINITIONS	= ../../include/linux/sunrpc/xdrgen/nfs2.h \
 			  ../../include/linux/sunrpc/xdrgen/nfs_acl2.h \
 			  ../../include/linux/sunrpc/xdrgen/nfs3.h \
+			  ../../include/linux/sunrpc/xdrgen/nfs_acl3.h \
 			  ../../include/linux/sunrpc/xdrgen/nfs4_1.h
 XDRGEN_DECLARATIONS	= nfs2xdr_gen.h nfs_acl2xdr_gen.h \
-			  nfs3xdr_gen.h nfs4xdr_gen.h
+			  nfs3xdr_gen.h nfs_acl3xdr_gen.h nfs4xdr_gen.h
 XDRGEN_SOURCE		= nfs2xdr_gen.c nfs_acl2xdr_gen.c \
-			  nfs3xdr_gen.c nfs4xdr_gen.c
+			  nfs3xdr_gen.c nfs_acl3xdr_gen.c nfs4xdr_gen.c
 
 xdrgen: $(XDRGEN_DEFINITIONS) $(XDRGEN_DECLARATIONS) $(XDRGEN_SOURCE)
 
@@ -54,6 +55,8 @@ xdrgen: $(XDRGEN_DEFINITIONS) $(XDRGEN_DECLARATIONS) $(XDRGEN_SOURCE)
 	../../tools/net/sunrpc/xdrgen/xdrgen definitions $< > $@
 ../../include/linux/sunrpc/xdrgen/nfs3.h: ../../Documentation/sunrpc/xdr/nfs3.x
 	../../tools/net/sunrpc/xdrgen/xdrgen definitions $< > $@
+../../include/linux/sunrpc/xdrgen/nfs_acl3.h: ../../Documentation/sunrpc/xdr/nfs_acl3.x
+	../../tools/net/sunrpc/xdrgen/xdrgen definitions $< > $@
 ../../include/linux/sunrpc/xdrgen/nfs4_1.h: ../../Documentation/sunrpc/xdr/nfs4_1.x
 	../../tools/net/sunrpc/xdrgen/xdrgen definitions $< > $@
 
@@ -63,6 +66,8 @@ nfs_acl2xdr_gen.h: ../../Documentation/sunrpc/xdr/nfs_acl2.x
 	../../tools/net/sunrpc/xdrgen/xdrgen declarations $< > $@
 nfs3xdr_gen.h: ../../Documentation/sunrpc/xdr/nfs3.x
 	../../tools/net/sunrpc/xdrgen/xdrgen declarations $< > $@
+nfs_acl3xdr_gen.h: ../../Documentation/sunrpc/xdr/nfs_acl3.x
+	../../tools/net/sunrpc/xdrgen/xdrgen declarations $< > $@
 nfs4xdr_gen.h: ../../Documentation/sunrpc/xdr/nfs4_1.x
 	../../tools/net/sunrpc/xdrgen/xdrgen declarations $< > $@
 
@@ -72,5 +77,7 @@ nfs_acl2xdr_gen.c: ../../Documentation/sunrpc/xdr/nfs_acl2.x
 	../../tools/net/sunrpc/xdrgen/xdrgen source $< > $@
 nfs3xdr_gen.c: ../../Documentation/sunrpc/xdr/nfs3.x
 	../../tools/net/sunrpc/xdrgen/xdrgen source $< > $@
+nfs_acl3xdr_gen.c: ../../Documentation/sunrpc/xdr/nfs_acl3.x
+	../../tools/net/sunrpc/xdrgen/xdrgen source $< > $@
 nfs4xdr_gen.c: ../../Documentation/sunrpc/xdr/nfs4_1.x
 	../../tools/net/sunrpc/xdrgen/xdrgen source $< > $@
diff --git a/fs/nfsd/nfs_acl3xdr_gen.c b/fs/nfsd/nfs_acl3xdr_gen.c
new file mode 100644
index 000000000000..5bdeb29addfe
--- /dev/null
+++ b/fs/nfsd/nfs_acl3xdr_gen.c
@@ -0,0 +1,749 @@
+// SPDX-License-Identifier: GPL-2.0
+// Generated by xdrgen. Manual edits will be lost.
+// XDR specification file: ../../Documentation/sunrpc/xdr/nfs_acl3.x
+// XDR specification modification time: Fri Jul 10 20:10:15 2026
+
+#include <linux/sunrpc/svc.h>
+
+#include "nfs_acl3xdr_gen.h"
+
+static bool __maybe_unused
+xdrgen_decode_uid(struct xdr_stream *xdr, uid *ptr)
+{
+	return xdrgen_decode_unsigned_int(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_o_mode(struct xdr_stream *xdr, o_mode *ptr)
+{
+	return xdrgen_decode_unsigned_short(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_aclent(struct xdr_stream *xdr, struct aclent *ptr)
+{
+	if (!xdrgen_decode_int(xdr, &ptr->type))
+		return false;
+	if (!xdrgen_decode_uid(xdr, &ptr->id))
+		return false;
+	if (!xdrgen_decode_o_mode(xdr, &ptr->perm))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_secattr(struct xdr_stream *xdr, struct secattr *ptr)
+{
+	if (!xdrgen_decode_unsigned_int(xdr, &ptr->mask))
+		return false;
+	if (!xdrgen_decode_int(xdr, &ptr->aclcnt))
+		return false;
+	if (xdr_stream_decode_u32(xdr, &ptr->aclent.count) < 0)
+		return false;
+	if (ptr->aclent.count > NFS_ACL_MAX_ENTRIES)
+		return false;
+	for (u32 i = 0; i < ptr->aclent.count; i++)
+		if (!xdrgen_decode_aclent(xdr, &ptr->aclent.element[i]))
+			return false;
+	if (!xdrgen_decode_int(xdr, &ptr->dfaclcnt))
+		return false;
+	if (xdr_stream_decode_u32(xdr, &ptr->dfaclent.count) < 0)
+		return false;
+	if (ptr->dfaclent.count > NFS_ACL_MAX_ENTRIES)
+		return false;
+	for (u32 i = 0; i < ptr->dfaclent.count; i++)
+		if (!xdrgen_decode_aclent(xdr, &ptr->dfaclent.element[i]))
+			return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_uint64(struct xdr_stream *xdr, uint64 *ptr)
+{
+	return xdrgen_decode_unsigned_hyper(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_uint32(struct xdr_stream *xdr, uint32 *ptr)
+{
+	return xdrgen_decode_unsigned_long(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_fileid3(struct xdr_stream *xdr, fileid3 *ptr)
+{
+	return xdrgen_decode_uint64(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_uid3(struct xdr_stream *xdr, uid3 *ptr)
+{
+	return xdrgen_decode_uint32(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_gid3(struct xdr_stream *xdr, gid3 *ptr)
+{
+	return xdrgen_decode_uint32(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_size3(struct xdr_stream *xdr, size3 *ptr)
+{
+	return xdrgen_decode_uint64(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_mode3(struct xdr_stream *xdr, mode3 *ptr)
+{
+	return xdrgen_decode_uint32(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_ftype3(struct xdr_stream *xdr, ftype3 *ptr)
+{
+	u32 val;
+
+	if (xdr_stream_decode_u32(xdr, &val) < 0)
+		return false;
+	/* Compiler may optimize to a range check for dense enums */
+	switch (val) {
+	case NF3REG:
+	case NF3DIR:
+	case NF3BLK:
+	case NF3CHR:
+	case NF3LNK:
+	case NF3SOCK:
+	case NF3FIFO:
+		break;
+	default:
+		return false;
+	}
+	*ptr = val;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_specdata3(struct xdr_stream *xdr, struct specdata3 *ptr)
+{
+	if (!xdrgen_decode_uint32(xdr, &ptr->specdata1))
+		return false;
+	if (!xdrgen_decode_uint32(xdr, &ptr->specdata2))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh3 *ptr)
+{
+	if (!xdrgen_decode_opaque(xdr, &ptr->data, NFS3_FHSIZE))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfstime3(struct xdr_stream *xdr, struct nfstime3 *ptr)
+{
+	if (!xdrgen_decode_uint32(xdr, &ptr->seconds))
+		return false;
+	if (!xdrgen_decode_uint32(xdr, &ptr->nseconds))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_fattr3(struct xdr_stream *xdr, struct fattr3 *ptr)
+{
+	if (!xdrgen_decode_ftype3(xdr, &ptr->type))
+		return false;
+	if (!xdrgen_decode_mode3(xdr, &ptr->mode))
+		return false;
+	if (!xdrgen_decode_uint32(xdr, &ptr->nlink))
+		return false;
+	if (!xdrgen_decode_uid3(xdr, &ptr->uid))
+		return false;
+	if (!xdrgen_decode_gid3(xdr, &ptr->gid))
+		return false;
+	if (!xdrgen_decode_size3(xdr, &ptr->size))
+		return false;
+	if (!xdrgen_decode_size3(xdr, &ptr->used))
+		return false;
+	if (!xdrgen_decode_specdata3(xdr, &ptr->rdev))
+		return false;
+	if (!xdrgen_decode_uint64(xdr, &ptr->fsid))
+		return false;
+	if (!xdrgen_decode_fileid3(xdr, &ptr->fileid))
+		return false;
+	if (!xdrgen_decode_nfstime3(xdr, &ptr->atime))
+		return false;
+	if (!xdrgen_decode_nfstime3(xdr, &ptr->mtime))
+		return false;
+	if (!xdrgen_decode_nfstime3(xdr, &ptr->ctime))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_post_op_attr(struct xdr_stream *xdr, struct post_op_attr *ptr)
+{
+	if (!xdrgen_decode_bool(xdr, &ptr->attributes_follow))
+		return false;
+	if (ptr->attributes_follow) {
+		if (!xdrgen_decode_fattr3(xdr, &ptr->u.attributes))
+			return false;
+	}
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_aclstat3(struct xdr_stream *xdr, aclstat3 *ptr)
+{
+	u32 val;
+
+	if (xdr_stream_decode_u32(xdr, &val) < 0)
+		return false;
+	/* Compiler may optimize to a range check for dense enums */
+	switch (val) {
+	case ACL3_OK:
+	case ACL3ERR_PERM:
+	case ACL3ERR_NOENT:
+	case ACL3ERR_IO:
+	case ACL3ERR_ACCES:
+	case ACL3ERR_INVAL:
+	case ACL3ERR_NOSPC:
+	case ACL3ERR_ROFS:
+	case ACL3ERR_DQUOT:
+	case ACL3ERR_STALE:
+	case ACL3ERR_BADHANDLE:
+	case ACL3ERR_NOTSUPP:
+	case ACL3ERR_SERVERFAULT:
+	case ACL3ERR_JUKEBOX:
+		break;
+	default:
+		return false;
+	}
+	*ptr = val;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETACL3args(struct xdr_stream *xdr, struct GETACL3args *ptr)
+{
+	if (!xdrgen_decode_nfs_fh3(xdr, &ptr->fh))
+		return false;
+	if (!xdrgen_decode_unsigned_int(xdr, &ptr->mask))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETACL3resok(struct xdr_stream *xdr, struct GETACL3resok *ptr)
+{
+	if (!xdrgen_decode_post_op_attr(xdr, &ptr->attr))
+		return false;
+	if (!xdrgen_decode_secattr(xdr, &ptr->acl))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETACL3resfail(struct xdr_stream *xdr, struct GETACL3resfail *ptr)
+{
+	if (!xdrgen_decode_post_op_attr(xdr, &ptr->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETACL3res(struct xdr_stream *xdr, struct GETACL3res *ptr)
+{
+	if (!xdrgen_decode_aclstat3(xdr, &ptr->status))
+		return false;
+	switch (ptr->status) {
+	case ACL3_OK:
+		if (!xdrgen_decode_GETACL3resok(xdr, &ptr->u.resok))
+			return false;
+		break;
+	default:
+		if (!xdrgen_decode_GETACL3resfail(xdr, &ptr->u.resfail))
+			return false;
+	}
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_SETACL3args(struct xdr_stream *xdr, struct SETACL3args *ptr)
+{
+	if (!xdrgen_decode_nfs_fh3(xdr, &ptr->fh))
+		return false;
+	if (!xdrgen_decode_secattr(xdr, &ptr->acl))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_SETACL3resok(struct xdr_stream *xdr, struct SETACL3resok *ptr)
+{
+	if (!xdrgen_decode_post_op_attr(xdr, &ptr->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_SETACL3resfail(struct xdr_stream *xdr, struct SETACL3resfail *ptr)
+{
+	if (!xdrgen_decode_post_op_attr(xdr, &ptr->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_SETACL3res(struct xdr_stream *xdr, struct SETACL3res *ptr)
+{
+	if (!xdrgen_decode_aclstat3(xdr, &ptr->status))
+		return false;
+	switch (ptr->status) {
+	case ACL3_OK:
+		if (!xdrgen_decode_SETACL3resok(xdr, &ptr->u.resok))
+			return false;
+		break;
+	default:
+		if (!xdrgen_decode_SETACL3resfail(xdr, &ptr->u.resfail))
+			return false;
+	}
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETXATTRDIR3args(struct xdr_stream *xdr, struct GETXATTRDIR3args *ptr)
+{
+	if (!xdrgen_decode_nfs_fh3(xdr, &ptr->fh))
+		return false;
+	if (!xdrgen_decode_bool(xdr, &ptr->create))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETXATTRDIR3resok(struct xdr_stream *xdr, struct GETXATTRDIR3resok *ptr)
+{
+	if (!xdrgen_decode_nfs_fh3(xdr, &ptr->fh))
+		return false;
+	if (!xdrgen_decode_post_op_attr(xdr, &ptr->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_GETXATTRDIR3res(struct xdr_stream *xdr, struct GETXATTRDIR3res *ptr)
+{
+	if (!xdrgen_decode_aclstat3(xdr, &ptr->status))
+		return false;
+	switch (ptr->status) {
+	case ACL3_OK:
+		if (!xdrgen_decode_GETXATTRDIR3resok(xdr, &ptr->u.resok))
+			return false;
+		break;
+	default:
+		break;
+	}
+	return true;
+}
+
+/**
+ * nfs_acl_svc_decode_GETACL3args - Decode a GETACL3args argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ *   %true: procedure arguments decoded successfully
+ *   %false: decode failed
+ */
+bool nfs_acl_svc_decode_GETACL3args(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	struct GETACL3args *argp = rqstp->rq_argp;
+
+	return xdrgen_decode_GETACL3args(xdr, argp);
+}
+
+/**
+ * nfs_acl_svc_decode_SETACL3args - Decode a SETACL3args argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ *   %true: procedure arguments decoded successfully
+ *   %false: decode failed
+ */
+bool nfs_acl_svc_decode_SETACL3args(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	struct SETACL3args *argp = rqstp->rq_argp;
+
+	return xdrgen_decode_SETACL3args(xdr, argp);
+}
+
+/**
+ * nfs_acl_svc_decode_GETXATTRDIR3args - Decode a GETXATTRDIR3args argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ *   %true: procedure arguments decoded successfully
+ *   %false: decode failed
+ */
+bool nfs_acl_svc_decode_GETXATTRDIR3args(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	struct GETXATTRDIR3args *argp = rqstp->rq_argp;
+
+	return xdrgen_decode_GETXATTRDIR3args(xdr, argp);
+}
+
+static bool __maybe_unused
+xdrgen_encode_uid(struct xdr_stream *xdr, const uid value)
+{
+	return xdrgen_encode_unsigned_int(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_o_mode(struct xdr_stream *xdr, const o_mode value)
+{
+	return xdrgen_encode_unsigned_short(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_aclent(struct xdr_stream *xdr, const struct aclent *value)
+{
+	if (!xdrgen_encode_int(xdr, value->type))
+		return false;
+	if (!xdrgen_encode_uid(xdr, value->id))
+		return false;
+	if (!xdrgen_encode_o_mode(xdr, value->perm))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_secattr(struct xdr_stream *xdr, const struct secattr *value)
+{
+	if (!xdrgen_encode_unsigned_int(xdr, value->mask))
+		return false;
+	if (!xdrgen_encode_int(xdr, value->aclcnt))
+		return false;
+	if (value->aclent.count > NFS_ACL_MAX_ENTRIES)
+		return false;
+	if (xdr_stream_encode_u32(xdr, value->aclent.count) != XDR_UNIT)
+		return false;
+	for (u32 i = 0; i < value->aclent.count; i++)
+		if (!xdrgen_encode_aclent(xdr, &value->aclent.element[i]))
+			return false;
+	if (!xdrgen_encode_int(xdr, value->dfaclcnt))
+		return false;
+	if (value->dfaclent.count > NFS_ACL_MAX_ENTRIES)
+		return false;
+	if (xdr_stream_encode_u32(xdr, value->dfaclent.count) != XDR_UNIT)
+		return false;
+	for (u32 i = 0; i < value->dfaclent.count; i++)
+		if (!xdrgen_encode_aclent(xdr, &value->dfaclent.element[i]))
+			return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_uint64(struct xdr_stream *xdr, const uint64 value)
+{
+	return xdrgen_encode_unsigned_hyper(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_uint32(struct xdr_stream *xdr, const uint32 value)
+{
+	return xdrgen_encode_unsigned_long(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_fileid3(struct xdr_stream *xdr, const fileid3 value)
+{
+	return xdrgen_encode_uint64(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_uid3(struct xdr_stream *xdr, const uid3 value)
+{
+	return xdrgen_encode_uint32(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_gid3(struct xdr_stream *xdr, const gid3 value)
+{
+	return xdrgen_encode_uint32(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_size3(struct xdr_stream *xdr, const size3 value)
+{
+	return xdrgen_encode_uint64(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_mode3(struct xdr_stream *xdr, const mode3 value)
+{
+	return xdrgen_encode_uint32(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_ftype3(struct xdr_stream *xdr, ftype3 value)
+{
+	return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_specdata3(struct xdr_stream *xdr, const struct specdata3 *value)
+{
+	if (!xdrgen_encode_uint32(xdr, value->specdata1))
+		return false;
+	if (!xdrgen_encode_uint32(xdr, value->specdata2))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh3 *value)
+{
+	if (value->data.len > NFS3_FHSIZE)
+		return false;
+	if (xdr_stream_encode_opaque(xdr, value->data.data, value->data.len) < 0)
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfstime3(struct xdr_stream *xdr, const struct nfstime3 *value)
+{
+	if (!xdrgen_encode_uint32(xdr, value->seconds))
+		return false;
+	if (!xdrgen_encode_uint32(xdr, value->nseconds))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_fattr3(struct xdr_stream *xdr, const struct fattr3 *value)
+{
+	if (!xdrgen_encode_ftype3(xdr, value->type))
+		return false;
+	if (!xdrgen_encode_mode3(xdr, value->mode))
+		return false;
+	if (!xdrgen_encode_uint32(xdr, value->nlink))
+		return false;
+	if (!xdrgen_encode_uid3(xdr, value->uid))
+		return false;
+	if (!xdrgen_encode_gid3(xdr, value->gid))
+		return false;
+	if (!xdrgen_encode_size3(xdr, value->size))
+		return false;
+	if (!xdrgen_encode_size3(xdr, value->used))
+		return false;
+	if (!xdrgen_encode_specdata3(xdr, &value->rdev))
+		return false;
+	if (!xdrgen_encode_uint64(xdr, value->fsid))
+		return false;
+	if (!xdrgen_encode_fileid3(xdr, value->fileid))
+		return false;
+	if (!xdrgen_encode_nfstime3(xdr, &value->atime))
+		return false;
+	if (!xdrgen_encode_nfstime3(xdr, &value->mtime))
+		return false;
+	if (!xdrgen_encode_nfstime3(xdr, &value->ctime))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_post_op_attr(struct xdr_stream *xdr, const struct post_op_attr *ptr)
+{
+	if (!xdrgen_encode_bool(xdr, ptr->attributes_follow))
+		return false;
+	if (ptr->attributes_follow) {
+		if (!xdrgen_encode_fattr3(xdr, &ptr->u.attributes))
+			return false;
+	}
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_aclstat3(struct xdr_stream *xdr, aclstat3 value)
+{
+	return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETACL3args(struct xdr_stream *xdr, const struct GETACL3args *value)
+{
+	if (!xdrgen_encode_nfs_fh3(xdr, &value->fh))
+		return false;
+	if (!xdrgen_encode_unsigned_int(xdr, value->mask))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETACL3resok(struct xdr_stream *xdr, const struct GETACL3resok *value)
+{
+	if (!xdrgen_encode_post_op_attr(xdr, &value->attr))
+		return false;
+	if (!xdrgen_encode_secattr(xdr, &value->acl))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETACL3resfail(struct xdr_stream *xdr, const struct GETACL3resfail *value)
+{
+	if (!xdrgen_encode_post_op_attr(xdr, &value->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETACL3res(struct xdr_stream *xdr, const struct GETACL3res *ptr)
+{
+	if (!xdrgen_encode_aclstat3(xdr, ptr->status))
+		return false;
+	switch (ptr->status) {
+	case ACL3_OK:
+		if (!xdrgen_encode_GETACL3resok(xdr, &ptr->u.resok))
+			return false;
+		break;
+	default:
+		if (!xdrgen_encode_GETACL3resfail(xdr, &ptr->u.resfail))
+			return false;
+	}
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_SETACL3args(struct xdr_stream *xdr, const struct SETACL3args *value)
+{
+	if (!xdrgen_encode_nfs_fh3(xdr, &value->fh))
+		return false;
+	if (!xdrgen_encode_secattr(xdr, &value->acl))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_SETACL3resok(struct xdr_stream *xdr, const struct SETACL3resok *value)
+{
+	if (!xdrgen_encode_post_op_attr(xdr, &value->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_SETACL3resfail(struct xdr_stream *xdr, const struct SETACL3resfail *value)
+{
+	if (!xdrgen_encode_post_op_attr(xdr, &value->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_SETACL3res(struct xdr_stream *xdr, const struct SETACL3res *ptr)
+{
+	if (!xdrgen_encode_aclstat3(xdr, ptr->status))
+		return false;
+	switch (ptr->status) {
+	case ACL3_OK:
+		if (!xdrgen_encode_SETACL3resok(xdr, &ptr->u.resok))
+			return false;
+		break;
+	default:
+		if (!xdrgen_encode_SETACL3resfail(xdr, &ptr->u.resfail))
+			return false;
+	}
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETXATTRDIR3args(struct xdr_stream *xdr, const struct GETXATTRDIR3args *value)
+{
+	if (!xdrgen_encode_nfs_fh3(xdr, &value->fh))
+		return false;
+	if (!xdrgen_encode_bool(xdr, value->create))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETXATTRDIR3resok(struct xdr_stream *xdr, const struct GETXATTRDIR3resok *value)
+{
+	if (!xdrgen_encode_nfs_fh3(xdr, &value->fh))
+		return false;
+	if (!xdrgen_encode_post_op_attr(xdr, &value->attr))
+		return false;
+	return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_GETXATTRDIR3res(struct xdr_stream *xdr, const struct GETXATTRDIR3res *ptr)
+{
+	if (!xdrgen_encode_aclstat3(xdr, ptr->status))
+		return false;
+	switch (ptr->status) {
+	case ACL3_OK:
+		if (!xdrgen_encode_GETXATTRDIR3resok(xdr, &ptr->u.resok))
+			return false;
+		break;
+	default:
+		break;
+	}
+	return true;
+}
+
+/**
+ * nfs_acl_svc_encode_GETACL3res - Encode a GETACL3res result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ *   %true: procedure results encoded successfully
+ *   %false: encode failed
+ */
+bool nfs_acl_svc_encode_GETACL3res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	struct GETACL3res *resp = rqstp->rq_resp;
+
+	return xdrgen_encode_GETACL3res(xdr, resp);
+}
+
+/**
+ * nfs_acl_svc_encode_SETACL3res - Encode a SETACL3res result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ *   %true: procedure results encoded successfully
+ *   %false: encode failed
+ */
+bool nfs_acl_svc_encode_SETACL3res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	struct SETACL3res *resp = rqstp->rq_resp;
+
+	return xdrgen_encode_SETACL3res(xdr, resp);
+}
+
+/**
+ * nfs_acl_svc_encode_GETXATTRDIR3res - Encode a GETXATTRDIR3res result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ *   %true: procedure results encoded successfully
+ *   %false: encode failed
+ */
+bool nfs_acl_svc_encode_GETXATTRDIR3res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+	struct GETXATTRDIR3res *resp = rqstp->rq_resp;
+
+	return xdrgen_encode_GETXATTRDIR3res(xdr, resp);
+}
diff --git a/fs/nfsd/nfs_acl3xdr_gen.h b/fs/nfsd/nfs_acl3xdr_gen.h
new file mode 100644
index 000000000000..d778004ba26a
--- /dev/null
+++ b/fs/nfsd/nfs_acl3xdr_gen.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Generated by xdrgen. Manual edits will be lost. */
+/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs_acl3.x */
+/* XDR specification modification time: Fri Jul 10 20:10:15 2026 */
+
+#ifndef _LINUX_XDRGEN_NFS_ACL3_DECL_H
+#define _LINUX_XDRGEN_NFS_ACL3_DECL_H
+
+#include <linux/types.h>
+
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/xdrgen/_defs.h>
+#include <linux/sunrpc/xdrgen/_builtins.h>
+#include <linux/sunrpc/xdrgen/nfs_acl3.h>
+
+bool nfs_acl_svc_decode_GETACL3args(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nfs_acl_svc_decode_SETACL3args(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nfs_acl_svc_decode_GETXATTRDIR3args(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+
+bool nfs_acl_svc_encode_GETACL3res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nfs_acl_svc_encode_SETACL3res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nfs_acl_svc_encode_GETXATTRDIR3res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+
+#endif /* _LINUX_XDRGEN_NFS_ACL3_DECL_H */
diff --git a/include/linux/sunrpc/xdrgen/nfs_acl3.h b/include/linux/sunrpc/xdrgen/nfs_acl3.h
new file mode 100644
index 000000000000..8758450dbca0
--- /dev/null
+++ b/include/linux/sunrpc/xdrgen/nfs_acl3.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Generated by xdrgen. Manual edits will be lost. */
+/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs_acl3.x */
+/* XDR specification modification time: Fri Jul 10 20:10:15 2026 */
+
+#ifndef _LINUX_XDRGEN_NFS_ACL3_DEF_H
+#define _LINUX_XDRGEN_NFS_ACL3_DEF_H
+
+#include <linux/types.h>
+#include <linux/sunrpc/xdrgen/_defs.h>
+
+enum { NFS_ACL_MAX_ENTRIES = 1024 };
+
+typedef u32 uid;
+
+typedef u16 o_mode;
+
+struct aclent {
+	s32 type;
+	uid id;
+	o_mode perm;
+};
+
+enum { NA_USER_OBJ = 0x1 };
+
+enum { NA_USER = 0x2 };
+
+enum { NA_GROUP_OBJ = 0x4 };
+
+enum { NA_GROUP = 0x8 };
+
+enum { NA_CLASS_OBJ = 0x10 };
+
+enum { NA_OTHER_OBJ = 0x20 };
+
+enum { NA_ACL_DEFAULT = 0x1000 };
+
+enum { NA_READ = 0x4 };
+
+enum { NA_WRITE = 0x2 };
+
+enum { NA_EXEC = 0x1 };
+
+struct secattr {
+	u32 mask;
+	s32 aclcnt;
+	struct {
+		u32 count;
+		struct aclent *element;
+	} aclent;
+	s32 dfaclcnt;
+	struct {
+		u32 count;
+		struct aclent *element;
+	} dfaclent;
+};
+
+enum { NA_ACL = 0x1 };
+
+enum { NA_ACLCNT = 0x2 };
+
+enum { NA_DFACL = 0x4 };
+
+enum { NA_DFACLCNT = 0x8 };
+
+enum { NFS_ACL_PORT = 2049 };
+
+enum { NFS_ACL_RDMA_PORT = 20049 };
+
+typedef u64 uint64;
+
+typedef u32 uint32;
+
+typedef uint64 fileid3;
+
+typedef uint32 uid3;
+
+typedef uint32 gid3;
+
+typedef uint64 size3;
+
+typedef uint32 mode3;
+
+enum ftype3 {
+	NF3REG = 1,
+	NF3DIR = 2,
+	NF3BLK = 3,
+	NF3CHR = 4,
+	NF3LNK = 5,
+	NF3SOCK = 6,
+	NF3FIFO = 7,
+};
+
+typedef enum ftype3 ftype3;
+
+struct specdata3 {
+	uint32 specdata1;
+	uint32 specdata2;
+};
+
+enum { NFS3_FHSIZE = 64 };
+
+struct nfs_fh3 {
+	opaque data;
+};
+
+struct nfstime3 {
+	uint32 seconds;
+	uint32 nseconds;
+};
+
+struct fattr3 {
+	ftype3 type;
+	mode3 mode;
+	uint32 nlink;
+	uid3 uid;
+	gid3 gid;
+	size3 size;
+	size3 used;
+	struct specdata3 rdev;
+	uint64 fsid;
+	fileid3 fileid;
+	struct nfstime3 atime;
+	struct nfstime3 mtime;
+	struct nfstime3 ctime;
+};
+
+struct post_op_attr {
+	bool attributes_follow;
+	union {
+		struct fattr3 attributes;
+	} u;
+};
+
+enum aclstat3 {
+	ACL3_OK = 0,
+	ACL3ERR_PERM = 1,
+	ACL3ERR_NOENT = 2,
+	ACL3ERR_IO = 5,
+	ACL3ERR_ACCES = 13,
+	ACL3ERR_INVAL = 22,
+	ACL3ERR_NOSPC = 28,
+	ACL3ERR_ROFS = 30,
+	ACL3ERR_DQUOT = 69,
+	ACL3ERR_STALE = 70,
+	ACL3ERR_BADHANDLE = 10001,
+	ACL3ERR_NOTSUPP = 10004,
+	ACL3ERR_SERVERFAULT = 10006,
+	ACL3ERR_JUKEBOX = 10008,
+};
+
+typedef enum aclstat3 aclstat3;
+
+struct GETACL3args {
+	struct nfs_fh3 fh;
+	u32 mask;
+};
+
+struct GETACL3resok {
+	struct post_op_attr attr;
+	struct secattr acl;
+};
+
+struct GETACL3resfail {
+	struct post_op_attr attr;
+};
+
+struct GETACL3res {
+	aclstat3 status;
+	union {
+		struct GETACL3resok resok;
+		struct GETACL3resfail resfail;
+	} u;
+};
+
+struct SETACL3args {
+	struct nfs_fh3 fh;
+	struct secattr acl;
+};
+
+struct SETACL3resok {
+	struct post_op_attr attr;
+};
+
+struct SETACL3resfail {
+	struct post_op_attr attr;
+};
+
+struct SETACL3res {
+	aclstat3 status;
+	union {
+		struct SETACL3resok resok;
+		struct SETACL3resfail resfail;
+	} u;
+};
+
+struct GETXATTRDIR3args {
+	struct nfs_fh3 fh;
+	bool create;
+};
+
+struct GETXATTRDIR3resok {
+	struct nfs_fh3 fh;
+	struct post_op_attr attr;
+};
+
+struct GETXATTRDIR3res {
+	aclstat3 status;
+	union {
+		struct GETXATTRDIR3resok resok;
+	} u;
+};
+
+enum {
+	ACLPROC3_NULL = 0,
+	ACLPROC3_GETACL = 1,
+	ACLPROC3_SETACL = 2,
+	ACLPROC3_GETXATTRDIR = 3,
+};
+
+#ifndef NFS_ACL_PROGRAM
+#define NFS_ACL_PROGRAM (100227)
+#endif
+
+#define NFS_ACL3_uid_sz                 \
+	(XDR_unsigned_int)
+#define NFS_ACL3_o_mode_sz              \
+	(XDR_unsigned_short)
+#define NFS_ACL3_aclent_sz              \
+	(XDR_int + NFS_ACL3_uid_sz + NFS_ACL3_o_mode_sz)
+#define NFS_ACL3_secattr_sz             \
+	(XDR_unsigned_int + XDR_int + XDR_unsigned_int + (NFS_ACL_MAX_ENTRIES * (NFS_ACL3_aclent_sz)) + XDR_int + XDR_unsigned_int + (NFS_ACL_MAX_ENTRIES * (NFS_ACL3_aclent_sz)))
+#define NFS_ACL3_uint64_sz              \
+	(XDR_unsigned_hyper)
+#define NFS_ACL3_uint32_sz              \
+	(XDR_unsigned_long)
+#define NFS_ACL3_fileid3_sz             \
+	(NFS_ACL3_uint64_sz)
+#define NFS_ACL3_uid3_sz                \
+	(NFS_ACL3_uint32_sz)
+#define NFS_ACL3_gid3_sz                \
+	(NFS_ACL3_uint32_sz)
+#define NFS_ACL3_size3_sz               \
+	(NFS_ACL3_uint64_sz)
+#define NFS_ACL3_mode3_sz               \
+	(NFS_ACL3_uint32_sz)
+#define NFS_ACL3_ftype3_sz              (XDR_int)
+#define NFS_ACL3_specdata3_sz           \
+	(NFS_ACL3_uint32_sz + NFS_ACL3_uint32_sz)
+#define NFS_ACL3_nfs_fh3_sz             \
+	(XDR_unsigned_int + XDR_QUADLEN(NFS3_FHSIZE))
+#define NFS_ACL3_nfstime3_sz            \
+	(NFS_ACL3_uint32_sz + NFS_ACL3_uint32_sz)
+#define NFS_ACL3_fattr3_sz              \
+	(NFS_ACL3_ftype3_sz + NFS_ACL3_mode3_sz + NFS_ACL3_uint32_sz + NFS_ACL3_uid3_sz + NFS_ACL3_gid3_sz + NFS_ACL3_size3_sz + NFS_ACL3_size3_sz + NFS_ACL3_specdata3_sz + NFS_ACL3_uint64_sz + NFS_ACL3_fileid3_sz + NFS_ACL3_nfstime3_sz + NFS_ACL3_nfstime3_sz + NFS_ACL3_nfstime3_sz)
+#define NFS_ACL3_post_op_attr_sz        \
+	(XDR_bool + NFS_ACL3_fattr3_sz)
+#define NFS_ACL3_aclstat3_sz            (XDR_int)
+#define NFS_ACL3_GETACL3args_sz         \
+	(NFS_ACL3_nfs_fh3_sz + XDR_unsigned_int)
+#define NFS_ACL3_GETACL3resok_sz        \
+	(NFS_ACL3_post_op_attr_sz + NFS_ACL3_secattr_sz)
+#define NFS_ACL3_GETACL3resfail_sz      \
+	(NFS_ACL3_post_op_attr_sz)
+#define NFS_ACL3_GETACL3res_sz          \
+	(NFS_ACL3_aclstat3_sz + NFS_ACL3_GETACL3resok_sz)
+#define NFS_ACL3_SETACL3args_sz         \
+	(NFS_ACL3_nfs_fh3_sz + NFS_ACL3_secattr_sz)
+#define NFS_ACL3_SETACL3resok_sz        \
+	(NFS_ACL3_post_op_attr_sz)
+#define NFS_ACL3_SETACL3resfail_sz      \
+	(NFS_ACL3_post_op_attr_sz)
+#define NFS_ACL3_SETACL3res_sz          \
+	(NFS_ACL3_aclstat3_sz + NFS_ACL3_SETACL3resok_sz)
+#define NFS_ACL3_GETXATTRDIR3args_sz    \
+	(NFS_ACL3_nfs_fh3_sz + XDR_bool)
+#define NFS_ACL3_GETXATTRDIR3resok_sz   \
+	(NFS_ACL3_nfs_fh3_sz + NFS_ACL3_post_op_attr_sz)
+#define NFS_ACL3_GETXATTRDIR3res_sz     \
+	(NFS_ACL3_aclstat3_sz + NFS_ACL3_GETXATTRDIR3resok_sz)
+#define NFS_ACL3_MAX_ARGS_SZ            \
+	(NFS_ACL3_SETACL3args_sz)
+
+#endif /* _LINUX_XDRGEN_NFS_ACL3_DEF_H */
-- 
2.56.0


  parent reply	other threads:[~2026-10-26 21:36 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-25 15:16 [PATCH v1 00/13] Convert server-side NFS_ACLv3 XDR to use xdrgen Chuck Lever
2026-10-25 15:16 ` [PATCH v1 01/13] Documentation: Add the RPC language description of NFS_ACLv3 Chuck Lever
2026-10-25 15:16 ` Chuck Lever [this message]
2026-10-25 15:16 ` [PATCH v1 03/13] NFSD: Remove '#include "xdr3.h"' from nfs3acl.c Chuck Lever
2026-10-25 15:16 ` [PATCH v1 04/13] NFSD: New NFS_ACLv3 status codes Chuck Lever
2026-10-25 15:16 ` [PATCH v1 05/13] NFSD: Use xdrgen XDR functions for the NFS-ACL v3 NULL procedure Chuck Lever
2026-10-25 15:16 ` [PATCH v1 06/13] NFSD: Implement NFS-ACL v3 ACL encoding and decoding with xdrgen Chuck Lever
2026-10-25 15:16 ` [PATCH v1 07/13] NFSD: Use xdrgen XDR functions for the NFS-ACL v3 GETACL procedure Chuck Lever
2026-10-25 15:16 ` [PATCH v1 08/13] NFSD: Use xdrgen XDR functions for the NFS-ACL v3 SETACL procedure Chuck Lever
2026-10-25 15:16 ` [PATCH v1 09/13] NFSD: Map every NFS_ACLv3 reply status into aclstat3 Chuck Lever
2026-10-25 15:16 ` [PATCH v1 10/13] NFSD: Remove the hand-coded XDR helpers for the NFS_ACLv3 procedures Chuck Lever
2026-10-25 15:16 ` [PATCH v1 11/13] NFS: Move NFSACL_MAXPAGES into fs/nfs/nfs3_fs.h Chuck Lever
2026-10-26 22:50   ` Anna Schumaker
2026-10-25 15:16 ` [PATCH v1 12/13] NFSD: Share the attribute conversion helpers with the NFS_ACL procs Chuck Lever
2026-10-25 15:16 ` [PATCH v1 13/13] nfs_common: Remove the unused NFS ACL stream codecs Chuck Lever
2026-10-27 10:56 ` [PATCH v1 00/13] Convert server-side NFS_ACLv3 XDR to use xdrgen 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=20261025151622.141025-3-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