linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/11] nfsd_dispatch() clean up
@ 2020-09-29 14:03 Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 01/11] nfsd: rq_lease_breaker cleanup Chuck Lever
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:03 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Hi Bruce-

I've tested the latest version of your rq_lease_breaker patch plus
my nfsd_dispatch() clean ups and haven't found any new issues.

Changes since v1:
- Pulled in latest version of rq_lease_breaker cleanup
- Added patches to make NFSv2 error encoding similar to NFSv3
- Clarified nfsd_dispatch's new documenting comment
- Renamed a variable

---

Chuck Lever (10):
      lockd: Replace PROC() macro with open code
      NFSACL: Replace PROC() macro with open code
      NFSD: Encoder and decoder functions are always present
      NFSD: Clean up switch statement in nfsd_dispatch()
      NFSD: Clean up stale comments in nfsd_dispatch()
      NFSD: Clean up nfsd_dispatch() variables
      NFSD: Refactor nfsd_dispatch() error paths
      NFSD: Set *statp in success path
      NFSD: Fix .pc_release method for NFSv2
      NFSD: Call NFSv2 encoders on error returns

J. Bruce Fields (1):
      nfsd: rq_lease_breaker cleanup


 fs/lockd/svc4proc.c         | 242 +++++++++++++++++++++++++++--------
 fs/lockd/svcproc.c          | 244 ++++++++++++++++++++++++++++--------
 fs/nfsd/nfs2acl.c           |  87 +++++++++----
 fs/nfsd/nfs3acl.c           |  50 +++++---
 fs/nfsd/nfs3proc.c          |   1 +
 fs/nfsd/nfs3xdr.c           |   6 +
 fs/nfsd/nfs4proc.c          |   1 +
 fs/nfsd/nfs4xdr.c           |   6 +
 fs/nfsd/nfsproc.c           | 173 ++++++++++++-------------
 fs/nfsd/nfssvc.c            | 109 ++++++++--------
 fs/nfsd/nfsxdr.c            |  37 +++++-
 fs/nfsd/xdr.h               |  11 +-
 fs/nfsd/xdr3.h              |   1 +
 fs/nfsd/xdr4.h              |   1 +
 include/uapi/linux/nfsacl.h |   2 +
 15 files changed, 691 insertions(+), 280 deletions(-)

--
Chuck Lever


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 01/11] nfsd: rq_lease_breaker cleanup
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
@ 2020-09-29 14:03 ` Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 02/11] lockd: Replace PROC() macro with open code Chuck Lever
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:03 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

From: J. Bruce Fields <bfields@redhat.com>

Since only the v4 code cares about it, maybe it's better to leave
rq_lease_breaker out of the common dispatch code?

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
---
 fs/nfsd/nfs4state.c |    3 ++-
 fs/nfsd/nfssvc.c    |    1 -
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 767dc1b27e91..603c0a227a64 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4601,7 +4601,8 @@ static bool nfsd_breaker_owns_lease(struct file_lock *fl)
 	if (!i_am_nfsd())
 		return NULL;
 	rqst = kthread_data(current);
-	if (!rqst->rq_lease_breaker)
+	/* Note rq_prog == NFS_ACL_PROGRAM is also possible: */
+	if (rqst->rq_prog != NFS_PROGRAM || rqst->rq_vers < 4)
 		return NULL;
 	clp = *(rqst->rq_lease_breaker);
 	return dl->dl_stid.sc_client == clp;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index f7f6473578af..f6bc94cab9da 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1016,7 +1016,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 		*statp = rpc_garbage_args;
 		return 1;
 	}
-	rqstp->rq_lease_breaker = NULL;
 	/*
 	 * Give the xdr decoder a chance to change this if it wants
 	 * (necessary in the NFSv4.0 compound case)



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 02/11] lockd: Replace PROC() macro with open code
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 01/11] nfsd: rq_lease_breaker cleanup Chuck Lever
@ 2020-09-29 14:03 ` Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 03/11] NFSACL: " Chuck Lever
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:03 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Clean up: Follow-up on ten-year-old commit b9081d90f5b9 ("NFS: kill
off complicated macro 'PROC'") by performing the same conversion in
the lockd code. To reduce the chance of error, I copied the original
C preprocessor output and then made some minor edits.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/lockd/svc4proc.c |  242 ++++++++++++++++++++++++++++++++++++++++-----------
 fs/lockd/svcproc.c  |  244 ++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 386 insertions(+), 100 deletions(-)

diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index e4d3f783e06a..9913b823a5e7 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -491,60 +491,204 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
  * NLM Server procedures.
  */
 
-#define nlm4svc_encode_norep	nlm4svc_encode_void
-#define nlm4svc_decode_norep	nlm4svc_decode_void
-#define nlm4svc_decode_testres	nlm4svc_decode_void
-#define nlm4svc_decode_lockres	nlm4svc_decode_void
-#define nlm4svc_decode_unlockres	nlm4svc_decode_void
-#define nlm4svc_decode_cancelres	nlm4svc_decode_void
-#define nlm4svc_decode_grantedres	nlm4svc_decode_void
-
-#define nlm4svc_proc_none	nlm4svc_proc_null
-#define nlm4svc_proc_test_res	nlm4svc_proc_null
-#define nlm4svc_proc_lock_res	nlm4svc_proc_null
-#define nlm4svc_proc_cancel_res	nlm4svc_proc_null
-#define nlm4svc_proc_unlock_res	nlm4svc_proc_null
-
 struct nlm_void			{ int dummy; };
 
-#define PROC(name, xargt, xrest, argt, rest, respsize)	\
- { .pc_func	= nlm4svc_proc_##name,	\
-   .pc_decode	= nlm4svc_decode_##xargt,	\
-   .pc_encode	= nlm4svc_encode_##xrest,	\
-   .pc_release	= NULL,					\
-   .pc_argsize	= sizeof(struct nlm_##argt),		\
-   .pc_ressize	= sizeof(struct nlm_##rest),		\
-   .pc_xdrressize = respsize,				\
- }
 #define	Ck	(1+XDR_QUADLEN(NLM_MAXCOOKIELEN))	/* cookie */
 #define	No	(1+1024/4)				/* netobj */
 #define	St	1					/* status */
 #define	Rg	4					/* range (offset + length) */
-const struct svc_procedure nlmsvc_procedures4[] = {
-  PROC(null,		void,		void,		void,	void, 1),
-  PROC(test,		testargs,	testres,	args,	res, Ck+St+2+No+Rg),
-  PROC(lock,		lockargs,	res,		args,	res, Ck+St),
-  PROC(cancel,		cancargs,	res,		args,	res, Ck+St),
-  PROC(unlock,		unlockargs,	res,		args,	res, Ck+St),
-  PROC(granted,		testargs,	res,		args,	res, Ck+St),
-  PROC(test_msg,	testargs,	norep,		args,	void, 1),
-  PROC(lock_msg,	lockargs,	norep,		args,	void, 1),
-  PROC(cancel_msg,	cancargs,	norep,		args,	void, 1),
-  PROC(unlock_msg,	unlockargs,	norep,		args,	void, 1),
-  PROC(granted_msg,	testargs,	norep,		args,	void, 1),
-  PROC(test_res,	testres,	norep,		res,	void, 1),
-  PROC(lock_res,	lockres,	norep,		res,	void, 1),
-  PROC(cancel_res,	cancelres,	norep,		res,	void, 1),
-  PROC(unlock_res,	unlockres,	norep,		res,	void, 1),
-  PROC(granted_res,	res,		norep,		res,	void, 1),
-  /* statd callback */
-  PROC(sm_notify,	reboot,		void,		reboot,	void, 1),
-  PROC(none,		void,		void,		void,	void, 0),
-  PROC(none,		void,		void,		void,	void, 0),
-  PROC(none,		void,		void,		void,	void, 0),
-  PROC(share,		shareargs,	shareres,	args,	res, Ck+St+1),
-  PROC(unshare,		shareargs,	shareres,	args,	res, Ck+St+1),
-  PROC(nm_lock,		lockargs,	res,		args,	res, Ck+St),
-  PROC(free_all,	notify,		void,		args,	void, 1),
 
+const struct svc_procedure nlmsvc_procedures4[24] = {
+	[NLMPROC_NULL] = {
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_TEST] = {
+		.pc_func = nlm4svc_proc_test,
+		.pc_decode = nlm4svc_decode_testargs,
+		.pc_encode = nlm4svc_encode_testres,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St+2+No+Rg,
+	},
+	[NLMPROC_LOCK] = {
+		.pc_func = nlm4svc_proc_lock,
+		.pc_decode = nlm4svc_decode_lockargs,
+		.pc_encode = nlm4svc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_CANCEL] = {
+		.pc_func = nlm4svc_proc_cancel,
+		.pc_decode = nlm4svc_decode_cancargs,
+		.pc_encode = nlm4svc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_UNLOCK] = {
+		.pc_func = nlm4svc_proc_unlock,
+		.pc_decode = nlm4svc_decode_unlockargs,
+		.pc_encode = nlm4svc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_GRANTED] = {
+		.pc_func = nlm4svc_proc_granted,
+		.pc_decode = nlm4svc_decode_testargs,
+		.pc_encode = nlm4svc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_TEST_MSG] = {
+		.pc_func = nlm4svc_proc_test_msg,
+		.pc_decode = nlm4svc_decode_testargs,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_LOCK_MSG] = {
+		.pc_func = nlm4svc_proc_lock_msg,
+		.pc_decode = nlm4svc_decode_lockargs,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_CANCEL_MSG] = {
+		.pc_func = nlm4svc_proc_cancel_msg,
+		.pc_decode = nlm4svc_decode_cancargs,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_UNLOCK_MSG] = {
+		.pc_func = nlm4svc_proc_unlock_msg,
+		.pc_decode = nlm4svc_decode_unlockargs,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_GRANTED_MSG] = {
+		.pc_func = nlm4svc_proc_granted_msg,
+		.pc_decode = nlm4svc_decode_testargs,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_TEST_RES] = {
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_LOCK_RES] = {
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_CANCEL_RES] = {
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_UNLOCK_RES] = {
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_GRANTED_RES] = {
+		.pc_func = nlm4svc_proc_granted_res,
+		.pc_decode = nlm4svc_decode_res,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_NSM_NOTIFY] = {
+		.pc_func = nlm4svc_proc_sm_notify,
+		.pc_decode = nlm4svc_decode_reboot,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_reboot),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[17] = { /* unused procedure */
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = 0,
+	},
+	[18] = { /* unused procedure */
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = 0,
+	},
+	[19] = { /* unused procedure */
+		.pc_func = nlm4svc_proc_null,
+		.pc_decode = nlm4svc_decode_void,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = 0,
+	},
+	[NLMPROC_SHARE] = {
+		.pc_func = nlm4svc_proc_share,
+		.pc_decode = nlm4svc_decode_shareargs,
+		.pc_encode = nlm4svc_encode_shareres,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St+1,
+	},
+	[NLMPROC_UNSHARE] = {
+		.pc_func = nlm4svc_proc_unshare,
+		.pc_decode = nlm4svc_decode_shareargs,
+		.pc_encode = nlm4svc_encode_shareres,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St+1,
+	},
+	[NLMPROC_NM_LOCK] = {
+		.pc_func = nlm4svc_proc_nm_lock,
+		.pc_decode = nlm4svc_decode_lockargs,
+		.pc_encode = nlm4svc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_FREE_ALL] = {
+		.pc_func = nlm4svc_proc_free_all,
+		.pc_decode = nlm4svc_decode_notify,
+		.pc_encode = nlm4svc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
 };
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index d0bb7a6bf005..dbcfa67a36b1 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -533,62 +533,204 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
  * NLM Server procedures.
  */
 
-#define nlmsvc_encode_norep	nlmsvc_encode_void
-#define nlmsvc_decode_norep	nlmsvc_decode_void
-#define nlmsvc_decode_testres	nlmsvc_decode_void
-#define nlmsvc_decode_lockres	nlmsvc_decode_void
-#define nlmsvc_decode_unlockres	nlmsvc_decode_void
-#define nlmsvc_decode_cancelres	nlmsvc_decode_void
-#define nlmsvc_decode_grantedres	nlmsvc_decode_void
-
-#define nlmsvc_proc_none	nlmsvc_proc_null
-#define nlmsvc_proc_test_res	nlmsvc_proc_null
-#define nlmsvc_proc_lock_res	nlmsvc_proc_null
-#define nlmsvc_proc_cancel_res	nlmsvc_proc_null
-#define nlmsvc_proc_unlock_res	nlmsvc_proc_null
-
 struct nlm_void			{ int dummy; };
 
-#define PROC(name, xargt, xrest, argt, rest, respsize)	\
- { .pc_func	= nlmsvc_proc_##name,			\
-   .pc_decode	= nlmsvc_decode_##xargt,		\
-   .pc_encode	= nlmsvc_encode_##xrest,		\
-   .pc_release	= NULL,					\
-   .pc_argsize	= sizeof(struct nlm_##argt),		\
-   .pc_ressize	= sizeof(struct nlm_##rest),		\
-   .pc_xdrressize = respsize,				\
- }
-
 #define	Ck	(1+XDR_QUADLEN(NLM_MAXCOOKIELEN))	/* cookie */
 #define	St	1				/* status */
 #define	No	(1+1024/4)			/* Net Obj */
 #define	Rg	2				/* range - offset + size */
 
-const struct svc_procedure nlmsvc_procedures[] = {
-  PROC(null,		void,		void,		void,	void, 1),
-  PROC(test,		testargs,	testres,	args,	res, Ck+St+2+No+Rg),
-  PROC(lock,		lockargs,	res,		args,	res, Ck+St),
-  PROC(cancel,		cancargs,	res,		args,	res, Ck+St),
-  PROC(unlock,		unlockargs,	res,		args,	res, Ck+St),
-  PROC(granted,		testargs,	res,		args,	res, Ck+St),
-  PROC(test_msg,	testargs,	norep,		args,	void, 1),
-  PROC(lock_msg,	lockargs,	norep,		args,	void, 1),
-  PROC(cancel_msg,	cancargs,	norep,		args,	void, 1),
-  PROC(unlock_msg,	unlockargs,	norep,		args,	void, 1),
-  PROC(granted_msg,	testargs,	norep,		args,	void, 1),
-  PROC(test_res,	testres,	norep,		res,	void, 1),
-  PROC(lock_res,	lockres,	norep,		res,	void, 1),
-  PROC(cancel_res,	cancelres,	norep,		res,	void, 1),
-  PROC(unlock_res,	unlockres,	norep,		res,	void, 1),
-  PROC(granted_res,	res,		norep,		res,	void, 1),
-  /* statd callback */
-  PROC(sm_notify,	reboot,		void,		reboot,	void, 1),
-  PROC(none,		void,		void,		void,	void, 1),
-  PROC(none,		void,		void,		void,	void, 1),
-  PROC(none,		void,		void,		void,	void, 1),
-  PROC(share,		shareargs,	shareres,	args,	res, Ck+St+1),
-  PROC(unshare,		shareargs,	shareres,	args,	res, Ck+St+1),
-  PROC(nm_lock,		lockargs,	res,		args,	res, Ck+St),
-  PROC(free_all,	notify,		void,		args,	void, 0),
-
+const struct svc_procedure nlmsvc_procedures[24] = {
+	[NLMPROC_NULL] = {
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_TEST] = {
+		.pc_func = nlmsvc_proc_test,
+		.pc_decode = nlmsvc_decode_testargs,
+		.pc_encode = nlmsvc_encode_testres,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St+2+No+Rg,
+	},
+	[NLMPROC_LOCK] = {
+		.pc_func = nlmsvc_proc_lock,
+		.pc_decode = nlmsvc_decode_lockargs,
+		.pc_encode = nlmsvc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_CANCEL] = {
+		.pc_func = nlmsvc_proc_cancel,
+		.pc_decode = nlmsvc_decode_cancargs,
+		.pc_encode = nlmsvc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_UNLOCK] = {
+		.pc_func = nlmsvc_proc_unlock,
+		.pc_decode = nlmsvc_decode_unlockargs,
+		.pc_encode = nlmsvc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_GRANTED] = {
+		.pc_func = nlmsvc_proc_granted,
+		.pc_decode = nlmsvc_decode_testargs,
+		.pc_encode = nlmsvc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_TEST_MSG] = {
+		.pc_func = nlmsvc_proc_test_msg,
+		.pc_decode = nlmsvc_decode_testargs,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_LOCK_MSG] = {
+		.pc_func = nlmsvc_proc_lock_msg,
+		.pc_decode = nlmsvc_decode_lockargs,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_CANCEL_MSG] = {
+		.pc_func = nlmsvc_proc_cancel_msg,
+		.pc_decode = nlmsvc_decode_cancargs,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_UNLOCK_MSG] = {
+		.pc_func = nlmsvc_proc_unlock_msg,
+		.pc_decode = nlmsvc_decode_unlockargs,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_GRANTED_MSG] = {
+		.pc_func = nlmsvc_proc_granted_msg,
+		.pc_decode = nlmsvc_decode_testargs,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_TEST_RES] = {
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_LOCK_RES] = {
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_CANCEL_RES] = {
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_UNLOCK_RES] = {
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_GRANTED_RES] = {
+		.pc_func = nlmsvc_proc_granted_res,
+		.pc_decode = nlmsvc_decode_res,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_res),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_NSM_NOTIFY] = {
+		.pc_func = nlmsvc_proc_sm_notify,
+		.pc_decode = nlmsvc_decode_reboot,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_reboot),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[17] = { /* unused procedure */
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[18] = { /* unused procedure */
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[19] = { /* unused procedure */
+		.pc_func = nlmsvc_proc_null,
+		.pc_decode = nlmsvc_decode_void,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_void),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = St,
+	},
+	[NLMPROC_SHARE] = {
+		.pc_func = nlmsvc_proc_share,
+		.pc_decode = nlmsvc_decode_shareargs,
+		.pc_encode = nlmsvc_encode_shareres,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St+1,
+	},
+	[NLMPROC_UNSHARE] = {
+		.pc_func = nlmsvc_proc_unshare,
+		.pc_decode = nlmsvc_decode_shareargs,
+		.pc_encode = nlmsvc_encode_shareres,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St+1,
+	},
+	[NLMPROC_NM_LOCK] = {
+		.pc_func = nlmsvc_proc_nm_lock,
+		.pc_decode = nlmsvc_decode_lockargs,
+		.pc_encode = nlmsvc_encode_res,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_res),
+		.pc_xdrressize = Ck+St,
+	},
+	[NLMPROC_FREE_ALL] = {
+		.pc_func = nlmsvc_proc_free_all,
+		.pc_decode = nlmsvc_decode_notify,
+		.pc_encode = nlmsvc_encode_void,
+		.pc_argsize = sizeof(struct nlm_args),
+		.pc_ressize = sizeof(struct nlm_void),
+		.pc_xdrressize = 0,
+	},
 };



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 03/11] NFSACL: Replace PROC() macro with open code
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 01/11] nfsd: rq_lease_breaker cleanup Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 02/11] lockd: Replace PROC() macro with open code Chuck Lever
@ 2020-09-29 14:03 ` Chuck Lever
  2020-09-29 14:03 ` [PATCH v2 04/11] NFSD: Encoder and decoder functions are always present Chuck Lever
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:03 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Clean up: Follow-up on ten-year-old commit b9081d90f5b9 ("NFS: kill
off complicated macro 'PROC'") by performing the same conversion in
the NFSACL code. To reduce the chance of error, I copied the original
C preprocessor output and then made some minor edits.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c           |   72 +++++++++++++++++++++++++++++--------------
 fs/nfsd/nfs3acl.c           |   49 +++++++++++++++++------------
 include/uapi/linux/nfsacl.h |    2 +
 3 files changed, 80 insertions(+), 43 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index cbab1d2d8a75..8d20e0d74417 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -347,36 +347,62 @@ static void nfsaclsvc_release_access(struct svc_rqst *rqstp)
 	fh_put(&resp->fh);
 }
 
-#define nfsaclsvc_decode_voidargs	NULL
-#define nfsaclsvc_release_void		NULL
-#define nfsd3_fhandleargs	nfsd_fhandle
-#define nfsd3_attrstatres	nfsd_attrstat
-#define nfsd3_voidres		nfsd3_voidargs
 struct nfsd3_voidargs { int dummy; };
 
-#define PROC(name, argt, rest, relt, cache, respsize)			\
-{									\
-	.pc_func	= nfsacld_proc_##name,				\
-	.pc_decode	= nfsaclsvc_decode_##argt##args,		\
-	.pc_encode	= nfsaclsvc_encode_##rest##res,			\
-	.pc_release	= nfsaclsvc_release_##relt,	\
-	.pc_argsize	= sizeof(struct nfsd3_##argt##args),		\
-	.pc_ressize	= sizeof(struct nfsd3_##rest##res),		\
-	.pc_cachetype	= cache,					\
-	.pc_xdrressize	= respsize,					\
-}
-
 #define ST 1		/* status*/
 #define AT 21		/* attributes */
 #define pAT (1+AT)	/* post attributes - conditional */
 #define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
 
-static const struct svc_procedure nfsd_acl_procedures2[] = {
-  PROC(null,	void,		void,		void,	  RC_NOCACHE, ST),
-  PROC(getacl,	getacl,		getacl,		getacl,	  RC_NOCACHE, ST+1+2*(1+ACL)),
-  PROC(setacl,	setacl,		attrstat,	attrstat, RC_NOCACHE, ST+AT),
-  PROC(getattr, fhandle,	attrstat,	attrstat, RC_NOCACHE, ST+AT),
-  PROC(access,	access,		access,		access,   RC_NOCACHE, ST+AT+1),
+static const struct svc_procedure nfsd_acl_procedures2[5] = {
+	[ACLPROC2_NULL] = {
+		.pc_func = nfsacld_proc_null,
+		.pc_encode = nfsaclsvc_encode_voidres,
+		.pc_argsize = sizeof(struct nfsd3_voidargs),
+		.pc_ressize = sizeof(struct nfsd3_voidargs),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST,
+	},
+	[ACLPROC2_GETACL] = {
+		.pc_func = nfsacld_proc_getacl,
+		.pc_decode = nfsaclsvc_decode_getaclargs,
+		.pc_encode = nfsaclsvc_encode_getaclres,
+		.pc_release = nfsaclsvc_release_getacl,
+		.pc_argsize = sizeof(struct nfsd3_getaclargs),
+		.pc_ressize = sizeof(struct nfsd3_getaclres),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST+1+2*(1+ACL),
+	},
+	[ACLPROC2_SETACL] = {
+		.pc_func = nfsacld_proc_setacl,
+		.pc_decode = nfsaclsvc_decode_setaclargs,
+		.pc_encode = nfsaclsvc_encode_attrstatres,
+		.pc_release = nfsaclsvc_release_attrstat,
+		.pc_argsize = sizeof(struct nfsd3_setaclargs),
+		.pc_ressize = sizeof(struct nfsd_attrstat),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST+AT,
+	},
+	[ACLPROC2_GETATTR] = {
+		.pc_func = nfsacld_proc_getattr,
+		.pc_decode = nfsaclsvc_decode_fhandleargs,
+		.pc_encode = nfsaclsvc_encode_attrstatres,
+		.pc_release = nfsaclsvc_release_attrstat,
+		.pc_argsize = sizeof(struct nfsd_fhandle),
+		.pc_ressize = sizeof(struct nfsd_attrstat),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST+AT,
+	},
+	[ACLPROC2_ACCESS] = {
+		.pc_func = nfsacld_proc_access,
+		.pc_decode = nfsaclsvc_decode_accessargs,
+		.pc_encode = nfsaclsvc_encode_accessres,
+		.pc_release = nfsaclsvc_release_access,
+		.pc_argsize = sizeof(struct nfsd3_accessargs),
+		.pc_ressize = sizeof(struct nfsd3_accessres),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST+AT+1,
+	},
 };
 
 static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 13bca4a2f89d..292acb2e529c 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -235,33 +235,42 @@ static void nfs3svc_release_getacl(struct svc_rqst *rqstp)
 	posix_acl_release(resp->acl_default);
 }
 
-#define nfs3svc_decode_voidargs		NULL
-#define nfs3svc_release_void		NULL
-#define nfsd3_setaclres			nfsd3_attrstat
-#define nfsd3_voidres			nfsd3_voidargs
 struct nfsd3_voidargs { int dummy; };
 
-#define PROC(name, argt, rest, relt, cache, respsize)			\
-{									\
-	.pc_func	= nfsd3_proc_##name,				\
-	.pc_decode	= nfs3svc_decode_##argt##args,			\
-	.pc_encode	= nfs3svc_encode_##rest##res,			\
-	.pc_release	= nfs3svc_release_##relt,			\
-	.pc_argsize	= sizeof(struct nfsd3_##argt##args),		\
-	.pc_ressize	= sizeof(struct nfsd3_##rest##res),		\
-	.pc_cachetype	= cache,					\
-	.pc_xdrressize	= respsize,					\
-}
-
 #define ST 1		/* status*/
 #define AT 21		/* attributes */
 #define pAT (1+AT)	/* post attributes - conditional */
 #define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
 
-static const struct svc_procedure nfsd_acl_procedures3[] = {
-  PROC(null,	void,		void,		void,	  RC_NOCACHE, ST),
-  PROC(getacl,	getacl,		getacl,		getacl,	  RC_NOCACHE, ST+1+2*(1+ACL)),
-  PROC(setacl,	setacl,		setacl,		fhandle,  RC_NOCACHE, ST+pAT),
+static const struct svc_procedure nfsd_acl_procedures3[3] = {
+	[ACLPROC3_NULL] = {
+		.pc_func = nfsd3_proc_null,
+		.pc_encode = nfs3svc_encode_voidres,
+		.pc_argsize = sizeof(struct nfsd3_voidargs),
+		.pc_ressize = sizeof(struct nfsd3_voidargs),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST,
+	},
+	[ACLPROC3_GETACL] = {
+		.pc_func = nfsd3_proc_getacl,
+		.pc_decode = nfs3svc_decode_getaclargs,
+		.pc_encode = nfs3svc_encode_getaclres,
+		.pc_release = nfs3svc_release_getacl,
+		.pc_argsize = sizeof(struct nfsd3_getaclargs),
+		.pc_ressize = sizeof(struct nfsd3_getaclres),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST+1+2*(1+ACL),
+	},
+	[ACLPROC3_SETACL] = {
+		.pc_func = nfsd3_proc_setacl,
+		.pc_decode = nfs3svc_decode_setaclargs,
+		.pc_encode = nfs3svc_encode_setaclres,
+		.pc_release = nfs3svc_release_fhandle,
+		.pc_argsize = sizeof(struct nfsd3_setaclargs),
+		.pc_ressize = sizeof(struct nfsd3_attrstat),
+		.pc_cachetype = RC_NOCACHE,
+		.pc_xdrressize = ST+pAT,
+	},
 };
 
 static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)];
diff --git a/include/uapi/linux/nfsacl.h b/include/uapi/linux/nfsacl.h
index ca9a8501ff30..2c2ad204d3b0 100644
--- a/include/uapi/linux/nfsacl.h
+++ b/include/uapi/linux/nfsacl.h
@@ -9,11 +9,13 @@
 
 #define NFS_ACL_PROGRAM	100227
 
+#define ACLPROC2_NULL		0
 #define ACLPROC2_GETACL		1
 #define ACLPROC2_SETACL		2
 #define ACLPROC2_GETATTR	3
 #define ACLPROC2_ACCESS		4
 
+#define ACLPROC3_NULL		0
 #define ACLPROC3_GETACL		1
 #define ACLPROC3_SETACL		2
 



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 04/11] NFSD: Encoder and decoder functions are always present
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (2 preceding siblings ...)
  2020-09-29 14:03 ` [PATCH v2 03/11] NFSACL: " Chuck Lever
@ 2020-09-29 14:03 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 05/11] NFSD: Clean up switch statement in nfsd_dispatch() Chuck Lever
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:03 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

nfsd_dispatch() is a hot path. Let's optimize the XDR method calls
for the by-far common case, which is that the methods are indeed
present.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c  |    6 ++++++
 fs/nfsd/nfs3acl.c  |    1 +
 fs/nfsd/nfs3proc.c |    1 +
 fs/nfsd/nfs3xdr.c  |    6 ++++++
 fs/nfsd/nfs4proc.c |    1 +
 fs/nfsd/nfs4xdr.c  |    6 ++++++
 fs/nfsd/nfssvc.c   |    5 ++---
 fs/nfsd/xdr3.h     |    1 +
 fs/nfsd/xdr4.h     |    1 +
 9 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 8d20e0d74417..3c8b9250dc4a 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -183,6 +183,11 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
 /*
  * XDR decode functions
  */
+static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
+{
+	return 1;
+}
+
 static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_getaclargs *argp = rqstp->rq_argp;
@@ -357,6 +362,7 @@ struct nfsd3_voidargs { int dummy; };
 static const struct svc_procedure nfsd_acl_procedures2[5] = {
 	[ACLPROC2_NULL] = {
 		.pc_func = nfsacld_proc_null,
+		.pc_decode = nfsaclsvc_decode_voidarg,
 		.pc_encode = nfsaclsvc_encode_voidres,
 		.pc_argsize = sizeof(struct nfsd3_voidargs),
 		.pc_ressize = sizeof(struct nfsd3_voidargs),
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 292acb2e529c..614168675c17 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -245,6 +245,7 @@ struct nfsd3_voidargs { int dummy; };
 static const struct svc_procedure nfsd_acl_procedures3[3] = {
 	[ACLPROC3_NULL] = {
 		.pc_func = nfsd3_proc_null,
+		.pc_decode = nfs3svc_decode_voidarg,
 		.pc_encode = nfs3svc_encode_voidres,
 		.pc_argsize = sizeof(struct nfsd3_voidargs),
 		.pc_ressize = sizeof(struct nfsd3_voidargs),
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 288bc76b4574..3d09959c7042 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -716,6 +716,7 @@ struct nfsd3_voidargs { int dummy; };
 static const struct svc_procedure nfsd_procedures3[22] = {
 	[NFS3PROC_NULL] = {
 		.pc_func = nfsd3_proc_null,
+		.pc_decode = nfs3svc_decode_voidarg,
 		.pc_encode = nfs3svc_encode_voidres,
 		.pc_argsize = sizeof(struct nfsd3_voidargs),
 		.pc_ressize = sizeof(struct nfsd3_voidres),
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index aae514d40b64..e540fd1a29d8 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -304,6 +304,12 @@ void fill_post_wcc(struct svc_fh *fhp)
 /*
  * XDR decode functions
  */
+int
+nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
+{
+	return 1;
+}
+
 int
 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
 {
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index eaf50eafa935..b99c050797db 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -3279,6 +3279,7 @@ struct nfsd4_voidargs { int dummy; };
 static const struct svc_procedure nfsd_procedures4[2] = {
 	[NFSPROC4_NULL] = {
 		.pc_func = nfsd4_proc_null,
+		.pc_decode = nfs4svc_decode_voidarg,
 		.pc_encode = nfs4svc_encode_voidres,
 		.pc_argsize = sizeof(struct nfsd4_voidargs),
 		.pc_ressize = sizeof(struct nfsd4_voidres),
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f14d90a95fe3..758d8154a5b3 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -5156,6 +5156,12 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp)
 	}
 }
 
+int
+nfs4svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
+{
+	return 1;
+}
+
 int
 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
 {
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index f6bc94cab9da..b2d20920a998 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1022,8 +1022,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	 */
 	rqstp->rq_cachetype = proc->pc_cachetype;
 	/* Decode arguments */
-	if (proc->pc_decode &&
-	    !proc->pc_decode(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base)) {
+	if (!proc->pc_decode(rqstp, (__be32 *)rqstp->rq_arg.head[0].iov_base)) {
 		dprintk("nfsd: failed to decode arguments!\n");
 		*statp = rpc_garbage_args;
 		return 1;
@@ -1062,7 +1061,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	 * For NFSv2, additional info is never returned in case of an error.
 	 */
 	if (!(nfserr && rqstp->rq_vers == 2)) {
-		if (proc->pc_encode && !proc->pc_encode(rqstp, nfserrp)) {
+		if (!proc->pc_encode(rqstp, nfserrp)) {
 			/* Failed to encode result. Release cache entry */
 			dprintk("nfsd: failed to encode result!\n");
 			nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 4155fd71714c..ae6fa6c9cb46 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -273,6 +273,7 @@ union nfsd3_xdrstore {
 
 #define NFS3_SVC_XDRSIZE		sizeof(union nfsd3_xdrstore)
 
+int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);
 int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 66499fb6b567..679d40af1bbb 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -781,6 +781,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 
 
 bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
+int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *);
 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *);
 int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *);
 int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *);



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 05/11] NFSD: Clean up switch statement in nfsd_dispatch()
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (3 preceding siblings ...)
  2020-09-29 14:03 ` [PATCH v2 04/11] NFSD: Encoder and decoder functions are always present Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 06/11] NFSD: Clean up stale comments " Chuck Lever
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Reorder the arms so the compiler places checks for the most frequent
cases first.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfssvc.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index b2d20920a998..3cdefb2294ce 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1030,12 +1030,12 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 
 	/* Check whether we have this call in the cache. */
 	switch (nfsd_cache_lookup(rqstp)) {
-	case RC_DROPIT:
-		return 0;
+	case RC_DOIT:
+		break;
 	case RC_REPLY:
 		return 1;
-	case RC_DOIT:;
-		/* do it */
+	case RC_DROPIT:
+		return 0;
 	}
 
 	/* need to grab the location to store the status, as



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 06/11] NFSD: Clean up stale comments in nfsd_dispatch()
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (4 preceding siblings ...)
  2020-09-29 14:04 ` [PATCH v2 05/11] NFSD: Clean up switch statement in nfsd_dispatch() Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 07/11] NFSD: Clean up nfsd_dispatch() variables Chuck Lever
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Add a documenting comment for the function. Remove comments that
simply describe obvious aspects of the code, but leave comments
that explain the differences in processing of each NFS version.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfssvc.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 3cdefb2294ce..9be2e14b3bca 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1000,8 +1000,18 @@ static bool nfs_request_too_big(struct svc_rqst *rqstp,
 	return rqstp->rq_arg.len > PAGE_SIZE;
 }
 
-int
-nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+/**
+ * nfsd_dispatch - Process an NFS or NFSACL Request
+ * @rqstp: incoming request
+ * @statp: pointer to location of accept_stat field in RPC Reply buffer
+ *
+ * This RPC dispatcher integrates the NFS server's duplicate reply cache.
+ *
+ * Return values:
+ *  %0: Processing complete; do not send a Reply
+ *  %1: Processing complete; send Reply in rqstp->rq_res
+ */
+int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
 	const struct svc_procedure *proc;
 	__be32			nfserr;
@@ -1021,14 +1031,12 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	 * (necessary in the NFSv4.0 compound case)
 	 */
 	rqstp->rq_cachetype = proc->pc_cachetype;
-	/* Decode arguments */
 	if (!proc->pc_decode(rqstp, (__be32 *)rqstp->rq_arg.head[0].iov_base)) {
 		dprintk("nfsd: failed to decode arguments!\n");
 		*statp = rpc_garbage_args;
 		return 1;
 	}
 
-	/* Check whether we have this call in the cache. */
 	switch (nfsd_cache_lookup(rqstp)) {
 	case RC_DOIT:
 		break;
@@ -1038,14 +1046,14 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 		return 0;
 	}
 
-	/* need to grab the location to store the status, as
-	 * nfsv4 does some encoding while processing 
+	/*
+	 * Need to grab the location to store the status, as
+	 * NFSv4 does some encoding while processing
 	 */
 	nfserrp = rqstp->rq_res.head[0].iov_base
 		+ rqstp->rq_res.head[0].iov_len;
 	rqstp->rq_res.head[0].iov_len += sizeof(__be32);
 
-	/* Now call the procedure handler, and encode NFS status. */
 	nfserr = proc->pc_func(rqstp);
 	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
 	if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) {
@@ -1057,12 +1065,11 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	if (rqstp->rq_proc != 0)
 		*nfserrp++ = nfserr;
 
-	/* Encode result.
+	/*
 	 * For NFSv2, additional info is never returned in case of an error.
 	 */
 	if (!(nfserr && rqstp->rq_vers == 2)) {
 		if (!proc->pc_encode(rqstp, nfserrp)) {
-			/* Failed to encode result. Release cache entry */
 			dprintk("nfsd: failed to encode result!\n");
 			nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
 			*statp = rpc_system_err;
@@ -1070,7 +1077,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 		}
 	}
 
-	/* Store reply in cache. */
 	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
 	return 1;
 }



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 07/11] NFSD: Clean up nfsd_dispatch() variables
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (5 preceding siblings ...)
  2020-09-29 14:04 ` [PATCH v2 06/11] NFSD: Clean up stale comments " Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 08/11] NFSD: Refactor nfsd_dispatch() error paths Chuck Lever
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

For consistency and code legibility, use a similar organization of
variables as svc_generic_dispatch().

Since @nfserrp does not always point to the NFS status code, let's
give it a more generic name.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfssvc.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 9be2e14b3bca..18ec22a8580a 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1013,13 +1013,13 @@ static bool nfs_request_too_big(struct svc_rqst *rqstp,
  */
 int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
-	const struct svc_procedure *proc;
-	__be32			nfserr;
-	__be32			*nfserrp;
+	const struct svc_procedure *proc = rqstp->rq_procinfo;
+	struct kvec *argv = &rqstp->rq_arg.head[0];
+	struct kvec *resv = &rqstp->rq_res.head[0];
+	__be32 *p, nfserr;
 
 	dprintk("nfsd_dispatch: vers %d proc %d\n",
 				rqstp->rq_vers, rqstp->rq_proc);
-	proc = rqstp->rq_procinfo;
 
 	if (nfs_request_too_big(rqstp, proc)) {
 		dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
@@ -1031,7 +1031,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	 * (necessary in the NFSv4.0 compound case)
 	 */
 	rqstp->rq_cachetype = proc->pc_cachetype;
-	if (!proc->pc_decode(rqstp, (__be32 *)rqstp->rq_arg.head[0].iov_base)) {
+	if (!proc->pc_decode(rqstp, argv->iov_base)) {
 		dprintk("nfsd: failed to decode arguments!\n");
 		*statp = rpc_garbage_args;
 		return 1;
@@ -1050,9 +1050,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	 * Need to grab the location to store the status, as
 	 * NFSv4 does some encoding while processing
 	 */
-	nfserrp = rqstp->rq_res.head[0].iov_base
-		+ rqstp->rq_res.head[0].iov_len;
-	rqstp->rq_res.head[0].iov_len += sizeof(__be32);
+	p = resv->iov_base + resv->iov_len;
+	resv->iov_len += sizeof(__be32);
 
 	nfserr = proc->pc_func(rqstp);
 	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
@@ -1063,13 +1062,13 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	}
 
 	if (rqstp->rq_proc != 0)
-		*nfserrp++ = nfserr;
+		*p++ = nfserr;
 
 	/*
 	 * For NFSv2, additional info is never returned in case of an error.
 	 */
 	if (!(nfserr && rqstp->rq_vers == 2)) {
-		if (!proc->pc_encode(rqstp, nfserrp)) {
+		if (!proc->pc_encode(rqstp, p)) {
 			dprintk("nfsd: failed to encode result!\n");
 			nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
 			*statp = rpc_system_err;



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 08/11] NFSD: Refactor nfsd_dispatch() error paths
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (6 preceding siblings ...)
  2020-09-29 14:04 ` [PATCH v2 07/11] NFSD: Clean up nfsd_dispatch() variables Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 09/11] NFSD: Set *statp in success path Chuck Lever
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

nfsd_dispatch() is a hot path. Ensure the compiler takes the
processing of infrequent errors out of line.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfssvc.c |   60 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 35 insertions(+), 25 deletions(-)

diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 18ec22a8580a..283d29ecae43 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1021,29 +1021,24 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	dprintk("nfsd_dispatch: vers %d proc %d\n",
 				rqstp->rq_vers, rqstp->rq_proc);
 
-	if (nfs_request_too_big(rqstp, proc)) {
-		dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
-		*statp = rpc_garbage_args;
-		return 1;
-	}
+	if (nfs_request_too_big(rqstp, proc))
+		goto out_too_large;
+
 	/*
 	 * Give the xdr decoder a chance to change this if it wants
 	 * (necessary in the NFSv4.0 compound case)
 	 */
 	rqstp->rq_cachetype = proc->pc_cachetype;
-	if (!proc->pc_decode(rqstp, argv->iov_base)) {
-		dprintk("nfsd: failed to decode arguments!\n");
-		*statp = rpc_garbage_args;
-		return 1;
-	}
+	if (!proc->pc_decode(rqstp, argv->iov_base))
+		goto out_decode_err;
 
 	switch (nfsd_cache_lookup(rqstp)) {
 	case RC_DOIT:
 		break;
 	case RC_REPLY:
-		return 1;
+		goto out_cached_reply;
 	case RC_DROPIT:
-		return 0;
+		goto out_dropit;
 	}
 
 	/*
@@ -1055,11 +1050,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 
 	nfserr = proc->pc_func(rqstp);
 	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
-	if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) {
-		dprintk("nfsd: Dropping request; may be revisited later\n");
-		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
-		return 0;
-	}
+	if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags))
+		goto out_update_drop;
 
 	if (rqstp->rq_proc != 0)
 		*p++ = nfserr;
@@ -1067,16 +1059,34 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	/*
 	 * For NFSv2, additional info is never returned in case of an error.
 	 */
-	if (!(nfserr && rqstp->rq_vers == 2)) {
-		if (!proc->pc_encode(rqstp, p)) {
-			dprintk("nfsd: failed to encode result!\n");
-			nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
-			*statp = rpc_system_err;
-			return 1;
-		}
-	}
+	if (!(nfserr && rqstp->rq_vers == 2))
+		if (!proc->pc_encode(rqstp, p))
+			goto out_encode_err;
 
 	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
+out_cached_reply:
+	return 1;
+
+out_too_large:
+	dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
+	*statp = rpc_garbage_args;
+	return 1;
+
+out_decode_err:
+	dprintk("nfsd: failed to decode arguments!\n");
+	*statp = rpc_garbage_args;
+	return 1;
+
+out_update_drop:
+	dprintk("nfsd: Dropping request; may be revisited later\n");
+	nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
+out_dropit:
+	return 0;
+
+out_encode_err:
+	dprintk("nfsd: failed to encode result!\n");
+	nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
+	*statp = rpc_system_err;
 	return 1;
 }
 



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 09/11] NFSD: Set *statp in success path
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (7 preceding siblings ...)
  2020-09-29 14:04 ` [PATCH v2 08/11] NFSD: Refactor nfsd_dispatch() error paths Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 10/11] NFSD: Fix .pc_release method for NFSv2 Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 11/11] NFSD: Call NFSv2 encoders on error returns Chuck Lever
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

*statp is supposed to be set in every path through nfsd_dispatch().
The success case appears to leave *statp uninitialized.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfssvc.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 283d29ecae43..08776b44cde6 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1065,6 +1065,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 
 	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
 out_cached_reply:
+	*statp = rpc_success;
 	return 1;
 
 out_too_large:



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 10/11] NFSD: Fix .pc_release method for NFSv2
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (8 preceding siblings ...)
  2020-09-29 14:04 ` [PATCH v2 09/11] NFSD: Set *statp in success path Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 14:04 ` [PATCH v2 11/11] NFSD: Call NFSv2 encoders on error returns Chuck Lever
  10 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

nfsd_release_fhandle() assumes that rqstp->rq_resp always points to
an nfsd_fhandle struct. In fact, no NFSv2 procedure uses struct
nfsd_fhandle as its response structure.

So far that has been "safe" to do because the res structs put the
resp->fh field at that same offset as struct nfsd_fhandle. I don't
think that's a guarantee, though, and there is certainly nothing
preventing a developer from altering the fields in those structures.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfsproc.c |   14 +++++++-------
 fs/nfsd/nfsxdr.c  |   19 ++++++++++++++++---
 fs/nfsd/xdr.h     |    4 +++-
 3 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 6e0b066480c5..33204d83709c 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -600,7 +600,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_getattr,
 		.pc_decode = nfssvc_decode_fhandle,
 		.pc_encode = nfssvc_encode_attrstat,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_attrstat,
 		.pc_argsize = sizeof(struct nfsd_fhandle),
 		.pc_ressize = sizeof(struct nfsd_attrstat),
 		.pc_cachetype = RC_NOCACHE,
@@ -610,7 +610,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_setattr,
 		.pc_decode = nfssvc_decode_sattrargs,
 		.pc_encode = nfssvc_encode_attrstat,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_attrstat,
 		.pc_argsize = sizeof(struct nfsd_sattrargs),
 		.pc_ressize = sizeof(struct nfsd_attrstat),
 		.pc_cachetype = RC_REPLBUFF,
@@ -628,7 +628,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_lookup,
 		.pc_decode = nfssvc_decode_diropargs,
 		.pc_encode = nfssvc_encode_diropres,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_diropres,
 		.pc_argsize = sizeof(struct nfsd_diropargs),
 		.pc_ressize = sizeof(struct nfsd_diropres),
 		.pc_cachetype = RC_NOCACHE,
@@ -647,7 +647,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_read,
 		.pc_decode = nfssvc_decode_readargs,
 		.pc_encode = nfssvc_encode_readres,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_readres,
 		.pc_argsize = sizeof(struct nfsd_readargs),
 		.pc_ressize = sizeof(struct nfsd_readres),
 		.pc_cachetype = RC_NOCACHE,
@@ -665,7 +665,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_write,
 		.pc_decode = nfssvc_decode_writeargs,
 		.pc_encode = nfssvc_encode_attrstat,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_attrstat,
 		.pc_argsize = sizeof(struct nfsd_writeargs),
 		.pc_ressize = sizeof(struct nfsd_attrstat),
 		.pc_cachetype = RC_REPLBUFF,
@@ -675,7 +675,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_create,
 		.pc_decode = nfssvc_decode_createargs,
 		.pc_encode = nfssvc_encode_diropres,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_diropres,
 		.pc_argsize = sizeof(struct nfsd_createargs),
 		.pc_ressize = sizeof(struct nfsd_diropres),
 		.pc_cachetype = RC_REPLBUFF,
@@ -721,7 +721,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
 		.pc_func = nfsd_proc_mkdir,
 		.pc_decode = nfssvc_decode_createargs,
 		.pc_encode = nfssvc_encode_diropres,
-		.pc_release = nfssvc_release_fhandle,
+		.pc_release = nfssvc_release_diropres,
 		.pc_argsize = sizeof(struct nfsd_createargs),
 		.pc_ressize = sizeof(struct nfsd_diropres),
 		.pc_cachetype = RC_REPLBUFF,
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index b51fe515f06f..39c004ec7d85 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -561,10 +561,23 @@ nfssvc_encode_entry(void *ccdv, const char *name,
 /*
  * XDR release functions
  */
-void
-nfssvc_release_fhandle(struct svc_rqst *rqstp)
+void nfssvc_release_attrstat(struct svc_rqst *rqstp)
 {
-	struct nfsd_fhandle *resp = rqstp->rq_resp;
+	struct nfsd_attrstat *resp = rqstp->rq_resp;
+
+	fh_put(&resp->fh);
+}
+
+void nfssvc_release_diropres(struct svc_rqst *rqstp)
+{
+	struct nfsd_diropres *resp = rqstp->rq_resp;
+
+	fh_put(&resp->fh);
+}
+
+void nfssvc_release_readres(struct svc_rqst *rqstp)
+{
+	struct nfsd_readres *resp = rqstp->rq_resp;
 
 	fh_put(&resp->fh);
 }
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index ea7cca3a64b7..3d3e16d48268 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -156,7 +156,9 @@ int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *);
 int nfssvc_encode_entry(void *, const char *name,
 			int namlen, loff_t offset, u64 ino, unsigned int);
 
-void nfssvc_release_fhandle(struct svc_rqst *);
+void nfssvc_release_attrstat(struct svc_rqst *rqstp);
+void nfssvc_release_diropres(struct svc_rqst *rqstp);
+void nfssvc_release_readres(struct svc_rqst *rqstp);
 
 /* Helper functions for NFSv2 ACL code */
 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 11/11] NFSD: Call NFSv2 encoders on error returns
  2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
                   ` (9 preceding siblings ...)
  2020-09-29 14:04 ` [PATCH v2 10/11] NFSD: Fix .pc_release method for NFSv2 Chuck Lever
@ 2020-09-29 14:04 ` Chuck Lever
  2020-09-29 15:53   ` Chuck Lever
  10 siblings, 1 reply; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 14:04 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Eventually we want to deprecate NFSv2 entirely.

Remove special dispatcher logic for NFSv2 error responses. These are
rare to the point of becoming extinct, but all NFS responses have to
pay the cost of the extra conditional branches.

This also means the NFSv2 error cases now get proper
xdr_ressize_check() calls.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfsd/nfs2acl.c |    9 +++
 fs/nfsd/nfsproc.c |  159 +++++++++++++++++++++++++++--------------------------
 fs/nfsd/nfssvc.c  |    8 +--
 fs/nfsd/nfsxdr.c  |   18 ++++++
 fs/nfsd/xdr.h     |    7 ++
 5 files changed, 118 insertions(+), 83 deletions(-)

diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 3c8b9250dc4a..70b3a90cfe92 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -273,6 +273,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
 	int n;
 	int w;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	/*
 	 * Since this is version 2, the check for nfserr in
 	 * nfsd_dispatch actually ensures the following cannot happen.
@@ -312,6 +315,9 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd_attrstat *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 	return xdr_ressize_check(rqstp, p);
 }
@@ -321,6 +327,9 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd3_accessres *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 	*p++ = htonl(resp->access);
 	return xdr_ressize_check(rqstp, p);
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 33204d83709c..9727f2fdf5e4 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -16,6 +16,7 @@ typedef struct svc_buf	svc_buf;
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
+#define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
 
 static __be32
 nfsd_proc_null(struct svc_rqst *rqstp)
@@ -23,18 +24,6 @@ nfsd_proc_null(struct svc_rqst *rqstp)
 	return nfs_ok;
 }
 
-static __be32
-nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
-{
-	if (err) return err;
-	return fh_getattr(&resp->fh, &resp->stat);
-}
-static __be32
-nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
-{
-	if (err) return err;
-	return fh_getattr(&resp->fh, &resp->stat);
-}
 /*
  * Get a file's attributes
  * N.B. After this call resp->fh needs an fh_put
@@ -44,13 +33,17 @@ nfsd_proc_getattr(struct svc_rqst *rqstp)
 {
 	struct nfsd_fhandle *argp = rqstp->rq_argp;
 	struct nfsd_attrstat *resp = rqstp->rq_resp;
-	__be32 nfserr;
+
 	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
-	nfserr = fh_verify(rqstp, &resp->fh, 0,
-			NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
-	return nfsd_return_attrs(nfserr, resp);
+	resp->status = fh_verify(rqstp, &resp->fh, 0,
+				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
+	if (resp->status != nfs_ok)
+		return resp->status;
+
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 /*
@@ -64,7 +57,6 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
 	struct nfsd_attrstat *resp = rqstp->rq_resp;
 	struct iattr *iap = &argp->attrs;
 	struct svc_fh *fhp;
-	__be32 nfserr;
 
 	dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld\n",
 		SVCFH_fmt(&argp->fh),
@@ -96,9 +88,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
 		 */
 		time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();
 
-		nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
-		if (nfserr)
-			goto done;
+		resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
+		if (resp->status != nfs_ok)
+			return resp->status;
 
 		if (delta < 0)
 			delta = -delta;
@@ -113,9 +105,12 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
 		}
 	}
 
-	nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
-done:
-	return nfsd_return_attrs(nfserr, resp);
+	resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
+	if (resp->status != nfs_ok)
+		return resp->status;
+
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 /*
@@ -129,17 +124,19 @@ nfsd_proc_lookup(struct svc_rqst *rqstp)
 {
 	struct nfsd_diropargs *argp = rqstp->rq_argp;
 	struct nfsd_diropres *resp = rqstp->rq_resp;
-	__be32	nfserr;
 
 	dprintk("nfsd: LOOKUP   %s %.*s\n",
 		SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
 	fh_init(&resp->fh, NFS_FHSIZE);
-	nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
-				 &resp->fh);
-
+	resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
+				   &resp->fh);
 	fh_put(&argp->fh);
-	return nfsd_return_dirop(nfserr, resp);
+	if (resp->status != nfs_ok)
+		return resp->status;
+
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 /*
@@ -150,16 +147,15 @@ nfsd_proc_readlink(struct svc_rqst *rqstp)
 {
 	struct nfsd_readlinkargs *argp = rqstp->rq_argp;
 	struct nfsd_readlinkres *resp = rqstp->rq_resp;
-	__be32	nfserr;
 
 	dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
 
 	/* Read the symlink. */
 	resp->len = NFS_MAXPATHLEN;
-	nfserr = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
+	resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
 
 	fh_put(&argp->fh);
-	return nfserr;
+	return resp->status;
 }
 
 /*
@@ -171,7 +167,6 @@ nfsd_proc_read(struct svc_rqst *rqstp)
 {
 	struct nfsd_readargs *argp = rqstp->rq_argp;
 	struct nfsd_readres *resp = rqstp->rq_resp;
-	__be32	nfserr;
 	u32 eof;
 
 	dprintk("nfsd: READ    %s %d bytes at %d\n",
@@ -193,14 +188,16 @@ nfsd_proc_read(struct svc_rqst *rqstp)
 	svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
 
 	resp->count = argp->count;
-	nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
-				  argp->offset,
-			   	  rqstp->rq_vec, argp->vlen,
-				  &resp->count,
-				  &eof);
-
-	if (nfserr) return nfserr;
-	return fh_getattr(&resp->fh, &resp->stat);
+	resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
+				 argp->offset,
+				 rqstp->rq_vec, argp->vlen,
+				 &resp->count,
+				 &eof);
+	if (resp->status != nfs_ok)
+		return resp->status;
+
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 /*
@@ -212,7 +209,6 @@ nfsd_proc_write(struct svc_rqst *rqstp)
 {
 	struct nfsd_writeargs *argp = rqstp->rq_argp;
 	struct nfsd_attrstat *resp = rqstp->rq_resp;
-	__be32	nfserr;
 	unsigned long cnt = argp->len;
 	unsigned int nvecs;
 
@@ -224,10 +220,14 @@ nfsd_proc_write(struct svc_rqst *rqstp)
 				      &argp->first, cnt);
 	if (!nvecs)
 		return nfserr_io;
-	nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
-			    argp->offset, rqstp->rq_vec, nvecs,
-			    &cnt, NFS_DATA_SYNC, NULL);
-	return nfsd_return_attrs(nfserr, resp);
+	resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
+				  argp->offset, rqstp->rq_vec, nvecs,
+				  &cnt, NFS_DATA_SYNC, NULL);
+	if (resp->status != nfs_ok)
+		return resp->status;
+
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 /*
@@ -247,7 +247,6 @@ nfsd_proc_create(struct svc_rqst *rqstp)
 	struct inode	*inode;
 	struct dentry	*dchild;
 	int		type, mode;
-	__be32		nfserr;
 	int		hosterr;
 	dev_t		rdev = 0, wanted = new_decode_dev(attr->ia_size);
 
@@ -255,40 +254,40 @@ nfsd_proc_create(struct svc_rqst *rqstp)
 		SVCFH_fmt(dirfhp), argp->len, argp->name);
 
 	/* First verify the parent file handle */
-	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
-	if (nfserr)
+	resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
+	if (resp->status != nfs_ok)
 		goto done; /* must fh_put dirfhp even on error */
 
 	/* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
 
-	nfserr = nfserr_exist;
+	resp->status = nfserr_exist;
 	if (isdotent(argp->name, argp->len))
 		goto done;
 	hosterr = fh_want_write(dirfhp);
 	if (hosterr) {
-		nfserr = nfserrno(hosterr);
+		resp->status = nfserrno(hosterr);
 		goto done;
 	}
 
 	fh_lock_nested(dirfhp, I_MUTEX_PARENT);
 	dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
 	if (IS_ERR(dchild)) {
-		nfserr = nfserrno(PTR_ERR(dchild));
+		resp->status = nfserrno(PTR_ERR(dchild));
 		goto out_unlock;
 	}
 	fh_init(newfhp, NFS_FHSIZE);
-	nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
-	if (!nfserr && d_really_is_negative(dchild))
-		nfserr = nfserr_noent;
+	resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
+	if (!resp->status && d_really_is_negative(dchild))
+		resp->status = nfserr_noent;
 	dput(dchild);
-	if (nfserr) {
-		if (nfserr != nfserr_noent)
+	if (resp->status) {
+		if (resp->status != nfserr_noent)
 			goto out_unlock;
 		/*
 		 * If the new file handle wasn't verified, we can't tell
 		 * whether the file exists or not. Time to bail ...
 		 */
-		nfserr = nfserr_acces;
+		resp->status = nfserr_acces;
 		if (!newfhp->fh_dentry) {
 			printk(KERN_WARNING 
 				"nfsd_proc_create: file handle not verified\n");
@@ -321,11 +320,11 @@ nfsd_proc_create(struct svc_rqst *rqstp)
 					 *   echo thing > device-special-file-or-pipe
 					 * by doing a CREATE with type==0
 					 */
-					nfserr = nfsd_permission(rqstp,
+					resp->status = nfsd_permission(rqstp,
 								 newfhp->fh_export,
 								 newfhp->fh_dentry,
 								 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
-					if (nfserr && nfserr != nfserr_rofs)
+					if (resp->status && resp->status != nfserr_rofs)
 						goto out_unlock;
 				}
 			} else
@@ -361,16 +360,17 @@ nfsd_proc_create(struct svc_rqst *rqstp)
 		attr->ia_valid &= ~ATTR_SIZE;
 
 		/* Make sure the type and device matches */
-		nfserr = nfserr_exist;
+		resp->status = nfserr_exist;
 		if (inode && type != (inode->i_mode & S_IFMT))
 			goto out_unlock;
 	}
 
-	nfserr = 0;
+	resp->status = nfs_ok;
 	if (!inode) {
 		/* File doesn't exist. Create it and set attrs */
-		nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name,
-					argp->len, attr, type, rdev, newfhp);
+		resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
+						  argp->len, attr, type, rdev,
+						  newfhp);
 	} else if (type == S_IFREG) {
 		dprintk("nfsd:   existing %s, valid=%x, size=%ld\n",
 			argp->name, attr->ia_valid, (long) attr->ia_size);
@@ -380,7 +380,8 @@ nfsd_proc_create(struct svc_rqst *rqstp)
 		 */
 		attr->ia_valid &= ATTR_SIZE;
 		if (attr->ia_valid)
-			nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time64_t)0);
+			resp->status = nfsd_setattr(rqstp, newfhp, attr, 0,
+						    (time64_t)0);
 	}
 
 out_unlock:
@@ -389,7 +390,10 @@ nfsd_proc_create(struct svc_rqst *rqstp)
 	fh_drop_write(dirfhp);
 done:
 	fh_put(dirfhp);
-	return nfsd_return_dirop(nfserr, resp);
+	if (resp->status != nfs_ok)
+		return resp->status;
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 static __be32
@@ -484,7 +488,6 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
 {
 	struct nfsd_createargs *argp = rqstp->rq_argp;
 	struct nfsd_diropres *resp = rqstp->rq_resp;
-	__be32	nfserr;
 
 	dprintk("nfsd: MKDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
@@ -495,10 +498,14 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
 
 	argp->attrs.ia_valid &= ~ATTR_SIZE;
 	fh_init(&resp->fh, NFS_FHSIZE);
-	nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
-				    &argp->attrs, S_IFDIR, 0, &resp->fh);
+	resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
+				   &argp->attrs, S_IFDIR, 0, &resp->fh);
 	fh_put(&argp->fh);
-	return nfsd_return_dirop(nfserr, resp);
+	if (resp->status != nfs_ok)
+		return resp->status;
+
+	resp->status = fh_getattr(&resp->fh, &resp->stat);
+	return resp->status;
 }
 
 /*
@@ -526,7 +533,6 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
 	struct nfsd_readdirargs *argp = rqstp->rq_argp;
 	struct nfsd_readdirres *resp = rqstp->rq_resp;
 	int		count;
-	__be32		nfserr;
 	loff_t		offset;
 
 	dprintk("nfsd: READDIR  %s %d bytes at %d\n",
@@ -547,15 +553,15 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
 	resp->common.err = nfs_ok;
 	/* Read directory and encode entries on the fly */
 	offset = argp->cookie;
-	nfserr = nfsd_readdir(rqstp, &argp->fh, &offset, 
-			      &resp->common, nfssvc_encode_entry);
+	resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
+				    &resp->common, nfssvc_encode_entry);
 
 	resp->count = resp->buffer - argp->buffer;
 	if (resp->offset)
 		*resp->offset = htonl(offset);
 
 	fh_put(&argp->fh);
-	return nfserr;
+	return resp->status;
 }
 
 /*
@@ -566,14 +572,13 @@ nfsd_proc_statfs(struct svc_rqst *rqstp)
 {
 	struct nfsd_fhandle *argp = rqstp->rq_argp;
 	struct nfsd_statfsres *resp = rqstp->rq_resp;
-	__be32	nfserr;
 
 	dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
 
-	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
-			NFSD_MAY_BYPASS_GSS_ON_ROOT);
+	resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
+				   NFSD_MAY_BYPASS_GSS_ON_ROOT);
 	fh_put(&argp->fh);
-	return nfserr;
+	return resp->status;
 }
 
 /*
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 08776b44cde6..9faf9224ef62 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1056,12 +1056,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	if (rqstp->rq_proc != 0)
 		*p++ = nfserr;
 
-	/*
-	 * For NFSv2, additional info is never returned in case of an error.
-	 */
-	if (!(nfserr && rqstp->rq_vers == 2))
-		if (!proc->pc_encode(rqstp, p))
-			goto out_encode_err;
+	if (!proc->pc_encode(rqstp, p))
+		goto out_encode_err;
 
 	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
 out_cached_reply:
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 39c004ec7d85..952e71c95d4e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -434,6 +434,9 @@ nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd_attrstat *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 	return xdr_ressize_check(rqstp, p);
 }
@@ -443,6 +446,9 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd_diropres *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	p = encode_fh(p, &resp->fh);
 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 	return xdr_ressize_check(rqstp, p);
@@ -453,6 +459,9 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd_readlinkres *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	*p++ = htonl(resp->len);
 	xdr_ressize_check(rqstp, p);
 	rqstp->rq_res.page_len = resp->len;
@@ -470,6 +479,9 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd_readres *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 	*p++ = htonl(resp->count);
 	xdr_ressize_check(rqstp, p);
@@ -490,6 +502,9 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct nfsd_readdirres *resp = rqstp->rq_resp;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	xdr_ressize_check(rqstp, p);
 	p = resp->buffer;
 	*p++ = 0;			/* no more entries */
@@ -505,6 +520,9 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
 	struct nfsd_statfsres *resp = rqstp->rq_resp;
 	struct kstatfs	*stat = &resp->stats;
 
+	if (resp->status != nfs_ok)
+		return xdr_ressize_check(rqstp, p);
+
 	*p++ = htonl(NFSSVC_MAXBLKSIZE_V2);	/* max transfer size */
 	*p++ = htonl(stat->f_bsize);
 	*p++ = htonl(stat->f_blocks);
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 3d3e16d48268..17221931815f 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -83,26 +83,32 @@ struct nfsd_readdirargs {
 };
 
 struct nfsd_attrstat {
+	__be32			status;
 	struct svc_fh		fh;
 	struct kstat		stat;
 };
 
 struct nfsd_diropres  {
+	__be32			status;
 	struct svc_fh		fh;
 	struct kstat		stat;
 };
 
 struct nfsd_readlinkres {
+	__be32			status;
 	int			len;
 };
 
 struct nfsd_readres {
+	__be32			status;
 	struct svc_fh		fh;
 	unsigned long		count;
 	struct kstat		stat;
 };
 
 struct nfsd_readdirres {
+	__be32			status;
+
 	int			count;
 
 	struct readdir_cd	common;
@@ -112,6 +118,7 @@ struct nfsd_readdirres {
 };
 
 struct nfsd_statfsres {
+	__be32			status;
 	struct kstatfs		stats;
 };
 



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 11/11] NFSD: Call NFSv2 encoders on error returns
  2020-09-29 14:04 ` [PATCH v2 11/11] NFSD: Call NFSv2 encoders on error returns Chuck Lever
@ 2020-09-29 15:53   ` Chuck Lever
  0 siblings, 0 replies; 13+ messages in thread
From: Chuck Lever @ 2020-09-29 15:53 UTC (permalink / raw)
  To: Bruce Fields; +Cc: Linux NFS Mailing List



> On Sep 29, 2020, at 10:04 AM, Chuck Lever <chuck.lever@oracle.com> wrote:
> 
> Eventually we want to deprecate NFSv2 entirely.
> 
> Remove special dispatcher logic for NFSv2 error responses. These are
> rare to the point of becoming extinct, but all NFS responses have to
> pay the cost of the extra conditional branches.
> 
> This also means the NFSv2 error cases now get proper
> xdr_ressize_check() calls.
> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
> fs/nfsd/nfs2acl.c |    9 +++
> fs/nfsd/nfsproc.c |  159 +++++++++++++++++++++++++++--------------------------
> fs/nfsd/nfssvc.c  |    8 +--
> fs/nfsd/nfsxdr.c  |   18 ++++++
> fs/nfsd/xdr.h     |    7 ++
> 5 files changed, 118 insertions(+), 83 deletions(-)
> 
> diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
> index 3c8b9250dc4a..70b3a90cfe92 100644
> --- a/fs/nfsd/nfs2acl.c
> +++ b/fs/nfsd/nfs2acl.c
> @@ -273,6 +273,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
> 	int n;
> 	int w;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	/*
> 	 * Since this is version 2, the check for nfserr in
> 	 * nfsd_dispatch actually ensures the following cannot happen.
> @@ -312,6 +315,9 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd_attrstat *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);

Looks like proc_setacl doesn't set resp->status. Will be fixed
in the next version of this series.


> +
> 	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
> 	return xdr_ressize_check(rqstp, p);
> }
> @@ -321,6 +327,9 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd3_accessres *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
> 	*p++ = htonl(resp->access);
> 	return xdr_ressize_check(rqstp, p);
> diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
> index 33204d83709c..9727f2fdf5e4 100644
> --- a/fs/nfsd/nfsproc.c
> +++ b/fs/nfsd/nfsproc.c
> @@ -16,6 +16,7 @@ typedef struct svc_buf	svc_buf;
> 
> #define NFSDDBG_FACILITY		NFSDDBG_PROC
> 
> +#define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
> 
> static __be32
> nfsd_proc_null(struct svc_rqst *rqstp)
> @@ -23,18 +24,6 @@ nfsd_proc_null(struct svc_rqst *rqstp)
> 	return nfs_ok;
> }
> 
> -static __be32
> -nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
> -{
> -	if (err) return err;
> -	return fh_getattr(&resp->fh, &resp->stat);
> -}
> -static __be32
> -nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
> -{
> -	if (err) return err;
> -	return fh_getattr(&resp->fh, &resp->stat);
> -}
> /*
>  * Get a file's attributes
>  * N.B. After this call resp->fh needs an fh_put
> @@ -44,13 +33,17 @@ nfsd_proc_getattr(struct svc_rqst *rqstp)
> {
> 	struct nfsd_fhandle *argp = rqstp->rq_argp;
> 	struct nfsd_attrstat *resp = rqstp->rq_resp;
> -	__be32 nfserr;
> +
> 	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
> 
> 	fh_copy(&resp->fh, &argp->fh);
> -	nfserr = fh_verify(rqstp, &resp->fh, 0,
> -			NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
> -	return nfsd_return_attrs(nfserr, resp);
> +	resp->status = fh_verify(rqstp, &resp->fh, 0,
> +				 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> /*
> @@ -64,7 +57,6 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
> 	struct nfsd_attrstat *resp = rqstp->rq_resp;
> 	struct iattr *iap = &argp->attrs;
> 	struct svc_fh *fhp;
> -	__be32 nfserr;
> 
> 	dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld\n",
> 		SVCFH_fmt(&argp->fh),
> @@ -96,9 +88,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
> 		 */
> 		time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();
> 
> -		nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
> -		if (nfserr)
> -			goto done;
> +		resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
> +		if (resp->status != nfs_ok)
> +			return resp->status;
> 
> 		if (delta < 0)
> 			delta = -delta;
> @@ -113,9 +105,12 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
> 		}
> 	}
> 
> -	nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
> -done:
> -	return nfsd_return_attrs(nfserr, resp);
> +	resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> /*
> @@ -129,17 +124,19 @@ nfsd_proc_lookup(struct svc_rqst *rqstp)
> {
> 	struct nfsd_diropargs *argp = rqstp->rq_argp;
> 	struct nfsd_diropres *resp = rqstp->rq_resp;
> -	__be32	nfserr;
> 
> 	dprintk("nfsd: LOOKUP   %s %.*s\n",
> 		SVCFH_fmt(&argp->fh), argp->len, argp->name);
> 
> 	fh_init(&resp->fh, NFS_FHSIZE);
> -	nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
> -				 &resp->fh);
> -
> +	resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
> +				   &resp->fh);
> 	fh_put(&argp->fh);
> -	return nfsd_return_dirop(nfserr, resp);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> /*
> @@ -150,16 +147,15 @@ nfsd_proc_readlink(struct svc_rqst *rqstp)
> {
> 	struct nfsd_readlinkargs *argp = rqstp->rq_argp;
> 	struct nfsd_readlinkres *resp = rqstp->rq_resp;
> -	__be32	nfserr;
> 
> 	dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
> 
> 	/* Read the symlink. */
> 	resp->len = NFS_MAXPATHLEN;
> -	nfserr = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
> +	resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
> 
> 	fh_put(&argp->fh);
> -	return nfserr;
> +	return resp->status;
> }
> 
> /*
> @@ -171,7 +167,6 @@ nfsd_proc_read(struct svc_rqst *rqstp)
> {
> 	struct nfsd_readargs *argp = rqstp->rq_argp;
> 	struct nfsd_readres *resp = rqstp->rq_resp;
> -	__be32	nfserr;
> 	u32 eof;
> 
> 	dprintk("nfsd: READ    %s %d bytes at %d\n",
> @@ -193,14 +188,16 @@ nfsd_proc_read(struct svc_rqst *rqstp)
> 	svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
> 
> 	resp->count = argp->count;
> -	nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
> -				  argp->offset,
> -			   	  rqstp->rq_vec, argp->vlen,
> -				  &resp->count,
> -				  &eof);
> -
> -	if (nfserr) return nfserr;
> -	return fh_getattr(&resp->fh, &resp->stat);
> +	resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
> +				 argp->offset,
> +				 rqstp->rq_vec, argp->vlen,
> +				 &resp->count,
> +				 &eof);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> /*
> @@ -212,7 +209,6 @@ nfsd_proc_write(struct svc_rqst *rqstp)
> {
> 	struct nfsd_writeargs *argp = rqstp->rq_argp;
> 	struct nfsd_attrstat *resp = rqstp->rq_resp;
> -	__be32	nfserr;
> 	unsigned long cnt = argp->len;
> 	unsigned int nvecs;
> 
> @@ -224,10 +220,14 @@ nfsd_proc_write(struct svc_rqst *rqstp)
> 				      &argp->first, cnt);
> 	if (!nvecs)
> 		return nfserr_io;
> -	nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
> -			    argp->offset, rqstp->rq_vec, nvecs,
> -			    &cnt, NFS_DATA_SYNC, NULL);
> -	return nfsd_return_attrs(nfserr, resp);
> +	resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
> +				  argp->offset, rqstp->rq_vec, nvecs,
> +				  &cnt, NFS_DATA_SYNC, NULL);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> /*
> @@ -247,7 +247,6 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> 	struct inode	*inode;
> 	struct dentry	*dchild;
> 	int		type, mode;
> -	__be32		nfserr;
> 	int		hosterr;
> 	dev_t		rdev = 0, wanted = new_decode_dev(attr->ia_size);
> 
> @@ -255,40 +254,40 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> 		SVCFH_fmt(dirfhp), argp->len, argp->name);
> 
> 	/* First verify the parent file handle */
> -	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
> -	if (nfserr)
> +	resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
> +	if (resp->status != nfs_ok)
> 		goto done; /* must fh_put dirfhp even on error */
> 
> 	/* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
> 
> -	nfserr = nfserr_exist;
> +	resp->status = nfserr_exist;
> 	if (isdotent(argp->name, argp->len))
> 		goto done;
> 	hosterr = fh_want_write(dirfhp);
> 	if (hosterr) {
> -		nfserr = nfserrno(hosterr);
> +		resp->status = nfserrno(hosterr);
> 		goto done;
> 	}
> 
> 	fh_lock_nested(dirfhp, I_MUTEX_PARENT);
> 	dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
> 	if (IS_ERR(dchild)) {
> -		nfserr = nfserrno(PTR_ERR(dchild));
> +		resp->status = nfserrno(PTR_ERR(dchild));
> 		goto out_unlock;
> 	}
> 	fh_init(newfhp, NFS_FHSIZE);
> -	nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
> -	if (!nfserr && d_really_is_negative(dchild))
> -		nfserr = nfserr_noent;
> +	resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
> +	if (!resp->status && d_really_is_negative(dchild))
> +		resp->status = nfserr_noent;
> 	dput(dchild);
> -	if (nfserr) {
> -		if (nfserr != nfserr_noent)
> +	if (resp->status) {
> +		if (resp->status != nfserr_noent)
> 			goto out_unlock;
> 		/*
> 		 * If the new file handle wasn't verified, we can't tell
> 		 * whether the file exists or not. Time to bail ...
> 		 */
> -		nfserr = nfserr_acces;
> +		resp->status = nfserr_acces;
> 		if (!newfhp->fh_dentry) {
> 			printk(KERN_WARNING 
> 				"nfsd_proc_create: file handle not verified\n");
> @@ -321,11 +320,11 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> 					 *   echo thing > device-special-file-or-pipe
> 					 * by doing a CREATE with type==0
> 					 */
> -					nfserr = nfsd_permission(rqstp,
> +					resp->status = nfsd_permission(rqstp,
> 								 newfhp->fh_export,
> 								 newfhp->fh_dentry,
> 								 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
> -					if (nfserr && nfserr != nfserr_rofs)
> +					if (resp->status && resp->status != nfserr_rofs)
> 						goto out_unlock;
> 				}
> 			} else
> @@ -361,16 +360,17 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> 		attr->ia_valid &= ~ATTR_SIZE;
> 
> 		/* Make sure the type and device matches */
> -		nfserr = nfserr_exist;
> +		resp->status = nfserr_exist;
> 		if (inode && type != (inode->i_mode & S_IFMT))
> 			goto out_unlock;
> 	}
> 
> -	nfserr = 0;
> +	resp->status = nfs_ok;
> 	if (!inode) {
> 		/* File doesn't exist. Create it and set attrs */
> -		nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name,
> -					argp->len, attr, type, rdev, newfhp);
> +		resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
> +						  argp->len, attr, type, rdev,
> +						  newfhp);
> 	} else if (type == S_IFREG) {
> 		dprintk("nfsd:   existing %s, valid=%x, size=%ld\n",
> 			argp->name, attr->ia_valid, (long) attr->ia_size);
> @@ -380,7 +380,8 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> 		 */
> 		attr->ia_valid &= ATTR_SIZE;
> 		if (attr->ia_valid)
> -			nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time64_t)0);
> +			resp->status = nfsd_setattr(rqstp, newfhp, attr, 0,
> +						    (time64_t)0);
> 	}
> 
> out_unlock:
> @@ -389,7 +390,10 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> 	fh_drop_write(dirfhp);
> done:
> 	fh_put(dirfhp);
> -	return nfsd_return_dirop(nfserr, resp);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> static __be32
> @@ -484,7 +488,6 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
> {
> 	struct nfsd_createargs *argp = rqstp->rq_argp;
> 	struct nfsd_diropres *resp = rqstp->rq_resp;
> -	__be32	nfserr;
> 
> 	dprintk("nfsd: MKDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
> 
> @@ -495,10 +498,14 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
> 
> 	argp->attrs.ia_valid &= ~ATTR_SIZE;
> 	fh_init(&resp->fh, NFS_FHSIZE);
> -	nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
> -				    &argp->attrs, S_IFDIR, 0, &resp->fh);
> +	resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
> +				   &argp->attrs, S_IFDIR, 0, &resp->fh);
> 	fh_put(&argp->fh);
> -	return nfsd_return_dirop(nfserr, resp);
> +	if (resp->status != nfs_ok)
> +		return resp->status;
> +
> +	resp->status = fh_getattr(&resp->fh, &resp->stat);
> +	return resp->status;
> }
> 
> /*
> @@ -526,7 +533,6 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
> 	struct nfsd_readdirargs *argp = rqstp->rq_argp;
> 	struct nfsd_readdirres *resp = rqstp->rq_resp;
> 	int		count;
> -	__be32		nfserr;
> 	loff_t		offset;
> 
> 	dprintk("nfsd: READDIR  %s %d bytes at %d\n",
> @@ -547,15 +553,15 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
> 	resp->common.err = nfs_ok;
> 	/* Read directory and encode entries on the fly */
> 	offset = argp->cookie;
> -	nfserr = nfsd_readdir(rqstp, &argp->fh, &offset, 
> -			      &resp->common, nfssvc_encode_entry);
> +	resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
> +				    &resp->common, nfssvc_encode_entry);
> 
> 	resp->count = resp->buffer - argp->buffer;
> 	if (resp->offset)
> 		*resp->offset = htonl(offset);
> 
> 	fh_put(&argp->fh);
> -	return nfserr;
> +	return resp->status;
> }
> 
> /*
> @@ -566,14 +572,13 @@ nfsd_proc_statfs(struct svc_rqst *rqstp)
> {
> 	struct nfsd_fhandle *argp = rqstp->rq_argp;
> 	struct nfsd_statfsres *resp = rqstp->rq_resp;
> -	__be32	nfserr;
> 
> 	dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
> 
> -	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
> -			NFSD_MAY_BYPASS_GSS_ON_ROOT);
> +	resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
> +				   NFSD_MAY_BYPASS_GSS_ON_ROOT);
> 	fh_put(&argp->fh);
> -	return nfserr;
> +	return resp->status;
> }
> 
> /*
> diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
> index 08776b44cde6..9faf9224ef62 100644
> --- a/fs/nfsd/nfssvc.c
> +++ b/fs/nfsd/nfssvc.c
> @@ -1056,12 +1056,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
> 	if (rqstp->rq_proc != 0)
> 		*p++ = nfserr;
> 
> -	/*
> -	 * For NFSv2, additional info is never returned in case of an error.
> -	 */
> -	if (!(nfserr && rqstp->rq_vers == 2))
> -		if (!proc->pc_encode(rqstp, p))
> -			goto out_encode_err;
> +	if (!proc->pc_encode(rqstp, p))
> +		goto out_encode_err;
> 
> 	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
> out_cached_reply:
> diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
> index 39c004ec7d85..952e71c95d4e 100644
> --- a/fs/nfsd/nfsxdr.c
> +++ b/fs/nfsd/nfsxdr.c
> @@ -434,6 +434,9 @@ nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd_attrstat *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
> 	return xdr_ressize_check(rqstp, p);
> }
> @@ -443,6 +446,9 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd_diropres *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	p = encode_fh(p, &resp->fh);
> 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
> 	return xdr_ressize_check(rqstp, p);
> @@ -453,6 +459,9 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd_readlinkres *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	*p++ = htonl(resp->len);
> 	xdr_ressize_check(rqstp, p);
> 	rqstp->rq_res.page_len = resp->len;
> @@ -470,6 +479,9 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd_readres *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
> 	*p++ = htonl(resp->count);
> 	xdr_ressize_check(rqstp, p);
> @@ -490,6 +502,9 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
> {
> 	struct nfsd_readdirres *resp = rqstp->rq_resp;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	xdr_ressize_check(rqstp, p);
> 	p = resp->buffer;
> 	*p++ = 0;			/* no more entries */
> @@ -505,6 +520,9 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
> 	struct nfsd_statfsres *resp = rqstp->rq_resp;
> 	struct kstatfs	*stat = &resp->stats;
> 
> +	if (resp->status != nfs_ok)
> +		return xdr_ressize_check(rqstp, p);
> +
> 	*p++ = htonl(NFSSVC_MAXBLKSIZE_V2);	/* max transfer size */
> 	*p++ = htonl(stat->f_bsize);
> 	*p++ = htonl(stat->f_blocks);
> diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
> index 3d3e16d48268..17221931815f 100644
> --- a/fs/nfsd/xdr.h
> +++ b/fs/nfsd/xdr.h
> @@ -83,26 +83,32 @@ struct nfsd_readdirargs {
> };
> 
> struct nfsd_attrstat {
> +	__be32			status;
> 	struct svc_fh		fh;
> 	struct kstat		stat;
> };
> 
> struct nfsd_diropres  {
> +	__be32			status;
> 	struct svc_fh		fh;
> 	struct kstat		stat;
> };
> 
> struct nfsd_readlinkres {
> +	__be32			status;
> 	int			len;
> };
> 
> struct nfsd_readres {
> +	__be32			status;
> 	struct svc_fh		fh;
> 	unsigned long		count;
> 	struct kstat		stat;
> };
> 
> struct nfsd_readdirres {
> +	__be32			status;
> +
> 	int			count;
> 
> 	struct readdir_cd	common;
> @@ -112,6 +118,7 @@ struct nfsd_readdirres {
> };
> 
> struct nfsd_statfsres {
> +	__be32			status;
> 	struct kstatfs		stats;
> };
> 
> 
> 

--
Chuck Lever




^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-09-29 15:54 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-29 14:03 [PATCH v2 00/11] nfsd_dispatch() clean up Chuck Lever
2020-09-29 14:03 ` [PATCH v2 01/11] nfsd: rq_lease_breaker cleanup Chuck Lever
2020-09-29 14:03 ` [PATCH v2 02/11] lockd: Replace PROC() macro with open code Chuck Lever
2020-09-29 14:03 ` [PATCH v2 03/11] NFSACL: " Chuck Lever
2020-09-29 14:03 ` [PATCH v2 04/11] NFSD: Encoder and decoder functions are always present Chuck Lever
2020-09-29 14:04 ` [PATCH v2 05/11] NFSD: Clean up switch statement in nfsd_dispatch() Chuck Lever
2020-09-29 14:04 ` [PATCH v2 06/11] NFSD: Clean up stale comments " Chuck Lever
2020-09-29 14:04 ` [PATCH v2 07/11] NFSD: Clean up nfsd_dispatch() variables Chuck Lever
2020-09-29 14:04 ` [PATCH v2 08/11] NFSD: Refactor nfsd_dispatch() error paths Chuck Lever
2020-09-29 14:04 ` [PATCH v2 09/11] NFSD: Set *statp in success path Chuck Lever
2020-09-29 14:04 ` [PATCH v2 10/11] NFSD: Fix .pc_release method for NFSv2 Chuck Lever
2020-09-29 14:04 ` [PATCH v2 11/11] NFSD: Call NFSv2 encoders on error returns Chuck Lever
2020-09-29 15:53   ` Chuck Lever

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).