* [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).