All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.