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 07/27] NFSD: Use xdrgen XDR functions for NFSv2 GETATTR procedure
Date: Wed, 16 Sep 2026 12:28:38 -0400	[thread overview]
Message-ID: <20260916162859.2051-10-cel@kernel.org> (raw)
In-Reply-To: <20260916162859.2051-1-cel@kernel.org>

Replace the NFSPROC_GETATTR entry in the nfsd_procedures2 array
with an entry that dispatches the xdrgen-generated
nfs_svc_decode_fhandle and nfs_svc_encode_attrstat. Wrapper
structures bridge the generated xdrgen types and the legacy
svc_fh and kstat representations the NFSD VFS layer still uses. A
few helper functions are introduced which will be used here and
in subsequent patches.

The pc_argzero field is now set to zero for the NFSv2 GETATTR
procedure. The xdrgen decoders are trusted to initialize all
arguments in the argp->xdrgen field, making the early defensive
memset unnecessary. The remaining argp fields are cleared as
needed.

This refactor replaces the use of svcxdr_encode_fattr(), so the
reference to the file handle can be released directly by
nfsd_proc_getattr(). A separate ->pc_release callback is thus no
longer needed. This makes it straightforward to confirm that the
file handle is properly released during every error flow.

The new nfsd_mode_to_ftype() utility no longer maps socket and
FIFO devices to non-standard values: NFSOCK=6 which is outside
the ftype enum, and NFCHR for FIFOs which is semantically wrong.
The Linux NFS client implementation does not seem to use or
depend on these non-standard values. The new utility function
returns NFNON for both, which is the RFC-compliant behavior.

Signed-off-by: Chuck Lever <cel@kernel.org>
---
 Documentation/sunrpc/xdr/nfs2.x    |   1 +
 fs/nfsd/nfs2xdr_gen.c              |  34 +++---
 fs/nfsd/nfs2xdr_gen.h              |   2 +-
 fs/nfsd/nfsproc.c                  | 170 ++++++++++++++++++++++++-----
 include/linux/sunrpc/xdrgen/nfs2.h |   4 +-
 5 files changed, 166 insertions(+), 45 deletions(-)

diff --git a/Documentation/sunrpc/xdr/nfs2.x b/Documentation/sunrpc/xdr/nfs2.x
index 5e6208d857f3..abec81cecbae 100644
--- a/Documentation/sunrpc/xdr/nfs2.x
+++ b/Documentation/sunrpc/xdr/nfs2.x
@@ -44,6 +44,7 @@ enum nfsstat {
 	NFSERR_STALE		= 70,
 	NFSERR_WFLUSH		= 99
 };
+pragma big_endian nfsstat;
 
 enum ftype {
 	NFNON		= 0,
diff --git a/fs/nfsd/nfs2xdr_gen.c b/fs/nfsd/nfs2xdr_gen.c
index ae81d1731ac6..59bee2746650 100644
--- a/fs/nfsd/nfs2xdr_gen.c
+++ b/fs/nfsd/nfs2xdr_gen.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 // Generated by xdrgen. Manual edits will be lost.
 // XDR specification file: ../../Documentation/sunrpc/xdr/nfs2.x
-// XDR specification modification time: Tue Sep  8 11:23:43 2026
+// XDR specification modification time: Tue Sep  8 11:24:48 2026
 
 #include <linux/sunrpc/svc.h>
 
@@ -10,10 +10,12 @@
 static bool __maybe_unused
 xdrgen_decode_nfsstat(struct xdr_stream *xdr, nfsstat *ptr)
 {
+	__be32 raw;
 	u32 val;
 
-	if (xdr_stream_decode_u32(xdr, &val) < 0)
+	if (xdr_stream_decode_be32(xdr, &raw) < 0)
 		return false;
+	val = be32_to_cpu(raw);
 	/* Compiler may optimize to a range check for dense enums */
 	switch (val) {
 	case NFS_OK:
@@ -38,7 +40,7 @@ xdrgen_decode_nfsstat(struct xdr_stream *xdr, nfsstat *ptr)
 	default:
 		return false;
 	}
-	*ptr = val;
+	*ptr = raw;
 	return true;
 }
 
@@ -157,7 +159,7 @@ xdrgen_decode_attrstat(struct xdr_stream *xdr, struct attrstat *ptr)
 	if (!xdrgen_decode_nfsstat(xdr, &ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_decode_fattr(xdr, &ptr->u.attributes))
 			return false;
 		break;
@@ -193,7 +195,7 @@ xdrgen_decode_diropres(struct xdr_stream *xdr, struct diropres *ptr)
 	if (!xdrgen_decode_nfsstat(xdr, &ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_decode_diropok(xdr, &ptr->u.diropok))
 			return false;
 		break;
@@ -219,7 +221,7 @@ xdrgen_decode_readlinkres(struct xdr_stream *xdr, struct readlinkres *ptr)
 	if (!xdrgen_decode_nfsstat(xdr, &ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_decode_path(xdr, &ptr->u.data))
 			return false;
 		break;
@@ -259,7 +261,7 @@ xdrgen_decode_readres(struct xdr_stream *xdr, struct readres *ptr)
 	if (!xdrgen_decode_nfsstat(xdr, &ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_decode_readresok(xdr, &ptr->u.readresok))
 			return false;
 		break;
@@ -374,7 +376,7 @@ xdrgen_decode_readdirres(struct xdr_stream *xdr, struct readdirres *ptr)
 	if (!xdrgen_decode_nfsstat(xdr, &ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_decode_readdirok(xdr, &ptr->u.readdirok))
 			return false;
 		break;
@@ -406,7 +408,7 @@ xdrgen_decode_statfsres(struct xdr_stream *xdr, struct statfsres *ptr)
 	if (!xdrgen_decode_nfsstat(xdr, &ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_decode_info(xdr, &ptr->u.info))
 			return false;
 		break;
@@ -579,7 +581,7 @@ bool nfs_svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 static bool __maybe_unused
 xdrgen_encode_nfsstat(struct xdr_stream *xdr, nfsstat value)
 {
-	return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+	return xdr_stream_encode_be32(xdr, value) == XDR_UNIT;
 }
 
 static bool __maybe_unused
@@ -680,7 +682,7 @@ xdrgen_encode_attrstat(struct xdr_stream *xdr, const struct attrstat *ptr)
 	if (!xdrgen_encode_nfsstat(xdr, ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_encode_fattr(xdr, &ptr->u.attributes))
 			return false;
 		break;
@@ -716,7 +718,7 @@ xdrgen_encode_diropres(struct xdr_stream *xdr, const struct diropres *ptr)
 	if (!xdrgen_encode_nfsstat(xdr, ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_encode_diropok(xdr, &ptr->u.diropok))
 			return false;
 		break;
@@ -742,7 +744,7 @@ xdrgen_encode_readlinkres(struct xdr_stream *xdr, const struct readlinkres *ptr)
 	if (!xdrgen_encode_nfsstat(xdr, ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_encode_path(xdr, ptr->u.data))
 			return false;
 		break;
@@ -784,7 +786,7 @@ xdrgen_encode_readres(struct xdr_stream *xdr, const struct readres *ptr)
 	if (!xdrgen_encode_nfsstat(xdr, ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_encode_readresok(xdr, &ptr->u.readresok))
 			return false;
 		break;
@@ -899,7 +901,7 @@ xdrgen_encode_readdirres(struct xdr_stream *xdr, const struct readdirres *ptr)
 	if (!xdrgen_encode_nfsstat(xdr, ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_encode_readdirok(xdr, &ptr->u.readdirok))
 			return false;
 		break;
@@ -931,7 +933,7 @@ xdrgen_encode_statfsres(struct xdr_stream *xdr, const struct statfsres *ptr)
 	if (!xdrgen_encode_nfsstat(xdr, ptr->status))
 		return false;
 	switch (ptr->status) {
-	case NFS_OK:
+	case __constant_cpu_to_be32(NFS_OK):
 		if (!xdrgen_encode_info(xdr, &ptr->u.info))
 			return false;
 		break;
diff --git a/fs/nfsd/nfs2xdr_gen.h b/fs/nfsd/nfs2xdr_gen.h
index df800e42b80e..150f4215dbe3 100644
--- a/fs/nfsd/nfs2xdr_gen.h
+++ b/fs/nfsd/nfs2xdr_gen.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs2.x */
-/* XDR specification modification time: Tue Sep  8 11:23:43 2026 */
+/* XDR specification modification time: Tue Sep  8 11:24:48 2026 */
 
 #ifndef _LINUX_XDRGEN_NFS2_DECL_H
 #define _LINUX_XDRGEN_NFS2_DECL_H
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0a1c184217e0..0196a554de5e 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -9,6 +9,9 @@
 #include <linux/sunrpc/svc.h>
 
 #include "nfs2xdr_gen.h"
+
+#include "auth.h"
+#include "nfsd.h"
 #include "cache.h"
 #include "xdr.h"
 #include "vfs.h"
@@ -17,6 +20,26 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
+/*
+ * Wrapper structures combine xdrgen types with legacy structures.
+ * The xdrgen field must be first so the structure can be cast
+ * to its XDR type for the RPC dispatch layer.
+ */
+
+struct fhandle_wrapper {
+	fhandle			xdrgen;
+	struct svc_fh		fh;
+};
+
+static_assert(offsetof(struct fhandle_wrapper, xdrgen) == 0);
+
+struct attrstat_wrapper {
+	struct attrstat		xdrgen;
+	struct kstat		stat;
+};
+
+static_assert(offsetof(struct attrstat_wrapper, xdrgen) == 0);
+
 static __be32 nfsd_map_status(__be32 status)
 {
 	switch (status) {
@@ -42,6 +65,88 @@ static __be32 nfsd_map_status(__be32 status)
 	return status;
 }
 
+static __always_inline void
+nfsd_fhandle_to_svc_fh(struct svc_fh *fhp, const fhandle *fhandle)
+{
+	fh_init(fhp, NFS_FHSIZE);
+	fhp->fh_handle.fh_size = NFS_FHSIZE;
+	memcpy(&fhp->fh_handle.fh_raw, fhandle, NFS_FHSIZE);
+}
+
+static __always_inline void
+nfsd_timespec64_to_timeval(struct timeval *dst,
+			   const struct timespec64 *src)
+{
+	dst->seconds = src->tv_sec;
+	dst->useconds = src->tv_nsec / NSEC_PER_USEC;
+}
+
+static u32
+nfsd_mode_to_ftype(umode_t mode)
+{
+	switch (mode & S_IFMT) {
+	case S_IFREG:  return NFREG;
+	case S_IFDIR:  return NFDIR;
+	case S_IFBLK:  return NFBLK;
+	case S_IFCHR:  return NFCHR;
+	case S_IFLNK:  return NFLNK;
+	/*
+	 * The NFSv2 protocol's ftype enum does not provide specific values
+	 * for sockets and FIFOs.
+	 */
+	case S_IFSOCK: return NFNON;
+	case S_IFIFO:  return NFNON;
+	}
+	return NFNON;
+}
+
+static void
+nfsd_stat_to_fattr(struct svc_rqst *rqstp, struct fattr *fattr,
+		   const struct kstat *stat, const struct svc_fh *fhp)
+{
+	struct user_namespace *userns = nfsd_user_namespace(rqstp);
+	struct timespec64 time;
+	u32 fsid;
+
+	fattr->type = nfsd_mode_to_ftype(stat->mode);
+	fattr->mode = stat->mode;
+	fattr->nlink = stat->nlink;
+	fattr->uid = from_kuid_munged(userns, stat->uid);
+	fattr->gid = from_kgid_munged(userns, stat->gid);
+	if (S_ISLNK(stat->mode) && stat->size > NFS_MAXPATHLEN)
+		fattr->size = NFS_MAXPATHLEN;
+	else
+		fattr->size = stat->size;
+	fattr->blocksize = stat->blksize;
+	if (S_ISCHR(stat->mode) || S_ISBLK(stat->mode))
+		fattr->rdev = new_encode_dev(stat->rdev);
+	else
+		fattr->rdev = 0xffffffff;
+	fattr->blocks = stat->blocks;
+
+	switch (fsid_source(fhp)) {
+	case FSIDSOURCE_FSID:
+		fsid = (u32)fhp->fh_export->ex_fsid;
+		break;
+	case FSIDSOURCE_UUID:
+		fsid = ((u32 *)fhp->fh_export->ex_uuid)[0];
+		fsid ^= ((u32 *)fhp->fh_export->ex_uuid)[1];
+		fsid ^= ((u32 *)fhp->fh_export->ex_uuid)[2];
+		fsid ^= ((u32 *)fhp->fh_export->ex_uuid)[3];
+		break;
+	default:
+		fsid = new_encode_dev(stat->dev);
+	}
+	fattr->fsid = fsid;
+	fattr->fileid = stat->ino;
+
+	nfsd_timespec64_to_timeval(&fattr->atime, &stat->atime);
+	time = stat->mtime;
+	lease_get_mtime(d_inode(fhp->fh_dentry), &time);
+	nfsd_timespec64_to_timeval(&fattr->mtime, &time);
+	nfsd_timespec64_to_timeval(&fattr->ctime, &stat->ctime);
+}
+
 /*
  * Because NFSv2 does not have an NFSERR_SYMLINK, Solaris returns
  * NFSERR_ISDIR when the target of a READ or WRITE is any object
@@ -77,26 +182,39 @@ static __be32 nfsd_proc_null(struct svc_rqst *rqstp)
 	return rpc_success;
 }
 
-/*
- * Get a file's attributes
- * N.B. After this call resp->fh needs an fh_put
+/**
+ * nfsd_proc_getattr - GETATTR: Get file attributes
+ * @rqstp: RPC transaction context
+ *
+ * Return:
+ *   %rpc_success:		RPC executed successfully
+ *
+ * RPC synopsis:
+ *   attrstat NFSPROC_GETATTR(fhandle) = 1;
  */
-static __be32
-nfsd_proc_getattr(struct svc_rqst *rqstp)
+static __be32 nfsd_proc_getattr(struct svc_rqst *rqstp)
 {
-	struct nfsd_fhandle *argp = rqstp->rq_argp;
-	struct nfsd_attrstat *resp = rqstp->rq_resp;
+	struct fhandle_wrapper *argp = rqstp->rq_argp;
+	struct attrstat_wrapper *resp = rqstp->rq_resp;
+	struct kstat *statp = &resp->stat;
+	struct svc_fh *fhp = &argp->fh;
 
-	trace_nfsd_vfs_getattr(rqstp, &argp->fh);
-
-	fh_copy(&resp->fh, &argp->fh);
-	resp->status = fh_verify(rqstp, &resp->fh, 0,
-				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
-	if (resp->status != nfs_ok)
+	nfsd_fhandle_to_svc_fh(fhp, &argp->xdrgen);
+	trace_nfsd_vfs_getattr(rqstp, fhp);
+	resp->xdrgen.status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP |
+					NFSD_MAY_BYPASS_GSS_ON_ROOT);
+	if (resp->xdrgen.status != nfs_ok)
 		goto out;
-	resp->status = fh_getattr(&resp->fh, &resp->stat);
+
+	resp->xdrgen.status = fh_getattr(fhp, statp);
+
 out:
-	resp->status = nfsd_map_status(resp->status);
+	if (resp->xdrgen.status == nfs_ok)
+		nfsd_stat_to_fattr(rqstp, &resp->xdrgen.u.attributes, statp, fhp);
+	else
+		resp->xdrgen.status = nfsd_map_status(resp->xdrgen.status);
+
+	fh_put(fhp);
 	return rpc_success;
 }
 
@@ -698,16 +816,15 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_name	= "NULL",
 	},
 	[NFSPROC_GETATTR] = {
-		.pc_func = nfsd_proc_getattr,
-		.pc_decode = nfssvc_decode_fhandleargs,
-		.pc_encode = nfssvc_encode_attrstatres,
-		.pc_release = nfssvc_release_attrstat,
-		.pc_argsize = sizeof(struct nfsd_fhandle),
-		.pc_argzero = sizeof(struct nfsd_fhandle),
-		.pc_ressize = sizeof(struct nfsd_attrstat),
-		.pc_cachetype = RC_NOCACHE,
-		.pc_xdrressize = ST+AT,
-		.pc_name = "GETATTR",
+		.pc_func	= nfsd_proc_getattr,
+		.pc_decode	= nfs_svc_decode_fhandle,
+		.pc_encode	= nfs_svc_encode_attrstat,
+		.pc_argsize	= sizeof(struct fhandle_wrapper),
+		.pc_argzero	= 0,
+		.pc_ressize	= sizeof(struct attrstat_wrapper),
+		.pc_cachetype	= RC_NOCACHE,
+		.pc_xdrressize	= NFS2_attrstat_sz,
+		.pc_name	= "GETATTR",
 	},
 	[NFSPROC_SETATTR] = {
 		.pc_func = nfsd_proc_setattr,
@@ -896,6 +1013,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
  * Storage requirements for XDR arguments and results.
  */
 union nfsd_xdrstore {
+	struct fhandle_wrapper		fhandle;
 	struct nfsd_sattrargs	sattr;
 	struct nfsd_diropargs	dirop;
 	struct nfsd_readargs	read;
@@ -905,7 +1023,7 @@ union nfsd_xdrstore {
 	struct nfsd_linkargs	link;
 	struct nfsd_symlinkargs	symlink;
 	struct nfsd_readdirargs	readdir;
-	struct nfsd_attrstat	attrstat;
+	struct attrstat_wrapper		attrstat;
 	struct nfsd_diropres	diropres;
 	struct nfsd_readlinkres	readlinkres;
 	struct nfsd_readres	readres;
diff --git a/include/linux/sunrpc/xdrgen/nfs2.h b/include/linux/sunrpc/xdrgen/nfs2.h
index 4a022b670b0c..7e3af2ad90a7 100644
--- a/include/linux/sunrpc/xdrgen/nfs2.h
+++ b/include/linux/sunrpc/xdrgen/nfs2.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs2.x */
-/* XDR specification modification time: Tue Sep  8 11:23:43 2026 */
+/* XDR specification modification time: Tue Sep  8 11:24:48 2026 */
 
 #ifndef _LINUX_XDRGEN_NFS2_DEF_H
 #define _LINUX_XDRGEN_NFS2_DEF_H
@@ -40,7 +40,7 @@ enum nfsstat {
 	NFSERR_WFLUSH = 99,
 };
 
-typedef enum nfsstat nfsstat;
+typedef __be32 nfsstat;
 
 enum ftype {
 	NFNON = 0,
-- 
2.55.0


  parent reply	other threads:[~2026-09-16 16:29 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16 16:28 [PATCH v1 00/27] Convert server-side NFSv2 XDR to use xdrgen Chuck Lever
2026-09-16 16:28 ` [PATCH v1 01/27] Documentation: Add the RPC language description of NFSv2 Chuck Lever
2026-09-16 16:28 ` [PATCH v1 1/2] NFSD: map fh_verify() status codes for NFS_ACLv2 replies Chuck Lever
2026-09-17 11:57   ` Jeff Layton
2026-09-16 16:28 ` [PATCH v1 02/27] NFSD: Add infrastructure for generating NFSv2 XDR encoders and decoders Chuck Lever
2026-09-16 16:28 ` [PATCH v1 2/2] NFSD: map fh_verify() status codes for NFS_ACLv3 replies Chuck Lever
2026-09-17 11:57   ` Jeff Layton
2026-09-16 16:28 ` [PATCH v1 03/27] NFSD: Use xdrgen-generated NFSv2 protocol definitions Chuck Lever
2026-09-16 16:28 ` [PATCH v1 04/27] NFSD: Remove '#include "xdr.h"' from fs/nfsd/xdr3.h Chuck Lever
2026-09-16 16:28 ` [PATCH v1 05/27] NFSD: Relocate the NFSv2 XDR storage union into nfsproc.c Chuck Lever
2026-09-16 16:28 ` [PATCH v1 06/27] NFSD: Use xdrgen XDR functions for the NFSv2 NULL procedure Chuck Lever
2026-09-16 16:28 ` Chuck Lever [this message]
2026-09-16 16:28 ` [PATCH v1 08/27] NFSD: Use xdrgen XDR functions for NFSv2 SETATTR procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 09/27] NFSD: Use xdrgen XDR functions for the NFSv2 ROOT procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 10/27] NFSD: Use xdrgen XDR functions for the NFSv2 LOOKUP procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 11/27] NFSD: Use xdrgen XDR functions for NFSv2 READLINK procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 12/27] NFSD: Use xdrgen XDR functions for NFSv2 READ procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 13/27] NFSD: Use xdrgen XDR functions for the NFSv2 WRITECACHE procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 14/27] NFSD: Use xdrgen XDR functions for NFSv2 WRITE procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 15/27] NFSD: Refactor nfsd_proc_create() Chuck Lever
2026-09-16 16:28 ` [PATCH v1 16/27] NFSD: Use xdrgen XDR functions for NFSv2 CREATE procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 17/27] NFSD: Use xdrgen XDR functions for the NFSv2 REMOVE procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 18/27] NFSD: Use xdrgen XDR functions for the NFSv2 RENAME procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 19/27] NFSD: Use xdrgen XDR functions for the NFSv2 LINK procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 20/27] NFSD: Use xdrgen XDR functions for NFSv2 SYMLINK procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 21/27] NFSD: Use xdrgen XDR functions for NFSv2 MKDIR procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 22/27] NFSD: Use xdrgen XDR functions for NFSv2 RMDIR procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 23/27] NFSD: Use xdrgen XDR functions for the NFSv2 STATFS procedure Chuck Lever
2026-09-16 16:28 ` [PATCH v1 24/27] NFSD: Use xdrgen XDR functions for NFSv2 READDIR arguments Chuck Lever
2026-09-16 16:28 ` [PATCH v1 25/27] NFSD: Add a streaming directory reader Chuck Lever
2026-09-16 16:28 ` [PATCH v1 26/27] NFSD: Refactor NFSv2 directory cookie encoding Chuck Lever
2026-09-16 16:28 ` [PATCH v1 27/27] NFSD: Use xdrgen XDR functions for NFSv2 READDIR results Chuck Lever
2026-09-17 11:56 ` [PATCH v1 00/27] Convert server-side NFSv2 XDR to use xdrgen Jeff Layton
2026-09-17 14:57   ` Chuck Lever

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=20260916162859.2051-10-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