History

Merge tag 'nfsd-5.10' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields: "The one new feature this time, from Anna Schumaker, is READ_PLUS, which has the same arguments as READ but allows the server to return an array of data and hole extents. Otherwise it's a lot of cleanup and bugfixes" * tag 'nfsd-5.10' of git://linux-nfs.org/~bfields/linux: (43 commits) NFSv4.2: Fix NFS4ERR_STALE error when doing inter server copy SUNRPC: fix copying of multiple pages in gss_read_proxy_verf() sunrpc: raise kernel RPC channel buffer size svcrdma: fix bounce buffers for unaligned offsets and multiple pages nfsd: remove unneeded break net/sunrpc: Fix return value for sysctl sunrpc.transports NFSD: Encode a full READ_PLUS reply NFSD: Return both a hole and a data segment NFSD: Add READ_PLUS hole segment encoding NFSD: Add READ_PLUS data support NFSD: Hoist status code encoding into XDR encoder functions NFSD: Map nfserr_wrongsec outside of nfsd_dispatch NFSD: Remove the RETURN_STATUS() macro NFSD: Call NFSv2 encoders on error returns NFSD: Fix .pc_release method for NFSv2 NFSD: Remove vestigial typedefs NFSD: Refactor nfsd_dispatch() error paths NFSD: Clean up nfsd_dispatch() variables NFSD: Clean up stale comments in nfsd_dispatch() NFSD: Clean up switch statement in nfsd_dispatch() ...

Linus Torvalds committed 6 years ago

Commit 24717cf2 parents 9b06f57 0cfcd4044 files · +1490 −1368Browse files

Unified · Split

44 files
  1. Documentation/admin-guide/nfs/fault_injection.rst +0 −70
  2. Documentation/admin-guide/nfs/index.rst +0 −1
  3. Documentation/filesystems/nfs/rpc-server-gss.rst +2 −3
  4. MAINTAINERS +2 −0
  5. fs/lockd/svc4proc.c +199 −49
  6. fs/lockd/svcproc.c +199 −51
  7. fs/nfs/nfs4file.c +32 −6
  8. fs/nfs/nfs4super.c +5 −0
  9. fs/nfs/super.c +17 −0
  10. fs/nfs_common/Makefile +1 −0
  11. fs/nfs_common/nfs_ssc.c +94 −0
  12. fs/nfsd/Kconfig +1 −11
  13. fs/nfsd/Makefile +0 −1
  14. fs/nfsd/export.c +1 −1
  15. fs/nfsd/filecache.c +1 −1
  16. fs/nfsd/nfs2acl.c +104 −56
  17. fs/nfsd/nfs3acl.c +49 −39
  18. fs/nfsd/nfs3proc.c +116 −122
  19. fs/nfsd/nfs3xdr.c +21 −4
  20. fs/nfsd/nfs4proc.c +28 −6
  21. fs/nfsd/nfs4state.c +6 −599
  22. fs/nfsd/nfs4xdr.c +164 −38
  23. fs/nfsd/nfscache.c +4 −8
  24. fs/nfsd/nfsctl.c +0 −3
  25. fs/nfsd/nfsproc.c +157 −126
  26. fs/nfsd/nfssvc.c +59 −63
  27. fs/nfsd/nfsxdr.c +49 −3
  28. fs/nfsd/state.h +0 −27
  29. fs/nfsd/trace.h +2 −2
  30. fs/nfsd/vfs.c +4 −2
  31. fs/nfsd/xdr.h +15 −1
  32. fs/nfsd/xdr3.h +1 −0
  33. fs/nfsd/xdr4.h +1 −0
  34. include/linux/nfs_ssc.h +67 −0
  35. include/linux/sunrpc/xdr.h +2 −0
  36. include/uapi/linux/nfsacl.h +2 −0
  37. net/sunrpc/auth_gss/svcauth_gss.c +17 −10
  38. net/sunrpc/backchannel_rqst.c +1 −1
  39. net/sunrpc/cache.c +11 −10
  40. net/sunrpc/sysctl.c +7 −1
  41. net/sunrpc/xdr.c +46 −1
  42. net/sunrpc/xprtrdma/svc_rdma_rw.c +1 −1
  43. net/sunrpc/xprtrdma/svc_rdma_sendto.c +2 −1
  44. tools/nfsd/inject_fault.sh +0 −50
Documentation/admin-guide/nfs/fault_injection.rst+0−70
@@ -1,70 +0,0 @@
1−===================
2−NFS Fault Injection
3−===================
4−
5−Fault injection is a method for forcing errors that may not normally occur, or
6−may be difficult to reproduce. Forcing these errors in a controlled environment
7−can help the developer find and fix bugs before their code is shipped in a
8−production system. Injecting an error on the Linux NFS server will allow us to
9−observe how the client reacts and if it manages to recover its state correctly.
10−
11−NFSD_FAULT_INJECTION must be selected when configuring the kernel to use this
12−feature.
13−
14−
15−Using Fault Injection
16−=====================
17−On the client, mount the fault injection server through NFS v4.0+ and do some
18−work over NFS (open files, take locks, ...).
19−
20−On the server, mount the debugfs filesystem to <debug_dir> and ls
21−<debug_dir>/nfsd. This will show a list of files that will be used for
22−injecting faults on the NFS server. As root, write a number n to the file
23−corresponding to the action you want the server to take. The server will then
24−process the first n items it finds. So if you want to forget 5 locks, echo '5'
25−to <debug_dir>/nfsd/forget_locks. A value of 0 will tell the server to forget
26−all corresponding items. A log message will be created containing the number
27−of items forgotten (check dmesg).
28−
29−Go back to work on the client and check if the client recovered from the error
30−correctly.
31−
32−
33−Available Faults
34−================
35−forget_clients:
36− The NFS server keeps a list of clients that have placed a mount call. If
37− this list is cleared, the server will have no knowledge of who the client
38− is, forcing the client to reauthenticate with the server.
39−
40−forget_openowners:
41− The NFS server keeps a list of what files are currently opened and who
42− they were opened by. Clearing this list will force the client to reopen
43− its files.
44−
45−forget_locks:
46− The NFS server keeps a list of what files are currently locked in the VFS.
47− Clearing this list will force the client to reclaim its locks (files are
48− unlocked through the VFS as they are cleared from this list).
49−
50−forget_delegations:
51− A delegation is used to assure the client that a file, or part of a file,
52− has not changed since the delegation was awarded. Clearing this list will
53− force the client to reacquire its delegation before accessing the file
54− again.
55−
56−recall_delegations:
57− Delegations can be recalled by the server when another client attempts to
58− access a file. This test will notify the client that its delegation has
59− been revoked, forcing the client to reacquire the delegation before using
60− the file again.
61−
62−
63−tools/nfs/inject_faults.sh script
64−=================================
65−This script has been created to ease the fault injection process. This script
66−will detect the mounted debugfs directory and write to the files located there
67−based on the arguments passed by the user. For example, running
68−`inject_faults.sh forget_locks 1` as root will instruct the server to forget
69−one lock. Running `inject_faults forget_locks` will instruct the server to
70−forgetall locks.
Documentation/admin-guide/nfs/index.rst+0−1
@@ -12,4 +12,3 @@ NFS · 11 unmodified lines
1212 nfs-idmapper
1313 pnfs-block-server
1414 pnfs-scsi-server
15− fault_injection
Documentation/filesystems/nfs/rpc-server-gss.rst+2−3
@@ -13,10 +13,9 @@ RPCGSS is specified in a few IETF documents: · 12 unmodified lines
1313 - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt
1414 - RFC5403 v2: https://tools.ietf.org/rfc/rfc5403.txt
1515
16−and there is a 3rd version being proposed:
16+There is a third version that we don't currently implement:
1717
18− - https://tools.ietf.org/id/draft-williams-rpcsecgssv3.txt
19− (At draft n. 02 at the time of writing)
18+ - RFC7861 v3: https://tools.ietf.org/rfc/rfc7861.txt
2019
2120 Background
2221 ==========
MAINTAINERS+2−0
@@ -9556,6 +9556,7 @@ F: include/linux/sunrpc/ · 9555 unmodified lines
95569556 F: include/uapi/linux/nfsd/
95579557 F: include/uapi/linux/sunrpc/
95589558 F: net/sunrpc/
9559+F: Documentation/filesystems/nfs/
95599560
95609561 KERNEL SELFTEST FRAMEWORK
95619562 M: Shuah Khan <shuah@kernel.org>
@@ -12337,6 +12338,7 @@ F: include/linux/sunrpc/ · 2775 unmodified lines
1233712338 F: include/uapi/linux/nfs*
1233812339 F: include/uapi/linux/sunrpc/
1233912340 F: net/sunrpc/
12341+F: Documentation/filesystems/nfs/
1234012342
1234112343 NILFS2 FILESYSTEM
1234212344 M: Ryusuke Konishi <konishi.ryusuke@gmail.com>
fs/lockd/svc4proc.c+199−49
@@ -486,65 +486,215 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp) · 485 unmodified lines
486486 return rpc_success;
487487 }
488488
489+static __be32
490+nlm4svc_proc_unused(struct svc_rqst *rqstp)
491+{
492+ return rpc_proc_unavail;
493+}
494+
489495
490496 /*
491497 * NLM Server procedures.
492498 */
493499
494−#define nlm4svc_encode_norep nlm4svc_encode_void
495−#define nlm4svc_decode_norep nlm4svc_decode_void
496−#define nlm4svc_decode_testres nlm4svc_decode_void
497−#define nlm4svc_decode_lockres nlm4svc_decode_void
498−#define nlm4svc_decode_unlockres nlm4svc_decode_void
499−#define nlm4svc_decode_cancelres nlm4svc_decode_void
500−#define nlm4svc_decode_grantedres nlm4svc_decode_void
501−
502−#define nlm4svc_proc_none nlm4svc_proc_null
503−#define nlm4svc_proc_test_res nlm4svc_proc_null
504−#define nlm4svc_proc_lock_res nlm4svc_proc_null
505−#define nlm4svc_proc_cancel_res nlm4svc_proc_null
506−#define nlm4svc_proc_unlock_res nlm4svc_proc_null
507−
508500 struct nlm_void { int dummy; };
509501
510−#define PROC(name, xargt, xrest, argt, rest, respsize) \
511− { .pc_func = nlm4svc_proc_##name, \
512− .pc_decode = nlm4svc_decode_##xargt, \
513− .pc_encode = nlm4svc_encode_##xrest, \
514− .pc_release = NULL, \
515− .pc_argsize = sizeof(struct nlm_##argt), \
516− .pc_ressize = sizeof(struct nlm_##rest), \
517− .pc_xdrressize = respsize, \
518− }
519502 #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */
520503 #define No (1+1024/4) /* netobj */
521504 #define St 1 /* status */
522505 #define Rg 4 /* range (offset + length) */
523−const struct svc_procedure nlmsvc_procedures4[] = {
524− PROC(null, void, void, void, void, 1),
525− PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg),
526− PROC(lock, lockargs, res, args, res, Ck+St),
527− PROC(cancel, cancargs, res, args, res, Ck+St),
528− PROC(unlock, unlockargs, res, args, res, Ck+St),
529− PROC(granted, testargs, res, args, res, Ck+St),
530− PROC(test_msg, testargs, norep, args, void, 1),
531− PROC(lock_msg, lockargs, norep, args, void, 1),
532− PROC(cancel_msg, cancargs, norep, args, void, 1),
533− PROC(unlock_msg, unlockargs, norep, args, void, 1),
534− PROC(granted_msg, testargs, norep, args, void, 1),
535− PROC(test_res, testres, norep, res, void, 1),
536− PROC(lock_res, lockres, norep, res, void, 1),
537− PROC(cancel_res, cancelres, norep, res, void, 1),
538− PROC(unlock_res, unlockres, norep, res, void, 1),
539− PROC(granted_res, res, norep, res, void, 1),
540− /* statd callback */
541− PROC(sm_notify, reboot, void, reboot, void, 1),
542− PROC(none, void, void, void, void, 0),
543− PROC(none, void, void, void, void, 0),
544− PROC(none, void, void, void, void, 0),
545− PROC(share, shareargs, shareres, args, res, Ck+St+1),
546− PROC(unshare, shareargs, shareres, args, res, Ck+St+1),
547− PROC(nm_lock, lockargs, res, args, res, Ck+St),
548− PROC(free_all, notify, void, args, void, 1),
549506
507+const struct svc_procedure nlmsvc_procedures4[24] = {
508+ [NLMPROC_NULL] = {
509+ .pc_func = nlm4svc_proc_null,
510+ .pc_decode = nlm4svc_decode_void,
511+ .pc_encode = nlm4svc_encode_void,
512+ .pc_argsize = sizeof(struct nlm_void),
513+ .pc_ressize = sizeof(struct nlm_void),
514+ .pc_xdrressize = St,
515+ },
516+ [NLMPROC_TEST] = {
517+ .pc_func = nlm4svc_proc_test,
518+ .pc_decode = nlm4svc_decode_testargs,
519+ .pc_encode = nlm4svc_encode_testres,
520+ .pc_argsize = sizeof(struct nlm_args),
521+ .pc_ressize = sizeof(struct nlm_res),
522+ .pc_xdrressize = Ck+St+2+No+Rg,
523+ },
524+ [NLMPROC_LOCK] = {
525+ .pc_func = nlm4svc_proc_lock,
526+ .pc_decode = nlm4svc_decode_lockargs,
527+ .pc_encode = nlm4svc_encode_res,
528+ .pc_argsize = sizeof(struct nlm_args),
529+ .pc_ressize = sizeof(struct nlm_res),
530+ .pc_xdrressize = Ck+St,
531+ },
532+ [NLMPROC_CANCEL] = {
533+ .pc_func = nlm4svc_proc_cancel,
534+ .pc_decode = nlm4svc_decode_cancargs,
535+ .pc_encode = nlm4svc_encode_res,
536+ .pc_argsize = sizeof(struct nlm_args),
537+ .pc_ressize = sizeof(struct nlm_res),
538+ .pc_xdrressize = Ck+St,
539+ },
540+ [NLMPROC_UNLOCK] = {
541+ .pc_func = nlm4svc_proc_unlock,
542+ .pc_decode = nlm4svc_decode_unlockargs,
543+ .pc_encode = nlm4svc_encode_res,
544+ .pc_argsize = sizeof(struct nlm_args),
545+ .pc_ressize = sizeof(struct nlm_res),
546+ .pc_xdrressize = Ck+St,
547+ },
548+ [NLMPROC_GRANTED] = {
549+ .pc_func = nlm4svc_proc_granted,
550+ .pc_decode = nlm4svc_decode_testargs,
551+ .pc_encode = nlm4svc_encode_res,
552+ .pc_argsize = sizeof(struct nlm_args),
553+ .pc_ressize = sizeof(struct nlm_res),
554+ .pc_xdrressize = Ck+St,
555+ },
556+ [NLMPROC_TEST_MSG] = {
557+ .pc_func = nlm4svc_proc_test_msg,
558+ .pc_decode = nlm4svc_decode_testargs,
559+ .pc_encode = nlm4svc_encode_void,
560+ .pc_argsize = sizeof(struct nlm_args),
561+ .pc_ressize = sizeof(struct nlm_void),
562+ .pc_xdrressize = St,
563+ },
564+ [NLMPROC_LOCK_MSG] = {
565+ .pc_func = nlm4svc_proc_lock_msg,
566+ .pc_decode = nlm4svc_decode_lockargs,
567+ .pc_encode = nlm4svc_encode_void,
568+ .pc_argsize = sizeof(struct nlm_args),
569+ .pc_ressize = sizeof(struct nlm_void),
570+ .pc_xdrressize = St,
571+ },
572+ [NLMPROC_CANCEL_MSG] = {
573+ .pc_func = nlm4svc_proc_cancel_msg,
574+ .pc_decode = nlm4svc_decode_cancargs,
575+ .pc_encode = nlm4svc_encode_void,
576+ .pc_argsize = sizeof(struct nlm_args),
577+ .pc_ressize = sizeof(struct nlm_void),
578+ .pc_xdrressize = St,
579+ },
580+ [NLMPROC_UNLOCK_MSG] = {
581+ .pc_func = nlm4svc_proc_unlock_msg,
582+ .pc_decode = nlm4svc_decode_unlockargs,
583+ .pc_encode = nlm4svc_encode_void,
584+ .pc_argsize = sizeof(struct nlm_args),
585+ .pc_ressize = sizeof(struct nlm_void),
586+ .pc_xdrressize = St,
587+ },
588+ [NLMPROC_GRANTED_MSG] = {
589+ .pc_func = nlm4svc_proc_granted_msg,
590+ .pc_decode = nlm4svc_decode_testargs,
591+ .pc_encode = nlm4svc_encode_void,
592+ .pc_argsize = sizeof(struct nlm_args),
593+ .pc_ressize = sizeof(struct nlm_void),
594+ .pc_xdrressize = St,
595+ },
596+ [NLMPROC_TEST_RES] = {
597+ .pc_func = nlm4svc_proc_null,
598+ .pc_decode = nlm4svc_decode_void,
599+ .pc_encode = nlm4svc_encode_void,
600+ .pc_argsize = sizeof(struct nlm_res),
601+ .pc_ressize = sizeof(struct nlm_void),
602+ .pc_xdrressize = St,
603+ },
604+ [NLMPROC_LOCK_RES] = {
605+ .pc_func = nlm4svc_proc_null,
606+ .pc_decode = nlm4svc_decode_void,
607+ .pc_encode = nlm4svc_encode_void,
608+ .pc_argsize = sizeof(struct nlm_res),
609+ .pc_ressize = sizeof(struct nlm_void),
610+ .pc_xdrressize = St,
611+ },
612+ [NLMPROC_CANCEL_RES] = {
613+ .pc_func = nlm4svc_proc_null,
614+ .pc_decode = nlm4svc_decode_void,
615+ .pc_encode = nlm4svc_encode_void,
616+ .pc_argsize = sizeof(struct nlm_res),
617+ .pc_ressize = sizeof(struct nlm_void),
618+ .pc_xdrressize = St,
619+ },
620+ [NLMPROC_UNLOCK_RES] = {
621+ .pc_func = nlm4svc_proc_null,
622+ .pc_decode = nlm4svc_decode_void,
623+ .pc_encode = nlm4svc_encode_void,
624+ .pc_argsize = sizeof(struct nlm_res),
625+ .pc_ressize = sizeof(struct nlm_void),
626+ .pc_xdrressize = St,
627+ },
628+ [NLMPROC_GRANTED_RES] = {
629+ .pc_func = nlm4svc_proc_granted_res,
630+ .pc_decode = nlm4svc_decode_res,
631+ .pc_encode = nlm4svc_encode_void,
632+ .pc_argsize = sizeof(struct nlm_res),
633+ .pc_ressize = sizeof(struct nlm_void),
634+ .pc_xdrressize = St,
635+ },
636+ [NLMPROC_NSM_NOTIFY] = {
637+ .pc_func = nlm4svc_proc_sm_notify,
638+ .pc_decode = nlm4svc_decode_reboot,
639+ .pc_encode = nlm4svc_encode_void,
640+ .pc_argsize = sizeof(struct nlm_reboot),
641+ .pc_ressize = sizeof(struct nlm_void),
642+ .pc_xdrressize = St,
643+ },
644+ [17] = {
645+ .pc_func = nlm4svc_proc_unused,
646+ .pc_decode = nlm4svc_decode_void,
647+ .pc_encode = nlm4svc_encode_void,
648+ .pc_argsize = sizeof(struct nlm_void),
649+ .pc_ressize = sizeof(struct nlm_void),
650+ .pc_xdrressize = 0,
651+ },
652+ [18] = {
653+ .pc_func = nlm4svc_proc_unused,
654+ .pc_decode = nlm4svc_decode_void,
655+ .pc_encode = nlm4svc_encode_void,
656+ .pc_argsize = sizeof(struct nlm_void),
657+ .pc_ressize = sizeof(struct nlm_void),
658+ .pc_xdrressize = 0,
659+ },
660+ [19] = {
661+ .pc_func = nlm4svc_proc_unused,
662+ .pc_decode = nlm4svc_decode_void,
663+ .pc_encode = nlm4svc_encode_void,
664+ .pc_argsize = sizeof(struct nlm_void),
665+ .pc_ressize = sizeof(struct nlm_void),
666+ .pc_xdrressize = 0,
667+ },
668+ [NLMPROC_SHARE] = {
669+ .pc_func = nlm4svc_proc_share,
670+ .pc_decode = nlm4svc_decode_shareargs,
671+ .pc_encode = nlm4svc_encode_shareres,
672+ .pc_argsize = sizeof(struct nlm_args),
673+ .pc_ressize = sizeof(struct nlm_res),
674+ .pc_xdrressize = Ck+St+1,
675+ },
676+ [NLMPROC_UNSHARE] = {
677+ .pc_func = nlm4svc_proc_unshare,
678+ .pc_decode = nlm4svc_decode_shareargs,
679+ .pc_encode = nlm4svc_encode_shareres,
680+ .pc_argsize = sizeof(struct nlm_args),
681+ .pc_ressize = sizeof(struct nlm_res),
682+ .pc_xdrressize = Ck+St+1,
683+ },
684+ [NLMPROC_NM_LOCK] = {
685+ .pc_func = nlm4svc_proc_nm_lock,
686+ .pc_decode = nlm4svc_decode_lockargs,
687+ .pc_encode = nlm4svc_encode_res,
688+ .pc_argsize = sizeof(struct nlm_args),
689+ .pc_ressize = sizeof(struct nlm_res),
690+ .pc_xdrressize = Ck+St,
691+ },
692+ [NLMPROC_FREE_ALL] = {
693+ .pc_func = nlm4svc_proc_free_all,
694+ .pc_decode = nlm4svc_decode_notify,
695+ .pc_encode = nlm4svc_encode_void,
696+ .pc_argsize = sizeof(struct nlm_args),
697+ .pc_ressize = sizeof(struct nlm_void),
698+ .pc_xdrressize = St,
699+ },
550700 };
fs/lockd/svcproc.c+199−51
@@ -529,66 +529,214 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp) · 528 unmodified lines
529529 return rpc_success;
530530 }
531531
532+static __be32
533+nlmsvc_proc_unused(struct svc_rqst *rqstp)
534+{
535+ return rpc_proc_unavail;
536+}
537+
532538 /*
533539 * NLM Server procedures.
534540 */
535541
536−#define nlmsvc_encode_norep nlmsvc_encode_void
537−#define nlmsvc_decode_norep nlmsvc_decode_void
538−#define nlmsvc_decode_testres nlmsvc_decode_void
539−#define nlmsvc_decode_lockres nlmsvc_decode_void
540−#define nlmsvc_decode_unlockres nlmsvc_decode_void
541−#define nlmsvc_decode_cancelres nlmsvc_decode_void
542−#define nlmsvc_decode_grantedres nlmsvc_decode_void
543−
544−#define nlmsvc_proc_none nlmsvc_proc_null
545−#define nlmsvc_proc_test_res nlmsvc_proc_null
546−#define nlmsvc_proc_lock_res nlmsvc_proc_null
547−#define nlmsvc_proc_cancel_res nlmsvc_proc_null
548−#define nlmsvc_proc_unlock_res nlmsvc_proc_null
549−
550542 struct nlm_void { int dummy; };
551543
552−#define PROC(name, xargt, xrest, argt, rest, respsize) \
553− { .pc_func = nlmsvc_proc_##name, \
554− .pc_decode = nlmsvc_decode_##xargt, \
555− .pc_encode = nlmsvc_encode_##xrest, \
556− .pc_release = NULL, \
557− .pc_argsize = sizeof(struct nlm_##argt), \
558− .pc_ressize = sizeof(struct nlm_##rest), \
559− .pc_xdrressize = respsize, \
560− }
561−
562544 #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */
563545 #define St 1 /* status */
564546 #define No (1+1024/4) /* Net Obj */
565547 #define Rg 2 /* range - offset + size */
566548
567−const struct svc_procedure nlmsvc_procedures[] = {
568− PROC(null, void, void, void, void, 1),
569− PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg),
570− PROC(lock, lockargs, res, args, res, Ck+St),
571− PROC(cancel, cancargs, res, args, res, Ck+St),
572− PROC(unlock, unlockargs, res, args, res, Ck+St),
573− PROC(granted, testargs, res, args, res, Ck+St),
574− PROC(test_msg, testargs, norep, args, void, 1),
575− PROC(lock_msg, lockargs, norep, args, void, 1),
576− PROC(cancel_msg, cancargs, norep, args, void, 1),
577− PROC(unlock_msg, unlockargs, norep, args, void, 1),
578− PROC(granted_msg, testargs, norep, args, void, 1),
579− PROC(test_res, testres, norep, res, void, 1),
580− PROC(lock_res, lockres, norep, res, void, 1),
581− PROC(cancel_res, cancelres, norep, res, void, 1),
582− PROC(unlock_res, unlockres, norep, res, void, 1),
583− PROC(granted_res, res, norep, res, void, 1),
584− /* statd callback */
585− PROC(sm_notify, reboot, void, reboot, void, 1),
586− PROC(none, void, void, void, void, 1),
587− PROC(none, void, void, void, void, 1),
588− PROC(none, void, void, void, void, 1),
589− PROC(share, shareargs, shareres, args, res, Ck+St+1),
590− PROC(unshare, shareargs, shareres, args, res, Ck+St+1),
591− PROC(nm_lock, lockargs, res, args, res, Ck+St),
592− PROC(free_all, notify, void, args, void, 0),
593−
549+const struct svc_procedure nlmsvc_procedures[24] = {
550+ [NLMPROC_NULL] = {
551+ .pc_func = nlmsvc_proc_null,
552+ .pc_decode = nlmsvc_decode_void,
553+ .pc_encode = nlmsvc_encode_void,
554+ .pc_argsize = sizeof(struct nlm_void),
555+ .pc_ressize = sizeof(struct nlm_void),
556+ .pc_xdrressize = St,
557+ },
558+ [NLMPROC_TEST] = {
559+ .pc_func = nlmsvc_proc_test,
560+ .pc_decode = nlmsvc_decode_testargs,
561+ .pc_encode = nlmsvc_encode_testres,
562+ .pc_argsize = sizeof(struct nlm_args),
563+ .pc_ressize = sizeof(struct nlm_res),
564+ .pc_xdrressize = Ck+St+2+No+Rg,
565+ },
566+ [NLMPROC_LOCK] = {
567+ .pc_func = nlmsvc_proc_lock,
568+ .pc_decode = nlmsvc_decode_lockargs,
569+ .pc_encode = nlmsvc_encode_res,
570+ .pc_argsize = sizeof(struct nlm_args),
571+ .pc_ressize = sizeof(struct nlm_res),
572+ .pc_xdrressize = Ck+St,
573+ },
574+ [NLMPROC_CANCEL] = {
575+ .pc_func = nlmsvc_proc_cancel,
576+ .pc_decode = nlmsvc_decode_cancargs,
577+ .pc_encode = nlmsvc_encode_res,
578+ .pc_argsize = sizeof(struct nlm_args),
579+ .pc_ressize = sizeof(struct nlm_res),
580+ .pc_xdrressize = Ck+St,
581+ },
582+ [NLMPROC_UNLOCK] = {
583+ .pc_func = nlmsvc_proc_unlock,
584+ .pc_decode = nlmsvc_decode_unlockargs,
585+ .pc_encode = nlmsvc_encode_res,
586+ .pc_argsize = sizeof(struct nlm_args),
587+ .pc_ressize = sizeof(struct nlm_res),
588+ .pc_xdrressize = Ck+St,
589+ },
590+ [NLMPROC_GRANTED] = {
591+ .pc_func = nlmsvc_proc_granted,
592+ .pc_decode = nlmsvc_decode_testargs,
593+ .pc_encode = nlmsvc_encode_res,
594+ .pc_argsize = sizeof(struct nlm_args),
595+ .pc_ressize = sizeof(struct nlm_res),
596+ .pc_xdrressize = Ck+St,
597+ },
598+ [NLMPROC_TEST_MSG] = {
599+ .pc_func = nlmsvc_proc_test_msg,
600+ .pc_decode = nlmsvc_decode_testargs,
601+ .pc_encode = nlmsvc_encode_void,
602+ .pc_argsize = sizeof(struct nlm_args),
603+ .pc_ressize = sizeof(struct nlm_void),
604+ .pc_xdrressize = St,
605+ },
606+ [NLMPROC_LOCK_MSG] = {
607+ .pc_func = nlmsvc_proc_lock_msg,
608+ .pc_decode = nlmsvc_decode_lockargs,
609+ .pc_encode = nlmsvc_encode_void,
610+ .pc_argsize = sizeof(struct nlm_args),
611+ .pc_ressize = sizeof(struct nlm_void),
612+ .pc_xdrressize = St,
613+ },
614+ [NLMPROC_CANCEL_MSG] = {
615+ .pc_func = nlmsvc_proc_cancel_msg,
616+ .pc_decode = nlmsvc_decode_cancargs,
617+ .pc_encode = nlmsvc_encode_void,
618+ .pc_argsize = sizeof(struct nlm_args),
619+ .pc_ressize = sizeof(struct nlm_void),
620+ .pc_xdrressize = St,
621+ },
622+ [NLMPROC_UNLOCK_MSG] = {
623+ .pc_func = nlmsvc_proc_unlock_msg,
624+ .pc_decode = nlmsvc_decode_unlockargs,
625+ .pc_encode = nlmsvc_encode_void,
626+ .pc_argsize = sizeof(struct nlm_args),
627+ .pc_ressize = sizeof(struct nlm_void),
628+ .pc_xdrressize = St,
629+ },
630+ [NLMPROC_GRANTED_MSG] = {
631+ .pc_func = nlmsvc_proc_granted_msg,
632+ .pc_decode = nlmsvc_decode_testargs,
633+ .pc_encode = nlmsvc_encode_void,
634+ .pc_argsize = sizeof(struct nlm_args),
635+ .pc_ressize = sizeof(struct nlm_void),
636+ .pc_xdrressize = St,
637+ },
638+ [NLMPROC_TEST_RES] = {
639+ .pc_func = nlmsvc_proc_null,
640+ .pc_decode = nlmsvc_decode_void,
641+ .pc_encode = nlmsvc_encode_void,
642+ .pc_argsize = sizeof(struct nlm_res),
643+ .pc_ressize = sizeof(struct nlm_void),
644+ .pc_xdrressize = St,
645+ },
646+ [NLMPROC_LOCK_RES] = {
647+ .pc_func = nlmsvc_proc_null,
648+ .pc_decode = nlmsvc_decode_void,
649+ .pc_encode = nlmsvc_encode_void,
650+ .pc_argsize = sizeof(struct nlm_res),
651+ .pc_ressize = sizeof(struct nlm_void),
652+ .pc_xdrressize = St,
653+ },
654+ [NLMPROC_CANCEL_RES] = {
655+ .pc_func = nlmsvc_proc_null,
656+ .pc_decode = nlmsvc_decode_void,
657+ .pc_encode = nlmsvc_encode_void,
658+ .pc_argsize = sizeof(struct nlm_res),
659+ .pc_ressize = sizeof(struct nlm_void),
660+ .pc_xdrressize = St,
661+ },
662+ [NLMPROC_UNLOCK_RES] = {
663+ .pc_func = nlmsvc_proc_null,
664+ .pc_decode = nlmsvc_decode_void,
665+ .pc_encode = nlmsvc_encode_void,
666+ .pc_argsize = sizeof(struct nlm_res),
667+ .pc_ressize = sizeof(struct nlm_void),
668+ .pc_xdrressize = St,
669+ },
670+ [NLMPROC_GRANTED_RES] = {
671+ .pc_func = nlmsvc_proc_granted_res,
672+ .pc_decode = nlmsvc_decode_res,
673+ .pc_encode = nlmsvc_encode_void,
674+ .pc_argsize = sizeof(struct nlm_res),
675+ .pc_ressize = sizeof(struct nlm_void),
676+ .pc_xdrressize = St,
677+ },
678+ [NLMPROC_NSM_NOTIFY] = {
679+ .pc_func = nlmsvc_proc_sm_notify,
680+ .pc_decode = nlmsvc_decode_reboot,
681+ .pc_encode = nlmsvc_encode_void,
682+ .pc_argsize = sizeof(struct nlm_reboot),
683+ .pc_ressize = sizeof(struct nlm_void),
684+ .pc_xdrressize = St,
685+ },
686+ [17] = {
687+ .pc_func = nlmsvc_proc_unused,
688+ .pc_decode = nlmsvc_decode_void,
689+ .pc_encode = nlmsvc_encode_void,
690+ .pc_argsize = sizeof(struct nlm_void),
691+ .pc_ressize = sizeof(struct nlm_void),
692+ .pc_xdrressize = St,
693+ },
694+ [18] = {
695+ .pc_func = nlmsvc_proc_unused,
696+ .pc_decode = nlmsvc_decode_void,
697+ .pc_encode = nlmsvc_encode_void,
698+ .pc_argsize = sizeof(struct nlm_void),
699+ .pc_ressize = sizeof(struct nlm_void),
700+ .pc_xdrressize = St,
701+ },
702+ [19] = {
703+ .pc_func = nlmsvc_proc_unused,
704+ .pc_decode = nlmsvc_decode_void,
705+ .pc_encode = nlmsvc_encode_void,
706+ .pc_argsize = sizeof(struct nlm_void),
707+ .pc_ressize = sizeof(struct nlm_void),
708+ .pc_xdrressize = St,
709+ },
710+ [NLMPROC_SHARE] = {
711+ .pc_func = nlmsvc_proc_share,
712+ .pc_decode = nlmsvc_decode_shareargs,
713+ .pc_encode = nlmsvc_encode_shareres,
714+ .pc_argsize = sizeof(struct nlm_args),
715+ .pc_ressize = sizeof(struct nlm_res),
716+ .pc_xdrressize = Ck+St+1,
717+ },
718+ [NLMPROC_UNSHARE] = {
719+ .pc_func = nlmsvc_proc_unshare,
720+ .pc_decode = nlmsvc_decode_shareargs,
721+ .pc_encode = nlmsvc_encode_shareres,
722+ .pc_argsize = sizeof(struct nlm_args),
723+ .pc_ressize = sizeof(struct nlm_res),
724+ .pc_xdrressize = Ck+St+1,
725+ },
726+ [NLMPROC_NM_LOCK] = {
727+ .pc_func = nlmsvc_proc_nm_lock,
728+ .pc_decode = nlmsvc_decode_lockargs,
729+ .pc_encode = nlmsvc_encode_res,
730+ .pc_argsize = sizeof(struct nlm_args),
731+ .pc_ressize = sizeof(struct nlm_res),
732+ .pc_xdrressize = Ck+St,
733+ },
734+ [NLMPROC_FREE_ALL] = {
735+ .pc_func = nlmsvc_proc_free_all,
736+ .pc_decode = nlmsvc_decode_notify,
737+ .pc_encode = nlmsvc_encode_void,
738+ .pc_argsize = sizeof(struct nlm_args),
739+ .pc_ressize = sizeof(struct nlm_void),
740+ .pc_xdrressize = 0,
741+ },
594742 };
fs/nfs/nfs4file.c+32−6
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include <linux/falloc.h>
1010 #include <linux/mount.h>
1111 #include <linux/nfs_fs.h>
12+#include <linux/nfs_ssc.h>
1213 #include "delegation.h"
1314 #include "internal.h"
1415 #include "iostat.h"
@@ -315,9 +316,8 @@ out: · 300 unmodified lines
315316 static int read_name_gen = 1;
316317 #define SSC_READ_NAME_BODY "ssc_read_%d"
317318
318−struct file *
319−nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
320− nfs4_stateid *stateid)
319+static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
320+ struct nfs_fh *src_fh, nfs4_stateid *stateid)
321321 {
322322 struct nfs_fattr fattr;
323323 struct file *filep, *res;
@@ -399,14 +399,40 @@ out_filep: · 75 unmodified lines
399399 fput(filep);
400400 goto out_free_name;
401401 }
402−EXPORT_SYMBOL_GPL(nfs42_ssc_open);
403−void nfs42_ssc_close(struct file *filep)
402+
403+static void __nfs42_ssc_close(struct file *filep)
404404 {
405405 struct nfs_open_context *ctx = nfs_file_open_context(filep);
406406
407407 ctx->state->flags = 0;
408408 }
409−EXPORT_SYMBOL_GPL(nfs42_ssc_close);
409+
410+static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = {
411+ .sco_open = __nfs42_ssc_open,
412+ .sco_close = __nfs42_ssc_close,
413+};
414+
415+/**
416+ * nfs42_ssc_register_ops - Wrapper to register NFS_V4 ops in nfs_common
417+ *
418+ * Return values:
419+ * None
420+ */
421+void nfs42_ssc_register_ops(void)
422+{
423+ nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl);
424+}
425+
426+/**
427+ * nfs42_ssc_unregister_ops - wrapper to un-register NFS_V4 ops in nfs_common
428+ *
429+ * Return values:
430+ * None.
431+ */
432+void nfs42_ssc_unregister_ops(void)
433+{
434+ nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl);
435+}
410436 #endif /* CONFIG_NFS_V4_2 */
411437
412438 const struct file_operations nfs4_file_operations = {
fs/nfs/nfs4super.c+5−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
77 #include <linux/mount.h>
88 #include <linux/nfs4_mount.h>
99 #include <linux/nfs_fs.h>
10+#include <linux/nfs_ssc.h>
1011 #include "delegation.h"
1112 #include "internal.h"
1213 #include "nfs4_fs.h"
@@ -279,6 +280,9 @@ static int __init init_nfs_v4(void) · 266 unmodified lines
279280 if (err)
280281 goto out2;
281282
283+#ifdef CONFIG_NFS_V4_2
284+ nfs42_ssc_register_ops();
285+#endif
282286 register_nfs_version(&nfs_v4);
283287 return 0;
284288 out2:
@@ -297,6 +301,7 @@ static void __exit exit_nfs_v4(void) · 12 unmodified lines
297301 unregister_nfs_version(&nfs_v4);
298302 #ifdef CONFIG_NFS_V4_2
299303 nfs4_xattr_cache_exit();
304+ nfs42_ssc_unregister_ops();
300305 #endif
301306 nfs4_unregister_sysctl();
302307 nfs_idmap_quit();
fs/nfs/super.c+17−0
@@ -57,6 +57,7 @@ · 56 unmodified lines
5757 #include <linux/rcupdate.h>
5858
5959 #include <linux/uaccess.h>
60+#include <linux/nfs_ssc.h>
6061
6162 #include "nfs4_fs.h"
6263 #include "callback.h"
@@ -85,6 +86,10 @@ const struct super_operations nfs_sops = { · 22 unmodified lines
8586 };
8687 EXPORT_SYMBOL_GPL(nfs_sops);
8788
89+static const struct nfs_ssc_client_ops nfs_ssc_clnt_ops_tbl = {
90+ .sco_sb_deactive = nfs_sb_deactive,
91+};
92+
8893 #if IS_ENABLED(CONFIG_NFS_V4)
8994 static int __init register_nfs4_fs(void)
9095 {
@@ -106,6 +111,16 @@ static void unregister_nfs4_fs(void) · 15 unmodified lines
106111 }
107112 #endif
108113
114+static void nfs_ssc_register_ops(void)
115+{
116+ nfs_ssc_register(&nfs_ssc_clnt_ops_tbl);
117+}
118+
119+static void nfs_ssc_unregister_ops(void)
120+{
121+ nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl);
122+}
123+
109124 static struct shrinker acl_shrinker = {
110125 .count_objects = nfs_access_cache_count,
111126 .scan_objects = nfs_access_cache_scan,
@@ -133,6 +148,7 @@ int __init register_nfs_fs(void) · 21 unmodified lines
133148 ret = register_shrinker(&acl_shrinker);
134149 if (ret < 0)
135150 goto error_3;
151+ nfs_ssc_register_ops();
136152 return 0;
137153 error_3:
138154 nfs_unregister_sysctl();
@@ -152,6 +168,7 @@ void __exit unregister_nfs_fs(void) · 13 unmodified lines
152168 unregister_shrinker(&acl_shrinker);
153169 nfs_unregister_sysctl();
154170 unregister_nfs4_fs();
171+ nfs_ssc_unregister_ops();
155172 unregister_filesystem(&nfs_fs_type);
156173 }
157174
fs/nfs_common/Makefile+1−0
@@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o · 6 unmodified lines
77 nfs_acl-objs := nfsacl.o
88
99 obj-$(CONFIG_GRACE_PERIOD) += grace.o
10+obj-$(CONFIG_GRACE_PERIOD) += nfs_ssc.o
fs/nfs_common/nfs_ssc.c+94−0
@@ -0,0 +1,94 @@
1+// SPDX-License-Identifier: GPL-2.0-only
2+/*
3+ * fs/nfs_common/nfs_ssc_comm.c
4+ *
5+ * Helper for knfsd's SSC to access ops in NFS client modules
6+ *
7+ * Author: Dai Ngo <dai.ngo@oracle.com>
8+ *
9+ * Copyright (c) 2020, Oracle and/or its affiliates.
10+ */
11+
12+#include <linux/module.h>
13+#include <linux/fs.h>
14+#include <linux/nfs_ssc.h>
15+#include "../nfs/nfs4_fs.h"
16+
17+MODULE_LICENSE("GPL");
18+
19+struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
20+EXPORT_SYMBOL_GPL(nfs_ssc_client_tbl);
21+
22+#ifdef CONFIG_NFS_V4_2
23+/**
24+ * nfs42_ssc_register - install the NFS_V4 client ops in the nfs_ssc_client_tbl
25+ * @ops: NFS_V4 ops to be installed
26+ *
27+ * Return values:
28+ * None
29+ */
30+void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops)
31+{
32+ nfs_ssc_client_tbl.ssc_nfs4_ops = ops;
33+}
34+EXPORT_SYMBOL_GPL(nfs42_ssc_register);
35+
36+/**
37+ * nfs42_ssc_unregister - uninstall the NFS_V4 client ops from
38+ * the nfs_ssc_client_tbl
39+ * @ops: ops to be uninstalled
40+ *
41+ * Return values:
42+ * None
43+ */
44+void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops)
45+{
46+ if (nfs_ssc_client_tbl.ssc_nfs4_ops != ops)
47+ return;
48+
49+ nfs_ssc_client_tbl.ssc_nfs4_ops = NULL;
50+}
51+EXPORT_SYMBOL_GPL(nfs42_ssc_unregister);
52+#endif /* CONFIG_NFS_V4_2 */
53+
54+#ifdef CONFIG_NFS_V4_2
55+/**
56+ * nfs_ssc_register - install the NFS_FS client ops in the nfs_ssc_client_tbl
57+ * @ops: NFS_FS ops to be installed
58+ *
59+ * Return values:
60+ * None
61+ */
62+void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
63+{
64+ nfs_ssc_client_tbl.ssc_nfs_ops = ops;
65+}
66+EXPORT_SYMBOL_GPL(nfs_ssc_register);
67+
68+/**
69+ * nfs_ssc_unregister - uninstall the NFS_FS client ops from
70+ * the nfs_ssc_client_tbl
71+ * @ops: ops to be uninstalled
72+ *
73+ * Return values:
74+ * None
75+ */
76+void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
77+{
78+ if (nfs_ssc_client_tbl.ssc_nfs_ops != ops)
79+ return;
80+ nfs_ssc_client_tbl.ssc_nfs_ops = NULL;
81+}
82+EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
83+
84+#else
85+void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
86+{
87+}
88+EXPORT_SYMBOL_GPL(nfs_ssc_register);
89+
90+void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
91+{
92+}
93+EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
94+#endif /* CONFIG_NFS_V4_2 */
fs/nfsd/Kconfig+1−11
@@ -136,7 +136,7 @@ config NFSD_FLEXFILELAYOUT · 135 unmodified lines
136136
137137 config NFSD_V4_2_INTER_SSC
138138 bool "NFSv4.2 inter server to server COPY"
139− depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 && NFS_FS=y
139+ depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
140140 help
141141 This option enables support for NFSv4.2 inter server to
142142 server copy where the destination server calls the NFSv4.2
@@ -156,13 +156,3 @@ config NFSD_V4_SECURITY_LABEL · 13 unmodified lines
156156
157157 If you do not wish to enable fine-grained security labels SELinux or
158158 Smack policies on NFSv4 files, say N.
159−
160−config NFSD_FAULT_INJECTION
161− bool "NFS server manual fault injection"
162− depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS && BROKEN
163− help
164− This option enables support for manually injecting faults
165− into the NFS server. This is intended to be used for
166− testing error recovery on the NFS client.
167−
168− If unsure, say N.
fs/nfsd/Makefile+0−1
@@ -13,7 +13,6 @@ nfsd-y += trace.o · 12 unmodified lines
1313 nfsd-y += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
1414 export.o auth.o lockd.o nfscache.o nfsxdr.o \
1515 stats.o filecache.o
16−nfsd-$(CONFIG_NFSD_FAULT_INJECTION) += fault_inject.o
1716 nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
1817 nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
1918 nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
fs/nfsd/export.c+1−1
@@ -1002,7 +1002,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) · 1001 unmodified lines
10021002 if (nfsd4_spo_must_allow(rqstp))
10031003 return 0;
10041004
1005− return nfserr_wrongsec;
1005+ return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
10061006 }
10071007
10081008 /*
fs/nfsd/filecache.c+1−1
@@ -889,7 +889,7 @@ nfsd_file_find_locked(struct inode *inode, unsigned int may_flags, · 888 unmodified lines
889889
890890 hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head,
891891 nf_node, lockdep_is_held(&nfsd_file_hashtbl[hashval].nfb_lock)) {
892− if ((need & nf->nf_may) != need)
892+ if (nf->nf_may != need)
893893 continue;
894894 if (nf->nf_inode != inode)
895895 continue;
fs/nfsd/nfs2acl.c+104−56
@@ -14,7 +14,6 @@ · 13 unmodified lines
1414 #include "vfs.h"
1515
1616 #define NFSDDBG_FACILITY NFSDDBG_PROC
17−#define RETURN_STATUS(st) { resp->status = (st); return (st); }
1817
1918 /*
2019 * NULL call.
@@ -22,7 +21,7 @@ · 1 unmodified line
2221 static __be32
2322 nfsacld_proc_null(struct svc_rqst *rqstp)
2423 {
25− return nfs_ok;
24+ return rpc_success;
2625 }
2726
2827 /*
@@ -35,24 +34,25 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 6 unmodified lines
3534 struct posix_acl *acl;
3635 struct inode *inode;
3736 svc_fh *fh;
38− __be32 nfserr = 0;
3937
4038 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
4139
4240 fh = fh_copy(&resp->fh, &argp->fh);
43− nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
44− if (nfserr)
45− RETURN_STATUS(nfserr);
41+ resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
42+ if (resp->status != nfs_ok)
43+ goto out;
4644
4745 inode = d_inode(fh->fh_dentry);
4846
49− if (argp->mask & ~NFS_ACL_MASK)
50− RETURN_STATUS(nfserr_inval);
47+ if (argp->mask & ~NFS_ACL_MASK) {
48+ resp->status = nfserr_inval;
49+ goto out;
50+ }
5151 resp->mask = argp->mask;
5252
53− nfserr = fh_getattr(fh, &resp->stat);
54− if (nfserr)
55− RETURN_STATUS(nfserr);
53+ resp->status = fh_getattr(fh, &resp->stat);
54+ if (resp->status != nfs_ok)
55+ goto out;
5656
5757 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
5858 acl = get_acl(inode, ACL_TYPE_ACCESS);
@@ -61,7 +61,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 2 unmodified lines
6161 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
6262 }
6363 if (IS_ERR(acl)) {
64− nfserr = nfserrno(PTR_ERR(acl));
64+ resp->status = nfserrno(PTR_ERR(acl));
6565 goto fail;
6666 }
6767 resp->acl_access = acl;
@@ -71,19 +71,20 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines
7171 of a non-directory! */
7272 acl = get_acl(inode, ACL_TYPE_DEFAULT);
7373 if (IS_ERR(acl)) {
74− nfserr = nfserrno(PTR_ERR(acl));
74+ resp->status = nfserrno(PTR_ERR(acl));
7575 goto fail;
7676 }
7777 resp->acl_default = acl;
7878 }
7979
8080 /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
81− RETURN_STATUS(0);
81+out:
82+ return rpc_success;
8283
8384 fail:
8485 posix_acl_release(resp->acl_access);
8586 posix_acl_release(resp->acl_default);
86− RETURN_STATUS(nfserr);
87+ goto out;
8788 }
8889
8990 /*
@@ -95,14 +96,13 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp) · 5 unmodified lines
9596 struct nfsd_attrstat *resp = rqstp->rq_resp;
9697 struct inode *inode;
9798 svc_fh *fh;
98− __be32 nfserr = 0;
9999 int error;
100100
101101 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
102102
103103 fh = fh_copy(&resp->fh, &argp->fh);
104− nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
105− if (nfserr)
104+ resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
105+ if (resp->status != nfs_ok)
106106 goto out;
107107
108108 inode = d_inode(fh->fh_dentry);
@@ -124,19 +124,20 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp) · 15 unmodified lines
124124
125125 fh_drop_write(fh);
126126
127− nfserr = fh_getattr(fh, &resp->stat);
127+ resp->status = fh_getattr(fh, &resp->stat);
128128
129129 out:
130130 /* argp->acl_{access,default} may have been allocated in
131131 nfssvc_decode_setaclargs. */
132132 posix_acl_release(argp->acl_access);
133133 posix_acl_release(argp->acl_default);
134− return nfserr;
134+ return rpc_success;
135+
135136 out_drop_lock:
136137 fh_unlock(fh);
137138 fh_drop_write(fh);
138139 out_errno:
139− nfserr = nfserrno(error);
140+ resp->status = nfserrno(error);
140141 goto out;
141142 }
142143
@@ -147,15 +148,16 @@ static __be32 nfsacld_proc_getattr(struct svc_rqst *rqstp) · 4 unmodified lines
147148 {
148149 struct nfsd_fhandle *argp = rqstp->rq_argp;
149150 struct nfsd_attrstat *resp = rqstp->rq_resp;
150− __be32 nfserr;
151+
151152 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
152153
153154 fh_copy(&resp->fh, &argp->fh);
154− nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
155− if (nfserr)
156− return nfserr;
157− nfserr = fh_getattr(&resp->fh, &resp->stat);
158− return nfserr;
155+ resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
156+ if (resp->status != nfs_ok)
157+ goto out;
158+ resp->status = fh_getattr(&resp->fh, &resp->stat);
159+out:
160+ return rpc_success;
159161 }
160162
161163 /*
@@ -165,7 +167,6 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp) · 3 unmodified lines
165167 {
166168 struct nfsd3_accessargs *argp = rqstp->rq_argp;
167169 struct nfsd3_accessres *resp = rqstp->rq_resp;
168− __be32 nfserr;
169170
170171 dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
171172 SVCFH_fmt(&argp->fh),
@@ -173,16 +174,22 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp) · 1 unmodified line
173174
174175 fh_copy(&resp->fh, &argp->fh);
175176 resp->access = argp->access;
176− nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
177− if (nfserr)
178− return nfserr;
179− nfserr = fh_getattr(&resp->fh, &resp->stat);
180− return nfserr;
177+ resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
178+ if (resp->status != nfs_ok)
179+ goto out;
180+ resp->status = fh_getattr(&resp->fh, &resp->stat);
181+out:
182+ return rpc_success;
181183 }
182184
183185 /*
184186 * XDR decode functions
185187 */
188+static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
189+{
190+ return 1;
191+}
192+
186193 static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
187194 {
188195 struct nfsd3_getaclargs *argp = rqstp->rq_argp;
@@ -268,6 +275,10 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) · 79 unmodified lines
268275 int n;
269276 int w;
270277
278+ *p++ = resp->status;
279+ if (resp->status != nfs_ok)
280+ return xdr_ressize_check(rqstp, p);
281+
271282 /*
272283 * Since this is version 2, the check for nfserr in
273284 * nfsd_dispatch actually ensures the following cannot happen.
@@ -307,7 +318,12 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p) · 33 unmodified lines
307318 {
308319 struct nfsd_attrstat *resp = rqstp->rq_resp;
309320
321+ *p++ = resp->status;
322+ if (resp->status != nfs_ok)
323+ goto out;
324+
310325 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
326+out:
311327 return xdr_ressize_check(rqstp, p);
312328 }
313329
@@ -316,8 +332,13 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p) · 2 unmodified lines
316332 {
317333 struct nfsd3_accessres *resp = rqstp->rq_resp;
318334
335+ *p++ = resp->status;
336+ if (resp->status != nfs_ok)
337+ goto out;
338+
319339 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
320340 *p++ = htonl(resp->access);
341+out:
321342 return xdr_ressize_check(rqstp, p);
322343 }
323344
@@ -347,36 +368,63 @@ static void nfsaclsvc_release_access(struct svc_rqst *rqstp) · 23 unmodified lines
347368 fh_put(&resp->fh);
348369 }
349370
350−#define nfsaclsvc_decode_voidargs NULL
351−#define nfsaclsvc_release_void NULL
352−#define nfsd3_fhandleargs nfsd_fhandle
353−#define nfsd3_attrstatres nfsd_attrstat
354−#define nfsd3_voidres nfsd3_voidargs
355371 struct nfsd3_voidargs { int dummy; };
356372
357−#define PROC(name, argt, rest, relt, cache, respsize) \
358−{ \
359− .pc_func = nfsacld_proc_##name, \
360− .pc_decode = nfsaclsvc_decode_##argt##args, \
361− .pc_encode = nfsaclsvc_encode_##rest##res, \
362− .pc_release = nfsaclsvc_release_##relt, \
363− .pc_argsize = sizeof(struct nfsd3_##argt##args), \
364− .pc_ressize = sizeof(struct nfsd3_##rest##res), \
365− .pc_cachetype = cache, \
366− .pc_xdrressize = respsize, \
367−}
368−
369373 #define ST 1 /* status*/
370374 #define AT 21 /* attributes */
371375 #define pAT (1+AT) /* post attributes - conditional */
372376 #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
373377
374−static const struct svc_procedure nfsd_acl_procedures2[] = {
375− PROC(null, void, void, void, RC_NOCACHE, ST),
376− PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
377− PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT),
378− PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT),
379− PROC(access, access, access, access, RC_NOCACHE, ST+AT+1),
378+static const struct svc_procedure nfsd_acl_procedures2[5] = {
379+ [ACLPROC2_NULL] = {
380+ .pc_func = nfsacld_proc_null,
381+ .pc_decode = nfsaclsvc_decode_voidarg,
382+ .pc_encode = nfsaclsvc_encode_voidres,
383+ .pc_argsize = sizeof(struct nfsd3_voidargs),
384+ .pc_ressize = sizeof(struct nfsd3_voidargs),
385+ .pc_cachetype = RC_NOCACHE,
386+ .pc_xdrressize = ST,
387+ },
388+ [ACLPROC2_GETACL] = {
389+ .pc_func = nfsacld_proc_getacl,
390+ .pc_decode = nfsaclsvc_decode_getaclargs,
391+ .pc_encode = nfsaclsvc_encode_getaclres,
392+ .pc_release = nfsaclsvc_release_getacl,
393+ .pc_argsize = sizeof(struct nfsd3_getaclargs),
394+ .pc_ressize = sizeof(struct nfsd3_getaclres),
395+ .pc_cachetype = RC_NOCACHE,
396+ .pc_xdrressize = ST+1+2*(1+ACL),
397+ },
398+ [ACLPROC2_SETACL] = {
399+ .pc_func = nfsacld_proc_setacl,
400+ .pc_decode = nfsaclsvc_decode_setaclargs,
401+ .pc_encode = nfsaclsvc_encode_attrstatres,
402+ .pc_release = nfsaclsvc_release_attrstat,
403+ .pc_argsize = sizeof(struct nfsd3_setaclargs),
404+ .pc_ressize = sizeof(struct nfsd_attrstat),
405+ .pc_cachetype = RC_NOCACHE,
406+ .pc_xdrressize = ST+AT,
407+ },
408+ [ACLPROC2_GETATTR] = {
409+ .pc_func = nfsacld_proc_getattr,
410+ .pc_decode = nfsaclsvc_decode_fhandleargs,
411+ .pc_encode = nfsaclsvc_encode_attrstatres,
412+ .pc_release = nfsaclsvc_release_attrstat,
413+ .pc_argsize = sizeof(struct nfsd_fhandle),
414+ .pc_ressize = sizeof(struct nfsd_attrstat),
415+ .pc_cachetype = RC_NOCACHE,
416+ .pc_xdrressize = ST+AT,
417+ },
418+ [ACLPROC2_ACCESS] = {
419+ .pc_func = nfsacld_proc_access,
420+ .pc_decode = nfsaclsvc_decode_accessargs,
421+ .pc_encode = nfsaclsvc_encode_accessres,
422+ .pc_release = nfsaclsvc_release_access,
423+ .pc_argsize = sizeof(struct nfsd3_accessargs),
424+ .pc_ressize = sizeof(struct nfsd3_accessres),
425+ .pc_cachetype = RC_NOCACHE,
426+ .pc_xdrressize = ST+AT+1,
427+ },
380428 };
381429
382430 static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];
fs/nfsd/nfs3acl.c+49−39
@@ -13,15 +13,13 @@ · 12 unmodified lines
1313 #include "xdr3.h"
1414 #include "vfs.h"
1515
16−#define RETURN_STATUS(st) { resp->status = (st); return (st); }
17−
1816 /*
1917 * NULL call.
2018 */
2119 static __be32
2220 nfsd3_proc_null(struct svc_rqst *rqstp)
2321 {
24− return nfs_ok;
22+ return rpc_success;
2523 }
2624
2725 /*
@@ -34,17 +32,18 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 6 unmodified lines
3432 struct posix_acl *acl;
3533 struct inode *inode;
3634 svc_fh *fh;
37− __be32 nfserr = 0;
3835
3936 fh = fh_copy(&resp->fh, &argp->fh);
40− nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
41− if (nfserr)
42− RETURN_STATUS(nfserr);
37+ resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
38+ if (resp->status != nfs_ok)
39+ goto out;
4340
4441 inode = d_inode(fh->fh_dentry);
4542
46− if (argp->mask & ~NFS_ACL_MASK)
47− RETURN_STATUS(nfserr_inval);
43+ if (argp->mask & ~NFS_ACL_MASK) {
44+ resp->status = nfserr_inval;
45+ goto out;
46+ }
4847 resp->mask = argp->mask;
4948
5049 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
@@ -54,7 +53,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines
5453 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
5554 }
5655 if (IS_ERR(acl)) {
57− nfserr = nfserrno(PTR_ERR(acl));
56+ resp->status = nfserrno(PTR_ERR(acl));
5857 goto fail;
5958 }
6059 resp->acl_access = acl;
@@ -64,19 +63,20 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines
6463 of a non-directory! */
6564 acl = get_acl(inode, ACL_TYPE_DEFAULT);
6665 if (IS_ERR(acl)) {
67− nfserr = nfserrno(PTR_ERR(acl));
66+ resp->status = nfserrno(PTR_ERR(acl));
6867 goto fail;
6968 }
7069 resp->acl_default = acl;
7170 }
7271
7372 /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
74− RETURN_STATUS(0);
73+out:
74+ return rpc_success;
7575
7676 fail:
7777 posix_acl_release(resp->acl_access);
7878 posix_acl_release(resp->acl_default);
79− RETURN_STATUS(nfserr);
79+ goto out;
8080 }
8181
8282 /*
@@ -88,12 +88,11 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp) · 5 unmodified lines
8888 struct nfsd3_attrstat *resp = rqstp->rq_resp;
8989 struct inode *inode;
9090 svc_fh *fh;
91− __be32 nfserr = 0;
9291 int error;
9392
9493 fh = fh_copy(&resp->fh, &argp->fh);
95− nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
96− if (nfserr)
94+ resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
95+ if (resp->status != nfs_ok)
9796 goto out;
9897
9998 inode = d_inode(fh->fh_dentry);
@@ -113,13 +112,13 @@ out_drop_lock: · 13 unmodified lines
113112 fh_unlock(fh);
114113 fh_drop_write(fh);
115114 out_errno:
116− nfserr = nfserrno(error);
115+ resp->status = nfserrno(error);
117116 out:
118117 /* argp->acl_{access,default} may have been allocated in
119118 nfs3svc_decode_setaclargs. */
120119 posix_acl_release(argp->acl_access);
121120 posix_acl_release(argp->acl_default);
122− RETURN_STATUS(nfserr);
121+ return rpc_success;
123122 }
124123
125124 /*
@@ -174,6 +173,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) · 48 unmodified lines
174173 struct nfsd3_getaclres *resp = rqstp->rq_resp;
175174 struct dentry *dentry = resp->fh.fh_dentry;
176175
176+ *p++ = resp->status;
177177 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
178178 if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {
179179 struct inode *inode = d_inode(dentry);
@@ -218,8 +218,8 @@ static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p) · 38 unmodified lines
218218 {
219219 struct nfsd3_attrstat *resp = rqstp->rq_resp;
220220
221+ *p++ = resp->status;
221222 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
222−
223223 return xdr_ressize_check(rqstp, p);
224224 }
225225
@@ -235,33 +235,43 @@ static void nfs3svc_release_getacl(struct svc_rqst *rqstp) · 9 unmodified lines
235235 posix_acl_release(resp->acl_default);
236236 }
237237
238−#define nfs3svc_decode_voidargs NULL
239−#define nfs3svc_release_void NULL
240−#define nfsd3_setaclres nfsd3_attrstat
241−#define nfsd3_voidres nfsd3_voidargs
242238 struct nfsd3_voidargs { int dummy; };
243239
244−#define PROC(name, argt, rest, relt, cache, respsize) \
245−{ \
246− .pc_func = nfsd3_proc_##name, \
247− .pc_decode = nfs3svc_decode_##argt##args, \
248− .pc_encode = nfs3svc_encode_##rest##res, \
249− .pc_release = nfs3svc_release_##relt, \
250− .pc_argsize = sizeof(struct nfsd3_##argt##args), \
251− .pc_ressize = sizeof(struct nfsd3_##rest##res), \
252− .pc_cachetype = cache, \
253− .pc_xdrressize = respsize, \
254−}
255−
256240 #define ST 1 /* status*/
257241 #define AT 21 /* attributes */
258242 #define pAT (1+AT) /* post attributes - conditional */
259243 #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
260244
261−static const struct svc_procedure nfsd_acl_procedures3[] = {
262− PROC(null, void, void, void, RC_NOCACHE, ST),
263− PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
264− PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT),
245+static const struct svc_procedure nfsd_acl_procedures3[3] = {
246+ [ACLPROC3_NULL] = {
247+ .pc_func = nfsd3_proc_null,
248+ .pc_decode = nfs3svc_decode_voidarg,
249+ .pc_encode = nfs3svc_encode_voidres,
250+ .pc_argsize = sizeof(struct nfsd3_voidargs),
251+ .pc_ressize = sizeof(struct nfsd3_voidargs),
252+ .pc_cachetype = RC_NOCACHE,
253+ .pc_xdrressize = ST,
254+ },
255+ [ACLPROC3_GETACL] = {
256+ .pc_func = nfsd3_proc_getacl,
257+ .pc_decode = nfs3svc_decode_getaclargs,
258+ .pc_encode = nfs3svc_encode_getaclres,
259+ .pc_release = nfs3svc_release_getacl,
260+ .pc_argsize = sizeof(struct nfsd3_getaclargs),
261+ .pc_ressize = sizeof(struct nfsd3_getaclres),
262+ .pc_cachetype = RC_NOCACHE,
263+ .pc_xdrressize = ST+1+2*(1+ACL),
264+ },
265+ [ACLPROC3_SETACL] = {
266+ .pc_func = nfsd3_proc_setacl,
267+ .pc_decode = nfs3svc_decode_setaclargs,
268+ .pc_encode = nfs3svc_encode_setaclres,
269+ .pc_release = nfs3svc_release_fhandle,
270+ .pc_argsize = sizeof(struct nfsd3_setaclargs),
271+ .pc_ressize = sizeof(struct nfsd3_attrstat),
272+ .pc_cachetype = RC_NOCACHE,
273+ .pc_xdrressize = ST+pAT,
274+ },
265275 };
266276
267277 static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)];
fs/nfsd/nfs3proc.c+116−122
@@ -15,8 +15,6 @@ · 14 unmodified lines
1515
1616 #define NFSDDBG_FACILITY NFSDDBG_PROC
1717
18−#define RETURN_STATUS(st) { resp->status = (st); return (st); }
19−
2018 static int nfs3_ftypes[] = {
2119 0, /* NF3NON */
2220 S_IFREG, /* NF3REG */
@@ -34,7 +32,7 @@ static int nfs3_ftypes[] = { · 11 unmodified lines
3432 static __be32
3533 nfsd3_proc_null(struct svc_rqst *rqstp)
3634 {
37− return nfs_ok;
35+ return rpc_success;
3836 }
3937
4038 /*
@@ -45,20 +43,19 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp) · 4 unmodified lines
4543 {
4644 struct nfsd_fhandle *argp = rqstp->rq_argp;
4745 struct nfsd3_attrstat *resp = rqstp->rq_resp;
48− __be32 nfserr;
4946
5047 dprintk("nfsd: GETATTR(3) %s\n",
5148 SVCFH_fmt(&argp->fh));
5249
5350 fh_copy(&resp->fh, &argp->fh);
54− nfserr = fh_verify(rqstp, &resp->fh, 0,
55− NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
56− if (nfserr)
57− RETURN_STATUS(nfserr);
58−
59− nfserr = fh_getattr(&resp->fh, &resp->stat);
60−
61− RETURN_STATUS(nfserr);
51+ resp->status = fh_verify(rqstp, &resp->fh, 0,
52+ NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
53+ if (resp->status != nfs_ok)
54+ goto out;
55+
56+ resp->status = fh_getattr(&resp->fh, &resp->stat);
57+out:
58+ return rpc_success;
6259 }
6360
6461 /*
@@ -69,15 +66,14 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp) · 4 unmodified lines
6966 {
7067 struct nfsd3_sattrargs *argp = rqstp->rq_argp;
7168 struct nfsd3_attrstat *resp = rqstp->rq_resp;
72− __be32 nfserr;
7369
7470 dprintk("nfsd: SETATTR(3) %s\n",
7571 SVCFH_fmt(&argp->fh));
7672
7773 fh_copy(&resp->fh, &argp->fh);
78− nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
79− argp->check_guard, argp->guardtime);
80− RETURN_STATUS(nfserr);
74+ resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
75+ argp->check_guard, argp->guardtime);
76+ return rpc_success;
8177 }
8278
8379 /*
@@ -88,7 +84,6 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp) · 4 unmodified lines
8884 {
8985 struct nfsd3_diropargs *argp = rqstp->rq_argp;
9086 struct nfsd3_diropres *resp = rqstp->rq_resp;
91− __be32 nfserr;
9287
9388 dprintk("nfsd: LOOKUP(3) %s %.*s\n",
9489 SVCFH_fmt(&argp->fh),
@@ -98,11 +93,10 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp) · 3 unmodified lines
9893 fh_copy(&resp->dirfh, &argp->fh);
9994 fh_init(&resp->fh, NFS3_FHSIZE);
10095
101− nfserr = nfsd_lookup(rqstp, &resp->dirfh,
102− argp->name,
103− argp->len,
104− &resp->fh);
105− RETURN_STATUS(nfserr);
96+ resp->status = nfsd_lookup(rqstp, &resp->dirfh,
97+ argp->name, argp->len,
98+ &resp->fh);
99+ return rpc_success;
106100 }
107101
108102 /*
@@ -113,7 +107,6 @@ nfsd3_proc_access(struct svc_rqst *rqstp) · 4 unmodified lines
113107 {
114108 struct nfsd3_accessargs *argp = rqstp->rq_argp;
115109 struct nfsd3_accessres *resp = rqstp->rq_resp;
116− __be32 nfserr;
117110
118111 dprintk("nfsd: ACCESS(3) %s 0x%x\n",
119112 SVCFH_fmt(&argp->fh),
@@ -121,8 +114,8 @@ nfsd3_proc_access(struct svc_rqst *rqstp) · 1 unmodified line
121114
122115 fh_copy(&resp->fh, &argp->fh);
123116 resp->access = argp->access;
124− nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
125− RETURN_STATUS(nfserr);
117+ resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
118+ return rpc_success;
126119 }
127120
128121 /*
@@ -133,15 +126,14 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp) · 4 unmodified lines
133126 {
134127 struct nfsd3_readlinkargs *argp = rqstp->rq_argp;
135128 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
136− __be32 nfserr;
137129
138130 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
139131
140132 /* Read the symlink. */
141133 fh_copy(&resp->fh, &argp->fh);
142134 resp->len = NFS3_MAXPATHLEN;
143− nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
144− RETURN_STATUS(nfserr);
135+ resp->status = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
136+ return rpc_success;
145137 }
146138
147139 /*
@@ -152,7 +144,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 4 unmodified lines
152144 {
153145 struct nfsd3_readargs *argp = rqstp->rq_argp;
154146 struct nfsd3_readres *resp = rqstp->rq_resp;
155− __be32 nfserr;
156147 u32 max_blocksize = svc_max_payload(rqstp);
157148 unsigned long cnt = min(argp->count, max_blocksize);
158149
@@ -169,12 +160,10 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 10 unmodified lines
169160 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
170161
171162 fh_copy(&resp->fh, &argp->fh);
172− nfserr = nfsd_read(rqstp, &resp->fh,
173− argp->offset,
174− rqstp->rq_vec, argp->vlen,
175− &resp->count,
176− &resp->eof);
177− RETURN_STATUS(nfserr);
163+ resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
164+ rqstp->rq_vec, argp->vlen, &resp->count,
165+ &resp->eof);
166+ return rpc_success;
178167 }
179168
180169 /*
@@ -185,7 +174,6 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 4 unmodified lines
185174 {
186175 struct nfsd3_writeargs *argp = rqstp->rq_argp;
187176 struct nfsd3_writeres *resp = rqstp->rq_resp;
188− __be32 nfserr;
189177 unsigned long cnt = argp->len;
190178 unsigned int nvecs;
191179
@@ -199,13 +187,16 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 7 unmodified lines
199187 resp->committed = argp->stable;
200188 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
201189 &argp->first, cnt);
202− if (!nvecs)
203− RETURN_STATUS(nfserr_io);
204− nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
205− rqstp->rq_vec, nvecs, &cnt,
206− resp->committed, resp->verf);
190+ if (!nvecs) {
191+ resp->status = nfserr_io;
192+ goto out;
193+ }
194+ resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
195+ rqstp->rq_vec, nvecs, &cnt,
196+ resp->committed, resp->verf);
207197 resp->count = cnt;
208− RETURN_STATUS(nfserr);
198+out:
199+ return rpc_success;
209200 }
210201
211202 /*
@@ -220,7 +211,6 @@ nfsd3_proc_create(struct svc_rqst *rqstp) · 8 unmodified lines
220211 struct nfsd3_diropres *resp = rqstp->rq_resp;
221212 svc_fh *dirfhp, *newfhp = NULL;
222213 struct iattr *attr;
223− __be32 nfserr;
224214
225215 dprintk("nfsd: CREATE(3) %s %.*s\n",
226216 SVCFH_fmt(&argp->fh),
@@ -241,11 +231,10 @@ nfsd3_proc_create(struct svc_rqst *rqstp) · 14 unmodified lines
241231 }
242232
243233 /* Now create the file and set attributes */
244− nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
245− attr, newfhp,
246− argp->createmode, (u32 *)argp->verf, NULL, NULL);
247−
248− RETURN_STATUS(nfserr);
234+ resp->status = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
235+ attr, newfhp, argp->createmode,
236+ (u32 *)argp->verf, NULL, NULL);
237+ return rpc_success;
249238 }
250239
251240 /*
@@ -256,7 +245,6 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) · 4 unmodified lines
256245 {
257246 struct nfsd3_createargs *argp = rqstp->rq_argp;
258247 struct nfsd3_diropres *resp = rqstp->rq_resp;
259− __be32 nfserr;
260248
261249 dprintk("nfsd: MKDIR(3) %s %.*s\n",
262250 SVCFH_fmt(&argp->fh),
@@ -266,10 +254,10 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) · 3 unmodified lines
266254 argp->attrs.ia_valid &= ~ATTR_SIZE;
267255 fh_copy(&resp->dirfh, &argp->fh);
268256 fh_init(&resp->fh, NFS3_FHSIZE);
269− nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
270− &argp->attrs, S_IFDIR, 0, &resp->fh);
257+ resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
258+ &argp->attrs, S_IFDIR, 0, &resp->fh);
271259 fh_unlock(&resp->dirfh);
272− RETURN_STATUS(nfserr);
260+ return rpc_success;
273261 }
274262
275263 static __be32
@@ -277,18 +265,23 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) · 1 unmodified line
277265 {
278266 struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
279267 struct nfsd3_diropres *resp = rqstp->rq_resp;
280− __be32 nfserr;
281268
282− if (argp->tlen == 0)
283− RETURN_STATUS(nfserr_inval);
284− if (argp->tlen > NFS3_MAXPATHLEN)
285− RETURN_STATUS(nfserr_nametoolong);
269+ if (argp->tlen == 0) {
270+ resp->status = nfserr_inval;
271+ goto out;
272+ }
273+ if (argp->tlen > NFS3_MAXPATHLEN) {
274+ resp->status = nfserr_nametoolong;
275+ goto out;
276+ }
286277
287278 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
288279 page_address(rqstp->rq_arg.pages[0]),
289280 argp->tlen);
290− if (IS_ERR(argp->tname))
291− RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));
281+ if (IS_ERR(argp->tname)) {
282+ resp->status = nfserrno(PTR_ERR(argp->tname));
283+ goto out;
284+ }
292285
293286 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
294287 SVCFH_fmt(&argp->ffh),
@@ -297,10 +290,11 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) · 2 unmodified lines
297290
298291 fh_copy(&resp->dirfh, &argp->ffh);
299292 fh_init(&resp->fh, NFS3_FHSIZE);
300− nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
301− argp->tname, &resp->fh);
293+ resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
294+ argp->flen, argp->tname, &resp->fh);
302295 kfree(argp->tname);
303− RETURN_STATUS(nfserr);
296+out:
297+ return rpc_success;
304298 }
305299
306300 /*
@@ -311,7 +305,6 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) · 4 unmodified lines
311305 {
312306 struct nfsd3_mknodargs *argp = rqstp->rq_argp;
313307 struct nfsd3_diropres *resp = rqstp->rq_resp;
314− __be32 nfserr;
315308 int type;
316309 dev_t rdev = 0;
317310
@@ -323,22 +316,28 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) · 5 unmodified lines
323316 fh_copy(&resp->dirfh, &argp->fh);
324317 fh_init(&resp->fh, NFS3_FHSIZE);
325318
326− if (argp->ftype == 0 || argp->ftype >= NF3BAD)
327− RETURN_STATUS(nfserr_inval);
319+ if (argp->ftype == 0 || argp->ftype >= NF3BAD) {
320+ resp->status = nfserr_inval;
321+ goto out;
322+ }
328323 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
329324 rdev = MKDEV(argp->major, argp->minor);
330325 if (MAJOR(rdev) != argp->major ||
331− MINOR(rdev) != argp->minor)
332− RETURN_STATUS(nfserr_inval);
333− } else
334− if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
335− RETURN_STATUS(nfserr_inval);
326+ MINOR(rdev) != argp->minor) {
327+ resp->status = nfserr_inval;
328+ goto out;
329+ }
330+ } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
331+ resp->status = nfserr_inval;
332+ goto out;
333+ }
336334
337335 type = nfs3_ftypes[argp->ftype];
338− nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
339− &argp->attrs, type, rdev, &resp->fh);
336+ resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
337+ &argp->attrs, type, rdev, &resp->fh);
340338 fh_unlock(&resp->dirfh);
341− RETURN_STATUS(nfserr);
339+out:
340+ return rpc_success;
342341 }
343342
344343 /*
@@ -349,7 +348,6 @@ nfsd3_proc_remove(struct svc_rqst *rqstp) · 4 unmodified lines
349348 {
350349 struct nfsd3_diropargs *argp = rqstp->rq_argp;
351350 struct nfsd3_attrstat *resp = rqstp->rq_resp;
352− __be32 nfserr;
353351
354352 dprintk("nfsd: REMOVE(3) %s %.*s\n",
355353 SVCFH_fmt(&argp->fh),
@@ -358,9 +356,10 @@ nfsd3_proc_remove(struct svc_rqst *rqstp) · 2 unmodified lines
358356
359357 /* Unlink. -S_IFDIR means file must not be a directory */
360358 fh_copy(&resp->fh, &argp->fh);
361− nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
359+ resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
360+ argp->name, argp->len);
362361 fh_unlock(&resp->fh);
363− RETURN_STATUS(nfserr);
362+ return rpc_success;
364363 }
365364
366365 /*
@@ -371,7 +370,6 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp) · 4 unmodified lines
371370 {
372371 struct nfsd3_diropargs *argp = rqstp->rq_argp;
373372 struct nfsd3_attrstat *resp = rqstp->rq_resp;
374− __be32 nfserr;
375373
376374 dprintk("nfsd: RMDIR(3) %s %.*s\n",
377375 SVCFH_fmt(&argp->fh),
@@ -379,9 +377,10 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp) · 1 unmodified line
379377 argp->name);
380378
381379 fh_copy(&resp->fh, &argp->fh);
382− nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
380+ resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
381+ argp->name, argp->len);
383382 fh_unlock(&resp->fh);
384− RETURN_STATUS(nfserr);
383+ return rpc_success;
385384 }
386385
387386 static __be32
@@ -389,7 +388,6 @@ nfsd3_proc_rename(struct svc_rqst *rqstp) · 1 unmodified line
389388 {
390389 struct nfsd3_renameargs *argp = rqstp->rq_argp;
391390 struct nfsd3_renameres *resp = rqstp->rq_resp;
392− __be32 nfserr;
393391
394392 dprintk("nfsd: RENAME(3) %s %.*s ->\n",
395393 SVCFH_fmt(&argp->ffh),
@@ -402,9 +400,9 @@ nfsd3_proc_rename(struct svc_rqst *rqstp) · 6 unmodified lines
402400
403401 fh_copy(&resp->ffh, &argp->ffh);
404402 fh_copy(&resp->tfh, &argp->tfh);
405− nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
406− &resp->tfh, argp->tname, argp->tlen);
407− RETURN_STATUS(nfserr);
403+ resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
404+ &resp->tfh, argp->tname, argp->tlen);
405+ return rpc_success;
408406 }
409407
410408 static __be32
@@ -412,7 +410,6 @@ nfsd3_proc_link(struct svc_rqst *rqstp) · 1 unmodified line
412410 {
413411 struct nfsd3_linkargs *argp = rqstp->rq_argp;
414412 struct nfsd3_linkres *resp = rqstp->rq_resp;
415− __be32 nfserr;
416413
417414 dprintk("nfsd: LINK(3) %s ->\n",
418415 SVCFH_fmt(&argp->ffh));
@@ -423,9 +420,9 @@ nfsd3_proc_link(struct svc_rqst *rqstp) · 4 unmodified lines
423420
424421 fh_copy(&resp->fh, &argp->ffh);
425422 fh_copy(&resp->tfh, &argp->tfh);
426− nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
427− &resp->fh);
428− RETURN_STATUS(nfserr);
423+ resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
424+ &resp->fh);
425+ return rpc_success;
429426 }
430427
431428 /*
@@ -436,7 +433,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 4 unmodified lines
436433 {
437434 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
438435 struct nfsd3_readdirres *resp = rqstp->rq_resp;
439− __be32 nfserr;
440436 int count = 0;
441437 struct page **p;
442438 caddr_t page_addr = NULL;
@@ -456,8 +452,8 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 13 unmodified lines
456452 resp->common.err = nfs_ok;
457453 resp->buffer = argp->buffer;
458454 resp->rqstp = rqstp;
459− nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie,
460− &resp->common, nfs3svc_encode_entry);
455+ resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie,
456+ &resp->common, nfs3svc_encode_entry);
461457 memcpy(resp->verf, argp->verf, 8);
462458 count = 0;
463459 for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
@@ -485,7 +481,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 21 unmodified lines
485481 resp->offset = NULL;
486482 }
487483
488− RETURN_STATUS(nfserr);
484+ return rpc_success;
489485 }
490486
491487 /*
@@ -497,7 +493,6 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 5 unmodified lines
497493 {
498494 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
499495 struct nfsd3_readdirres *resp = rqstp->rq_resp;
500− __be32 nfserr;
501496 int count = 0;
502497 loff_t offset;
503498 struct page **p;
@@ -520,17 +515,17 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 16 unmodified lines
520515 resp->rqstp = rqstp;
521516 offset = argp->cookie;
522517
523− nfserr = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
524− if (nfserr)
525− RETURN_STATUS(nfserr);
518+ resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
519+ if (resp->status != nfs_ok)
520+ goto out;
526521
527− if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS)
528− RETURN_STATUS(nfserr_notsupp);
522+ if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
523+ resp->status = nfserr_notsupp;
524+ goto out;
525+ }
529526
530− nfserr = nfsd_readdir(rqstp, &resp->fh,
531− &offset,
532− &resp->common,
533− nfs3svc_encode_entry_plus);
527+ resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
528+ &resp->common, nfs3svc_encode_entry_plus);
534529 memcpy(resp->verf, argp->verf, 8);
535530 for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
536531 page_addr = page_address(*p);
@@ -555,7 +550,8 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 18 unmodified lines
555550 resp->offset = NULL;
556551 }
557552
558− RETURN_STATUS(nfserr);
553+out:
554+ return rpc_success;
559555 }
560556
561557 /*
@@ -566,14 +562,13 @@ nfsd3_proc_fsstat(struct svc_rqst *rqstp) · 4 unmodified lines
566562 {
567563 struct nfsd_fhandle *argp = rqstp->rq_argp;
568564 struct nfsd3_fsstatres *resp = rqstp->rq_resp;
569− __be32 nfserr;
570565
571566 dprintk("nfsd: FSSTAT(3) %s\n",
572567 SVCFH_fmt(&argp->fh));
573568
574− nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
569+ resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
575570 fh_put(&argp->fh);
576− RETURN_STATUS(nfserr);
571+ return rpc_success;
577572 }
578573
579574 /*
@@ -584,7 +579,6 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp) · 4 unmodified lines
584579 {
585580 struct nfsd_fhandle *argp = rqstp->rq_argp;
586581 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
587− __be32 nfserr;
588582 u32 max_blocksize = svc_max_payload(rqstp);
589583
590584 dprintk("nfsd: FSINFO(3) %s\n",
@@ -600,13 +594,13 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp) · 9 unmodified lines
600594 resp->f_maxfilesize = ~(u32) 0;
601595 resp->f_properties = NFS3_FSF_DEFAULT;
602596
603− nfserr = fh_verify(rqstp, &argp->fh, 0,
604− NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
597+ resp->status = fh_verify(rqstp, &argp->fh, 0,
598+ NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
605599
606600 /* Check special features of the file system. May request
607601 * different read/write sizes for file systems known to have
608602 * problems with large blocks */
609− if (nfserr == 0) {
603+ if (resp->status == nfs_ok) {
610604 struct super_block *sb = argp->fh.fh_dentry->d_sb;
611605
612606 /* Note that we don't care for remote fs's here */
@@ -617,7 +611,7 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp) · 4 unmodified lines
617611 }
618612
619613 fh_put(&argp->fh);
620− RETURN_STATUS(nfserr);
614+ return rpc_success;
621615 }
622616
623617 /*
@@ -628,7 +622,6 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp) · 4 unmodified lines
628622 {
629623 struct nfsd_fhandle *argp = rqstp->rq_argp;
630624 struct nfsd3_pathconfres *resp = rqstp->rq_resp;
631− __be32 nfserr;
632625
633626 dprintk("nfsd: PATHCONF(3) %s\n",
634627 SVCFH_fmt(&argp->fh));
@@ -641,9 +634,9 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp) · 6 unmodified lines
641634 resp->p_case_insensitive = 0;
642635 resp->p_case_preserving = 1;
643636
644− nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
637+ resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
645638
646− if (nfserr == 0) {
639+ if (resp->status == nfs_ok) {
647640 struct super_block *sb = argp->fh.fh_dentry->d_sb;
648641
649642 /* Note that we don't care for remote fs's here */
@@ -660,10 +653,9 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp) · 10 unmodified lines
660653 }
661654
662655 fh_put(&argp->fh);
663− RETURN_STATUS(nfserr);
656+ return rpc_success;
664657 }
665658
666−
667659 /*
668660 * Commit a file (range) to stable storage.
669661 */
@@ -672,21 +664,22 @@ nfsd3_proc_commit(struct svc_rqst *rqstp) · 2 unmodified lines
672664 {
673665 struct nfsd3_commitargs *argp = rqstp->rq_argp;
674666 struct nfsd3_commitres *resp = rqstp->rq_resp;
675− __be32 nfserr;
676667
677668 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
678669 SVCFH_fmt(&argp->fh),
679670 argp->count,
680671 (unsigned long long) argp->offset);
681672
682− if (argp->offset > NFS_OFFSET_MAX)
683− RETURN_STATUS(nfserr_inval);
673+ if (argp->offset > NFS_OFFSET_MAX) {
674+ resp->status = nfserr_inval;
675+ goto out;
676+ }
684677
685678 fh_copy(&resp->fh, &argp->fh);
686− nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count,
687− resp->verf);
688−
689− RETURN_STATUS(nfserr);
679+ resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset,
680+ argp->count, resp->verf);
681+out:
682+ return rpc_success;
690683 }
691684
692685
@@ -716,6 +709,7 @@ struct nfsd3_voidargs { int dummy; }; · 23 unmodified lines
716709 static const struct svc_procedure nfsd_procedures3[22] = {
717710 [NFS3PROC_NULL] = {
718711 .pc_func = nfsd3_proc_null,
712+ .pc_decode = nfs3svc_decode_voidarg,
719713 .pc_encode = nfs3svc_encode_voidres,
720714 .pc_argsize = sizeof(struct nfsd3_voidargs),
721715 .pc_ressize = sizeof(struct nfsd3_voidres),
fs/nfsd/nfs3xdr.c+21−4
@@ -304,6 +304,12 @@ void fill_post_wcc(struct svc_fh *fhp) · 303 unmodified lines
304304 /*
305305 * XDR decode functions
306306 */
307+int
308+nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
309+{
310+ return 1;
311+}
312+
307313 int
308314 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
309315 {
@@ -635,10 +641,7 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p) · 325 unmodified lines
635641 /*
636642 * XDR encode functions
637643 */
638−/*
639− * There must be an encoding function for void results so svc_process
640− * will work properly.
641− */
644+
642645 int
643646 nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
644647 {
@@ -651,6 +654,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) · 6 unmodified lines
651654 {
652655 struct nfsd3_attrstat *resp = rqstp->rq_resp;
653656
657+ *p++ = resp->status;
654658 if (resp->status == 0) {
655659 lease_get_mtime(d_inode(resp->fh.fh_dentry),
656660 &resp->stat.mtime);
@@ -665,6 +669,7 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p) · 8 unmodified lines
665669 {
666670 struct nfsd3_attrstat *resp = rqstp->rq_resp;
667671
672+ *p++ = resp->status;
668673 p = encode_wcc_data(rqstp, p, &resp->fh);
669674 return xdr_ressize_check(rqstp, p);
670675 }
@@ -675,6 +680,7 @@ nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p) · 4 unmodified lines
675680 {
676681 struct nfsd3_diropres *resp = rqstp->rq_resp;
677682
683+ *p++ = resp->status;
678684 if (resp->status == 0) {
679685 p = encode_fh(p, &resp->fh);
680686 p = encode_post_op_attr(rqstp, p, &resp->fh);
@@ -689,6 +695,7 @@ nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p) · 8 unmodified lines
689695 {
690696 struct nfsd3_accessres *resp = rqstp->rq_resp;
691697
698+ *p++ = resp->status;
692699 p = encode_post_op_attr(rqstp, p, &resp->fh);
693700 if (resp->status == 0)
694701 *p++ = htonl(resp->access);
@@ -701,6 +708,7 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) · 6 unmodified lines
701708 {
702709 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
703710
711+ *p++ = resp->status;
704712 p = encode_post_op_attr(rqstp, p, &resp->fh);
705713 if (resp->status == 0) {
706714 *p++ = htonl(resp->len);
@@ -723,6 +731,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p) · 16 unmodified lines
723731 {
724732 struct nfsd3_readres *resp = rqstp->rq_resp;
725733
734+ *p++ = resp->status;
726735 p = encode_post_op_attr(rqstp, p, &resp->fh);
727736 if (resp->status == 0) {
728737 *p++ = htonl(resp->count);
@@ -748,6 +757,7 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) · 19 unmodified lines
748757 {
749758 struct nfsd3_writeres *resp = rqstp->rq_resp;
750759
760+ *p++ = resp->status;
751761 p = encode_wcc_data(rqstp, p, &resp->fh);
752762 if (resp->status == 0) {
753763 *p++ = htonl(resp->count);
@@ -764,6 +774,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p) · 10 unmodified lines
764774 {
765775 struct nfsd3_diropres *resp = rqstp->rq_resp;
766776
777+ *p++ = resp->status;
767778 if (resp->status == 0) {
768779 *p++ = xdr_one;
769780 p = encode_fh(p, &resp->fh);
@@ -779,6 +790,7 @@ nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p) · 9 unmodified lines
779790 {
780791 struct nfsd3_renameres *resp = rqstp->rq_resp;
781792
793+ *p++ = resp->status;
782794 p = encode_wcc_data(rqstp, p, &resp->ffh);
783795 p = encode_wcc_data(rqstp, p, &resp->tfh);
784796 return xdr_ressize_check(rqstp, p);
@@ -790,6 +802,7 @@ nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p) · 5 unmodified lines
790802 {
791803 struct nfsd3_linkres *resp = rqstp->rq_resp;
792804
805+ *p++ = resp->status;
793806 p = encode_post_op_attr(rqstp, p, &resp->fh);
794807 p = encode_wcc_data(rqstp, p, &resp->tfh);
795808 return xdr_ressize_check(rqstp, p);
@@ -801,6 +814,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) · 5 unmodified lines
801814 {
802815 struct nfsd3_readdirres *resp = rqstp->rq_resp;
803816
817+ *p++ = resp->status;
804818 p = encode_post_op_attr(rqstp, p, &resp->fh);
805819
806820 if (resp->status == 0) {
@@ -1053,6 +1067,7 @@ nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p) · 246 unmodified lines
10531067 struct kstatfs *s = &resp->stats;
10541068 u64 bs = s->f_bsize;
10551069
1070+ *p++ = resp->status;
10561071 *p++ = xdr_zero; /* no post_op_attr */
10571072
10581073 if (resp->status == 0) {
@@ -1073,6 +1088,7 @@ nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p) · 14 unmodified lines
10731088 {
10741089 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
10751090
1091+ *p++ = resp->status;
10761092 *p++ = xdr_zero; /* no post_op_attr */
10771093
10781094 if (resp->status == 0) {
@@ -1118,6 +1134,7 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) · 39 unmodified lines
11181134 {
11191135 struct nfsd3_commitres *resp = rqstp->rq_resp;
11201136
1137+ *p++ = resp->status;
11211138 p = encode_wcc_data(rqstp, p, &resp->fh);
11221139 /* Write verifier */
11231140 if (resp->status == 0) {
fs/nfsd/nfs4proc.c+28−6
@@ -38,6 +38,7 @@ · 37 unmodified lines
3838 #include <linux/slab.h>
3939 #include <linux/kthread.h>
4040 #include <linux/sunrpc/addr.h>
41+#include <linux/nfs_ssc.h>
4142
4243 #include "idmap.h"
4344 #include "cache.h"
@@ -1247,7 +1248,7 @@ out_err: · 1203 unmodified lines
12471248 static void
12481249 nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
12491250 {
1250− nfs_sb_deactive(ss_mnt->mnt_sb);
1251+ nfs_do_sb_deactive(ss_mnt->mnt_sb);
12511252 mntput(ss_mnt);
12521253 }
12531254
@@ -2165,7 +2166,7 @@ nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 911 unmodified lines
21652166 static __be32
21662167 nfsd4_proc_null(struct svc_rqst *rqstp)
21672168 {
2168− return nfs_ok;
2169+ return rpc_success;
21692170 }
21702171
21712172 static inline void nfsd4_increment_op_stats(u32 opnum)
@@ -2457,15 +2458,14 @@ encode_op: · 285 unmodified lines
24572458 nfsd4_increment_op_stats(op->opnum);
24582459 }
24592460
2460− cstate->status = status;
24612461 fh_put(current_fh);
24622462 fh_put(save_fh);
24632463 BUG_ON(cstate->replay_owner);
24642464 out:
2465+ cstate->status = status;
24652466 /* Reset deferral mechanism for RPC deferrals */
24662467 set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
2467− dprintk("nfsv4 compound returned %d\n", ntohl(status));
2468− return status;
2468+ return rpc_success;
24692469 }
24702470
24712471 #define op_encode_hdr_size (2)
@@ -2591,6 +2591,20 @@ static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) · 119 unmodified lines
25912591 return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
25922592 }
25932593
2594+static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
2595+{
2596+ u32 maxcount = svc_max_payload(rqstp);
2597+ u32 rlen = min(op->u.read.rd_length, maxcount);
2598+ /*
2599+ * If we detect that the file changed during hole encoding, then we
2600+ * recover by encoding the remaining reply as data. This means we need
2601+ * to set aside enough room to encode two data segments.
2602+ */
2603+ u32 seg_len = 2 * (1 + 2 + 1);
2604+
2605+ return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32);
2606+}
2607+
25942608 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
25952609 {
25962610 u32 maxcount = 0, rlen = 0;
@@ -3163,6 +3177,13 @@ static const struct nfsd4_operation nfsd4_ops[] = { · 566 unmodified lines
31633177 .op_name = "OP_COPY",
31643178 .op_rsize_bop = nfsd4_copy_rsize,
31653179 },
3180+ [OP_READ_PLUS] = {
3181+ .op_func = nfsd4_read,
3182+ .op_release = nfsd4_read_release,
3183+ .op_name = "OP_READ_PLUS",
3184+ .op_rsize_bop = nfsd4_read_plus_rsize,
3185+ .op_get_currentstateid = nfsd4_get_readstateid,
3186+ },
31663187 [OP_SEEK] = {
31673188 .op_func = nfsd4_seek,
31683189 .op_name = "OP_SEEK",
@@ -3231,7 +3252,7 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) · 62 unmodified lines
32313252 if (!cstate->minorversion)
32323253 return false;
32333254
3234− if (cstate->spo_must_allowed == true)
3255+ if (cstate->spo_must_allowed)
32353256 return true;
32363257
32373258 opiter = resp->opcnt;
@@ -3279,6 +3300,7 @@ struct nfsd4_voidargs { int dummy; }; · 41 unmodified lines
32793300 static const struct svc_procedure nfsd_procedures4[2] = {
32803301 [NFSPROC4_NULL] = {
32813302 .pc_func = nfsd4_proc_null,
3303+ .pc_decode = nfs4svc_decode_voidarg,
32823304 .pc_encode = nfs4svc_encode_voidres,
32833305 .pc_argsize = sizeof(struct nfsd4_voidargs),
32843306 .pc_ressize = sizeof(struct nfsd4_voidres),
fs/nfsd/nfs4state.c+6−599
@@ -4513,7 +4513,8 @@ static int nfsd4_cb_recall_done(struct nfsd4_callback *cb, · 4512 unmodified lines
45134513 {
45144514 struct nfs4_delegation *dp = cb_to_delegation(cb);
45154515
4516− if (dp->dl_stid.sc_type == NFS4_CLOSED_DELEG_STID)
4516+ if (dp->dl_stid.sc_type == NFS4_CLOSED_DELEG_STID ||
4517+ dp->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID)
45174518 return 1;
45184519
45194520 switch (task->tk_status) {
@@ -4597,7 +4598,8 @@ static bool nfsd_breaker_owns_lease(struct file_lock *fl) · 77 unmodified lines
45974598 if (!i_am_nfsd())
45984599 return NULL;
45994600 rqst = kthread_data(current);
4600− if (!rqst->rq_lease_breaker)
4601+ /* Note rq_prog == NFS_ACL_PROGRAM is also possible: */
4602+ if (rqst->rq_prog != NFS_PROGRAM || rqst->rq_vers < 4)
46014603 return NULL;
46024604 clp = *(rqst->rq_lease_breaker);
46034605 return dl->dl_stid.sc_client == clp;
@@ -4954,7 +4956,6 @@ static int nfsd4_check_conflicting_opens(struct nfs4_client *clp, · 350 unmodified lines
49544956 writes--;
49554957 if (fp->fi_fds[O_RDWR])
49564958 writes--;
4957− WARN_ON_ONCE(writes < 0);
49584959 if (writes > 0)
49594960 return -EAGAIN;
49604961 spin_lock(&fp->fi_lock);
@@ -5126,7 +5127,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, · 165 unmodified lines
51265127
51275128 memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
51285129
5129− trace_nfsd_deleg_open(&dp->dl_stid.sc_stateid);
5130+ trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
51305131 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
51315132 nfs4_put_stid(&dp->dl_stid);
51325133 return;
@@ -5243,7 +5244,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf · 110 unmodified lines
52435244 nfs4_open_delegation(current_fh, open, stp);
52445245 nodeleg:
52455246 status = nfs_ok;
5246− trace_nfsd_deleg_none(&stp->st_stid.sc_stateid);
5247+ trace_nfsd_open(&stp->st_stid.sc_stateid);
52475248 out:
52485249 /* 4.1 client trying to upgrade/downgrade delegation? */
52495250 if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
@@ -5722,7 +5723,6 @@ nfs4_find_file(struct nfs4_stid *s, int flags) · 472 unmodified lines
57225723 return find_readable_file(s->sc_file);
57235724 else
57245725 return find_writeable_file(s->sc_file);
5725− break;
57265726 }
57275727
57285728 return NULL;
@@ -7253,599 +7253,6 @@ nfs4_check_open_reclaim(clientid_t *clid, · 1524 unmodified lines
72537253 return nfs_ok;
72547254 }
72557255
7256−#ifdef CONFIG_NFSD_FAULT_INJECTION
7257−static inline void
7258−put_client(struct nfs4_client *clp)
7259−{
7260− atomic_dec(&clp->cl_rpc_users);
7261−}
7262−
7263−static struct nfs4_client *
7264−nfsd_find_client(struct sockaddr_storage *addr, size_t addr_size)
7265−{
7266− struct nfs4_client *clp;
7267− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7268− nfsd_net_id);
7269−
7270− if (!nfsd_netns_ready(nn))
7271− return NULL;
7272−
7273− list_for_each_entry(clp, &nn->client_lru, cl_lru) {
7274− if (memcmp(&clp->cl_addr, addr, addr_size) == 0)
7275− return clp;
7276− }
7277− return NULL;
7278−}
7279−
7280−u64
7281−nfsd_inject_print_clients(void)
7282−{
7283− struct nfs4_client *clp;
7284− u64 count = 0;
7285− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7286− nfsd_net_id);
7287− char buf[INET6_ADDRSTRLEN];
7288−
7289− if (!nfsd_netns_ready(nn))
7290− return 0;
7291−
7292− spin_lock(&nn->client_lock);
7293− list_for_each_entry(clp, &nn->client_lru, cl_lru) {
7294− rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
7295− pr_info("NFS Client: %s\n", buf);
7296− ++count;
7297− }
7298− spin_unlock(&nn->client_lock);
7299−
7300− return count;
7301−}
7302−
7303−u64
7304−nfsd_inject_forget_client(struct sockaddr_storage *addr, size_t addr_size)
7305−{
7306− u64 count = 0;
7307− struct nfs4_client *clp;
7308− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7309− nfsd_net_id);
7310−
7311− if (!nfsd_netns_ready(nn))
7312− return count;
7313−
7314− spin_lock(&nn->client_lock);
7315− clp = nfsd_find_client(addr, addr_size);
7316− if (clp) {
7317− if (mark_client_expired_locked(clp) == nfs_ok)
7318− ++count;
7319− else
7320− clp = NULL;
7321− }
7322− spin_unlock(&nn->client_lock);
7323−
7324− if (clp)
7325− expire_client(clp);
7326−
7327− return count;
7328−}
7329−
7330−u64
7331−nfsd_inject_forget_clients(u64 max)
7332−{
7333− u64 count = 0;
7334− struct nfs4_client *clp, *next;
7335− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7336− nfsd_net_id);
7337− LIST_HEAD(reaplist);
7338−
7339− if (!nfsd_netns_ready(nn))
7340− return count;
7341−
7342− spin_lock(&nn->client_lock);
7343− list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
7344− if (mark_client_expired_locked(clp) == nfs_ok) {
7345− list_add(&clp->cl_lru, &reaplist);
7346− if (max != 0 && ++count >= max)
7347− break;
7348− }
7349− }
7350− spin_unlock(&nn->client_lock);
7351−
7352− list_for_each_entry_safe(clp, next, &reaplist, cl_lru)
7353− expire_client(clp);
7354−
7355− return count;
7356−}
7357−
7358−static void nfsd_print_count(struct nfs4_client *clp, unsigned int count,
7359− const char *type)
7360−{
7361− char buf[INET6_ADDRSTRLEN];
7362− rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
7363− printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type);
7364−}
7365−
7366−static void
7367−nfsd_inject_add_lock_to_list(struct nfs4_ol_stateid *lst,
7368− struct list_head *collect)
7369−{
7370− struct nfs4_client *clp = lst->st_stid.sc_client;
7371− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7372− nfsd_net_id);
7373−
7374− if (!collect)
7375− return;
7376−
7377− lockdep_assert_held(&nn->client_lock);
7378− atomic_inc(&clp->cl_rpc_users);
7379− list_add(&lst->st_locks, collect);
7380−}
7381−
7382−static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max,
7383− struct list_head *collect,
7384− bool (*func)(struct nfs4_ol_stateid *))
7385−{
7386− struct nfs4_openowner *oop;
7387− struct nfs4_ol_stateid *stp, *st_next;
7388− struct nfs4_ol_stateid *lst, *lst_next;
7389− u64 count = 0;
7390−
7391− spin_lock(&clp->cl_lock);
7392− list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) {
7393− list_for_each_entry_safe(stp, st_next,
7394− &oop->oo_owner.so_stateids, st_perstateowner) {
7395− list_for_each_entry_safe(lst, lst_next,
7396− &stp->st_locks, st_locks) {
7397− if (func) {
7398− if (func(lst))
7399− nfsd_inject_add_lock_to_list(lst,
7400− collect);
7401− }
7402− ++count;
7403− /*
7404− * Despite the fact that these functions deal
7405− * with 64-bit integers for "count", we must
7406− * ensure that it doesn't blow up the
7407− * clp->cl_rpc_users. Throw a warning if we
7408− * start to approach INT_MAX here.
7409− */
7410− WARN_ON_ONCE(count == (INT_MAX / 2));
7411− if (count == max)
7412− goto out;
7413− }
7414− }
7415− }
7416−out:
7417− spin_unlock(&clp->cl_lock);
7418−
7419− return count;
7420−}
7421−
7422−static u64
7423−nfsd_collect_client_locks(struct nfs4_client *clp, struct list_head *collect,
7424− u64 max)
7425−{
7426− return nfsd_foreach_client_lock(clp, max, collect, unhash_lock_stateid);
7427−}
7428−
7429−static u64
7430−nfsd_print_client_locks(struct nfs4_client *clp)
7431−{
7432− u64 count = nfsd_foreach_client_lock(clp, 0, NULL, NULL);
7433− nfsd_print_count(clp, count, "locked files");
7434− return count;
7435−}
7436−
7437−u64
7438−nfsd_inject_print_locks(void)
7439−{
7440− struct nfs4_client *clp;
7441− u64 count = 0;
7442− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7443− nfsd_net_id);
7444−
7445− if (!nfsd_netns_ready(nn))
7446− return 0;
7447−
7448− spin_lock(&nn->client_lock);
7449− list_for_each_entry(clp, &nn->client_lru, cl_lru)
7450− count += nfsd_print_client_locks(clp);
7451− spin_unlock(&nn->client_lock);
7452−
7453− return count;
7454−}
7455−
7456−static void
7457−nfsd_reap_locks(struct list_head *reaplist)
7458−{
7459− struct nfs4_client *clp;
7460− struct nfs4_ol_stateid *stp, *next;
7461−
7462− list_for_each_entry_safe(stp, next, reaplist, st_locks) {
7463− list_del_init(&stp->st_locks);
7464− clp = stp->st_stid.sc_client;
7465− nfs4_put_stid(&stp->st_stid);
7466− put_client(clp);
7467− }
7468−}
7469−
7470−u64
7471−nfsd_inject_forget_client_locks(struct sockaddr_storage *addr, size_t addr_size)
7472−{
7473− unsigned int count = 0;
7474− struct nfs4_client *clp;
7475− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7476− nfsd_net_id);
7477− LIST_HEAD(reaplist);
7478−
7479− if (!nfsd_netns_ready(nn))
7480− return count;
7481−
7482− spin_lock(&nn->client_lock);
7483− clp = nfsd_find_client(addr, addr_size);
7484− if (clp)
7485− count = nfsd_collect_client_locks(clp, &reaplist, 0);
7486− spin_unlock(&nn->client_lock);
7487− nfsd_reap_locks(&reaplist);
7488− return count;
7489−}
7490−
7491−u64
7492−nfsd_inject_forget_locks(u64 max)
7493−{
7494− u64 count = 0;
7495− struct nfs4_client *clp;
7496− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7497− nfsd_net_id);
7498− LIST_HEAD(reaplist);
7499−
7500− if (!nfsd_netns_ready(nn))
7501− return count;
7502−
7503− spin_lock(&nn->client_lock);
7504− list_for_each_entry(clp, &nn->client_lru, cl_lru) {
7505− count += nfsd_collect_client_locks(clp, &reaplist, max - count);
7506− if (max != 0 && count >= max)
7507− break;
7508− }
7509− spin_unlock(&nn->client_lock);
7510− nfsd_reap_locks(&reaplist);
7511− return count;
7512−}
7513−
7514−static u64
7515−nfsd_foreach_client_openowner(struct nfs4_client *clp, u64 max,
7516− struct list_head *collect,
7517− void (*func)(struct nfs4_openowner *))
7518−{
7519− struct nfs4_openowner *oop, *next;
7520− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7521− nfsd_net_id);
7522− u64 count = 0;
7523−
7524− lockdep_assert_held(&nn->client_lock);
7525−
7526− spin_lock(&clp->cl_lock);
7527− list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) {
7528− if (func) {
7529− func(oop);
7530− if (collect) {
7531− atomic_inc(&clp->cl_rpc_users);
7532− list_add(&oop->oo_perclient, collect);
7533− }
7534− }
7535− ++count;
7536− /*
7537− * Despite the fact that these functions deal with
7538− * 64-bit integers for "count", we must ensure that
7539− * it doesn't blow up the clp->cl_rpc_users. Throw a
7540− * warning if we start to approach INT_MAX here.
7541− */
7542− WARN_ON_ONCE(count == (INT_MAX / 2));
7543− if (count == max)
7544− break;
7545− }
7546− spin_unlock(&clp->cl_lock);
7547−
7548− return count;
7549−}
7550−
7551−static u64
7552−nfsd_print_client_openowners(struct nfs4_client *clp)
7553−{
7554− u64 count = nfsd_foreach_client_openowner(clp, 0, NULL, NULL);
7555−
7556− nfsd_print_count(clp, count, "openowners");
7557− return count;
7558−}
7559−
7560−static u64
7561−nfsd_collect_client_openowners(struct nfs4_client *clp,
7562− struct list_head *collect, u64 max)
7563−{
7564− return nfsd_foreach_client_openowner(clp, max, collect,
7565− unhash_openowner_locked);
7566−}
7567−
7568−u64
7569−nfsd_inject_print_openowners(void)
7570−{
7571− struct nfs4_client *clp;
7572− u64 count = 0;
7573− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7574− nfsd_net_id);
7575−
7576− if (!nfsd_netns_ready(nn))
7577− return 0;
7578−
7579− spin_lock(&nn->client_lock);
7580− list_for_each_entry(clp, &nn->client_lru, cl_lru)
7581− count += nfsd_print_client_openowners(clp);
7582− spin_unlock(&nn->client_lock);
7583−
7584− return count;
7585−}
7586−
7587−static void
7588−nfsd_reap_openowners(struct list_head *reaplist)
7589−{
7590− struct nfs4_client *clp;
7591− struct nfs4_openowner *oop, *next;
7592−
7593− list_for_each_entry_safe(oop, next, reaplist, oo_perclient) {
7594− list_del_init(&oop->oo_perclient);
7595− clp = oop->oo_owner.so_client;
7596− release_openowner(oop);
7597− put_client(clp);
7598− }
7599−}
7600−
7601−u64
7602−nfsd_inject_forget_client_openowners(struct sockaddr_storage *addr,
7603− size_t addr_size)
7604−{
7605− unsigned int count = 0;
7606− struct nfs4_client *clp;
7607− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7608− nfsd_net_id);
7609− LIST_HEAD(reaplist);
7610−
7611− if (!nfsd_netns_ready(nn))
7612− return count;
7613−
7614− spin_lock(&nn->client_lock);
7615− clp = nfsd_find_client(addr, addr_size);
7616− if (clp)
7617− count = nfsd_collect_client_openowners(clp, &reaplist, 0);
7618− spin_unlock(&nn->client_lock);
7619− nfsd_reap_openowners(&reaplist);
7620− return count;
7621−}
7622−
7623−u64
7624−nfsd_inject_forget_openowners(u64 max)
7625−{
7626− u64 count = 0;
7627− struct nfs4_client *clp;
7628− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7629− nfsd_net_id);
7630− LIST_HEAD(reaplist);
7631−
7632− if (!nfsd_netns_ready(nn))
7633− return count;
7634−
7635− spin_lock(&nn->client_lock);
7636− list_for_each_entry(clp, &nn->client_lru, cl_lru) {
7637− count += nfsd_collect_client_openowners(clp, &reaplist,
7638− max - count);
7639− if (max != 0 && count >= max)
7640− break;
7641− }
7642− spin_unlock(&nn->client_lock);
7643− nfsd_reap_openowners(&reaplist);
7644− return count;
7645−}
7646−
7647−static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max,
7648− struct list_head *victims)
7649−{
7650− struct nfs4_delegation *dp, *next;
7651− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7652− nfsd_net_id);
7653− u64 count = 0;
7654−
7655− lockdep_assert_held(&nn->client_lock);
7656−
7657− spin_lock(&state_lock);
7658− list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) {
7659− if (victims) {
7660− /*
7661− * It's not safe to mess with delegations that have a
7662− * non-zero dl_time. They might have already been broken
7663− * and could be processed by the laundromat outside of
7664− * the state_lock. Just leave them be.
7665− */
7666− if (dp->dl_time != 0)
7667− continue;
7668−
7669− atomic_inc(&clp->cl_rpc_users);
7670− WARN_ON(!unhash_delegation_locked(dp));
7671− list_add(&dp->dl_recall_lru, victims);
7672− }
7673− ++count;
7674− /*
7675− * Despite the fact that these functions deal with
7676− * 64-bit integers for "count", we must ensure that
7677− * it doesn't blow up the clp->cl_rpc_users. Throw a
7678− * warning if we start to approach INT_MAX here.
7679− */
7680− WARN_ON_ONCE(count == (INT_MAX / 2));
7681− if (count == max)
7682− break;
7683− }
7684− spin_unlock(&state_lock);
7685− return count;
7686−}
7687−
7688−static u64
7689−nfsd_print_client_delegations(struct nfs4_client *clp)
7690−{
7691− u64 count = nfsd_find_all_delegations(clp, 0, NULL);
7692−
7693− nfsd_print_count(clp, count, "delegations");
7694− return count;
7695−}
7696−
7697−u64
7698−nfsd_inject_print_delegations(void)
7699−{
7700− struct nfs4_client *clp;
7701− u64 count = 0;
7702− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7703− nfsd_net_id);
7704−
7705− if (!nfsd_netns_ready(nn))
7706− return 0;
7707−
7708− spin_lock(&nn->client_lock);
7709− list_for_each_entry(clp, &nn->client_lru, cl_lru)
7710− count += nfsd_print_client_delegations(clp);
7711− spin_unlock(&nn->client_lock);
7712−
7713− return count;
7714−}
7715−
7716−static void
7717−nfsd_forget_delegations(struct list_head *reaplist)
7718−{
7719− struct nfs4_client *clp;
7720− struct nfs4_delegation *dp, *next;
7721−
7722− list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) {
7723− list_del_init(&dp->dl_recall_lru);
7724− clp = dp->dl_stid.sc_client;
7725− revoke_delegation(dp);
7726− put_client(clp);
7727− }
7728−}
7729−
7730−u64
7731−nfsd_inject_forget_client_delegations(struct sockaddr_storage *addr,
7732− size_t addr_size)
7733−{
7734− u64 count = 0;
7735− struct nfs4_client *clp;
7736− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7737− nfsd_net_id);
7738− LIST_HEAD(reaplist);
7739−
7740− if (!nfsd_netns_ready(nn))
7741− return count;
7742−
7743− spin_lock(&nn->client_lock);
7744− clp = nfsd_find_client(addr, addr_size);
7745− if (clp)
7746− count = nfsd_find_all_delegations(clp, 0, &reaplist);
7747− spin_unlock(&nn->client_lock);
7748−
7749− nfsd_forget_delegations(&reaplist);
7750− return count;
7751−}
7752−
7753−u64
7754−nfsd_inject_forget_delegations(u64 max)
7755−{
7756− u64 count = 0;
7757− struct nfs4_client *clp;
7758− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7759− nfsd_net_id);
7760− LIST_HEAD(reaplist);
7761−
7762− if (!nfsd_netns_ready(nn))
7763− return count;
7764−
7765− spin_lock(&nn->client_lock);
7766− list_for_each_entry(clp, &nn->client_lru, cl_lru) {
7767− count += nfsd_find_all_delegations(clp, max - count, &reaplist);
7768− if (max != 0 && count >= max)
7769− break;
7770− }
7771− spin_unlock(&nn->client_lock);
7772− nfsd_forget_delegations(&reaplist);
7773− return count;
7774−}
7775−
7776−static void
7777−nfsd_recall_delegations(struct list_head *reaplist)
7778−{
7779− struct nfs4_client *clp;
7780− struct nfs4_delegation *dp, *next;
7781−
7782− list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) {
7783− list_del_init(&dp->dl_recall_lru);
7784− clp = dp->dl_stid.sc_client;
7785−
7786− trace_nfsd_deleg_recall(&dp->dl_stid.sc_stateid);
7787−
7788− /*
7789− * We skipped all entries that had a zero dl_time before,
7790− * so we can now reset the dl_time back to 0. If a delegation
7791− * break comes in now, then it won't make any difference since
7792− * we're recalling it either way.
7793− */
7794− spin_lock(&state_lock);
7795− dp->dl_time = 0;
7796− spin_unlock(&state_lock);
7797− nfsd_break_one_deleg(dp);
7798− put_client(clp);
7799− }
7800−}
7801−
7802−u64
7803−nfsd_inject_recall_client_delegations(struct sockaddr_storage *addr,
7804− size_t addr_size)
7805−{
7806− u64 count = 0;
7807− struct nfs4_client *clp;
7808− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7809− nfsd_net_id);
7810− LIST_HEAD(reaplist);
7811−
7812− if (!nfsd_netns_ready(nn))
7813− return count;
7814−
7815− spin_lock(&nn->client_lock);
7816− clp = nfsd_find_client(addr, addr_size);
7817− if (clp)
7818− count = nfsd_find_all_delegations(clp, 0, &reaplist);
7819− spin_unlock(&nn->client_lock);
7820−
7821− nfsd_recall_delegations(&reaplist);
7822− return count;
7823−}
7824−
7825−u64
7826−nfsd_inject_recall_delegations(u64 max)
7827−{
7828− u64 count = 0;
7829− struct nfs4_client *clp, *next;
7830− struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
7831− nfsd_net_id);
7832− LIST_HEAD(reaplist);
7833−
7834− if (!nfsd_netns_ready(nn))
7835− return count;
7836−
7837− spin_lock(&nn->client_lock);
7838− list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
7839− count += nfsd_find_all_delegations(clp, max - count, &reaplist);
7840− if (max != 0 && ++count >= max)
7841− break;
7842− }
7843− spin_unlock(&nn->client_lock);
7844− nfsd_recall_delegations(&reaplist);
7845− return count;
7846−}
7847−#endif /* CONFIG_NFSD_FAULT_INJECTION */
7848−
78497256 /*
78507257 * Since the lifetime of a delegation isn't limited to that of an open, a
78517258 * client may quite reasonably hang on to a delegation as long as it has
fs/nfsd/nfs4xdr.c+164−38
@@ -1855,7 +1855,7 @@ static __be32 · 1854 unmodified lines
18551855 nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,
18561856 struct nfsd4_copy_notify *cn)
18571857 {
1858− int status;
1858+ __be32 status;
18591859
18601860 status = nfsd4_decode_stateid(argp, &cn->cpn_src_stateid);
18611861 if (status)
@@ -2173,7 +2173,7 @@ static const nfsd4_dec nfsd4_dec_ops[] = { · 311 unmodified lines
21732173 [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,
21742174 [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_offload_status,
21752175 [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_offload_status,
2176− [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp,
2176+ [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_read,
21772177 [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek,
21782178 [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp,
21792179 [OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone,
@@ -2261,7 +2261,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) · 81 unmodified lines
22612261 */
22622262 cachethis |= nfsd4_cache_this_op(op);
22632263
2264− if (op->opnum == OP_READ) {
2264+ if (op->opnum == OP_READ || op->opnum == OP_READ_PLUS) {
22652265 readcount++;
22662266 readbytes += nfsd4_max_reply(argp->rqstp, op);
22672267 } else
@@ -3814,36 +3814,14 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, · 1546 unmodified lines
38143814 {
38153815 struct xdr_stream *xdr = &resp->xdr;
38163816 u32 eof;
3817− int v;
38183817 int starting_len = xdr->buf->len - 8;
3819− long len;
3820− int thislen;
38213818 __be32 nfserr;
38223819 __be32 tmp;
3823− __be32 *p;
38243820 int pad;
38253821
3826− /*
3827− * svcrdma requires every READ payload to start somewhere
3828− * in xdr->pages.
3829− */
3830− if (xdr->iov == xdr->buf->head) {
3831− xdr->iov = NULL;
3832− xdr->end = xdr->p;
3833− }
3834−
3835− len = maxcount;
3836− v = 0;
3837− while (len) {
3838− thislen = min_t(long, len, PAGE_SIZE);
3839− p = xdr_reserve_space(xdr, thislen);
3840− WARN_ON_ONCE(!p);
3841− resp->rqstp->rq_vec[v].iov_base = p;
3842− resp->rqstp->rq_vec[v].iov_len = thislen;
3843− v++;
3844− len -= thislen;
3845− }
3846− read->rd_vlen = v;
3822+ read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount);
3823+ if (read->rd_vlen < 0)
3824+ return nfserr_resource;
38473825
38483826 nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
38493827 resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
@@ -4619,6 +4597,149 @@ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr, · 769 unmodified lines
46194597 return nfserr_resource;
46204598 p = xdr_encode_hyper(p, os->count);
46214599 *p++ = cpu_to_be32(0);
4600+ return nfserr;
4601+}
4602+
4603+static __be32
4604+nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp,
4605+ struct nfsd4_read *read,
4606+ unsigned long *maxcount, u32 *eof,
4607+ loff_t *pos)
4608+{
4609+ struct xdr_stream *xdr = &resp->xdr;
4610+ struct file *file = read->rd_nf->nf_file;
4611+ int starting_len = xdr->buf->len;
4612+ loff_t hole_pos;
4613+ __be32 nfserr;
4614+ __be32 *p, tmp;
4615+ __be64 tmp64;
4616+
4617+ hole_pos = pos ? *pos : vfs_llseek(file, read->rd_offset, SEEK_HOLE);
4618+ if (hole_pos > read->rd_offset)
4619+ *maxcount = min_t(unsigned long, *maxcount, hole_pos - read->rd_offset);
4620+ *maxcount = min_t(unsigned long, *maxcount, (xdr->buf->buflen - xdr->buf->len));
4621+
4622+ /* Content type, offset, byte count */
4623+ p = xdr_reserve_space(xdr, 4 + 8 + 4);
4624+ if (!p)
4625+ return nfserr_resource;
4626+
4627+ read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, *maxcount);
4628+ if (read->rd_vlen < 0)
4629+ return nfserr_resource;
4630+
4631+ nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
4632+ resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof);
4633+ if (nfserr)
4634+ return nfserr;
4635+
4636+ tmp = htonl(NFS4_CONTENT_DATA);
4637+ write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4);
4638+ tmp64 = cpu_to_be64(read->rd_offset);
4639+ write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp64, 8);
4640+ tmp = htonl(*maxcount);
4641+ write_bytes_to_xdr_buf(xdr->buf, starting_len + 12, &tmp, 4);
4642+ return nfs_ok;
4643+}
4644+
4645+static __be32
4646+nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp,
4647+ struct nfsd4_read *read,
4648+ unsigned long *maxcount, u32 *eof)
4649+{
4650+ struct file *file = read->rd_nf->nf_file;
4651+ loff_t data_pos = vfs_llseek(file, read->rd_offset, SEEK_DATA);
4652+ loff_t f_size = i_size_read(file_inode(file));
4653+ unsigned long count;
4654+ __be32 *p;
4655+
4656+ if (data_pos == -ENXIO)
4657+ data_pos = f_size;
4658+ else if (data_pos <= read->rd_offset || (data_pos < f_size && data_pos % PAGE_SIZE))
4659+ return nfsd4_encode_read_plus_data(resp, read, maxcount, eof, &f_size);
4660+ count = data_pos - read->rd_offset;
4661+
4662+ /* Content type, offset, byte count */
4663+ p = xdr_reserve_space(&resp->xdr, 4 + 8 + 8);
4664+ if (!p)
4665+ return nfserr_resource;
4666+
4667+ *p++ = htonl(NFS4_CONTENT_HOLE);
4668+ p = xdr_encode_hyper(p, read->rd_offset);
4669+ p = xdr_encode_hyper(p, count);
4670+
4671+ *eof = (read->rd_offset + count) >= f_size;
4672+ *maxcount = min_t(unsigned long, count, *maxcount);
4673+ return nfs_ok;
4674+}
4675+
4676+static __be32
4677+nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
4678+ struct nfsd4_read *read)
4679+{
4680+ unsigned long maxcount, count;
4681+ struct xdr_stream *xdr = &resp->xdr;
4682+ struct file *file;
4683+ int starting_len = xdr->buf->len;
4684+ int last_segment = xdr->buf->len;
4685+ int segments = 0;
4686+ __be32 *p, tmp;
4687+ bool is_data;
4688+ loff_t pos;
4689+ u32 eof;
4690+
4691+ if (nfserr)
4692+ return nfserr;
4693+ file = read->rd_nf->nf_file;
4694+
4695+ /* eof flag, segment count */
4696+ p = xdr_reserve_space(xdr, 4 + 4);
4697+ if (!p)
4698+ return nfserr_resource;
4699+ xdr_commit_encode(xdr);
4700+
4701+ maxcount = svc_max_payload(resp->rqstp);
4702+ maxcount = min_t(unsigned long, maxcount,
4703+ (xdr->buf->buflen - xdr->buf->len));
4704+ maxcount = min_t(unsigned long, maxcount, read->rd_length);
4705+ count = maxcount;
4706+
4707+ eof = read->rd_offset >= i_size_read(file_inode(file));
4708+ if (eof)
4709+ goto out;
4710+
4711+ pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE);
4712+ is_data = pos > read->rd_offset;
4713+
4714+ while (count > 0 && !eof) {
4715+ maxcount = count;
4716+ if (is_data)
4717+ nfserr = nfsd4_encode_read_plus_data(resp, read, &maxcount, &eof,
4718+ segments == 0 ? &pos : NULL);
4719+ else
4720+ nfserr = nfsd4_encode_read_plus_hole(resp, read, &maxcount, &eof);
4721+ if (nfserr)
4722+ goto out;
4723+ count -= maxcount;
4724+ read->rd_offset += maxcount;
4725+ is_data = !is_data;
4726+ last_segment = xdr->buf->len;
4727+ segments++;
4728+ }
4729+
4730+out:
4731+ if (nfserr && segments == 0)
4732+ xdr_truncate_encode(xdr, starting_len);
4733+ else {
4734+ tmp = htonl(eof);
4735+ write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4);
4736+ tmp = htonl(segments);
4737+ write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
4738+ if (nfserr) {
4739+ xdr_truncate_encode(xdr, last_segment);
4740+ nfserr = nfs_ok;
4741+ }
4742+ }
46224743
46234744 return nfserr;
46244745 }
@@ -4679,7 +4800,7 @@ nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) · 54 unmodified lines
46794800 /*
46804801 * Encode kmalloc-ed buffer in to XDR stream.
46814802 */
4682−static int
4803+static __be32
46834804 nfsd4_vbuf_to_stream(struct xdr_stream *xdr, char *buf, u32 buflen)
46844805 {
46854806 u32 cplen;
@@ -4795,7 +4916,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 109 unmodified lines
47954916 u32 xdrlen, offset;
47964917 u64 cookie;
47974918 char *sp;
4798− __be32 status;
4919+ __be32 status, tmp;
47994920 __be32 *p;
48004921 u32 nuser;
48014922
@@ -4828,7 +4949,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 26 unmodified lines
48284949 slen = strlen(sp);
48294950
48304951 /*
4831− * Check if this a user. attribute, skip it if not.
4952+ * Check if this is a "user." attribute, skip it if not.
48324953 */
48334954 if (strncmp(sp, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
48344955 goto contloop;
@@ -4859,7 +4980,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 24 unmodified lines
48594980 goto out;
48604981 }
48614982
4862− p = xdr_encode_opaque(p, sp, slen);
4983+ xdr_encode_opaque(p, sp, slen);
48634984
48644985 xdrleft -= xdrlen;
48654986 count++;
@@ -4888,8 +5009,8 @@ wreof: · 22 unmodified lines
48885009 cookie = offset + count;
48895010
48905011 write_bytes_to_xdr_buf(xdr->buf, cookie_offset, &cookie, 8);
4891− count = htonl(count);
4892− write_bytes_to_xdr_buf(xdr->buf, count_offset, &count, 4);
5012+ tmp = cpu_to_be32(count);
5013+ write_bytes_to_xdr_buf(xdr->buf, count_offset, &tmp, 4);
48935014 out:
48945015 if (listxattrs->lsxa_len)
48955016 kvfree(listxattrs->lsxa_buf);
@@ -4996,7 +5117,7 @@ static const nfsd4_enc nfsd4_enc_ops[] = { · 100 unmodified lines
49965117 [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop,
49975118 [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop,
49985119 [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_offload_status,
4999− [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop,
5120+ [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_read_plus,
50005121 [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek,
50015122 [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop,
50025123 [OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop,
@@ -5156,6 +5277,12 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp) · 153 unmodified lines
51565277 }
51575278 }
51585279
5280+int
5281+nfs4svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
5282+{
5283+ return 1;
5284+}
5285+
51595286 int
51605287 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
51615288 {
@@ -5183,15 +5310,14 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p) · 21 unmodified lines
51835310 int
51845311 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p)
51855312 {
5186− /*
5187− * All that remains is to write the tag and operation count...
5188− */
51895313 struct nfsd4_compoundres *resp = rqstp->rq_resp;
51905314 struct xdr_buf *buf = resp->xdr.buf;
51915315
51925316 WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len +
51935317 buf->tail[0].iov_len);
51945318
5319+ *p = resp->cstate.status;
5320+
51955321 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
51965322
51975323 p = resp->tagp;
fs/nfsd/nfscache.c+4−8
@@ -172,14 +172,10 @@ int nfsd_reply_cache_init(struct nfsd_net *nn) · 171 unmodified lines
172172 if (status)
173173 goto out_nomem;
174174
175− nn->drc_hashtbl = kcalloc(hashsize,
176− sizeof(*nn->drc_hashtbl), GFP_KERNEL);
177− if (!nn->drc_hashtbl) {
178− nn->drc_hashtbl = vzalloc(array_size(hashsize,
179− sizeof(*nn->drc_hashtbl)));
180− if (!nn->drc_hashtbl)
181− goto out_shrinker;
182− }
175+ nn->drc_hashtbl = kvzalloc(array_size(hashsize,
176+ sizeof(*nn->drc_hashtbl)), GFP_KERNEL);
177+ if (!nn->drc_hashtbl)
178+ goto out_shrinker;
183179
184180 for (i = 0; i < hashsize; i++) {
185181 INIT_LIST_HEAD(&nn->drc_hashtbl[i].lru_head);
fs/nfsd/nfsctl.c+0−3
@@ -1534,7 +1534,6 @@ static int __init init_nfsd(void) · 1533 unmodified lines
15341534 retval = nfsd4_init_pnfs();
15351535 if (retval)
15361536 goto out_free_slabs;
1537− nfsd_fault_inject_init(); /* nfsd fault injection controls */
15381537 nfsd_stat_init(); /* Statistics */
15391538 retval = nfsd_drc_slab_create();
15401539 if (retval)
@@ -1555,7 +1554,6 @@ out_free_lockd: · 14 unmodified lines
15551554 nfsd_drc_slab_free();
15561555 out_free_stat:
15571556 nfsd_stat_shutdown();
1558− nfsd_fault_inject_cleanup();
15591557 nfsd4_exit_pnfs();
15601558 out_free_slabs:
15611559 nfsd4_free_slabs();
@@ -1575,7 +1573,6 @@ static void __exit exit_nfsd(void) · 13 unmodified lines
15751573 nfsd_lockd_shutdown();
15761574 nfsd4_free_slabs();
15771575 nfsd4_exit_pnfs();
1578− nfsd_fault_inject_cleanup();
15791576 unregister_filesystem(&nfsd_fs_type);
15801577 unregister_cld_notifier();
15811578 unregister_pernet_subsys(&nfsd_net_ops);
fs/nfsd/nfsproc.c+157−126
@@ -11,30 +11,14 @@ · 10 unmodified lines
1111 #include "xdr.h"
1212 #include "vfs.h"
1313
14−typedef struct svc_rqst svc_rqst;
15−typedef struct svc_buf svc_buf;
16−
1714 #define NFSDDBG_FACILITY NFSDDBG_PROC
1815
19−
2016 static __be32
2117 nfsd_proc_null(struct svc_rqst *rqstp)
2218 {
23− return nfs_ok;
19+ return rpc_success;
2420 }
2521
26−static __be32
27−nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
28−{
29− if (err) return err;
30− return fh_getattr(&resp->fh, &resp->stat);
31−}
32−static __be32
33−nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
34−{
35− if (err) return err;
36− return fh_getattr(&resp->fh, &resp->stat);
37−}
3822 /*
3923 * Get a file's attributes
4024 * N.B. After this call resp->fh needs an fh_put
@@ -44,13 +28,17 @@ nfsd_proc_getattr(struct svc_rqst *rqstp) · 3 unmodified lines
4428 {
4529 struct nfsd_fhandle *argp = rqstp->rq_argp;
4630 struct nfsd_attrstat *resp = rqstp->rq_resp;
47− __be32 nfserr;
31+
4832 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
4933
5034 fh_copy(&resp->fh, &argp->fh);
51− nfserr = fh_verify(rqstp, &resp->fh, 0,
52− NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
53− return nfsd_return_attrs(nfserr, resp);
35+ resp->status = fh_verify(rqstp, &resp->fh, 0,
36+ NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
37+ if (resp->status != nfs_ok)
38+ goto out;
39+ resp->status = fh_getattr(&resp->fh, &resp->stat);
40+out:
41+ return rpc_success;
5442 }
5543
5644 /*
@@ -64,7 +52,6 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 7 unmodified lines
6452 struct nfsd_attrstat *resp = rqstp->rq_resp;
6553 struct iattr *iap = &argp->attrs;
6654 struct svc_fh *fhp;
67− __be32 nfserr;
6855
6956 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
7057 SVCFH_fmt(&argp->fh),
@@ -96,9 +83,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 25 unmodified lines
9683 */
9784 time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();
9885
99− nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
100− if (nfserr)
101− goto done;
86+ resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
87+ if (resp->status != nfs_ok)
88+ goto out;
10289
10390 if (delta < 0)
10491 delta = -delta;
@@ -113,9 +100,20 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 8 unmodified lines
113100 }
114101 }
115102
116− nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
117−done:
118− return nfsd_return_attrs(nfserr, resp);
103+ resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
104+ if (resp->status != nfs_ok)
105+ goto out;
106+
107+ resp->status = fh_getattr(&resp->fh, &resp->stat);
108+out:
109+ return rpc_success;
110+}
111+
112+/* Obsolete, replaced by MNTPROC_MNT. */
113+static __be32
114+nfsd_proc_root(struct svc_rqst *rqstp)
115+{
116+ return rpc_success;
119117 }
120118
121119 /*
@@ -129,17 +127,20 @@ nfsd_proc_lookup(struct svc_rqst *rqstp) · 7 unmodified lines
129127 {
130128 struct nfsd_diropargs *argp = rqstp->rq_argp;
131129 struct nfsd_diropres *resp = rqstp->rq_resp;
132− __be32 nfserr;
133130
134131 dprintk("nfsd: LOOKUP %s %.*s\n",
135132 SVCFH_fmt(&argp->fh), argp->len, argp->name);
136133
137134 fh_init(&resp->fh, NFS_FHSIZE);
138− nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
139− &resp->fh);
140−
135+ resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
136+ &resp->fh);
141137 fh_put(&argp->fh);
142− return nfsd_return_dirop(nfserr, resp);
138+ if (resp->status != nfs_ok)
139+ goto out;
140+
141+ resp->status = fh_getattr(&resp->fh, &resp->stat);
142+out:
143+ return rpc_success;
143144 }
144145
145146 /*
@@ -150,16 +151,15 @@ nfsd_proc_readlink(struct svc_rqst *rqstp) · 4 unmodified lines
150151 {
151152 struct nfsd_readlinkargs *argp = rqstp->rq_argp;
152153 struct nfsd_readlinkres *resp = rqstp->rq_resp;
153− __be32 nfserr;
154154
155155 dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
156156
157157 /* Read the symlink. */
158158 resp->len = NFS_MAXPATHLEN;
159− nfserr = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
159+ resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
160160
161161 fh_put(&argp->fh);
162− return nfserr;
162+ return rpc_success;
163163 }
164164
165165 /*
@@ -171,7 +171,6 @@ nfsd_proc_read(struct svc_rqst *rqstp) · 5 unmodified lines
171171 {
172172 struct nfsd_readargs *argp = rqstp->rq_argp;
173173 struct nfsd_readres *resp = rqstp->rq_resp;
174− __be32 nfserr;
175174 u32 eof;
176175
177176 dprintk("nfsd: READ %s %d bytes at %d\n",
@@ -193,14 +192,23 @@ nfsd_proc_read(struct svc_rqst *rqstp) · 15 unmodified lines
193192 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
194193
195194 resp->count = argp->count;
196− nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
197− argp->offset,
198− rqstp->rq_vec, argp->vlen,
199− &resp->count,
200− &eof);
201−
202− if (nfserr) return nfserr;
203− return fh_getattr(&resp->fh, &resp->stat);
195+ resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
196+ argp->offset,
197+ rqstp->rq_vec, argp->vlen,
198+ &resp->count,
199+ &eof);
200+ if (resp->status == nfs_ok)
201+ resp->status = fh_getattr(&resp->fh, &resp->stat);
202+ else if (resp->status == nfserr_jukebox)
203+ return rpc_drop_reply;
204+ return rpc_success;
205+}
206+
207+/* Reserved */
208+static __be32
209+nfsd_proc_writecache(struct svc_rqst *rqstp)
210+{
211+ return rpc_success;
204212 }
205213
206214 /*
@@ -212,7 +220,6 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 5 unmodified lines
212220 {
213221 struct nfsd_writeargs *argp = rqstp->rq_argp;
214222 struct nfsd_attrstat *resp = rqstp->rq_resp;
215− __be32 nfserr;
216223 unsigned long cnt = argp->len;
217224 unsigned int nvecs;
218225
@@ -222,12 +229,20 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 3 unmodified lines
222229
223230 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
224231 &argp->first, cnt);
225− if (!nvecs)
226− return nfserr_io;
227− nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
228− argp->offset, rqstp->rq_vec, nvecs,
229− &cnt, NFS_DATA_SYNC, NULL);
230− return nfsd_return_attrs(nfserr, resp);
232+ if (!nvecs) {
233+ resp->status = nfserr_io;
234+ goto out;
235+ }
236+
237+ resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
238+ argp->offset, rqstp->rq_vec, nvecs,
239+ &cnt, NFS_DATA_SYNC, NULL);
240+ if (resp->status == nfs_ok)
241+ resp->status = fh_getattr(&resp->fh, &resp->stat);
242+ else if (resp->status == nfserr_jukebox)
243+ return rpc_drop_reply;
244+out:
245+ return rpc_success;
231246 }
232247
233248 /*
@@ -247,7 +262,6 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 13 unmodified lines
247262 struct inode *inode;
248263 struct dentry *dchild;
249264 int type, mode;
250− __be32 nfserr;
251265 int hosterr;
252266 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size);
253267
@@ -255,40 +269,40 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 1 unmodified line
255269 SVCFH_fmt(dirfhp), argp->len, argp->name);
256270
257271 /* First verify the parent file handle */
258− nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
259− if (nfserr)
272+ resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
273+ if (resp->status != nfs_ok)
260274 goto done; /* must fh_put dirfhp even on error */
261275
262276 /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
263277
264− nfserr = nfserr_exist;
278+ resp->status = nfserr_exist;
265279 if (isdotent(argp->name, argp->len))
266280 goto done;
267281 hosterr = fh_want_write(dirfhp);
268282 if (hosterr) {
269− nfserr = nfserrno(hosterr);
283+ resp->status = nfserrno(hosterr);
270284 goto done;
271285 }
272286
273287 fh_lock_nested(dirfhp, I_MUTEX_PARENT);
274288 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
275289 if (IS_ERR(dchild)) {
276− nfserr = nfserrno(PTR_ERR(dchild));
290+ resp->status = nfserrno(PTR_ERR(dchild));
277291 goto out_unlock;
278292 }
279293 fh_init(newfhp, NFS_FHSIZE);
280− nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
281− if (!nfserr && d_really_is_negative(dchild))
282− nfserr = nfserr_noent;
294+ resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
295+ if (!resp->status && d_really_is_negative(dchild))
296+ resp->status = nfserr_noent;
283297 dput(dchild);
284− if (nfserr) {
285− if (nfserr != nfserr_noent)
298+ if (resp->status) {
299+ if (resp->status != nfserr_noent)
286300 goto out_unlock;
287301 /*
288302 * If the new file handle wasn't verified, we can't tell
289303 * whether the file exists or not. Time to bail ...
290304 */
291− nfserr = nfserr_acces;
305+ resp->status = nfserr_acces;
292306 if (!newfhp->fh_dentry) {
293307 printk(KERN_WARNING
294308 "nfsd_proc_create: file handle not verified\n");
@@ -321,11 +335,11 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 26 unmodified lines
321335 * echo thing > device-special-file-or-pipe
322336 * by doing a CREATE with type==0
323337 */
324− nfserr = nfsd_permission(rqstp,
338+ resp->status = nfsd_permission(rqstp,
325339 newfhp->fh_export,
326340 newfhp->fh_dentry,
327341 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
328− if (nfserr && nfserr != nfserr_rofs)
342+ if (resp->status && resp->status != nfserr_rofs)
329343 goto out_unlock;
330344 }
331345 } else
@@ -361,16 +375,17 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 29 unmodified lines
361375 attr->ia_valid &= ~ATTR_SIZE;
362376
363377 /* Make sure the type and device matches */
364− nfserr = nfserr_exist;
378+ resp->status = nfserr_exist;
365379 if (inode && type != (inode->i_mode & S_IFMT))
366380 goto out_unlock;
367381 }
368382
369− nfserr = 0;
383+ resp->status = nfs_ok;
370384 if (!inode) {
371385 /* File doesn't exist. Create it and set attrs */
372− nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name,
373− argp->len, attr, type, rdev, newfhp);
386+ resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
387+ argp->len, attr, type, rdev,
388+ newfhp);
374389 } else if (type == S_IFREG) {
375390 dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
376391 argp->name, attr->ia_valid, (long) attr->ia_size);
@@ -380,7 +395,8 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 3 unmodified lines
380395 */
381396 attr->ia_valid &= ATTR_SIZE;
382397 if (attr->ia_valid)
383− nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time64_t)0);
398+ resp->status = nfsd_setattr(rqstp, newfhp, attr, 0,
399+ (time64_t)0);
384400 }
385401
386402 out_unlock:
@@ -389,47 +405,52 @@ out_unlock: · 2 unmodified lines
389405 fh_drop_write(dirfhp);
390406 done:
391407 fh_put(dirfhp);
392− return nfsd_return_dirop(nfserr, resp);
408+ if (resp->status != nfs_ok)
409+ goto out;
410+ resp->status = fh_getattr(&resp->fh, &resp->stat);
411+out:
412+ return rpc_success;
393413 }
394414
395415 static __be32
396416 nfsd_proc_remove(struct svc_rqst *rqstp)
397417 {
398418 struct nfsd_diropargs *argp = rqstp->rq_argp;
399− __be32 nfserr;
419+ struct nfsd_stat *resp = rqstp->rq_resp;
400420
401421 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh),
402422 argp->len, argp->name);
403423
404424 /* Unlink. -SIFDIR means file must not be a directory */
405− nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
425+ resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR,
426+ argp->name, argp->len);
406427 fh_put(&argp->fh);
407− return nfserr;
428+ return rpc_success;
408429 }
409430
410431 static __be32
411432 nfsd_proc_rename(struct svc_rqst *rqstp)
412433 {
413434 struct nfsd_renameargs *argp = rqstp->rq_argp;
414− __be32 nfserr;
435+ struct nfsd_stat *resp = rqstp->rq_resp;
415436
416437 dprintk("nfsd: RENAME %s %.*s -> \n",
417438 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
418439 dprintk("nfsd: -> %s %.*s\n",
419440 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
420441
421− nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
422− &argp->tfh, argp->tname, argp->tlen);
442+ resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
443+ &argp->tfh, argp->tname, argp->tlen);
423444 fh_put(&argp->ffh);
424445 fh_put(&argp->tfh);
425− return nfserr;
446+ return rpc_success;
426447 }
427448
428449 static __be32
429450 nfsd_proc_link(struct svc_rqst *rqstp)
430451 {
431452 struct nfsd_linkargs *argp = rqstp->rq_argp;
432− __be32 nfserr;
453+ struct nfsd_stat *resp = rqstp->rq_resp;
433454
434455 dprintk("nfsd: LINK %s ->\n",
435456 SVCFH_fmt(&argp->ffh));
@@ -438,41 +459,46 @@ nfsd_proc_link(struct svc_rqst *rqstp) · 2 unmodified lines
438459 argp->tlen,
439460 argp->tname);
440461
441− nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
442− &argp->ffh);
462+ resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
463+ &argp->ffh);
443464 fh_put(&argp->ffh);
444465 fh_put(&argp->tfh);
445− return nfserr;
466+ return rpc_success;
446467 }
447468
448469 static __be32
449470 nfsd_proc_symlink(struct svc_rqst *rqstp)
450471 {
451472 struct nfsd_symlinkargs *argp = rqstp->rq_argp;
473+ struct nfsd_stat *resp = rqstp->rq_resp;
452474 struct svc_fh newfh;
453− __be32 nfserr;
454475
455− if (argp->tlen > NFS_MAXPATHLEN)
456− return nfserr_nametoolong;
476+ if (argp->tlen > NFS_MAXPATHLEN) {
477+ resp->status = nfserr_nametoolong;
478+ goto out;
479+ }
457480
458481 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
459482 page_address(rqstp->rq_arg.pages[0]),
460483 argp->tlen);
461− if (IS_ERR(argp->tname))
462− return nfserrno(PTR_ERR(argp->tname));
484+ if (IS_ERR(argp->tname)) {
485+ resp->status = nfserrno(PTR_ERR(argp->tname));
486+ goto out;
487+ }
463488
464489 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n",
465490 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
466491 argp->tlen, argp->tname);
467492
468493 fh_init(&newfh, NFS_FHSIZE);
469− nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
470− argp->tname, &newfh);
494+ resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
495+ argp->tname, &newfh);
471496
472497 kfree(argp->tname);
473498 fh_put(&argp->ffh);
474499 fh_put(&newfh);
475− return nfserr;
500+out:
501+ return rpc_success;
476502 }
477503
478504 /*
@@ -484,7 +510,6 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp) · 5 unmodified lines
484510 {
485511 struct nfsd_createargs *argp = rqstp->rq_argp;
486512 struct nfsd_diropres *resp = rqstp->rq_resp;
487− __be32 nfserr;
488513
489514 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
490515
@@ -495,10 +520,15 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp) · 4 unmodified lines
495520
496521 argp->attrs.ia_valid &= ~ATTR_SIZE;
497522 fh_init(&resp->fh, NFS_FHSIZE);
498− nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
499− &argp->attrs, S_IFDIR, 0, &resp->fh);
523+ resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
524+ &argp->attrs, S_IFDIR, 0, &resp->fh);
500525 fh_put(&argp->fh);
501− return nfsd_return_dirop(nfserr, resp);
526+ if (resp->status != nfs_ok)
527+ goto out;
528+
529+ resp->status = fh_getattr(&resp->fh, &resp->stat);
530+out:
531+ return rpc_success;
502532 }
503533
504534 /*
@@ -508,13 +538,14 @@ static __be32 · 3 unmodified lines
508538 nfsd_proc_rmdir(struct svc_rqst *rqstp)
509539 {
510540 struct nfsd_diropargs *argp = rqstp->rq_argp;
511− __be32 nfserr;
541+ struct nfsd_stat *resp = rqstp->rq_resp;
512542
513543 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
514544
515− nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
545+ resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR,
546+ argp->name, argp->len);
516547 fh_put(&argp->fh);
517− return nfserr;
548+ return rpc_success;
518549 }
519550
520551 /*
@@ -526,7 +557,6 @@ nfsd_proc_readdir(struct svc_rqst *rqstp) · 5 unmodified lines
526557 struct nfsd_readdirargs *argp = rqstp->rq_argp;
527558 struct nfsd_readdirres *resp = rqstp->rq_resp;
528559 int count;
529− __be32 nfserr;
530560 loff_t offset;
531561
532562 dprintk("nfsd: READDIR %s %d bytes at %d\n",
@@ -547,15 +577,15 @@ nfsd_proc_readdir(struct svc_rqst *rqstp) · 14 unmodified lines
547577 resp->common.err = nfs_ok;
548578 /* Read directory and encode entries on the fly */
549579 offset = argp->cookie;
550− nfserr = nfsd_readdir(rqstp, &argp->fh, &offset,
551− &resp->common, nfssvc_encode_entry);
580+ resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
581+ &resp->common, nfssvc_encode_entry);
552582
553583 resp->count = resp->buffer - argp->buffer;
554584 if (resp->offset)
555585 *resp->offset = htonl(offset);
556586
557587 fh_put(&argp->fh);
558− return nfserr;
588+ return rpc_success;
559589 }
560590
561591 /*
@@ -566,14 +596,13 @@ nfsd_proc_statfs(struct svc_rqst *rqstp) · 4 unmodified lines
566596 {
567597 struct nfsd_fhandle *argp = rqstp->rq_argp;
568598 struct nfsd_statfsres *resp = rqstp->rq_resp;
569− __be32 nfserr;
570599
571600 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
572601
573− nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
574− NFSD_MAY_BYPASS_GSS_ON_ROOT);
602+ resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
603+ NFSD_MAY_BYPASS_GSS_ON_ROOT);
575604 fh_put(&argp->fh);
576− return nfserr;
605+ return rpc_success;
577606 }
578607
579608 /*
@@ -594,13 +623,13 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 14 unmodified lines
594623 .pc_argsize = sizeof(struct nfsd_void),
595624 .pc_ressize = sizeof(struct nfsd_void),
596625 .pc_cachetype = RC_NOCACHE,
597− .pc_xdrressize = ST,
626+ .pc_xdrressize = 0,
598627 },
599628 [NFSPROC_GETATTR] = {
600629 .pc_func = nfsd_proc_getattr,
601630 .pc_decode = nfssvc_decode_fhandle,
602631 .pc_encode = nfssvc_encode_attrstat,
603− .pc_release = nfssvc_release_fhandle,
632+ .pc_release = nfssvc_release_attrstat,
604633 .pc_argsize = sizeof(struct nfsd_fhandle),
605634 .pc_ressize = sizeof(struct nfsd_attrstat),
606635 .pc_cachetype = RC_NOCACHE,
@@ -610,25 +639,26 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 3 unmodified lines
610639 .pc_func = nfsd_proc_setattr,
611640 .pc_decode = nfssvc_decode_sattrargs,
612641 .pc_encode = nfssvc_encode_attrstat,
613− .pc_release = nfssvc_release_fhandle,
642+ .pc_release = nfssvc_release_attrstat,
614643 .pc_argsize = sizeof(struct nfsd_sattrargs),
615644 .pc_ressize = sizeof(struct nfsd_attrstat),
616645 .pc_cachetype = RC_REPLBUFF,
617646 .pc_xdrressize = ST+AT,
618647 },
619648 [NFSPROC_ROOT] = {
649+ .pc_func = nfsd_proc_root,
620650 .pc_decode = nfssvc_decode_void,
621651 .pc_encode = nfssvc_encode_void,
622652 .pc_argsize = sizeof(struct nfsd_void),
623653 .pc_ressize = sizeof(struct nfsd_void),
624654 .pc_cachetype = RC_NOCACHE,
625− .pc_xdrressize = ST,
655+ .pc_xdrressize = 0,
626656 },
627657 [NFSPROC_LOOKUP] = {
628658 .pc_func = nfsd_proc_lookup,
629659 .pc_decode = nfssvc_decode_diropargs,
630660 .pc_encode = nfssvc_encode_diropres,
631− .pc_release = nfssvc_release_fhandle,
661+ .pc_release = nfssvc_release_diropres,
632662 .pc_argsize = sizeof(struct nfsd_diropargs),
633663 .pc_ressize = sizeof(struct nfsd_diropres),
634664 .pc_cachetype = RC_NOCACHE,
@@ -647,25 +677,26 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 12 unmodified lines
647677 .pc_func = nfsd_proc_read,
648678 .pc_decode = nfssvc_decode_readargs,
649679 .pc_encode = nfssvc_encode_readres,
650− .pc_release = nfssvc_release_fhandle,
680+ .pc_release = nfssvc_release_readres,
651681 .pc_argsize = sizeof(struct nfsd_readargs),
652682 .pc_ressize = sizeof(struct nfsd_readres),
653683 .pc_cachetype = RC_NOCACHE,
654684 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
655685 },
656686 [NFSPROC_WRITECACHE] = {
687+ .pc_func = nfsd_proc_writecache,
657688 .pc_decode = nfssvc_decode_void,
658689 .pc_encode = nfssvc_encode_void,
659690 .pc_argsize = sizeof(struct nfsd_void),
660691 .pc_ressize = sizeof(struct nfsd_void),
661692 .pc_cachetype = RC_NOCACHE,
662− .pc_xdrressize = ST,
693+ .pc_xdrressize = 0,
663694 },
664695 [NFSPROC_WRITE] = {
665696 .pc_func = nfsd_proc_write,
666697 .pc_decode = nfssvc_decode_writeargs,
667698 .pc_encode = nfssvc_encode_attrstat,
668− .pc_release = nfssvc_release_fhandle,
699+ .pc_release = nfssvc_release_attrstat,
669700 .pc_argsize = sizeof(struct nfsd_writeargs),
670701 .pc_ressize = sizeof(struct nfsd_attrstat),
671702 .pc_cachetype = RC_REPLBUFF,
@@ -675,7 +706,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 3 unmodified lines
675706 .pc_func = nfsd_proc_create,
676707 .pc_decode = nfssvc_decode_createargs,
677708 .pc_encode = nfssvc_encode_diropres,
678− .pc_release = nfssvc_release_fhandle,
709+ .pc_release = nfssvc_release_diropres,
679710 .pc_argsize = sizeof(struct nfsd_createargs),
680711 .pc_ressize = sizeof(struct nfsd_diropres),
681712 .pc_cachetype = RC_REPLBUFF,
@@ -684,36 +715,36 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 2 unmodified lines
684715 [NFSPROC_REMOVE] = {
685716 .pc_func = nfsd_proc_remove,
686717 .pc_decode = nfssvc_decode_diropargs,
687− .pc_encode = nfssvc_encode_void,
718+ .pc_encode = nfssvc_encode_stat,
688719 .pc_argsize = sizeof(struct nfsd_diropargs),
689− .pc_ressize = sizeof(struct nfsd_void),
720+ .pc_ressize = sizeof(struct nfsd_stat),
690721 .pc_cachetype = RC_REPLSTAT,
691722 .pc_xdrressize = ST,
692723 },
693724 [NFSPROC_RENAME] = {
694725 .pc_func = nfsd_proc_rename,
695726 .pc_decode = nfssvc_decode_renameargs,
696− .pc_encode = nfssvc_encode_void,
727+ .pc_encode = nfssvc_encode_stat,
697728 .pc_argsize = sizeof(struct nfsd_renameargs),
698− .pc_ressize = sizeof(struct nfsd_void),
729+ .pc_ressize = sizeof(struct nfsd_stat),
699730 .pc_cachetype = RC_REPLSTAT,
700731 .pc_xdrressize = ST,
701732 },
702733 [NFSPROC_LINK] = {
703734 .pc_func = nfsd_proc_link,
704735 .pc_decode = nfssvc_decode_linkargs,
705− .pc_encode = nfssvc_encode_void,
736+ .pc_encode = nfssvc_encode_stat,
706737 .pc_argsize = sizeof(struct nfsd_linkargs),
707− .pc_ressize = sizeof(struct nfsd_void),
738+ .pc_ressize = sizeof(struct nfsd_stat),
708739 .pc_cachetype = RC_REPLSTAT,
709740 .pc_xdrressize = ST,
710741 },
711742 [NFSPROC_SYMLINK] = {
712743 .pc_func = nfsd_proc_symlink,
713744 .pc_decode = nfssvc_decode_symlinkargs,
714− .pc_encode = nfssvc_encode_void,
745+ .pc_encode = nfssvc_encode_stat,
715746 .pc_argsize = sizeof(struct nfsd_symlinkargs),
716− .pc_ressize = sizeof(struct nfsd_void),
747+ .pc_ressize = sizeof(struct nfsd_stat),
717748 .pc_cachetype = RC_REPLSTAT,
718749 .pc_xdrressize = ST,
719750 },
@@ -721,7 +752,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 1 unmodified line
721752 .pc_func = nfsd_proc_mkdir,
722753 .pc_decode = nfssvc_decode_createargs,
723754 .pc_encode = nfssvc_encode_diropres,
724− .pc_release = nfssvc_release_fhandle,
755+ .pc_release = nfssvc_release_diropres,
725756 .pc_argsize = sizeof(struct nfsd_createargs),
726757 .pc_ressize = sizeof(struct nfsd_diropres),
727758 .pc_cachetype = RC_REPLBUFF,
@@ -730,9 +761,9 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 2 unmodified lines
730761 [NFSPROC_RMDIR] = {
731762 .pc_func = nfsd_proc_rmdir,
732763 .pc_decode = nfssvc_decode_diropargs,
733− .pc_encode = nfssvc_encode_void,
764+ .pc_encode = nfssvc_encode_stat,
734765 .pc_argsize = sizeof(struct nfsd_diropargs),
735− .pc_ressize = sizeof(struct nfsd_void),
766+ .pc_ressize = sizeof(struct nfsd_stat),
736767 .pc_cachetype = RC_REPLSTAT,
737768 .pc_xdrressize = ST,
738769 },
fs/nfsd/nfssvc.c+59−63
@@ -960,15 +960,6 @@ out: · 959 unmodified lines
960960 return 0;
961961 }
962962
963−static __be32 map_new_errors(u32 vers, __be32 nfserr)
964−{
965− if (nfserr == nfserr_jukebox && vers == 2)
966− return nfserr_dropit;
967− if (nfserr == nfserr_wrongsec && vers < 4)
968− return nfserr_acces;
969− return nfserr;
970−}
971−
972963 /*
973964 * A write procedure can have a large argument, and a read procedure can
974965 * have a large reply, but no NFSv2 or NFSv3 procedure has argument and
@@ -1000,80 +991,85 @@ static bool nfs_request_too_big(struct svc_rqst *rqstp, · 25 unmodified lines
1000991 return rqstp->rq_arg.len > PAGE_SIZE;
1001992 }
1002993
1003−int
1004−nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
994+/**
995+ * nfsd_dispatch - Process an NFS or NFSACL Request
996+ * @rqstp: incoming request
997+ * @statp: pointer to location of accept_stat field in RPC Reply buffer
998+ *
999+ * This RPC dispatcher integrates the NFS server's duplicate reply cache.
1000+ *
1001+ * Return values:
1002+ * %0: Processing complete; do not send a Reply
1003+ * %1: Processing complete; send Reply in rqstp->rq_res
1004+ */
1005+int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
10051006 {
1006− const struct svc_procedure *proc;
1007− __be32 nfserr;
1008− __be32 *nfserrp;
1007+ const struct svc_procedure *proc = rqstp->rq_procinfo;
1008+ struct kvec *argv = &rqstp->rq_arg.head[0];
1009+ struct kvec *resv = &rqstp->rq_res.head[0];
1010+ __be32 *p;
10091011
10101012 dprintk("nfsd_dispatch: vers %d proc %d\n",
10111013 rqstp->rq_vers, rqstp->rq_proc);
1012− proc = rqstp->rq_procinfo;
10131014
1014− if (nfs_request_too_big(rqstp, proc)) {
1015− dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
1016− *statp = rpc_garbage_args;
1017− return 1;
1018− }
1019− rqstp->rq_lease_breaker = NULL;
1015+ if (nfs_request_too_big(rqstp, proc))
1016+ goto out_too_large;
1017+
10201018 /*
10211019 * Give the xdr decoder a chance to change this if it wants
10221020 * (necessary in the NFSv4.0 compound case)
10231021 */
10241022 rqstp->rq_cachetype = proc->pc_cachetype;
1025− /* Decode arguments */
1026− if (proc->pc_decode &&
1027− !proc->pc_decode(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base)) {
1028− dprintk("nfsd: failed to decode arguments!\n");
1029− *statp = rpc_garbage_args;
1030− return 1;
1031− }
1023+ if (!proc->pc_decode(rqstp, argv->iov_base))
1024+ goto out_decode_err;
10321025
1033− /* Check whether we have this call in the cache. */
10341026 switch (nfsd_cache_lookup(rqstp)) {
1035− case RC_DROPIT:
1036− return 0;
1027+ case RC_DOIT:
1028+ break;
10371029 case RC_REPLY:
1038− return 1;
1039− case RC_DOIT:;
1040− /* do it */
1030+ goto out_cached_reply;
1031+ case RC_DROPIT:
1032+ goto out_dropit;
10411033 }
10421034
1043− /* need to grab the location to store the status, as
1044− * nfsv4 does some encoding while processing
1035+ /*
1036+ * Need to grab the location to store the status, as
1037+ * NFSv4 does some encoding while processing
10451038 */
1046− nfserrp = rqstp->rq_res.head[0].iov_base
1047− + rqstp->rq_res.head[0].iov_len;
1048− rqstp->rq_res.head[0].iov_len += sizeof(__be32);
1049−
1050− /* Now call the procedure handler, and encode NFS status. */
1051− nfserr = proc->pc_func(rqstp);
1052− nfserr = map_new_errors(rqstp->rq_vers, nfserr);
1053− if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) {
1054− dprintk("nfsd: Dropping request; may be revisited later\n");
1055− nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
1056− return 0;
1057− }
1039+ p = resv->iov_base + resv->iov_len;
1040+ resv->iov_len += sizeof(__be32);
10581041
1059− if (rqstp->rq_proc != 0)
1060− *nfserrp++ = nfserr;
1042+ *statp = proc->pc_func(rqstp);
1043+ if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
1044+ goto out_update_drop;
10611045
1062− /* Encode result.
1063− * For NFSv2, additional info is never returned in case of an error.
1064− */
1065− if (!(nfserr && rqstp->rq_vers == 2)) {
1066− if (proc->pc_encode && !proc->pc_encode(rqstp, nfserrp)) {
1067− /* Failed to encode result. Release cache entry */
1068− dprintk("nfsd: failed to encode result!\n");
1069− nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
1070− *statp = rpc_system_err;
1071− return 1;
1072− }
1073− }
1046+ if (!proc->pc_encode(rqstp, p))
1047+ goto out_encode_err;
10741048
1075− /* Store reply in cache. */
10761049 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
1050+out_cached_reply:
1051+ return 1;
1052+
1053+out_too_large:
1054+ dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
1055+ *statp = rpc_garbage_args;
1056+ return 1;
1057+
1058+out_decode_err:
1059+ dprintk("nfsd: failed to decode arguments!\n");
1060+ *statp = rpc_garbage_args;
1061+ return 1;
1062+
1063+out_update_drop:
1064+ dprintk("nfsd: Dropping request; may be revisited later\n");
1065+ nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
1066+out_dropit:
1067+ return 0;
1068+
1069+out_encode_err:
1070+ dprintk("nfsd: failed to encode result!\n");
1071+ nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
1072+ *statp = rpc_system_err;
10771073 return 1;
10781074 }
10791075
fs/nfsd/nfsxdr.c+49−3
@@ -429,12 +429,25 @@ nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p) · 428 unmodified lines
429429 return xdr_ressize_check(rqstp, p);
430430 }
431431
432+int
433+nfssvc_encode_stat(struct svc_rqst *rqstp, __be32 *p)
434+{
435+ struct nfsd_stat *resp = rqstp->rq_resp;
436+
437+ *p++ = resp->status;
438+ return xdr_ressize_check(rqstp, p);
439+}
440+
432441 int
433442 nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
434443 {
435444 struct nfsd_attrstat *resp = rqstp->rq_resp;
436445
446+ *p++ = resp->status;
447+ if (resp->status != nfs_ok)
448+ goto out;
437449 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
450+out:
438451 return xdr_ressize_check(rqstp, p);
439452 }
440453
@@ -443,8 +456,12 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p) · 2 unmodified lines
443456 {
444457 struct nfsd_diropres *resp = rqstp->rq_resp;
445458
459+ *p++ = resp->status;
460+ if (resp->status != nfs_ok)
461+ goto out;
446462 p = encode_fh(p, &resp->fh);
447463 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
464+out:
448465 return xdr_ressize_check(rqstp, p);
449466 }
450467
@@ -453,6 +470,10 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) · 2 unmodified lines
453470 {
454471 struct nfsd_readlinkres *resp = rqstp->rq_resp;
455472
473+ *p++ = resp->status;
474+ if (resp->status != nfs_ok)
475+ return xdr_ressize_check(rqstp, p);
476+
456477 *p++ = htonl(resp->len);
457478 xdr_ressize_check(rqstp, p);
458479 rqstp->rq_res.page_len = resp->len;
@@ -470,6 +491,10 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p) · 11 unmodified lines
470491 {
471492 struct nfsd_readres *resp = rqstp->rq_resp;
472493
494+ *p++ = resp->status;
495+ if (resp->status != nfs_ok)
496+ return xdr_ressize_check(rqstp, p);
497+
473498 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
474499 *p++ = htonl(resp->count);
475500 xdr_ressize_check(rqstp, p);
@@ -490,6 +515,10 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) · 14 unmodified lines
490515 {
491516 struct nfsd_readdirres *resp = rqstp->rq_resp;
492517
518+ *p++ = resp->status;
519+ if (resp->status != nfs_ok)
520+ return xdr_ressize_check(rqstp, p);
521+
493522 xdr_ressize_check(rqstp, p);
494523 p = resp->buffer;
495524 *p++ = 0; /* no more entries */
@@ -505,6 +534,10 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p) · 9 unmodified lines
505534 struct nfsd_statfsres *resp = rqstp->rq_resp;
506535 struct kstatfs *stat = &resp->stats;
507536
537+ *p++ = resp->status;
538+ if (resp->status != nfs_ok)
539+ return xdr_ressize_check(rqstp, p);
540+
508541 *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */
509542 *p++ = htonl(stat->f_bsize);
510543 *p++ = htonl(stat->f_blocks);
@@ -561,10 +594,23 @@ nfssvc_encode_entry(void *ccdv, const char *name, · 50 unmodified lines
561594 /*
562595 * XDR release functions
563596 */
564−void
565−nfssvc_release_fhandle(struct svc_rqst *rqstp)
597+void nfssvc_release_attrstat(struct svc_rqst *rqstp)
566598 {
567− struct nfsd_fhandle *resp = rqstp->rq_resp;
599+ struct nfsd_attrstat *resp = rqstp->rq_resp;
600+
601+ fh_put(&resp->fh);
602+}
603+
604+void nfssvc_release_diropres(struct svc_rqst *rqstp)
605+{
606+ struct nfsd_diropres *resp = rqstp->rq_resp;
607+
608+ fh_put(&resp->fh);
609+}
610+
611+void nfssvc_release_readres(struct svc_rqst *rqstp)
612+{
613+ struct nfsd_readres *resp = rqstp->rq_resp;
568614
569615 fh_put(&resp->fh);
570616 }
fs/nfsd/state.h+0−27
@@ -693,31 +693,4 @@ extern void nfsd4_client_record_remove(struct nfs4_client *clp); · 692 unmodified lines
693693 extern int nfsd4_client_record_check(struct nfs4_client *clp);
694694 extern void nfsd4_record_grace_done(struct nfsd_net *nn);
695695
696−/* nfs fault injection functions */
697−#ifdef CONFIG_NFSD_FAULT_INJECTION
698−void nfsd_fault_inject_init(void);
699−void nfsd_fault_inject_cleanup(void);
700−
701−u64 nfsd_inject_print_clients(void);
702−u64 nfsd_inject_forget_client(struct sockaddr_storage *, size_t);
703−u64 nfsd_inject_forget_clients(u64);
704−
705−u64 nfsd_inject_print_locks(void);
706−u64 nfsd_inject_forget_client_locks(struct sockaddr_storage *, size_t);
707−u64 nfsd_inject_forget_locks(u64);
708−
709−u64 nfsd_inject_print_openowners(void);
710−u64 nfsd_inject_forget_client_openowners(struct sockaddr_storage *, size_t);
711−u64 nfsd_inject_forget_openowners(u64);
712−
713−u64 nfsd_inject_print_delegations(void);
714−u64 nfsd_inject_forget_client_delegations(struct sockaddr_storage *, size_t);
715−u64 nfsd_inject_forget_delegations(u64);
716−u64 nfsd_inject_recall_client_delegations(struct sockaddr_storage *, size_t);
717−u64 nfsd_inject_recall_delegations(u64);
718−#else /* CONFIG_NFSD_FAULT_INJECTION */
719−static inline void nfsd_fault_inject_init(void) {}
720−static inline void nfsd_fault_inject_cleanup(void) {}
721−#endif /* CONFIG_NFSD_FAULT_INJECTION */
722−
723696 #endif /* NFSD4_STATE_H */
fs/nfsd/trace.h+2−2
@@ -289,8 +289,8 @@ DEFINE_STATEID_EVENT(layout_recall_done); · 288 unmodified lines
289289 DEFINE_STATEID_EVENT(layout_recall_fail);
290290 DEFINE_STATEID_EVENT(layout_recall_release);
291291
292−DEFINE_STATEID_EVENT(deleg_open);
293−DEFINE_STATEID_EVENT(deleg_none);
292+DEFINE_STATEID_EVENT(open);
293+DEFINE_STATEID_EVENT(deleg_read);
294294 DEFINE_STATEID_EVENT(deleg_break);
295295 DEFINE_STATEID_EVENT(deleg_recall);
296296
fs/nfsd/vfs.c+4−2
@@ -2259,7 +2259,8 @@ out: · 2258 unmodified lines
22592259 __be32
22602260 nfsd_removexattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name)
22612261 {
2262− int err, ret;
2262+ __be32 err;
2263+ int ret;
22632264
22642265 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE);
22652266 if (err)
@@ -2283,7 +2284,8 @@ __be32 · 17 unmodified lines
22832284 nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,
22842285 void *buf, u32 len, u32 flags)
22852286 {
2286− int err, ret;
2287+ __be32 err;
2288+ int ret;
22872289
22882290 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE);
22892291 if (err)
fs/nfsd/xdr.h+15−1
@@ -82,27 +82,37 @@ struct nfsd_readdirargs { · 81 unmodified lines
8282 __be32 * buffer;
8383 };
8484
85+struct nfsd_stat {
86+ __be32 status;
87+};
88+
8589 struct nfsd_attrstat {
90+ __be32 status;
8691 struct svc_fh fh;
8792 struct kstat stat;
8893 };
8994
9095 struct nfsd_diropres {
96+ __be32 status;
9197 struct svc_fh fh;
9298 struct kstat stat;
9399 };
94100
95101 struct nfsd_readlinkres {
102+ __be32 status;
96103 int len;
97104 };
98105
99106 struct nfsd_readres {
107+ __be32 status;
100108 struct svc_fh fh;
101109 unsigned long count;
102110 struct kstat stat;
103111 };
104112
105113 struct nfsd_readdirres {
114+ __be32 status;
115+
106116 int count;
107117
108118 struct readdir_cd common;
@@ -112,6 +122,7 @@ struct nfsd_readdirres { · 3 unmodified lines
112122 };
113123
114124 struct nfsd_statfsres {
125+ __be32 status;
115126 struct kstatfs stats;
116127 };
117128
@@ -146,6 +157,7 @@ int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *); · 28 unmodified lines
146157 int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *);
147158 int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *);
148159 int nfssvc_encode_void(struct svc_rqst *, __be32 *);
160+int nfssvc_encode_stat(struct svc_rqst *, __be32 *);
149161 int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *);
150162 int nfssvc_encode_diropres(struct svc_rqst *, __be32 *);
151163 int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *);
@@ -156,7 +168,9 @@ int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *); · 4 unmodified lines
156168 int nfssvc_encode_entry(void *, const char *name,
157169 int namlen, loff_t offset, u64 ino, unsigned int);
158170
159−void nfssvc_release_fhandle(struct svc_rqst *);
171+void nfssvc_release_attrstat(struct svc_rqst *rqstp);
172+void nfssvc_release_diropres(struct svc_rqst *rqstp);
173+void nfssvc_release_readres(struct svc_rqst *rqstp);
160174
161175 /* Helper functions for NFSv2 ACL code */
162176 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);
fs/nfsd/xdr3.h+1−0
@@ -273,6 +273,7 @@ union nfsd3_xdrstore { · 272 unmodified lines
273273
274274 #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
275275
276+int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *);
276277 int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *);
277278 int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);
278279 int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *);
fs/nfsd/xdr4.h+1−0
@@ -781,6 +781,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) · 780 unmodified lines
781781
782782
783783 bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
784+int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *);
784785 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *);
785786 int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *);
786787 int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *);
include/linux/nfs_ssc.h+67−0
@@ -0,0 +1,67 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * include/linux/nfs_ssc.h
4+ *
5+ * Author: Dai Ngo <dai.ngo@oracle.com>
6+ *
7+ * Copyright (c) 2020, Oracle and/or its affiliates.
8+ */
9+
10+#include <linux/nfs_fs.h>
11+
12+extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
13+
14+/*
15+ * NFS_V4
16+ */
17+struct nfs4_ssc_client_ops {
18+ struct file *(*sco_open)(struct vfsmount *ss_mnt,
19+ struct nfs_fh *src_fh, nfs4_stateid *stateid);
20+ void (*sco_close)(struct file *filep);
21+};
22+
23+/*
24+ * NFS_FS
25+ */
26+struct nfs_ssc_client_ops {
27+ void (*sco_sb_deactive)(struct super_block *sb);
28+};
29+
30+struct nfs_ssc_client_ops_tbl {
31+ const struct nfs4_ssc_client_ops *ssc_nfs4_ops;
32+ const struct nfs_ssc_client_ops *ssc_nfs_ops;
33+};
34+
35+extern void nfs42_ssc_register_ops(void);
36+extern void nfs42_ssc_unregister_ops(void);
37+
38+extern void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops);
39+extern void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops);
40+
41+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
42+static inline struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
43+ struct nfs_fh *src_fh, nfs4_stateid *stateid)
44+{
45+ if (nfs_ssc_client_tbl.ssc_nfs4_ops)
46+ return (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_open)(ss_mnt, src_fh, stateid);
47+ return ERR_PTR(-EIO);
48+}
49+
50+static inline void nfs42_ssc_close(struct file *filep)
51+{
52+ if (nfs_ssc_client_tbl.ssc_nfs4_ops)
53+ (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep);
54+}
55+#endif
56+
57+/*
58+ * NFS_FS
59+ */
60+extern void nfs_ssc_register(const struct nfs_ssc_client_ops *ops);
61+extern void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops);
62+
63+static inline void nfs_do_sb_deactive(struct super_block *sb)
64+{
65+ if (nfs_ssc_client_tbl.ssc_nfs_ops)
66+ (*nfs_ssc_client_tbl.ssc_nfs_ops->sco_sb_deactive)(sb);
67+}
include/linux/sunrpc/xdr.h+2−0
@@ -234,6 +234,8 @@ typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, · 233 unmodified lines
234234 extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
235235 __be32 *p, struct rpc_rqst *rqst);
236236 extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
237+extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec,
238+ size_t nbytes);
237239 extern void xdr_commit_encode(struct xdr_stream *xdr);
238240 extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
239241 extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
include/uapi/linux/nfsacl.h+2−0
@@ -9,11 +9,13 @@ · 8 unmodified lines
99
1010 #define NFS_ACL_PROGRAM 100227
1111
12+#define ACLPROC2_NULL 0
1213 #define ACLPROC2_GETACL 1
1314 #define ACLPROC2_SETACL 2
1415 #define ACLPROC2_GETATTR 3
1516 #define ACLPROC2_ACCESS 4
1617
18+#define ACLPROC3_NULL 0
1719 #define ACLPROC3_GETACL 1
1820 #define ACLPROC3_SETACL 2
1921
net/sunrpc/auth_gss/svcauth_gss.c+17−10
@@ -1147,9 +1147,9 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp, · 1146 unmodified lines
11471147 struct gssp_in_token *in_token)
11481148 {
11491149 struct kvec *argv = &rqstp->rq_arg.head[0];
1150− unsigned int page_base, length;
1151− int pages, i, res;
1152− size_t inlen;
1150+ unsigned int length, pgto_offs, pgfrom_offs;
1151+ int pages, i, res, pgto, pgfrom;
1152+ size_t inlen, to_offs, from_offs;
11531153
11541154 res = gss_read_common_verf(gc, argv, authp, in_handle);
11551155 if (res)
@@ -1177,17 +1177,24 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp, · 21 unmodified lines
11771177 memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
11781178 inlen -= length;
11791179
1180− i = 1;
1181− page_base = rqstp->rq_arg.page_base;
1180+ to_offs = length;
1181+ from_offs = rqstp->rq_arg.page_base;
11821182 while (inlen) {
1183− length = min_t(unsigned int, inlen, PAGE_SIZE);
1184− memcpy(page_address(in_token->pages[i]),
1185− page_address(rqstp->rq_arg.pages[i]) + page_base,
1183+ pgto = to_offs >> PAGE_SHIFT;
1184+ pgfrom = from_offs >> PAGE_SHIFT;
1185+ pgto_offs = to_offs & ~PAGE_MASK;
1186+ pgfrom_offs = from_offs & ~PAGE_MASK;
1187+
1188+ length = min_t(unsigned int, inlen,
1189+ min_t(unsigned int, PAGE_SIZE - pgto_offs,
1190+ PAGE_SIZE - pgfrom_offs));
1191+ memcpy(page_address(in_token->pages[pgto]) + pgto_offs,
1192+ page_address(rqstp->rq_arg.pages[pgfrom]) + pgfrom_offs,
11861193 length);
11871194
1195+ to_offs += length;
1196+ from_offs += length;
11881197 inlen -= length;
1189− page_base = 0;
1190− i++;
11911198 }
11921199 return 0;
11931200 }
net/sunrpc/backchannel_rqst.c+1−1
@@ -111,7 +111,7 @@ out_free: · 110 unmodified lines
111111 * by the backchannel. This function can be called multiple times
112112 * when creating new sessions that use the same rpc_xprt. The
113113 * preallocated buffers are added to the pool of resources used by
114− * the rpc_xprt. Anyone of these resources may be used used by an
114+ * the rpc_xprt. Any one of these resources may be used by an
115115 * incoming callback request. It's up to the higher levels in the
116116 * stack to enforce that the maximum number of session slots is not
117117 * being exceeded.
net/sunrpc/cache.c+11−10
@@ -498,16 +498,17 @@ static int cache_clean(void) · 497 unmodified lines
498498 */
499499 static void do_cache_clean(struct work_struct *work)
500500 {
501− int delay = 5;
502− if (cache_clean() == -1)
503− delay = round_jiffies_relative(30*HZ);
501+ int delay;
504502
505503 if (list_empty(&cache_list))
506− delay = 0;
504+ return;
505+
506+ if (cache_clean() == -1)
507+ delay = round_jiffies_relative(30*HZ);
508+ else
509+ delay = 5;
507510
508− if (delay)
509− queue_delayed_work(system_power_efficient_wq,
510− &cache_cleaner, delay);
511+ queue_delayed_work(system_power_efficient_wq, &cache_cleaner, delay);
511512 }
512513
513514
@@ -908,7 +909,7 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, · 394 unmodified lines
908909 static ssize_t cache_slow_downcall(const char __user *buf,
909910 size_t count, struct cache_detail *cd)
910911 {
911− static char write_buf[8192]; /* protected by queue_io_mutex */
912+ static char write_buf[32768]; /* protected by queue_io_mutex */
912913 ssize_t ret = -EINVAL;
913914
914915 if (count >= sizeof(write_buf))
@@ -1436,10 +1437,10 @@ static int c_show(struct seq_file *m, void *p) · 521 unmodified lines
14361437 cache_get(cp);
14371438 if (cache_check(cd, cp, NULL))
14381439 /* cache_check does a cache_put on failure */
1439− seq_printf(m, "# ");
1440+ seq_puts(m, "# ");
14401441 else {
14411442 if (cache_is_expired(cd, cp))
1442− seq_printf(m, "# ");
1443+ seq_puts(m, "# ");
14431444 cache_put(cp, cd);
14441445 }
14451446
net/sunrpc/sysctl.c+7−1
@@ -70,7 +70,13 @@ static int proc_do_xprt(struct ctl_table *table, int write, · 69 unmodified lines
7070 return 0;
7171 }
7272 len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
73− return memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
73+ *lenp = memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
74+
75+ if (*lenp < 0) {
76+ *lenp = 0;
77+ return -EINVAL;
78+ }
79+ return 0;
7480 }
7581
7682 static int
net/sunrpc/xdr.c+46−1
@@ -792,6 +792,51 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) · 791 unmodified lines
792792 }
793793 EXPORT_SYMBOL_GPL(xdr_reserve_space);
794794
795+
796+/**
797+ * xdr_reserve_space_vec - Reserves a large amount of buffer space for sending
798+ * @xdr: pointer to xdr_stream
799+ * @vec: pointer to a kvec array
800+ * @nbytes: number of bytes to reserve
801+ *
802+ * Reserves enough buffer space to encode 'nbytes' of data and stores the
803+ * pointers in 'vec'. The size argument passed to xdr_reserve_space() is
804+ * determined based on the number of bytes remaining in the current page to
805+ * avoid invalidating iov_base pointers when xdr_commit_encode() is called.
806+ */
807+int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, size_t nbytes)
808+{
809+ int thislen;
810+ int v = 0;
811+ __be32 *p;
812+
813+ /*
814+ * svcrdma requires every READ payload to start somewhere
815+ * in xdr->pages.
816+ */
817+ if (xdr->iov == xdr->buf->head) {
818+ xdr->iov = NULL;
819+ xdr->end = xdr->p;
820+ }
821+
822+ while (nbytes) {
823+ thislen = xdr->buf->page_len % PAGE_SIZE;
824+ thislen = min_t(size_t, nbytes, PAGE_SIZE - thislen);
825+
826+ p = xdr_reserve_space(xdr, thislen);
827+ if (!p)
828+ return -EIO;
829+
830+ vec[v].iov_base = p;
831+ vec[v].iov_len = thislen;
832+ v++;
833+ nbytes -= thislen;
834+ }
835+
836+ return v;
837+}
838+EXPORT_SYMBOL_GPL(xdr_reserve_space_vec);
839+
795840 /**
796841 * xdr_truncate_encode - truncate an encode buffer
797842 * @xdr: pointer to xdr_stream
@@ -802,7 +847,7 @@ EXPORT_SYMBOL_GPL(xdr_reserve_space); · 4 unmodified lines
802847 * head, tail, and page lengths are adjusted to correspond.
803848 *
804849 * If this means moving xdr->p to a different buffer, we assume that
805− * that the end pointer should be set to the end of the current page,
850+ * the end pointer should be set to the end of the current page,
806851 * except in the case of the head buffer when we assume the head
807852 * buffer's current length represents the end of the available buffer.
808853 *
net/sunrpc/xprtrdma/svc_rdma_rw.c+1−1
@@ -137,7 +137,7 @@ static int svc_rdma_rw_ctx_init(struct svcxprt_rdma *rdma, · 136 unmodified lines
137137 }
138138
139139 /* A chunk context tracks all I/O for moving one Read or Write
140− * chunk. This is a a set of rdma_rw's that handle data movement
140+ * chunk. This is a set of rdma_rw's that handle data movement
141141 * for all segments of one chunk.
142142 *
143143 * These are small, acquired with a single allocator call, and
net/sunrpc/xprtrdma/svc_rdma_sendto.c+2−1
@@ -638,10 +638,11 @@ static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma, · 637 unmodified lines
638638 while (remaining) {
639639 len = min_t(u32, PAGE_SIZE - pageoff, remaining);
640640
641− memcpy(dst, page_address(*ppages), len);
641+ memcpy(dst, page_address(*ppages) + pageoff, len);
642642 remaining -= len;
643643 dst += len;
644644 pageoff = 0;
645+ ppages++;
645646 }
646647 }
647648
tools/nfsd/inject_fault.sh+0−50
@@ -1,50 +0,0 @@
1−#!/bin/bash
2−# SPDX-License-Identifier: GPL-2.0
3−#
4−# Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
5−#
6−# Script for easier NFSD fault injection
7−
8−# Check that debugfs has been mounted
9−DEBUGFS=`cat /proc/mounts | grep debugfs`
10−if [ "$DEBUGFS" == "" ]; then
11− echo "debugfs does not appear to be mounted!"
12− echo "Please mount debugfs and try again"
13− exit 1
14−fi
15−
16−# Check that the fault injection directory exists
17−DEBUGDIR=`echo $DEBUGFS | awk '{print $2}'`/nfsd
18−if [ ! -d "$DEBUGDIR" ]; then
19− echo "$DEBUGDIR does not exist"
20− echo "Check that your .config selects CONFIG_NFSD_FAULT_INJECTION"
21− exit 1
22−fi
23−
24−function help()
25−{
26− echo "Usage $0 injection_type [count]"
27− echo ""
28− echo "Injection types are:"
29− ls $DEBUGDIR
30− exit 1
31−}
32−
33−if [ $# == 0 ]; then
34− help
35−elif [ ! -f $DEBUGDIR/$1 ]; then
36− help
37−elif [ $# != 2 ]; then
38− COUNT=0
39−else
40− COUNT=$2
41−fi
42−
43−BEFORE=`mktemp`
44−AFTER=`mktemp`
45−dmesg > $BEFORE
46−echo $COUNT > $DEBUGDIR/$1
47−dmesg > $AFTER
48−# Capture lines that only exist in the $AFTER file
49−diff $BEFORE $AFTER | grep ">"
50−rm -f $BEFORE $AFTER