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===================
2NFS Fault Injection
3===================
4
5Fault injection is a method for forcing errors that may not normally occur, or
6may be difficult to reproduce. Forcing these errors in a controlled environment
7can help the developer find and fix bugs before their code is shipped in a
8production system. Injecting an error on the Linux NFS server will allow us to
9observe how the client reacts and if it manages to recover its state correctly.
10
11NFSD_FAULT_INJECTION must be selected when configuring the kernel to use this
12feature.
13
14
15Using Fault Injection
16=====================
17On the client, mount the fault injection server through NFS v4.0+ and do some
18work over NFS (open files, take locks, ...).
19
20On 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
22injecting faults on the NFS server. As root, write a number n to the file
23corresponding to the action you want the server to take. The server will then
24process the first n items it finds. So if you want to forget 5 locks, echo '5'
25to <debug_dir>/nfsd/forget_locks. A value of 0 will tell the server to forget
26all corresponding items. A log message will be created containing the number
27of items forgotten (check dmesg).
28
29Go back to work on the client and check if the client recovered from the error
30correctly.
31
32
33Available Faults
34================
35forget_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
40forget_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
45forget_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
50forget_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
56recall_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
63tools/nfs/inject_faults.sh script
64=================================
65This script has been created to ease the fault injection process. This script
66will detect the mounted debugfs directory and write to the files located there
67based 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
69one lock. Running `inject_faults forget_locks` will instruct the server to
70forgetall locks.
Documentation/admin-guide/nfs/index.rst+0−1
@@ -12,4 +12,3 @@ NFS · 11 unmodified lines
12 nfs-idmapper12 nfs-idmapper
13 pnfs-block-server13 pnfs-block-server
14 pnfs-scsi-server14 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
13 - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt13 - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt
14 - RFC5403 v2: https://tools.ietf.org/rfc/rfc5403.txt14 - RFC5403 v2: https://tools.ietf.org/rfc/rfc5403.txt
15 15
16and there is a 3rd version being proposed:16There is a third version that we don't currently implement:
17 17
18 - https://tools.ietf.org/id/draft-williams-rpcsecgssv3.txt18 - RFC7861 v3: https://tools.ietf.org/rfc/rfc7861.txt
19 (At draft n. 02 at the time of writing)
20 19
21Background20Background
22==========21==========
MAINTAINERS+2−0
@@ -9556,6 +9556,7 @@ F: include/linux/sunrpc/ · 9555 unmodified lines
9556F: include/uapi/linux/nfsd/9556F: include/uapi/linux/nfsd/
9557F: include/uapi/linux/sunrpc/9557F: include/uapi/linux/sunrpc/
9558F: net/sunrpc/9558F: net/sunrpc/
9559F: Documentation/filesystems/nfs/
9559 9560
9560KERNEL SELFTEST FRAMEWORK9561KERNEL SELFTEST FRAMEWORK
9561M: Shuah Khan <shuah@kernel.org>9562M: Shuah Khan <shuah@kernel.org>
@@ -12337,6 +12338,7 @@ F: include/linux/sunrpc/ · 2775 unmodified lines
12337F: include/uapi/linux/nfs*12338F: include/uapi/linux/nfs*
12338F: include/uapi/linux/sunrpc/12339F: include/uapi/linux/sunrpc/
12339F: net/sunrpc/12340F: net/sunrpc/
12341F: Documentation/filesystems/nfs/
12340 12342
12341NILFS2 FILESYSTEM12343NILFS2 FILESYSTEM
12342M: Ryusuke Konishi <konishi.ryusuke@gmail.com>12344M: 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
486 return rpc_success;486 return rpc_success;
487}487}
488 488
489static __be32
490nlm4svc_proc_unused(struct svc_rqst *rqstp)
491{
492 return rpc_proc_unavail;
493}
494
489 495
490/*496/*
491 * NLM Server procedures.497 * NLM Server procedures.
492 */498 */
493 499
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
508struct nlm_void { int dummy; };500struct nlm_void { int dummy; };
509 501
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 }
519#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */502#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */
520#define No (1+1024/4) /* netobj */503#define No (1+1024/4) /* netobj */
521#define St 1 /* status */504#define St 1 /* status */
522#define Rg 4 /* range (offset + length) */505#define Rg 4 /* range (offset + length) */
523const 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),
549 506
507const 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 },
550};700};
fs/lockd/svcproc.c+199−51
@@ -529,66 +529,214 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp) · 528 unmodified lines
529 return rpc_success;529 return rpc_success;
530}530}
531 531
532static __be32
533nlmsvc_proc_unused(struct svc_rqst *rqstp)
534{
535 return rpc_proc_unavail;
536}
537
532/*538/*
533 * NLM Server procedures.539 * NLM Server procedures.
534 */540 */
535 541
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
550struct nlm_void { int dummy; };542struct nlm_void { int dummy; };
551 543
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
562#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */544#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */
563#define St 1 /* status */545#define St 1 /* status */
564#define No (1+1024/4) /* Net Obj */546#define No (1+1024/4) /* Net Obj */
565#define Rg 2 /* range - offset + size */547#define Rg 2 /* range - offset + size */
566 548
567const struct svc_procedure nlmsvc_procedures[] = {549const struct svc_procedure nlmsvc_procedures[24] = {
568 PROC(null, void, void, void, void, 1),550 [NLMPROC_NULL] = {
569 PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg),551 .pc_func = nlmsvc_proc_null,
570 PROC(lock, lockargs, res, args, res, Ck+St),552 .pc_decode = nlmsvc_decode_void,
571 PROC(cancel, cancargs, res, args, res, Ck+St),553 .pc_encode = nlmsvc_encode_void,
572 PROC(unlock, unlockargs, res, args, res, Ck+St),554 .pc_argsize = sizeof(struct nlm_void),
573 PROC(granted, testargs, res, args, res, Ck+St),555 .pc_ressize = sizeof(struct nlm_void),
574 PROC(test_msg, testargs, norep, args, void, 1),556 .pc_xdrressize = St,
575 PROC(lock_msg, lockargs, norep, args, void, 1),557 },
576 PROC(cancel_msg, cancargs, norep, args, void, 1),558 [NLMPROC_TEST] = {
577 PROC(unlock_msg, unlockargs, norep, args, void, 1),559 .pc_func = nlmsvc_proc_test,
578 PROC(granted_msg, testargs, norep, args, void, 1),560 .pc_decode = nlmsvc_decode_testargs,
579 PROC(test_res, testres, norep, res, void, 1),561 .pc_encode = nlmsvc_encode_testres,
580 PROC(lock_res, lockres, norep, res, void, 1),562 .pc_argsize = sizeof(struct nlm_args),
581 PROC(cancel_res, cancelres, norep, res, void, 1),563 .pc_ressize = sizeof(struct nlm_res),
582 PROC(unlock_res, unlockres, norep, res, void, 1),564 .pc_xdrressize = Ck+St+2+No+Rg,
583 PROC(granted_res, res, norep, res, void, 1),565 },
584 /* statd callback */566 [NLMPROC_LOCK] = {
585 PROC(sm_notify, reboot, void, reboot, void, 1),567 .pc_func = nlmsvc_proc_lock,
586 PROC(none, void, void, void, void, 1),568 .pc_decode = nlmsvc_decode_lockargs,
587 PROC(none, void, void, void, void, 1),569 .pc_encode = nlmsvc_encode_res,
588 PROC(none, void, void, void, void, 1),570 .pc_argsize = sizeof(struct nlm_args),
589 PROC(share, shareargs, shareres, args, res, Ck+St+1),571 .pc_ressize = sizeof(struct nlm_res),
590 PROC(unshare, shareargs, shareres, args, res, Ck+St+1),572 .pc_xdrressize = Ck+St,
591 PROC(nm_lock, lockargs, res, args, res, Ck+St),573 },
592 PROC(free_all, notify, void, args, void, 0),574 [NLMPROC_CANCEL] = {
593 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 },
594};742};
fs/nfs/nfs4file.c+32−6
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/falloc.h>9#include <linux/falloc.h>
10#include <linux/mount.h>10#include <linux/mount.h>
11#include <linux/nfs_fs.h>11#include <linux/nfs_fs.h>
12#include <linux/nfs_ssc.h>
12#include "delegation.h"13#include "delegation.h"
13#include "internal.h"14#include "internal.h"
14#include "iostat.h"15#include "iostat.h"
@@ -315,9 +316,8 @@ out: · 300 unmodified lines
315static int read_name_gen = 1;316static int read_name_gen = 1;
316#define SSC_READ_NAME_BODY "ssc_read_%d"317#define SSC_READ_NAME_BODY "ssc_read_%d"
317 318
318struct file *319static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
319nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,320 struct nfs_fh *src_fh, nfs4_stateid *stateid)
320 nfs4_stateid *stateid)
321{321{
322 struct nfs_fattr fattr;322 struct nfs_fattr fattr;
323 struct file *filep, *res;323 struct file *filep, *res;
@@ -399,14 +399,40 @@ out_filep: · 75 unmodified lines
399 fput(filep);399 fput(filep);
400 goto out_free_name;400 goto out_free_name;
401}401}
402EXPORT_SYMBOL_GPL(nfs42_ssc_open);402
403void nfs42_ssc_close(struct file *filep)403static void __nfs42_ssc_close(struct file *filep)
404{404{
405 struct nfs_open_context *ctx = nfs_file_open_context(filep);405 struct nfs_open_context *ctx = nfs_file_open_context(filep);
406 406
407 ctx->state->flags = 0;407 ctx->state->flags = 0;
408}408}
409EXPORT_SYMBOL_GPL(nfs42_ssc_close);409
410static 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 */
421void 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 */
432void nfs42_ssc_unregister_ops(void)
433{
434 nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl);
435}
410#endif /* CONFIG_NFS_V4_2 */436#endif /* CONFIG_NFS_V4_2 */
411 437
412const struct file_operations nfs4_file_operations = {438const struct file_operations nfs4_file_operations = {
fs/nfs/nfs4super.c+5−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
7#include <linux/mount.h>7#include <linux/mount.h>
8#include <linux/nfs4_mount.h>8#include <linux/nfs4_mount.h>
9#include <linux/nfs_fs.h>9#include <linux/nfs_fs.h>
10#include <linux/nfs_ssc.h>
10#include "delegation.h"11#include "delegation.h"
11#include "internal.h"12#include "internal.h"
12#include "nfs4_fs.h"13#include "nfs4_fs.h"
@@ -279,6 +280,9 @@ static int __init init_nfs_v4(void) · 266 unmodified lines
279 if (err)280 if (err)
280 goto out2;281 goto out2;
281 282
283#ifdef CONFIG_NFS_V4_2
284 nfs42_ssc_register_ops();
285#endif
282 register_nfs_version(&nfs_v4);286 register_nfs_version(&nfs_v4);
283 return 0;287 return 0;
284out2:288out2:
@@ -297,6 +301,7 @@ static void __exit exit_nfs_v4(void) · 12 unmodified lines
297 unregister_nfs_version(&nfs_v4);301 unregister_nfs_version(&nfs_v4);
298#ifdef CONFIG_NFS_V4_2302#ifdef CONFIG_NFS_V4_2
299 nfs4_xattr_cache_exit();303 nfs4_xattr_cache_exit();
304 nfs42_ssc_unregister_ops();
300#endif305#endif
301 nfs4_unregister_sysctl();306 nfs4_unregister_sysctl();
302 nfs_idmap_quit();307 nfs_idmap_quit();
fs/nfs/super.c+17−0
@@ -57,6 +57,7 @@ · 56 unmodified lines
57#include <linux/rcupdate.h>57#include <linux/rcupdate.h>
58 58
59#include <linux/uaccess.h>59#include <linux/uaccess.h>
60#include <linux/nfs_ssc.h>
60 61
61#include "nfs4_fs.h"62#include "nfs4_fs.h"
62#include "callback.h"63#include "callback.h"
@@ -85,6 +86,10 @@ const struct super_operations nfs_sops = { · 22 unmodified lines
85};86};
86EXPORT_SYMBOL_GPL(nfs_sops);87EXPORT_SYMBOL_GPL(nfs_sops);
87 88
89static const struct nfs_ssc_client_ops nfs_ssc_clnt_ops_tbl = {
90 .sco_sb_deactive = nfs_sb_deactive,
91};
92
88#if IS_ENABLED(CONFIG_NFS_V4)93#if IS_ENABLED(CONFIG_NFS_V4)
89static int __init register_nfs4_fs(void)94static int __init register_nfs4_fs(void)
90{95{
@@ -106,6 +111,16 @@ static void unregister_nfs4_fs(void) · 15 unmodified lines
106}111}
107#endif112#endif
108 113
114static void nfs_ssc_register_ops(void)
115{
116 nfs_ssc_register(&nfs_ssc_clnt_ops_tbl);
117}
118
119static void nfs_ssc_unregister_ops(void)
120{
121 nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl);
122}
123
109static struct shrinker acl_shrinker = {124static struct shrinker acl_shrinker = {
110 .count_objects = nfs_access_cache_count,125 .count_objects = nfs_access_cache_count,
111 .scan_objects = nfs_access_cache_scan,126 .scan_objects = nfs_access_cache_scan,
@@ -133,6 +148,7 @@ int __init register_nfs_fs(void) · 21 unmodified lines
133 ret = register_shrinker(&acl_shrinker);148 ret = register_shrinker(&acl_shrinker);
134 if (ret < 0)149 if (ret < 0)
135 goto error_3;150 goto error_3;
151 nfs_ssc_register_ops();
136 return 0;152 return 0;
137error_3:153error_3:
138 nfs_unregister_sysctl();154 nfs_unregister_sysctl();
@@ -152,6 +168,7 @@ void __exit unregister_nfs_fs(void) · 13 unmodified lines
152 unregister_shrinker(&acl_shrinker);168 unregister_shrinker(&acl_shrinker);
153 nfs_unregister_sysctl();169 nfs_unregister_sysctl();
154 unregister_nfs4_fs();170 unregister_nfs4_fs();
171 nfs_ssc_unregister_ops();
155 unregister_filesystem(&nfs_fs_type);172 unregister_filesystem(&nfs_fs_type);
156}173}
157 174
fs/nfs_common/Makefile+1−0
@@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o · 6 unmodified lines
7nfs_acl-objs := nfsacl.o7nfs_acl-objs := nfsacl.o
8 8
9obj-$(CONFIG_GRACE_PERIOD) += grace.o9obj-$(CONFIG_GRACE_PERIOD) += grace.o
10obj-$(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
17MODULE_LICENSE("GPL");
18
19struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
20EXPORT_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 */
30void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops)
31{
32 nfs_ssc_client_tbl.ssc_nfs4_ops = ops;
33}
34EXPORT_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 */
44void 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}
51EXPORT_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 */
62void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
63{
64 nfs_ssc_client_tbl.ssc_nfs_ops = ops;
65}
66EXPORT_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 */
76void 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}
82EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
83
84#else
85void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
86{
87}
88EXPORT_SYMBOL_GPL(nfs_ssc_register);
89
90void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
91{
92}
93EXPORT_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
136 136
137config NFSD_V4_2_INTER_SSC137config NFSD_V4_2_INTER_SSC
138 bool "NFSv4.2 inter server to server COPY"138 bool "NFSv4.2 inter server to server COPY"
139 depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 && NFS_FS=y139 depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
140 help140 help
141 This option enables support for NFSv4.2 inter server to141 This option enables support for NFSv4.2 inter server to
142 server copy where the destination server calls the NFSv4.2142 server copy where the destination server calls the NFSv4.2
@@ -156,13 +156,3 @@ config NFSD_V4_SECURITY_LABEL · 13 unmodified lines
156 156
157 If you do not wish to enable fine-grained security labels SELinux or157 If you do not wish to enable fine-grained security labels SELinux or
158 Smack policies on NFSv4 files, say N.158 Smack policies on NFSv4 files, say N.
159
160config 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
13nfsd-y += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \13nfsd-y += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
14 export.o auth.o lockd.o nfscache.o nfsxdr.o \14 export.o auth.o lockd.o nfscache.o nfsxdr.o \
15 stats.o filecache.o15 stats.o filecache.o
16nfsd-$(CONFIG_NFSD_FAULT_INJECTION) += fault_inject.o
17nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o16nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
18nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o17nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
19nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o18nfsd-$(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
1002 if (nfsd4_spo_must_allow(rqstp))1002 if (nfsd4_spo_must_allow(rqstp))
1003 return 0;1003 return 0;
1004 1004
1005 return nfserr_wrongsec;1005 return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
1006}1006}
1007 1007
1008/*1008/*
fs/nfsd/filecache.c+1−1
@@ -889,7 +889,7 @@ nfsd_file_find_locked(struct inode *inode, unsigned int may_flags, · 888 unmodified lines
889 889
890 hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head,890 hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head,
891 nf_node, lockdep_is_held(&nfsd_file_hashtbl[hashval].nfb_lock)) {891 nf_node, lockdep_is_held(&nfsd_file_hashtbl[hashval].nfb_lock)) {
892 if ((need & nf->nf_may) != need)892 if (nf->nf_may != need)
893 continue;893 continue;
894 if (nf->nf_inode != inode)894 if (nf->nf_inode != inode)
895 continue;895 continue;
fs/nfsd/nfs2acl.c+104−56
@@ -14,7 +14,6 @@ · 13 unmodified lines
14#include "vfs.h"14#include "vfs.h"
15 15
16#define NFSDDBG_FACILITY NFSDDBG_PROC16#define NFSDDBG_FACILITY NFSDDBG_PROC
17#define RETURN_STATUS(st) { resp->status = (st); return (st); }
18 17
19/*18/*
20 * NULL call.19 * NULL call.
@@ -22,7 +21,7 @@ · 1 unmodified line
22static __be3221static __be32
23nfsacld_proc_null(struct svc_rqst *rqstp)22nfsacld_proc_null(struct svc_rqst *rqstp)
24{23{
25 return nfs_ok;24 return rpc_success;
26}25}
27 26
28/*27/*
@@ -35,24 +34,25 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 6 unmodified lines
35 struct posix_acl *acl;34 struct posix_acl *acl;
36 struct inode *inode;35 struct inode *inode;
37 svc_fh *fh;36 svc_fh *fh;
38 __be32 nfserr = 0;
39 37
40 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));38 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
41 39
42 fh = fh_copy(&resp->fh, &argp->fh);40 fh = fh_copy(&resp->fh, &argp->fh);
43 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);41 resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
44 if (nfserr)42 if (resp->status != nfs_ok)
45 RETURN_STATUS(nfserr);43 goto out;
46 44
47 inode = d_inode(fh->fh_dentry);45 inode = d_inode(fh->fh_dentry);
48 46
49 if (argp->mask & ~NFS_ACL_MASK)47 if (argp->mask & ~NFS_ACL_MASK) {
50 RETURN_STATUS(nfserr_inval);48 resp->status = nfserr_inval;
49 goto out;
50 }
51 resp->mask = argp->mask;51 resp->mask = argp->mask;
52 52
53 nfserr = fh_getattr(fh, &resp->stat);53 resp->status = fh_getattr(fh, &resp->stat);
54 if (nfserr)54 if (resp->status != nfs_ok)
55 RETURN_STATUS(nfserr);55 goto out;
56 56
57 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {57 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
58 acl = get_acl(inode, ACL_TYPE_ACCESS);58 acl = get_acl(inode, ACL_TYPE_ACCESS);
@@ -61,7 +61,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 2 unmodified lines
61 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);61 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
62 }62 }
63 if (IS_ERR(acl)) {63 if (IS_ERR(acl)) {
64 nfserr = nfserrno(PTR_ERR(acl));64 resp->status = nfserrno(PTR_ERR(acl));
65 goto fail;65 goto fail;
66 }66 }
67 resp->acl_access = acl;67 resp->acl_access = acl;
@@ -71,19 +71,20 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines
71 of a non-directory! */71 of a non-directory! */
72 acl = get_acl(inode, ACL_TYPE_DEFAULT);72 acl = get_acl(inode, ACL_TYPE_DEFAULT);
73 if (IS_ERR(acl)) {73 if (IS_ERR(acl)) {
74 nfserr = nfserrno(PTR_ERR(acl));74 resp->status = nfserrno(PTR_ERR(acl));
75 goto fail;75 goto fail;
76 }76 }
77 resp->acl_default = acl;77 resp->acl_default = acl;
78 }78 }
79 79
80 /* resp->acl_{access,default} are released in nfssvc_release_getacl. */80 /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
81 RETURN_STATUS(0);81out:
82 return rpc_success;
82 83
83fail:84fail:
84 posix_acl_release(resp->acl_access);85 posix_acl_release(resp->acl_access);
85 posix_acl_release(resp->acl_default);86 posix_acl_release(resp->acl_default);
86 RETURN_STATUS(nfserr);87 goto out;
87}88}
88 89
89/*90/*
@@ -95,14 +96,13 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp) · 5 unmodified lines
95 struct nfsd_attrstat *resp = rqstp->rq_resp;96 struct nfsd_attrstat *resp = rqstp->rq_resp;
96 struct inode *inode;97 struct inode *inode;
97 svc_fh *fh;98 svc_fh *fh;
98 __be32 nfserr = 0;
99 int error;99 int error;
100 100
101 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));101 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
102 102
103 fh = fh_copy(&resp->fh, &argp->fh);103 fh = fh_copy(&resp->fh, &argp->fh);
104 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);104 resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
105 if (nfserr)105 if (resp->status != nfs_ok)
106 goto out;106 goto out;
107 107
108 inode = d_inode(fh->fh_dentry);108 inode = d_inode(fh->fh_dentry);
@@ -124,19 +124,20 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp) · 15 unmodified lines
124 124
125 fh_drop_write(fh);125 fh_drop_write(fh);
126 126
127 nfserr = fh_getattr(fh, &resp->stat);127 resp->status = fh_getattr(fh, &resp->stat);
128 128
129out:129out:
130 /* argp->acl_{access,default} may have been allocated in130 /* argp->acl_{access,default} may have been allocated in
131 nfssvc_decode_setaclargs. */131 nfssvc_decode_setaclargs. */
132 posix_acl_release(argp->acl_access);132 posix_acl_release(argp->acl_access);
133 posix_acl_release(argp->acl_default);133 posix_acl_release(argp->acl_default);
134 return nfserr;134 return rpc_success;
135
135out_drop_lock:136out_drop_lock:
136 fh_unlock(fh);137 fh_unlock(fh);
137 fh_drop_write(fh);138 fh_drop_write(fh);
138out_errno:139out_errno:
139 nfserr = nfserrno(error);140 resp->status = nfserrno(error);
140 goto out;141 goto out;
141}142}
142 143
@@ -147,15 +148,16 @@ static __be32 nfsacld_proc_getattr(struct svc_rqst *rqstp) · 4 unmodified lines
147{148{
148 struct nfsd_fhandle *argp = rqstp->rq_argp;149 struct nfsd_fhandle *argp = rqstp->rq_argp;
149 struct nfsd_attrstat *resp = rqstp->rq_resp;150 struct nfsd_attrstat *resp = rqstp->rq_resp;
150 __be32 nfserr;151
151 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));152 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
152 153
153 fh_copy(&resp->fh, &argp->fh);154 fh_copy(&resp->fh, &argp->fh);
154 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);155 resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
155 if (nfserr)156 if (resp->status != nfs_ok)
156 return nfserr;157 goto out;
157 nfserr = fh_getattr(&resp->fh, &resp->stat);158 resp->status = fh_getattr(&resp->fh, &resp->stat);
158 return nfserr;159out:
160 return rpc_success;
159}161}
160 162
161/*163/*
@@ -165,7 +167,6 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp) · 3 unmodified lines
165{167{
166 struct nfsd3_accessargs *argp = rqstp->rq_argp;168 struct nfsd3_accessargs *argp = rqstp->rq_argp;
167 struct nfsd3_accessres *resp = rqstp->rq_resp;169 struct nfsd3_accessres *resp = rqstp->rq_resp;
168 __be32 nfserr;
169 170
170 dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",171 dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
171 SVCFH_fmt(&argp->fh),172 SVCFH_fmt(&argp->fh),
@@ -173,16 +174,22 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp) · 1 unmodified line
173 174
174 fh_copy(&resp->fh, &argp->fh);175 fh_copy(&resp->fh, &argp->fh);
175 resp->access = argp->access;176 resp->access = argp->access;
176 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);177 resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
177 if (nfserr)178 if (resp->status != nfs_ok)
178 return nfserr;179 goto out;
179 nfserr = fh_getattr(&resp->fh, &resp->stat);180 resp->status = fh_getattr(&resp->fh, &resp->stat);
180 return nfserr;181out:
182 return rpc_success;
181}183}
182 184
183/*185/*
184 * XDR decode functions186 * XDR decode functions
185 */187 */
188static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
189{
190 return 1;
191}
192
186static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)193static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
187{194{
188 struct nfsd3_getaclargs *argp = rqstp->rq_argp;195 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
268 int n;275 int n;
269 int w;276 int w;
270 277
278 *p++ = resp->status;
279 if (resp->status != nfs_ok)
280 return xdr_ressize_check(rqstp, p);
281
271 /*282 /*
272 * Since this is version 2, the check for nfserr in283 * Since this is version 2, the check for nfserr in
273 * nfsd_dispatch actually ensures the following cannot happen.284 * 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
307{318{
308 struct nfsd_attrstat *resp = rqstp->rq_resp;319 struct nfsd_attrstat *resp = rqstp->rq_resp;
309 320
321 *p++ = resp->status;
322 if (resp->status != nfs_ok)
323 goto out;
324
310 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);325 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
326out:
311 return xdr_ressize_check(rqstp, p);327 return xdr_ressize_check(rqstp, p);
312}328}
313 329
@@ -316,8 +332,13 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p) · 2 unmodified lines
316{332{
317 struct nfsd3_accessres *resp = rqstp->rq_resp;333 struct nfsd3_accessres *resp = rqstp->rq_resp;
318 334
335 *p++ = resp->status;
336 if (resp->status != nfs_ok)
337 goto out;
338
319 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);339 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
320 *p++ = htonl(resp->access);340 *p++ = htonl(resp->access);
341out:
321 return xdr_ressize_check(rqstp, p);342 return xdr_ressize_check(rqstp, p);
322}343}
323 344
@@ -347,36 +368,63 @@ static void nfsaclsvc_release_access(struct svc_rqst *rqstp) · 23 unmodified lines
347 fh_put(&resp->fh);368 fh_put(&resp->fh);
348}369}
349 370
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
355struct nfsd3_voidargs { int dummy; };371struct nfsd3_voidargs { int dummy; };
356 372
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
369#define ST 1 /* status*/373#define ST 1 /* status*/
370#define AT 21 /* attributes */374#define AT 21 /* attributes */
371#define pAT (1+AT) /* post attributes - conditional */375#define pAT (1+AT) /* post attributes - conditional */
372#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */376#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
373 377
374static const struct svc_procedure nfsd_acl_procedures2[] = {378static const struct svc_procedure nfsd_acl_procedures2[5] = {
375 PROC(null, void, void, void, RC_NOCACHE, ST),379 [ACLPROC2_NULL] = {
376 PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),380 .pc_func = nfsacld_proc_null,
377 PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT),381 .pc_decode = nfsaclsvc_decode_voidarg,
378 PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT),382 .pc_encode = nfsaclsvc_encode_voidres,
379 PROC(access, access, access, access, RC_NOCACHE, ST+AT+1),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 },
380};428};
381 429
382static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];430static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];
fs/nfsd/nfs3acl.c+49−39
@@ -13,15 +13,13 @@ · 12 unmodified lines
13#include "xdr3.h"13#include "xdr3.h"
14#include "vfs.h"14#include "vfs.h"
15 15
16#define RETURN_STATUS(st) { resp->status = (st); return (st); }
17
18/*16/*
19 * NULL call.17 * NULL call.
20 */18 */
21static __be3219static __be32
22nfsd3_proc_null(struct svc_rqst *rqstp)20nfsd3_proc_null(struct svc_rqst *rqstp)
23{21{
24 return nfs_ok;22 return rpc_success;
25}23}
26 24
27/*25/*
@@ -34,17 +32,18 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 6 unmodified lines
34 struct posix_acl *acl;32 struct posix_acl *acl;
35 struct inode *inode;33 struct inode *inode;
36 svc_fh *fh;34 svc_fh *fh;
37 __be32 nfserr = 0;
38 35
39 fh = fh_copy(&resp->fh, &argp->fh);36 fh = fh_copy(&resp->fh, &argp->fh);
40 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);37 resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
41 if (nfserr)38 if (resp->status != nfs_ok)
42 RETURN_STATUS(nfserr);39 goto out;
43 40
44 inode = d_inode(fh->fh_dentry);41 inode = d_inode(fh->fh_dentry);
45 42
46 if (argp->mask & ~NFS_ACL_MASK)43 if (argp->mask & ~NFS_ACL_MASK) {
47 RETURN_STATUS(nfserr_inval);44 resp->status = nfserr_inval;
45 goto out;
46 }
48 resp->mask = argp->mask;47 resp->mask = argp->mask;
49 48
50 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {49 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
@@ -54,7 +53,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines
54 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);53 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
55 }54 }
56 if (IS_ERR(acl)) {55 if (IS_ERR(acl)) {
57 nfserr = nfserrno(PTR_ERR(acl));56 resp->status = nfserrno(PTR_ERR(acl));
58 goto fail;57 goto fail;
59 }58 }
60 resp->acl_access = acl;59 resp->acl_access = acl;
@@ -64,19 +63,20 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines
64 of a non-directory! */63 of a non-directory! */
65 acl = get_acl(inode, ACL_TYPE_DEFAULT);64 acl = get_acl(inode, ACL_TYPE_DEFAULT);
66 if (IS_ERR(acl)) {65 if (IS_ERR(acl)) {
67 nfserr = nfserrno(PTR_ERR(acl));66 resp->status = nfserrno(PTR_ERR(acl));
68 goto fail;67 goto fail;
69 }68 }
70 resp->acl_default = acl;69 resp->acl_default = acl;
71 }70 }
72 71
73 /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */72 /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
74 RETURN_STATUS(0);73out:
74 return rpc_success;
75 75
76fail:76fail:
77 posix_acl_release(resp->acl_access);77 posix_acl_release(resp->acl_access);
78 posix_acl_release(resp->acl_default);78 posix_acl_release(resp->acl_default);
79 RETURN_STATUS(nfserr);79 goto out;
80}80}
81 81
82/*82/*
@@ -88,12 +88,11 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp) · 5 unmodified lines
88 struct nfsd3_attrstat *resp = rqstp->rq_resp;88 struct nfsd3_attrstat *resp = rqstp->rq_resp;
89 struct inode *inode;89 struct inode *inode;
90 svc_fh *fh;90 svc_fh *fh;
91 __be32 nfserr = 0;
92 int error;91 int error;
93 92
94 fh = fh_copy(&resp->fh, &argp->fh);93 fh = fh_copy(&resp->fh, &argp->fh);
95 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);94 resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
96 if (nfserr)95 if (resp->status != nfs_ok)
97 goto out;96 goto out;
98 97
99 inode = d_inode(fh->fh_dentry);98 inode = d_inode(fh->fh_dentry);
@@ -113,13 +112,13 @@ out_drop_lock: · 13 unmodified lines
113 fh_unlock(fh);112 fh_unlock(fh);
114 fh_drop_write(fh);113 fh_drop_write(fh);
115out_errno:114out_errno:
116 nfserr = nfserrno(error);115 resp->status = nfserrno(error);
117out:116out:
118 /* argp->acl_{access,default} may have been allocated in117 /* argp->acl_{access,default} may have been allocated in
119 nfs3svc_decode_setaclargs. */118 nfs3svc_decode_setaclargs. */
120 posix_acl_release(argp->acl_access);119 posix_acl_release(argp->acl_access);
121 posix_acl_release(argp->acl_default);120 posix_acl_release(argp->acl_default);
122 RETURN_STATUS(nfserr);121 return rpc_success;
123}122}
124 123
125/*124/*
@@ -174,6 +173,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) · 48 unmodified lines
174 struct nfsd3_getaclres *resp = rqstp->rq_resp;173 struct nfsd3_getaclres *resp = rqstp->rq_resp;
175 struct dentry *dentry = resp->fh.fh_dentry;174 struct dentry *dentry = resp->fh.fh_dentry;
176 175
176 *p++ = resp->status;
177 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);177 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
178 if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {178 if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {
179 struct inode *inode = d_inode(dentry);179 struct inode *inode = d_inode(dentry);
@@ -218,8 +218,8 @@ static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p) · 38 unmodified lines
218{218{
219 struct nfsd3_attrstat *resp = rqstp->rq_resp;219 struct nfsd3_attrstat *resp = rqstp->rq_resp;
220 220
221 *p++ = resp->status;
221 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);222 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
222
223 return xdr_ressize_check(rqstp, p);223 return xdr_ressize_check(rqstp, p);
224}224}
225 225
@@ -235,33 +235,43 @@ static void nfs3svc_release_getacl(struct svc_rqst *rqstp) · 9 unmodified lines
235 posix_acl_release(resp->acl_default);235 posix_acl_release(resp->acl_default);
236}236}
237 237
238#define nfs3svc_decode_voidargs NULL
239#define nfs3svc_release_void NULL
240#define nfsd3_setaclres nfsd3_attrstat
241#define nfsd3_voidres nfsd3_voidargs
242struct nfsd3_voidargs { int dummy; };238struct nfsd3_voidargs { int dummy; };
243 239
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
256#define ST 1 /* status*/240#define ST 1 /* status*/
257#define AT 21 /* attributes */241#define AT 21 /* attributes */
258#define pAT (1+AT) /* post attributes - conditional */242#define pAT (1+AT) /* post attributes - conditional */
259#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */243#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
260 244
261static const struct svc_procedure nfsd_acl_procedures3[] = {245static const struct svc_procedure nfsd_acl_procedures3[3] = {
262 PROC(null, void, void, void, RC_NOCACHE, ST),246 [ACLPROC3_NULL] = {
263 PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),247 .pc_func = nfsd3_proc_null,
264 PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT),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 },
265};275};
266 276
267static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)];277static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)];
fs/nfsd/nfs3proc.c+116−122
@@ -15,8 +15,6 @@ · 14 unmodified lines
15 15
16#define NFSDDBG_FACILITY NFSDDBG_PROC16#define NFSDDBG_FACILITY NFSDDBG_PROC
17 17
18#define RETURN_STATUS(st) { resp->status = (st); return (st); }
19
20static int nfs3_ftypes[] = {18static int nfs3_ftypes[] = {
21 0, /* NF3NON */19 0, /* NF3NON */
22 S_IFREG, /* NF3REG */20 S_IFREG, /* NF3REG */
@@ -34,7 +32,7 @@ static int nfs3_ftypes[] = { · 11 unmodified lines
34static __be3232static __be32
35nfsd3_proc_null(struct svc_rqst *rqstp)33nfsd3_proc_null(struct svc_rqst *rqstp)
36{34{
37 return nfs_ok;35 return rpc_success;
38}36}
39 37
40/*38/*
@@ -45,20 +43,19 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp) · 4 unmodified lines
45{43{
46 struct nfsd_fhandle *argp = rqstp->rq_argp;44 struct nfsd_fhandle *argp = rqstp->rq_argp;
47 struct nfsd3_attrstat *resp = rqstp->rq_resp;45 struct nfsd3_attrstat *resp = rqstp->rq_resp;
48 __be32 nfserr;
49 46
50 dprintk("nfsd: GETATTR(3) %s\n",47 dprintk("nfsd: GETATTR(3) %s\n",
51 SVCFH_fmt(&argp->fh));48 SVCFH_fmt(&argp->fh));
52 49
53 fh_copy(&resp->fh, &argp->fh);50 fh_copy(&resp->fh, &argp->fh);
54 nfserr = fh_verify(rqstp, &resp->fh, 0,51 resp->status = fh_verify(rqstp, &resp->fh, 0,
55 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);52 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
56 if (nfserr)53 if (resp->status != nfs_ok)
57 RETURN_STATUS(nfserr);54 goto out;
58 55
59 nfserr = fh_getattr(&resp->fh, &resp->stat);56 resp->status = fh_getattr(&resp->fh, &resp->stat);
60 57out:
61 RETURN_STATUS(nfserr);58 return rpc_success;
62}59}
63 60
64/*61/*
@@ -69,15 +66,14 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp) · 4 unmodified lines
69{66{
70 struct nfsd3_sattrargs *argp = rqstp->rq_argp;67 struct nfsd3_sattrargs *argp = rqstp->rq_argp;
71 struct nfsd3_attrstat *resp = rqstp->rq_resp;68 struct nfsd3_attrstat *resp = rqstp->rq_resp;
72 __be32 nfserr;
73 69
74 dprintk("nfsd: SETATTR(3) %s\n",70 dprintk("nfsd: SETATTR(3) %s\n",
75 SVCFH_fmt(&argp->fh));71 SVCFH_fmt(&argp->fh));
76 72
77 fh_copy(&resp->fh, &argp->fh);73 fh_copy(&resp->fh, &argp->fh);
78 nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,74 resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
79 argp->check_guard, argp->guardtime);75 argp->check_guard, argp->guardtime);
80 RETURN_STATUS(nfserr);76 return rpc_success;
81}77}
82 78
83/*79/*
@@ -88,7 +84,6 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp) · 4 unmodified lines
88{84{
89 struct nfsd3_diropargs *argp = rqstp->rq_argp;85 struct nfsd3_diropargs *argp = rqstp->rq_argp;
90 struct nfsd3_diropres *resp = rqstp->rq_resp;86 struct nfsd3_diropres *resp = rqstp->rq_resp;
91 __be32 nfserr;
92 87
93 dprintk("nfsd: LOOKUP(3) %s %.*s\n",88 dprintk("nfsd: LOOKUP(3) %s %.*s\n",
94 SVCFH_fmt(&argp->fh),89 SVCFH_fmt(&argp->fh),
@@ -98,11 +93,10 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp) · 3 unmodified lines
98 fh_copy(&resp->dirfh, &argp->fh);93 fh_copy(&resp->dirfh, &argp->fh);
99 fh_init(&resp->fh, NFS3_FHSIZE);94 fh_init(&resp->fh, NFS3_FHSIZE);
100 95
101 nfserr = nfsd_lookup(rqstp, &resp->dirfh,96 resp->status = nfsd_lookup(rqstp, &resp->dirfh,
102 argp->name,97 argp->name, argp->len,
103 argp->len,98 &resp->fh);
104 &resp->fh);99 return rpc_success;
105 RETURN_STATUS(nfserr);
106}100}
107 101
108/*102/*
@@ -113,7 +107,6 @@ nfsd3_proc_access(struct svc_rqst *rqstp) · 4 unmodified lines
113{107{
114 struct nfsd3_accessargs *argp = rqstp->rq_argp;108 struct nfsd3_accessargs *argp = rqstp->rq_argp;
115 struct nfsd3_accessres *resp = rqstp->rq_resp;109 struct nfsd3_accessres *resp = rqstp->rq_resp;
116 __be32 nfserr;
117 110
118 dprintk("nfsd: ACCESS(3) %s 0x%x\n",111 dprintk("nfsd: ACCESS(3) %s 0x%x\n",
119 SVCFH_fmt(&argp->fh),112 SVCFH_fmt(&argp->fh),
@@ -121,8 +114,8 @@ nfsd3_proc_access(struct svc_rqst *rqstp) · 1 unmodified line
121 114
122 fh_copy(&resp->fh, &argp->fh);115 fh_copy(&resp->fh, &argp->fh);
123 resp->access = argp->access;116 resp->access = argp->access;
124 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);117 resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
125 RETURN_STATUS(nfserr);118 return rpc_success;
126}119}
127 120
128/*121/*
@@ -133,15 +126,14 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp) · 4 unmodified lines
133{126{
134 struct nfsd3_readlinkargs *argp = rqstp->rq_argp;127 struct nfsd3_readlinkargs *argp = rqstp->rq_argp;
135 struct nfsd3_readlinkres *resp = rqstp->rq_resp;128 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
136 __be32 nfserr;
137 129
138 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));130 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
139 131
140 /* Read the symlink. */132 /* Read the symlink. */
141 fh_copy(&resp->fh, &argp->fh);133 fh_copy(&resp->fh, &argp->fh);
142 resp->len = NFS3_MAXPATHLEN;134 resp->len = NFS3_MAXPATHLEN;
143 nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);135 resp->status = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
144 RETURN_STATUS(nfserr);136 return rpc_success;
145}137}
146 138
147/*139/*
@@ -152,7 +144,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 4 unmodified lines
152{144{
153 struct nfsd3_readargs *argp = rqstp->rq_argp;145 struct nfsd3_readargs *argp = rqstp->rq_argp;
154 struct nfsd3_readres *resp = rqstp->rq_resp;146 struct nfsd3_readres *resp = rqstp->rq_resp;
155 __be32 nfserr;
156 u32 max_blocksize = svc_max_payload(rqstp);147 u32 max_blocksize = svc_max_payload(rqstp);
157 unsigned long cnt = min(argp->count, max_blocksize);148 unsigned long cnt = min(argp->count, max_blocksize);
158 149
@@ -169,12 +160,10 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 10 unmodified lines
169 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);160 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
170 161
171 fh_copy(&resp->fh, &argp->fh);162 fh_copy(&resp->fh, &argp->fh);
172 nfserr = nfsd_read(rqstp, &resp->fh,163 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
173 argp->offset,164 rqstp->rq_vec, argp->vlen, &resp->count,
174 rqstp->rq_vec, argp->vlen,165 &resp->eof);
175 &resp->count,166 return rpc_success;
176 &resp->eof);
177 RETURN_STATUS(nfserr);
178}167}
179 168
180/*169/*
@@ -185,7 +174,6 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 4 unmodified lines
185{174{
186 struct nfsd3_writeargs *argp = rqstp->rq_argp;175 struct nfsd3_writeargs *argp = rqstp->rq_argp;
187 struct nfsd3_writeres *resp = rqstp->rq_resp;176 struct nfsd3_writeres *resp = rqstp->rq_resp;
188 __be32 nfserr;
189 unsigned long cnt = argp->len;177 unsigned long cnt = argp->len;
190 unsigned int nvecs;178 unsigned int nvecs;
191 179
@@ -199,13 +187,16 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 7 unmodified lines
199 resp->committed = argp->stable;187 resp->committed = argp->stable;
200 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,188 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
201 &argp->first, cnt);189 &argp->first, cnt);
202 if (!nvecs)190 if (!nvecs) {
203 RETURN_STATUS(nfserr_io);191 resp->status = nfserr_io;
204 nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,192 goto out;
205 rqstp->rq_vec, nvecs, &cnt,193 }
206 resp->committed, resp->verf);194 resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
195 rqstp->rq_vec, nvecs, &cnt,
196 resp->committed, resp->verf);
207 resp->count = cnt;197 resp->count = cnt;
208 RETURN_STATUS(nfserr);198out:
199 return rpc_success;
209}200}
210 201
211/*202/*
@@ -220,7 +211,6 @@ nfsd3_proc_create(struct svc_rqst *rqstp) · 8 unmodified lines
220 struct nfsd3_diropres *resp = rqstp->rq_resp;211 struct nfsd3_diropres *resp = rqstp->rq_resp;
221 svc_fh *dirfhp, *newfhp = NULL;212 svc_fh *dirfhp, *newfhp = NULL;
222 struct iattr *attr;213 struct iattr *attr;
223 __be32 nfserr;
224 214
225 dprintk("nfsd: CREATE(3) %s %.*s\n",215 dprintk("nfsd: CREATE(3) %s %.*s\n",
226 SVCFH_fmt(&argp->fh),216 SVCFH_fmt(&argp->fh),
@@ -241,11 +231,10 @@ nfsd3_proc_create(struct svc_rqst *rqstp) · 14 unmodified lines
241 }231 }
242 232
243 /* Now create the file and set attributes */233 /* Now create the file and set attributes */
244 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,234 resp->status = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
245 attr, newfhp,235 attr, newfhp, argp->createmode,
246 argp->createmode, (u32 *)argp->verf, NULL, NULL);236 (u32 *)argp->verf, NULL, NULL);
247 237 return rpc_success;
248 RETURN_STATUS(nfserr);
249}238}
250 239
251/*240/*
@@ -256,7 +245,6 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) · 4 unmodified lines
256{245{
257 struct nfsd3_createargs *argp = rqstp->rq_argp;246 struct nfsd3_createargs *argp = rqstp->rq_argp;
258 struct nfsd3_diropres *resp = rqstp->rq_resp;247 struct nfsd3_diropres *resp = rqstp->rq_resp;
259 __be32 nfserr;
260 248
261 dprintk("nfsd: MKDIR(3) %s %.*s\n",249 dprintk("nfsd: MKDIR(3) %s %.*s\n",
262 SVCFH_fmt(&argp->fh),250 SVCFH_fmt(&argp->fh),
@@ -266,10 +254,10 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) · 3 unmodified lines
266 argp->attrs.ia_valid &= ~ATTR_SIZE;254 argp->attrs.ia_valid &= ~ATTR_SIZE;
267 fh_copy(&resp->dirfh, &argp->fh);255 fh_copy(&resp->dirfh, &argp->fh);
268 fh_init(&resp->fh, NFS3_FHSIZE);256 fh_init(&resp->fh, NFS3_FHSIZE);
269 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,257 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
270 &argp->attrs, S_IFDIR, 0, &resp->fh);258 &argp->attrs, S_IFDIR, 0, &resp->fh);
271 fh_unlock(&resp->dirfh);259 fh_unlock(&resp->dirfh);
272 RETURN_STATUS(nfserr);260 return rpc_success;
273}261}
274 262
275static __be32263static __be32
@@ -277,18 +265,23 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) · 1 unmodified line
277{265{
278 struct nfsd3_symlinkargs *argp = rqstp->rq_argp;266 struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
279 struct nfsd3_diropres *resp = rqstp->rq_resp;267 struct nfsd3_diropres *resp = rqstp->rq_resp;
280 __be32 nfserr;
281 268
282 if (argp->tlen == 0)269 if (argp->tlen == 0) {
283 RETURN_STATUS(nfserr_inval);270 resp->status = nfserr_inval;
284 if (argp->tlen > NFS3_MAXPATHLEN)271 goto out;
285 RETURN_STATUS(nfserr_nametoolong);272 }
273 if (argp->tlen > NFS3_MAXPATHLEN) {
274 resp->status = nfserr_nametoolong;
275 goto out;
276 }
286 277
287 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,278 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
288 page_address(rqstp->rq_arg.pages[0]),279 page_address(rqstp->rq_arg.pages[0]),
289 argp->tlen);280 argp->tlen);
290 if (IS_ERR(argp->tname))281 if (IS_ERR(argp->tname)) {
291 RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));282 resp->status = nfserrno(PTR_ERR(argp->tname));
283 goto out;
284 }
292 285
293 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",286 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
294 SVCFH_fmt(&argp->ffh),287 SVCFH_fmt(&argp->ffh),
@@ -297,10 +290,11 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) · 2 unmodified lines
297 290
298 fh_copy(&resp->dirfh, &argp->ffh);291 fh_copy(&resp->dirfh, &argp->ffh);
299 fh_init(&resp->fh, NFS3_FHSIZE);292 fh_init(&resp->fh, NFS3_FHSIZE);
300 nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,293 resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
301 argp->tname, &resp->fh);294 argp->flen, argp->tname, &resp->fh);
302 kfree(argp->tname);295 kfree(argp->tname);
303 RETURN_STATUS(nfserr);296out:
297 return rpc_success;
304}298}
305 299
306/*300/*
@@ -311,7 +305,6 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) · 4 unmodified lines
311{305{
312 struct nfsd3_mknodargs *argp = rqstp->rq_argp;306 struct nfsd3_mknodargs *argp = rqstp->rq_argp;
313 struct nfsd3_diropres *resp = rqstp->rq_resp;307 struct nfsd3_diropres *resp = rqstp->rq_resp;
314 __be32 nfserr;
315 int type;308 int type;
316 dev_t rdev = 0;309 dev_t rdev = 0;
317 310
@@ -323,22 +316,28 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) · 5 unmodified lines
323 fh_copy(&resp->dirfh, &argp->fh);316 fh_copy(&resp->dirfh, &argp->fh);
324 fh_init(&resp->fh, NFS3_FHSIZE);317 fh_init(&resp->fh, NFS3_FHSIZE);
325 318
326 if (argp->ftype == 0 || argp->ftype >= NF3BAD)319 if (argp->ftype == 0 || argp->ftype >= NF3BAD) {
327 RETURN_STATUS(nfserr_inval);320 resp->status = nfserr_inval;
321 goto out;
322 }
328 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {323 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
329 rdev = MKDEV(argp->major, argp->minor);324 rdev = MKDEV(argp->major, argp->minor);
330 if (MAJOR(rdev) != argp->major ||325 if (MAJOR(rdev) != argp->major ||
331 MINOR(rdev) != argp->minor)326 MINOR(rdev) != argp->minor) {
332 RETURN_STATUS(nfserr_inval);327 resp->status = nfserr_inval;
333 } else328 goto out;
334 if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)329 }
335 RETURN_STATUS(nfserr_inval);330 } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
331 resp->status = nfserr_inval;
332 goto out;
333 }
336 334
337 type = nfs3_ftypes[argp->ftype];335 type = nfs3_ftypes[argp->ftype];
338 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,336 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
339 &argp->attrs, type, rdev, &resp->fh);337 &argp->attrs, type, rdev, &resp->fh);
340 fh_unlock(&resp->dirfh);338 fh_unlock(&resp->dirfh);
341 RETURN_STATUS(nfserr);339out:
340 return rpc_success;
342}341}
343 342
344/*343/*
@@ -349,7 +348,6 @@ nfsd3_proc_remove(struct svc_rqst *rqstp) · 4 unmodified lines
349{348{
350 struct nfsd3_diropargs *argp = rqstp->rq_argp;349 struct nfsd3_diropargs *argp = rqstp->rq_argp;
351 struct nfsd3_attrstat *resp = rqstp->rq_resp;350 struct nfsd3_attrstat *resp = rqstp->rq_resp;
352 __be32 nfserr;
353 351
354 dprintk("nfsd: REMOVE(3) %s %.*s\n",352 dprintk("nfsd: REMOVE(3) %s %.*s\n",
355 SVCFH_fmt(&argp->fh),353 SVCFH_fmt(&argp->fh),
@@ -358,9 +356,10 @@ nfsd3_proc_remove(struct svc_rqst *rqstp) · 2 unmodified lines
358 356
359 /* Unlink. -S_IFDIR means file must not be a directory */357 /* Unlink. -S_IFDIR means file must not be a directory */
360 fh_copy(&resp->fh, &argp->fh);358 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);
362 fh_unlock(&resp->fh);361 fh_unlock(&resp->fh);
363 RETURN_STATUS(nfserr);362 return rpc_success;
364}363}
365 364
366/*365/*
@@ -371,7 +370,6 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp) · 4 unmodified lines
371{370{
372 struct nfsd3_diropargs *argp = rqstp->rq_argp;371 struct nfsd3_diropargs *argp = rqstp->rq_argp;
373 struct nfsd3_attrstat *resp = rqstp->rq_resp;372 struct nfsd3_attrstat *resp = rqstp->rq_resp;
374 __be32 nfserr;
375 373
376 dprintk("nfsd: RMDIR(3) %s %.*s\n",374 dprintk("nfsd: RMDIR(3) %s %.*s\n",
377 SVCFH_fmt(&argp->fh),375 SVCFH_fmt(&argp->fh),
@@ -379,9 +377,10 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp) · 1 unmodified line
379 argp->name);377 argp->name);
380 378
381 fh_copy(&resp->fh, &argp->fh);379 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);
383 fh_unlock(&resp->fh);382 fh_unlock(&resp->fh);
384 RETURN_STATUS(nfserr);383 return rpc_success;
385}384}
386 385
387static __be32386static __be32
@@ -389,7 +388,6 @@ nfsd3_proc_rename(struct svc_rqst *rqstp) · 1 unmodified line
389{388{
390 struct nfsd3_renameargs *argp = rqstp->rq_argp;389 struct nfsd3_renameargs *argp = rqstp->rq_argp;
391 struct nfsd3_renameres *resp = rqstp->rq_resp;390 struct nfsd3_renameres *resp = rqstp->rq_resp;
392 __be32 nfserr;
393 391
394 dprintk("nfsd: RENAME(3) %s %.*s ->\n",392 dprintk("nfsd: RENAME(3) %s %.*s ->\n",
395 SVCFH_fmt(&argp->ffh),393 SVCFH_fmt(&argp->ffh),
@@ -402,9 +400,9 @@ nfsd3_proc_rename(struct svc_rqst *rqstp) · 6 unmodified lines
402 400
403 fh_copy(&resp->ffh, &argp->ffh);401 fh_copy(&resp->ffh, &argp->ffh);
404 fh_copy(&resp->tfh, &argp->tfh);402 fh_copy(&resp->tfh, &argp->tfh);
405 nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,403 resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
406 &resp->tfh, argp->tname, argp->tlen);404 &resp->tfh, argp->tname, argp->tlen);
407 RETURN_STATUS(nfserr);405 return rpc_success;
408}406}
409 407
410static __be32408static __be32
@@ -412,7 +410,6 @@ nfsd3_proc_link(struct svc_rqst *rqstp) · 1 unmodified line
412{410{
413 struct nfsd3_linkargs *argp = rqstp->rq_argp;411 struct nfsd3_linkargs *argp = rqstp->rq_argp;
414 struct nfsd3_linkres *resp = rqstp->rq_resp;412 struct nfsd3_linkres *resp = rqstp->rq_resp;
415 __be32 nfserr;
416 413
417 dprintk("nfsd: LINK(3) %s ->\n",414 dprintk("nfsd: LINK(3) %s ->\n",
418 SVCFH_fmt(&argp->ffh));415 SVCFH_fmt(&argp->ffh));
@@ -423,9 +420,9 @@ nfsd3_proc_link(struct svc_rqst *rqstp) · 4 unmodified lines
423 420
424 fh_copy(&resp->fh, &argp->ffh);421 fh_copy(&resp->fh, &argp->ffh);
425 fh_copy(&resp->tfh, &argp->tfh);422 fh_copy(&resp->tfh, &argp->tfh);
426 nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,423 resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
427 &resp->fh);424 &resp->fh);
428 RETURN_STATUS(nfserr);425 return rpc_success;
429}426}
430 427
431/*428/*
@@ -436,7 +433,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 4 unmodified lines
436{433{
437 struct nfsd3_readdirargs *argp = rqstp->rq_argp;434 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
438 struct nfsd3_readdirres *resp = rqstp->rq_resp;435 struct nfsd3_readdirres *resp = rqstp->rq_resp;
439 __be32 nfserr;
440 int count = 0;436 int count = 0;
441 struct page **p;437 struct page **p;
442 caddr_t page_addr = NULL;438 caddr_t page_addr = NULL;
@@ -456,8 +452,8 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 13 unmodified lines
456 resp->common.err = nfs_ok;452 resp->common.err = nfs_ok;
457 resp->buffer = argp->buffer;453 resp->buffer = argp->buffer;
458 resp->rqstp = rqstp;454 resp->rqstp = rqstp;
459 nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, 455 resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie,
460 &resp->common, nfs3svc_encode_entry);456 &resp->common, nfs3svc_encode_entry);
461 memcpy(resp->verf, argp->verf, 8);457 memcpy(resp->verf, argp->verf, 8);
462 count = 0;458 count = 0;
463 for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {459 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
485 resp->offset = NULL;481 resp->offset = NULL;
486 }482 }
487 483
488 RETURN_STATUS(nfserr);484 return rpc_success;
489}485}
490 486
491/*487/*
@@ -497,7 +493,6 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 5 unmodified lines
497{493{
498 struct nfsd3_readdirargs *argp = rqstp->rq_argp;494 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
499 struct nfsd3_readdirres *resp = rqstp->rq_resp;495 struct nfsd3_readdirres *resp = rqstp->rq_resp;
500 __be32 nfserr;
501 int count = 0;496 int count = 0;
502 loff_t offset;497 loff_t offset;
503 struct page **p;498 struct page **p;
@@ -520,17 +515,17 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 16 unmodified lines
520 resp->rqstp = rqstp;515 resp->rqstp = rqstp;
521 offset = argp->cookie;516 offset = argp->cookie;
522 517
523 nfserr = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);518 resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
524 if (nfserr)519 if (resp->status != nfs_ok)
525 RETURN_STATUS(nfserr);520 goto out;
526 521
527 if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS)522 if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
528 RETURN_STATUS(nfserr_notsupp);523 resp->status = nfserr_notsupp;
524 goto out;
525 }
529 526
530 nfserr = nfsd_readdir(rqstp, &resp->fh,527 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
531 &offset,528 &resp->common, nfs3svc_encode_entry_plus);
532 &resp->common,
533 nfs3svc_encode_entry_plus);
534 memcpy(resp->verf, argp->verf, 8);529 memcpy(resp->verf, argp->verf, 8);
535 for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {530 for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
536 page_addr = page_address(*p);531 page_addr = page_address(*p);
@@ -555,7 +550,8 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 18 unmodified lines
555 resp->offset = NULL;550 resp->offset = NULL;
556 }551 }
557 552
558 RETURN_STATUS(nfserr);553out:
554 return rpc_success;
559}555}
560 556
561/*557/*
@@ -566,14 +562,13 @@ nfsd3_proc_fsstat(struct svc_rqst *rqstp) · 4 unmodified lines
566{562{
567 struct nfsd_fhandle *argp = rqstp->rq_argp;563 struct nfsd_fhandle *argp = rqstp->rq_argp;
568 struct nfsd3_fsstatres *resp = rqstp->rq_resp;564 struct nfsd3_fsstatres *resp = rqstp->rq_resp;
569 __be32 nfserr;
570 565
571 dprintk("nfsd: FSSTAT(3) %s\n",566 dprintk("nfsd: FSSTAT(3) %s\n",
572 SVCFH_fmt(&argp->fh));567 SVCFH_fmt(&argp->fh));
573 568
574 nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);569 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
575 fh_put(&argp->fh);570 fh_put(&argp->fh);
576 RETURN_STATUS(nfserr);571 return rpc_success;
577}572}
578 573
579/*574/*
@@ -584,7 +579,6 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp) · 4 unmodified lines
584{579{
585 struct nfsd_fhandle *argp = rqstp->rq_argp;580 struct nfsd_fhandle *argp = rqstp->rq_argp;
586 struct nfsd3_fsinfores *resp = rqstp->rq_resp;581 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
587 __be32 nfserr;
588 u32 max_blocksize = svc_max_payload(rqstp);582 u32 max_blocksize = svc_max_payload(rqstp);
589 583
590 dprintk("nfsd: FSINFO(3) %s\n",584 dprintk("nfsd: FSINFO(3) %s\n",
@@ -600,13 +594,13 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp) · 9 unmodified lines
600 resp->f_maxfilesize = ~(u32) 0;594 resp->f_maxfilesize = ~(u32) 0;
601 resp->f_properties = NFS3_FSF_DEFAULT;595 resp->f_properties = NFS3_FSF_DEFAULT;
602 596
603 nfserr = fh_verify(rqstp, &argp->fh, 0,597 resp->status = fh_verify(rqstp, &argp->fh, 0,
604 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);598 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
605 599
606 /* Check special features of the file system. May request600 /* Check special features of the file system. May request
607 * different read/write sizes for file systems known to have601 * different read/write sizes for file systems known to have
608 * problems with large blocks */602 * problems with large blocks */
609 if (nfserr == 0) {603 if (resp->status == nfs_ok) {
610 struct super_block *sb = argp->fh.fh_dentry->d_sb;604 struct super_block *sb = argp->fh.fh_dentry->d_sb;
611 605
612 /* Note that we don't care for remote fs's here */606 /* 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
617 }611 }
618 612
619 fh_put(&argp->fh);613 fh_put(&argp->fh);
620 RETURN_STATUS(nfserr);614 return rpc_success;
621}615}
622 616
623/*617/*
@@ -628,7 +622,6 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp) · 4 unmodified lines
628{622{
629 struct nfsd_fhandle *argp = rqstp->rq_argp;623 struct nfsd_fhandle *argp = rqstp->rq_argp;
630 struct nfsd3_pathconfres *resp = rqstp->rq_resp;624 struct nfsd3_pathconfres *resp = rqstp->rq_resp;
631 __be32 nfserr;
632 625
633 dprintk("nfsd: PATHCONF(3) %s\n",626 dprintk("nfsd: PATHCONF(3) %s\n",
634 SVCFH_fmt(&argp->fh));627 SVCFH_fmt(&argp->fh));
@@ -641,9 +634,9 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp) · 6 unmodified lines
641 resp->p_case_insensitive = 0;634 resp->p_case_insensitive = 0;
642 resp->p_case_preserving = 1;635 resp->p_case_preserving = 1;
643 636
644 nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);637 resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
645 638
646 if (nfserr == 0) {639 if (resp->status == nfs_ok) {
647 struct super_block *sb = argp->fh.fh_dentry->d_sb;640 struct super_block *sb = argp->fh.fh_dentry->d_sb;
648 641
649 /* Note that we don't care for remote fs's here */642 /* 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
660 }653 }
661 654
662 fh_put(&argp->fh);655 fh_put(&argp->fh);
663 RETURN_STATUS(nfserr);656 return rpc_success;
664}657}
665 658
666
667/*659/*
668 * Commit a file (range) to stable storage.660 * Commit a file (range) to stable storage.
669 */661 */
@@ -672,21 +664,22 @@ nfsd3_proc_commit(struct svc_rqst *rqstp) · 2 unmodified lines
672{664{
673 struct nfsd3_commitargs *argp = rqstp->rq_argp;665 struct nfsd3_commitargs *argp = rqstp->rq_argp;
674 struct nfsd3_commitres *resp = rqstp->rq_resp;666 struct nfsd3_commitres *resp = rqstp->rq_resp;
675 __be32 nfserr;
676 667
677 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",668 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
678 SVCFH_fmt(&argp->fh),669 SVCFH_fmt(&argp->fh),
679 argp->count,670 argp->count,
680 (unsigned long long) argp->offset);671 (unsigned long long) argp->offset);
681 672
682 if (argp->offset > NFS_OFFSET_MAX)673 if (argp->offset > NFS_OFFSET_MAX) {
683 RETURN_STATUS(nfserr_inval);674 resp->status = nfserr_inval;
675 goto out;
676 }
684 677
685 fh_copy(&resp->fh, &argp->fh);678 fh_copy(&resp->fh, &argp->fh);
686 nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count,679 resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset,
687 resp->verf);680 argp->count, resp->verf);
688 681out:
689 RETURN_STATUS(nfserr);682 return rpc_success;
690}683}
691 684
692 685
@@ -716,6 +709,7 @@ struct nfsd3_voidargs { int dummy; }; · 23 unmodified lines
716static const struct svc_procedure nfsd_procedures3[22] = {709static const struct svc_procedure nfsd_procedures3[22] = {
717 [NFS3PROC_NULL] = {710 [NFS3PROC_NULL] = {
718 .pc_func = nfsd3_proc_null,711 .pc_func = nfsd3_proc_null,
712 .pc_decode = nfs3svc_decode_voidarg,
719 .pc_encode = nfs3svc_encode_voidres,713 .pc_encode = nfs3svc_encode_voidres,
720 .pc_argsize = sizeof(struct nfsd3_voidargs),714 .pc_argsize = sizeof(struct nfsd3_voidargs),
721 .pc_ressize = sizeof(struct nfsd3_voidres),715 .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
304/*304/*
305 * XDR decode functions305 * XDR decode functions
306 */306 */
307int
308nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
309{
310 return 1;
311}
312
307int313int
308nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)314nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
309{315{
@@ -635,10 +641,7 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p) · 325 unmodified lines
635/*641/*
636 * XDR encode functions642 * XDR encode functions
637 */643 */
638/*644
639 * There must be an encoding function for void results so svc_process
640 * will work properly.
641 */
642int645int
643nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)646nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
644{647{
@@ -651,6 +654,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) · 6 unmodified lines
651{654{
652 struct nfsd3_attrstat *resp = rqstp->rq_resp;655 struct nfsd3_attrstat *resp = rqstp->rq_resp;
653 656
657 *p++ = resp->status;
654 if (resp->status == 0) {658 if (resp->status == 0) {
655 lease_get_mtime(d_inode(resp->fh.fh_dentry),659 lease_get_mtime(d_inode(resp->fh.fh_dentry),
656 &resp->stat.mtime);660 &resp->stat.mtime);
@@ -665,6 +669,7 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p) · 8 unmodified lines
665{669{
666 struct nfsd3_attrstat *resp = rqstp->rq_resp;670 struct nfsd3_attrstat *resp = rqstp->rq_resp;
667 671
672 *p++ = resp->status;
668 p = encode_wcc_data(rqstp, p, &resp->fh);673 p = encode_wcc_data(rqstp, p, &resp->fh);
669 return xdr_ressize_check(rqstp, p);674 return xdr_ressize_check(rqstp, p);
670}675}
@@ -675,6 +680,7 @@ nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p) · 4 unmodified lines
675{680{
676 struct nfsd3_diropres *resp = rqstp->rq_resp;681 struct nfsd3_diropres *resp = rqstp->rq_resp;
677 682
683 *p++ = resp->status;
678 if (resp->status == 0) {684 if (resp->status == 0) {
679 p = encode_fh(p, &resp->fh);685 p = encode_fh(p, &resp->fh);
680 p = encode_post_op_attr(rqstp, p, &resp->fh);686 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
689{695{
690 struct nfsd3_accessres *resp = rqstp->rq_resp;696 struct nfsd3_accessres *resp = rqstp->rq_resp;
691 697
698 *p++ = resp->status;
692 p = encode_post_op_attr(rqstp, p, &resp->fh);699 p = encode_post_op_attr(rqstp, p, &resp->fh);
693 if (resp->status == 0)700 if (resp->status == 0)
694 *p++ = htonl(resp->access);701 *p++ = htonl(resp->access);
@@ -701,6 +708,7 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) · 6 unmodified lines
701{708{
702 struct nfsd3_readlinkres *resp = rqstp->rq_resp;709 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
703 710
711 *p++ = resp->status;
704 p = encode_post_op_attr(rqstp, p, &resp->fh);712 p = encode_post_op_attr(rqstp, p, &resp->fh);
705 if (resp->status == 0) {713 if (resp->status == 0) {
706 *p++ = htonl(resp->len);714 *p++ = htonl(resp->len);
@@ -723,6 +731,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p) · 16 unmodified lines
723{731{
724 struct nfsd3_readres *resp = rqstp->rq_resp;732 struct nfsd3_readres *resp = rqstp->rq_resp;
725 733
734 *p++ = resp->status;
726 p = encode_post_op_attr(rqstp, p, &resp->fh);735 p = encode_post_op_attr(rqstp, p, &resp->fh);
727 if (resp->status == 0) {736 if (resp->status == 0) {
728 *p++ = htonl(resp->count);737 *p++ = htonl(resp->count);
@@ -748,6 +757,7 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) · 19 unmodified lines
748{757{
749 struct nfsd3_writeres *resp = rqstp->rq_resp;758 struct nfsd3_writeres *resp = rqstp->rq_resp;
750 759
760 *p++ = resp->status;
751 p = encode_wcc_data(rqstp, p, &resp->fh);761 p = encode_wcc_data(rqstp, p, &resp->fh);
752 if (resp->status == 0) {762 if (resp->status == 0) {
753 *p++ = htonl(resp->count);763 *p++ = htonl(resp->count);
@@ -764,6 +774,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p) · 10 unmodified lines
764{774{
765 struct nfsd3_diropres *resp = rqstp->rq_resp;775 struct nfsd3_diropres *resp = rqstp->rq_resp;
766 776
777 *p++ = resp->status;
767 if (resp->status == 0) {778 if (resp->status == 0) {
768 *p++ = xdr_one;779 *p++ = xdr_one;
769 p = encode_fh(p, &resp->fh);780 p = encode_fh(p, &resp->fh);
@@ -779,6 +790,7 @@ nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p) · 9 unmodified lines
779{790{
780 struct nfsd3_renameres *resp = rqstp->rq_resp;791 struct nfsd3_renameres *resp = rqstp->rq_resp;
781 792
793 *p++ = resp->status;
782 p = encode_wcc_data(rqstp, p, &resp->ffh);794 p = encode_wcc_data(rqstp, p, &resp->ffh);
783 p = encode_wcc_data(rqstp, p, &resp->tfh);795 p = encode_wcc_data(rqstp, p, &resp->tfh);
784 return xdr_ressize_check(rqstp, p);796 return xdr_ressize_check(rqstp, p);
@@ -790,6 +802,7 @@ nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p) · 5 unmodified lines
790{802{
791 struct nfsd3_linkres *resp = rqstp->rq_resp;803 struct nfsd3_linkres *resp = rqstp->rq_resp;
792 804
805 *p++ = resp->status;
793 p = encode_post_op_attr(rqstp, p, &resp->fh);806 p = encode_post_op_attr(rqstp, p, &resp->fh);
794 p = encode_wcc_data(rqstp, p, &resp->tfh);807 p = encode_wcc_data(rqstp, p, &resp->tfh);
795 return xdr_ressize_check(rqstp, p);808 return xdr_ressize_check(rqstp, p);
@@ -801,6 +814,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) · 5 unmodified lines
801{814{
802 struct nfsd3_readdirres *resp = rqstp->rq_resp;815 struct nfsd3_readdirres *resp = rqstp->rq_resp;
803 816
817 *p++ = resp->status;
804 p = encode_post_op_attr(rqstp, p, &resp->fh);818 p = encode_post_op_attr(rqstp, p, &resp->fh);
805 819
806 if (resp->status == 0) {820 if (resp->status == 0) {
@@ -1053,6 +1067,7 @@ nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p) · 246 unmodified lines
1053 struct kstatfs *s = &resp->stats;1067 struct kstatfs *s = &resp->stats;
1054 u64 bs = s->f_bsize;1068 u64 bs = s->f_bsize;
1055 1069
1070 *p++ = resp->status;
1056 *p++ = xdr_zero; /* no post_op_attr */1071 *p++ = xdr_zero; /* no post_op_attr */
1057 1072
1058 if (resp->status == 0) {1073 if (resp->status == 0) {
@@ -1073,6 +1088,7 @@ nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p) · 14 unmodified lines
1073{1088{
1074 struct nfsd3_fsinfores *resp = rqstp->rq_resp;1089 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1075 1090
1091 *p++ = resp->status;
1076 *p++ = xdr_zero; /* no post_op_attr */1092 *p++ = xdr_zero; /* no post_op_attr */
1077 1093
1078 if (resp->status == 0) {1094 if (resp->status == 0) {
@@ -1118,6 +1134,7 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) · 39 unmodified lines
1118{1134{
1119 struct nfsd3_commitres *resp = rqstp->rq_resp;1135 struct nfsd3_commitres *resp = rqstp->rq_resp;
1120 1136
1137 *p++ = resp->status;
1121 p = encode_wcc_data(rqstp, p, &resp->fh);1138 p = encode_wcc_data(rqstp, p, &resp->fh);
1122 /* Write verifier */1139 /* Write verifier */
1123 if (resp->status == 0) {1140 if (resp->status == 0) {
fs/nfsd/nfs4proc.c+28−6
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#include <linux/slab.h>38#include <linux/slab.h>
39#include <linux/kthread.h>39#include <linux/kthread.h>
40#include <linux/sunrpc/addr.h>40#include <linux/sunrpc/addr.h>
41#include <linux/nfs_ssc.h>
41 42
42#include "idmap.h"43#include "idmap.h"
43#include "cache.h"44#include "cache.h"
@@ -1247,7 +1248,7 @@ out_err: · 1203 unmodified lines
1247static void1248static void
1248nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)1249nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
1249{1250{
1250 nfs_sb_deactive(ss_mnt->mnt_sb);1251 nfs_do_sb_deactive(ss_mnt->mnt_sb);
1251 mntput(ss_mnt);1252 mntput(ss_mnt);
1252}1253}
1253 1254
@@ -2165,7 +2166,7 @@ nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 911 unmodified lines
2165static __be322166static __be32
2166nfsd4_proc_null(struct svc_rqst *rqstp)2167nfsd4_proc_null(struct svc_rqst *rqstp)
2167{2168{
2168 return nfs_ok;2169 return rpc_success;
2169}2170}
2170 2171
2171static inline void nfsd4_increment_op_stats(u32 opnum)2172static inline void nfsd4_increment_op_stats(u32 opnum)
@@ -2457,15 +2458,14 @@ encode_op: · 285 unmodified lines
2457 nfsd4_increment_op_stats(op->opnum);2458 nfsd4_increment_op_stats(op->opnum);
2458 }2459 }
2459 2460
2460 cstate->status = status;
2461 fh_put(current_fh);2461 fh_put(current_fh);
2462 fh_put(save_fh);2462 fh_put(save_fh);
2463 BUG_ON(cstate->replay_owner);2463 BUG_ON(cstate->replay_owner);
2464out:2464out:
2465 cstate->status = status;
2465 /* Reset deferral mechanism for RPC deferrals */2466 /* Reset deferral mechanism for RPC deferrals */
2466 set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);2467 set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
2467 dprintk("nfsv4 compound returned %d\n", ntohl(status));2468 return rpc_success;
2468 return status;
2469}2469}
2470 2470
2471#define op_encode_hdr_size (2)2471#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
2591 return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);2591 return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2592}2592}
2593 2593
2594static 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
2594static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)2608static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
2595{2609{
2596 u32 maxcount = 0, rlen = 0;2610 u32 maxcount = 0, rlen = 0;
@@ -3163,6 +3177,13 @@ static const struct nfsd4_operation nfsd4_ops[] = { · 566 unmodified lines
3163 .op_name = "OP_COPY",3177 .op_name = "OP_COPY",
3164 .op_rsize_bop = nfsd4_copy_rsize,3178 .op_rsize_bop = nfsd4_copy_rsize,
3165 },3179 },
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 },
3166 [OP_SEEK] = {3187 [OP_SEEK] = {
3167 .op_func = nfsd4_seek,3188 .op_func = nfsd4_seek,
3168 .op_name = "OP_SEEK",3189 .op_name = "OP_SEEK",
@@ -3231,7 +3252,7 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) · 62 unmodified lines
3231 if (!cstate->minorversion)3252 if (!cstate->minorversion)
3232 return false;3253 return false;
3233 3254
3234 if (cstate->spo_must_allowed == true)3255 if (cstate->spo_must_allowed)
3235 return true;3256 return true;
3236 3257
3237 opiter = resp->opcnt;3258 opiter = resp->opcnt;
@@ -3279,6 +3300,7 @@ struct nfsd4_voidargs { int dummy; }; · 41 unmodified lines
3279static const struct svc_procedure nfsd_procedures4[2] = {3300static const struct svc_procedure nfsd_procedures4[2] = {
3280 [NFSPROC4_NULL] = {3301 [NFSPROC4_NULL] = {
3281 .pc_func = nfsd4_proc_null,3302 .pc_func = nfsd4_proc_null,
3303 .pc_decode = nfs4svc_decode_voidarg,
3282 .pc_encode = nfs4svc_encode_voidres,3304 .pc_encode = nfs4svc_encode_voidres,
3283 .pc_argsize = sizeof(struct nfsd4_voidargs),3305 .pc_argsize = sizeof(struct nfsd4_voidargs),
3284 .pc_ressize = sizeof(struct nfsd4_voidres),3306 .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
4513{4513{
4514 struct nfs4_delegation *dp = cb_to_delegation(cb);4514 struct nfs4_delegation *dp = cb_to_delegation(cb);
4515 4515
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)
4517 return 1;4518 return 1;
4518 4519
4519 switch (task->tk_status) {4520 switch (task->tk_status) {
@@ -4597,7 +4598,8 @@ static bool nfsd_breaker_owns_lease(struct file_lock *fl) · 77 unmodified lines
4597 if (!i_am_nfsd())4598 if (!i_am_nfsd())
4598 return NULL;4599 return NULL;
4599 rqst = kthread_data(current);4600 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)
4601 return NULL;4603 return NULL;
4602 clp = *(rqst->rq_lease_breaker);4604 clp = *(rqst->rq_lease_breaker);
4603 return dl->dl_stid.sc_client == clp;4605 return dl->dl_stid.sc_client == clp;
@@ -4954,7 +4956,6 @@ static int nfsd4_check_conflicting_opens(struct nfs4_client *clp, · 350 unmodified lines
4954 writes--;4956 writes--;
4955 if (fp->fi_fds[O_RDWR])4957 if (fp->fi_fds[O_RDWR])
4956 writes--;4958 writes--;
4957 WARN_ON_ONCE(writes < 0);
4958 if (writes > 0)4959 if (writes > 0)
4959 return -EAGAIN;4960 return -EAGAIN;
4960 spin_lock(&fp->fi_lock);4961 spin_lock(&fp->fi_lock);
@@ -5126,7 +5127,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, · 165 unmodified lines
5126 5127
5127 memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));5128 memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
5128 5129
5129 trace_nfsd_deleg_open(&dp->dl_stid.sc_stateid);5130 trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
5130 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;5131 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
5131 nfs4_put_stid(&dp->dl_stid);5132 nfs4_put_stid(&dp->dl_stid);
5132 return;5133 return;
@@ -5243,7 +5244,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf · 110 unmodified lines
5243 nfs4_open_delegation(current_fh, open, stp);5244 nfs4_open_delegation(current_fh, open, stp);
5244nodeleg:5245nodeleg:
5245 status = nfs_ok;5246 status = nfs_ok;
5246 trace_nfsd_deleg_none(&stp->st_stid.sc_stateid);5247 trace_nfsd_open(&stp->st_stid.sc_stateid);
5247out:5248out:
5248 /* 4.1 client trying to upgrade/downgrade delegation? */5249 /* 4.1 client trying to upgrade/downgrade delegation? */
5249 if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&5250 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
5722 return find_readable_file(s->sc_file);5723 return find_readable_file(s->sc_file);
5723 else5724 else
5724 return find_writeable_file(s->sc_file);5725 return find_writeable_file(s->sc_file);
5725 break;
5726 }5726 }
5727 5727
5728 return NULL;5728 return NULL;
@@ -7253,599 +7253,6 @@ nfs4_check_open_reclaim(clientid_t *clid, · 1524 unmodified lines
7253 return nfs_ok;7253 return nfs_ok;
7254}7254}
7255 7255
7256#ifdef CONFIG_NFSD_FAULT_INJECTION
7257static inline void
7258put_client(struct nfs4_client *clp)
7259{
7260 atomic_dec(&clp->cl_rpc_users);
7261}
7262
7263static struct nfs4_client *
7264nfsd_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
7280u64
7281nfsd_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
7303u64
7304nfsd_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
7330u64
7331nfsd_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
7358static 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
7366static void
7367nfsd_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
7382static 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 }
7416out:
7417 spin_unlock(&clp->cl_lock);
7418
7419 return count;
7420}
7421
7422static u64
7423nfsd_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
7429static u64
7430nfsd_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
7437u64
7438nfsd_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
7456static void
7457nfsd_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
7470u64
7471nfsd_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
7491u64
7492nfsd_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
7514static u64
7515nfsd_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
7551static u64
7552nfsd_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
7560static u64
7561nfsd_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
7568u64
7569nfsd_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
7587static void
7588nfsd_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
7601u64
7602nfsd_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
7623u64
7624nfsd_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
7647static 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
7688static u64
7689nfsd_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
7697u64
7698nfsd_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
7716static void
7717nfsd_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
7730u64
7731nfsd_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
7753u64
7754nfsd_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
7776static void
7777nfsd_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
7802u64
7803nfsd_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
7825u64
7826nfsd_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
7849/*7256/*
7850 * Since the lifetime of a delegation isn't limited to that of an open, a7257 * Since the lifetime of a delegation isn't limited to that of an open, a
7851 * client may quite reasonably hang on to a delegation as long as it has7258 * 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
1855nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,1855nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,
1856 struct nfsd4_copy_notify *cn)1856 struct nfsd4_copy_notify *cn)
1857{1857{
1858 int status;1858 __be32 status;
1859 1859
1860 status = nfsd4_decode_stateid(argp, &cn->cpn_src_stateid);1860 status = nfsd4_decode_stateid(argp, &cn->cpn_src_stateid);
1861 if (status)1861 if (status)
@@ -2173,7 +2173,7 @@ static const nfsd4_dec nfsd4_dec_ops[] = { · 311 unmodified lines
2173 [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,2173 [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,
2174 [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_offload_status,2174 [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_offload_status,
2175 [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_offload_status,2175 [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,
2177 [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek,2177 [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek,
2178 [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp,2178 [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp,
2179 [OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone,2179 [OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone,
@@ -2261,7 +2261,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) · 81 unmodified lines
2261 */2261 */
2262 cachethis |= nfsd4_cache_this_op(op);2262 cachethis |= nfsd4_cache_this_op(op);
2263 2263
2264 if (op->opnum == OP_READ) {2264 if (op->opnum == OP_READ || op->opnum == OP_READ_PLUS) {
2265 readcount++;2265 readcount++;
2266 readbytes += nfsd4_max_reply(argp->rqstp, op);2266 readbytes += nfsd4_max_reply(argp->rqstp, op);
2267 } else2267 } else
@@ -3814,36 +3814,14 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, · 1546 unmodified lines
3814{3814{
3815 struct xdr_stream *xdr = &resp->xdr;3815 struct xdr_stream *xdr = &resp->xdr;
3816 u32 eof;3816 u32 eof;
3817 int v;
3818 int starting_len = xdr->buf->len - 8;3817 int starting_len = xdr->buf->len - 8;
3819 long len;
3820 int thislen;
3821 __be32 nfserr;3818 __be32 nfserr;
3822 __be32 tmp;3819 __be32 tmp;
3823 __be32 *p;
3824 int pad;3820 int pad;
3825 3821
3826 /*3822 read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount);
3827 * svcrdma requires every READ payload to start somewhere3823 if (read->rd_vlen < 0)
3828 * in xdr->pages.3824 return nfserr_resource;
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;
3847 3825
3848 nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,3826 nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
3849 resp->rqstp->rq_vec, read->rd_vlen, &maxcount,3827 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
4619 return nfserr_resource;4597 return nfserr_resource;
4620 p = xdr_encode_hyper(p, os->count);4598 p = xdr_encode_hyper(p, os->count);
4621 *p++ = cpu_to_be32(0);4599 *p++ = cpu_to_be32(0);
4600 return nfserr;
4601}
4602
4603static __be32
4604nfsd4_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
4645static __be32
4646nfsd4_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
4676static __be32
4677nfsd4_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
4730out:
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 }
4622 4743
4623 return nfserr;4744 return nfserr;
4624}4745}
@@ -4679,7 +4800,7 @@ nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) · 54 unmodified lines
4679/*4800/*
4680 * Encode kmalloc-ed buffer in to XDR stream.4801 * Encode kmalloc-ed buffer in to XDR stream.
4681 */4802 */
4682static int4803static __be32
4683nfsd4_vbuf_to_stream(struct xdr_stream *xdr, char *buf, u32 buflen)4804nfsd4_vbuf_to_stream(struct xdr_stream *xdr, char *buf, u32 buflen)
4684{4805{
4685 u32 cplen;4806 u32 cplen;
@@ -4795,7 +4916,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 109 unmodified lines
4795 u32 xdrlen, offset;4916 u32 xdrlen, offset;
4796 u64 cookie;4917 u64 cookie;
4797 char *sp;4918 char *sp;
4798 __be32 status;4919 __be32 status, tmp;
4799 __be32 *p;4920 __be32 *p;
4800 u32 nuser;4921 u32 nuser;
4801 4922
@@ -4828,7 +4949,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 26 unmodified lines
4828 slen = strlen(sp);4949 slen = strlen(sp);
4829 4950
4830 /*4951 /*
4831 * Check if this a user. attribute, skip it if not.4952 * Check if this is a "user." attribute, skip it if not.
4832 */4953 */
4833 if (strncmp(sp, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))4954 if (strncmp(sp, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
4834 goto contloop;4955 goto contloop;
@@ -4859,7 +4980,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 24 unmodified lines
4859 goto out;4980 goto out;
4860 }4981 }
4861 4982
4862 p = xdr_encode_opaque(p, sp, slen);4983 xdr_encode_opaque(p, sp, slen);
4863 4984
4864 xdrleft -= xdrlen;4985 xdrleft -= xdrlen;
4865 count++;4986 count++;
@@ -4888,8 +5009,8 @@ wreof: · 22 unmodified lines
4888 cookie = offset + count;5009 cookie = offset + count;
4889 5010
4890 write_bytes_to_xdr_buf(xdr->buf, cookie_offset, &cookie, 8);5011 write_bytes_to_xdr_buf(xdr->buf, cookie_offset, &cookie, 8);
4891 count = htonl(count);5012 tmp = cpu_to_be32(count);
4892 write_bytes_to_xdr_buf(xdr->buf, count_offset, &count, 4);5013 write_bytes_to_xdr_buf(xdr->buf, count_offset, &tmp, 4);
4893out:5014out:
4894 if (listxattrs->lsxa_len)5015 if (listxattrs->lsxa_len)
4895 kvfree(listxattrs->lsxa_buf);5016 kvfree(listxattrs->lsxa_buf);
@@ -4996,7 +5117,7 @@ static const nfsd4_enc nfsd4_enc_ops[] = { · 100 unmodified lines
4996 [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop,5117 [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop,
4997 [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop,5118 [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop,
4998 [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_offload_status,5119 [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,
5000 [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek,5121 [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek,
5001 [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop,5122 [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop,
5002 [OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop,5123 [OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop,
@@ -5156,6 +5277,12 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp) · 153 unmodified lines
5156 }5277 }
5157}5278}
5158 5279
5280int
5281nfs4svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
5282{
5283 return 1;
5284}
5285
5159int5286int
5160nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)5287nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
5161{5288{
@@ -5183,15 +5310,14 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p) · 21 unmodified lines
5183int5310int
5184nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p)5311nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p)
5185{5312{
5186 /*
5187 * All that remains is to write the tag and operation count...
5188 */
5189 struct nfsd4_compoundres *resp = rqstp->rq_resp;5313 struct nfsd4_compoundres *resp = rqstp->rq_resp;
5190 struct xdr_buf *buf = resp->xdr.buf;5314 struct xdr_buf *buf = resp->xdr.buf;
5191 5315
5192 WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len +5316 WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len +
5193 buf->tail[0].iov_len);5317 buf->tail[0].iov_len);
5194 5318
5319 *p = resp->cstate.status;
5320
5195 rqstp->rq_next_page = resp->xdr.page_ptr + 1;5321 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
5196 5322
5197 p = resp->tagp;5323 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
172 if (status)172 if (status)
173 goto out_nomem;173 goto out_nomem;
174 174
175 nn->drc_hashtbl = kcalloc(hashsize,175 nn->drc_hashtbl = kvzalloc(array_size(hashsize,
176 sizeof(*nn->drc_hashtbl), GFP_KERNEL);176 sizeof(*nn->drc_hashtbl)), GFP_KERNEL);
177 if (!nn->drc_hashtbl) {177 if (!nn->drc_hashtbl)
178 nn->drc_hashtbl = vzalloc(array_size(hashsize,178 goto out_shrinker;
179 sizeof(*nn->drc_hashtbl)));
180 if (!nn->drc_hashtbl)
181 goto out_shrinker;
182 }
183 179
184 for (i = 0; i < hashsize; i++) {180 for (i = 0; i < hashsize; i++) {
185 INIT_LIST_HEAD(&nn->drc_hashtbl[i].lru_head);181 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
1534 retval = nfsd4_init_pnfs();1534 retval = nfsd4_init_pnfs();
1535 if (retval)1535 if (retval)
1536 goto out_free_slabs;1536 goto out_free_slabs;
1537 nfsd_fault_inject_init(); /* nfsd fault injection controls */
1538 nfsd_stat_init(); /* Statistics */1537 nfsd_stat_init(); /* Statistics */
1539 retval = nfsd_drc_slab_create();1538 retval = nfsd_drc_slab_create();
1540 if (retval)1539 if (retval)
@@ -1555,7 +1554,6 @@ out_free_lockd: · 14 unmodified lines
1555 nfsd_drc_slab_free();1554 nfsd_drc_slab_free();
1556out_free_stat:1555out_free_stat:
1557 nfsd_stat_shutdown();1556 nfsd_stat_shutdown();
1558 nfsd_fault_inject_cleanup();
1559 nfsd4_exit_pnfs();1557 nfsd4_exit_pnfs();
1560out_free_slabs:1558out_free_slabs:
1561 nfsd4_free_slabs();1559 nfsd4_free_slabs();
@@ -1575,7 +1573,6 @@ static void __exit exit_nfsd(void) · 13 unmodified lines
1575 nfsd_lockd_shutdown();1573 nfsd_lockd_shutdown();
1576 nfsd4_free_slabs();1574 nfsd4_free_slabs();
1577 nfsd4_exit_pnfs();1575 nfsd4_exit_pnfs();
1578 nfsd_fault_inject_cleanup();
1579 unregister_filesystem(&nfsd_fs_type);1576 unregister_filesystem(&nfsd_fs_type);
1580 unregister_cld_notifier();1577 unregister_cld_notifier();
1581 unregister_pernet_subsys(&nfsd_net_ops);1578 unregister_pernet_subsys(&nfsd_net_ops);
fs/nfsd/nfsproc.c+157−126
@@ -11,30 +11,14 @@ · 10 unmodified lines
11#include "xdr.h"11#include "xdr.h"
12#include "vfs.h"12#include "vfs.h"
13 13
14typedef struct svc_rqst svc_rqst;
15typedef struct svc_buf svc_buf;
16
17#define NFSDDBG_FACILITY NFSDDBG_PROC14#define NFSDDBG_FACILITY NFSDDBG_PROC
18 15
19
20static __be3216static __be32
21nfsd_proc_null(struct svc_rqst *rqstp)17nfsd_proc_null(struct svc_rqst *rqstp)
22{18{
23 return nfs_ok;19 return rpc_success;
24}20}
25 21
26static __be32
27nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
28{
29 if (err) return err;
30 return fh_getattr(&resp->fh, &resp->stat);
31}
32static __be32
33nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
34{
35 if (err) return err;
36 return fh_getattr(&resp->fh, &resp->stat);
37}
38/*22/*
39 * Get a file's attributes23 * Get a file's attributes
40 * N.B. After this call resp->fh needs an fh_put24 * 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
44{28{
45 struct nfsd_fhandle *argp = rqstp->rq_argp;29 struct nfsd_fhandle *argp = rqstp->rq_argp;
46 struct nfsd_attrstat *resp = rqstp->rq_resp;30 struct nfsd_attrstat *resp = rqstp->rq_resp;
47 __be32 nfserr;31
48 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));32 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
49 33
50 fh_copy(&resp->fh, &argp->fh);34 fh_copy(&resp->fh, &argp->fh);
51 nfserr = fh_verify(rqstp, &resp->fh, 0,35 resp->status = fh_verify(rqstp, &resp->fh, 0,
52 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);36 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
53 return nfsd_return_attrs(nfserr, resp);37 if (resp->status != nfs_ok)
38 goto out;
39 resp->status = fh_getattr(&resp->fh, &resp->stat);
40out:
41 return rpc_success;
54}42}
55 43
56/*44/*
@@ -64,7 +52,6 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 7 unmodified lines
64 struct nfsd_attrstat *resp = rqstp->rq_resp;52 struct nfsd_attrstat *resp = rqstp->rq_resp;
65 struct iattr *iap = &argp->attrs;53 struct iattr *iap = &argp->attrs;
66 struct svc_fh *fhp;54 struct svc_fh *fhp;
67 __be32 nfserr;
68 55
69 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",56 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
70 SVCFH_fmt(&argp->fh),57 SVCFH_fmt(&argp->fh),
@@ -96,9 +83,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 25 unmodified lines
96 */83 */
97 time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();84 time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();
98 85
99 nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);86 resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
100 if (nfserr)87 if (resp->status != nfs_ok)
101 goto done;88 goto out;
102 89
103 if (delta < 0)90 if (delta < 0)
104 delta = -delta;91 delta = -delta;
@@ -113,9 +100,20 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 8 unmodified lines
113 }100 }
114 }101 }
115 102
116 nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);103 resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
117done:104 if (resp->status != nfs_ok)
118 return nfsd_return_attrs(nfserr, resp);105 goto out;
106
107 resp->status = fh_getattr(&resp->fh, &resp->stat);
108out:
109 return rpc_success;
110}
111
112/* Obsolete, replaced by MNTPROC_MNT. */
113static __be32
114nfsd_proc_root(struct svc_rqst *rqstp)
115{
116 return rpc_success;
119}117}
120 118
121/*119/*
@@ -129,17 +127,20 @@ nfsd_proc_lookup(struct svc_rqst *rqstp) · 7 unmodified lines
129{127{
130 struct nfsd_diropargs *argp = rqstp->rq_argp;128 struct nfsd_diropargs *argp = rqstp->rq_argp;
131 struct nfsd_diropres *resp = rqstp->rq_resp;129 struct nfsd_diropres *resp = rqstp->rq_resp;
132 __be32 nfserr;
133 130
134 dprintk("nfsd: LOOKUP %s %.*s\n",131 dprintk("nfsd: LOOKUP %s %.*s\n",
135 SVCFH_fmt(&argp->fh), argp->len, argp->name);132 SVCFH_fmt(&argp->fh), argp->len, argp->name);
136 133
137 fh_init(&resp->fh, NFS_FHSIZE);134 fh_init(&resp->fh, NFS_FHSIZE);
138 nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,135 resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
139 &resp->fh);136 &resp->fh);
140
141 fh_put(&argp->fh);137 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);
142out:
143 return rpc_success;
143}144}
144 145
145/*146/*
@@ -150,16 +151,15 @@ nfsd_proc_readlink(struct svc_rqst *rqstp) · 4 unmodified lines
150{151{
151 struct nfsd_readlinkargs *argp = rqstp->rq_argp;152 struct nfsd_readlinkargs *argp = rqstp->rq_argp;
152 struct nfsd_readlinkres *resp = rqstp->rq_resp;153 struct nfsd_readlinkres *resp = rqstp->rq_resp;
153 __be32 nfserr;
154 154
155 dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));155 dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
156 156
157 /* Read the symlink. */157 /* Read the symlink. */
158 resp->len = NFS_MAXPATHLEN;158 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);
160 160
161 fh_put(&argp->fh);161 fh_put(&argp->fh);
162 return nfserr;162 return rpc_success;
163}163}
164 164
165/*165/*
@@ -171,7 +171,6 @@ nfsd_proc_read(struct svc_rqst *rqstp) · 5 unmodified lines
171{171{
172 struct nfsd_readargs *argp = rqstp->rq_argp;172 struct nfsd_readargs *argp = rqstp->rq_argp;
173 struct nfsd_readres *resp = rqstp->rq_resp;173 struct nfsd_readres *resp = rqstp->rq_resp;
174 __be32 nfserr;
175 u32 eof;174 u32 eof;
176 175
177 dprintk("nfsd: READ %s %d bytes at %d\n",176 dprintk("nfsd: READ %s %d bytes at %d\n",
@@ -193,14 +192,23 @@ nfsd_proc_read(struct svc_rqst *rqstp) · 15 unmodified lines
193 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);192 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
194 193
195 resp->count = argp->count;194 resp->count = argp->count;
196 nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),195 resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
197 argp->offset,196 argp->offset,
198 rqstp->rq_vec, argp->vlen,197 rqstp->rq_vec, argp->vlen,
199 &resp->count,198 &resp->count,
200 &eof);199 &eof);
201 200 if (resp->status == nfs_ok)
202 if (nfserr) return nfserr;201 resp->status = fh_getattr(&resp->fh, &resp->stat);
203 return 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 */
208static __be32
209nfsd_proc_writecache(struct svc_rqst *rqstp)
210{
211 return rpc_success;
204}212}
205 213
206/*214/*
@@ -212,7 +220,6 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 5 unmodified lines
212{220{
213 struct nfsd_writeargs *argp = rqstp->rq_argp;221 struct nfsd_writeargs *argp = rqstp->rq_argp;
214 struct nfsd_attrstat *resp = rqstp->rq_resp;222 struct nfsd_attrstat *resp = rqstp->rq_resp;
215 __be32 nfserr;
216 unsigned long cnt = argp->len;223 unsigned long cnt = argp->len;
217 unsigned int nvecs;224 unsigned int nvecs;
218 225
@@ -222,12 +229,20 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 3 unmodified lines
222 229
223 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,230 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
224 &argp->first, cnt);231 &argp->first, cnt);
225 if (!nvecs)232 if (!nvecs) {
226 return nfserr_io;233 resp->status = nfserr_io;
227 nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),234 goto out;
228 argp->offset, rqstp->rq_vec, nvecs,235 }
229 &cnt, NFS_DATA_SYNC, NULL);236
230 return nfsd_return_attrs(nfserr, resp);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;
244out:
245 return rpc_success;
231}246}
232 247
233/*248/*
@@ -247,7 +262,6 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 13 unmodified lines
247 struct inode *inode;262 struct inode *inode;
248 struct dentry *dchild;263 struct dentry *dchild;
249 int type, mode;264 int type, mode;
250 __be32 nfserr;
251 int hosterr;265 int hosterr;
252 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size);266 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size);
253 267
@@ -255,40 +269,40 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 1 unmodified line
255 SVCFH_fmt(dirfhp), argp->len, argp->name);269 SVCFH_fmt(dirfhp), argp->len, argp->name);
256 270
257 /* First verify the parent file handle */271 /* First verify the parent file handle */
258 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);272 resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
259 if (nfserr)273 if (resp->status != nfs_ok)
260 goto done; /* must fh_put dirfhp even on error */274 goto done; /* must fh_put dirfhp even on error */
261 275
262 /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */276 /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
263 277
264 nfserr = nfserr_exist;278 resp->status = nfserr_exist;
265 if (isdotent(argp->name, argp->len))279 if (isdotent(argp->name, argp->len))
266 goto done;280 goto done;
267 hosterr = fh_want_write(dirfhp);281 hosterr = fh_want_write(dirfhp);
268 if (hosterr) {282 if (hosterr) {
269 nfserr = nfserrno(hosterr);283 resp->status = nfserrno(hosterr);
270 goto done;284 goto done;
271 }285 }
272 286
273 fh_lock_nested(dirfhp, I_MUTEX_PARENT);287 fh_lock_nested(dirfhp, I_MUTEX_PARENT);
274 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);288 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
275 if (IS_ERR(dchild)) {289 if (IS_ERR(dchild)) {
276 nfserr = nfserrno(PTR_ERR(dchild));290 resp->status = nfserrno(PTR_ERR(dchild));
277 goto out_unlock;291 goto out_unlock;
278 }292 }
279 fh_init(newfhp, NFS_FHSIZE);293 fh_init(newfhp, NFS_FHSIZE);
280 nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);294 resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
281 if (!nfserr && d_really_is_negative(dchild))295 if (!resp->status && d_really_is_negative(dchild))
282 nfserr = nfserr_noent;296 resp->status = nfserr_noent;
283 dput(dchild);297 dput(dchild);
284 if (nfserr) {298 if (resp->status) {
285 if (nfserr != nfserr_noent)299 if (resp->status != nfserr_noent)
286 goto out_unlock;300 goto out_unlock;
287 /*301 /*
288 * If the new file handle wasn't verified, we can't tell302 * If the new file handle wasn't verified, we can't tell
289 * whether the file exists or not. Time to bail ...303 * whether the file exists or not. Time to bail ...
290 */304 */
291 nfserr = nfserr_acces;305 resp->status = nfserr_acces;
292 if (!newfhp->fh_dentry) {306 if (!newfhp->fh_dentry) {
293 printk(KERN_WARNING 307 printk(KERN_WARNING
294 "nfsd_proc_create: file handle not verified\n");308 "nfsd_proc_create: file handle not verified\n");
@@ -321,11 +335,11 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 26 unmodified lines
321 * echo thing > device-special-file-or-pipe335 * echo thing > device-special-file-or-pipe
322 * by doing a CREATE with type==0336 * by doing a CREATE with type==0
323 */337 */
324 nfserr = nfsd_permission(rqstp,338 resp->status = nfsd_permission(rqstp,
325 newfhp->fh_export,339 newfhp->fh_export,
326 newfhp->fh_dentry,340 newfhp->fh_dentry,
327 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);341 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
328 if (nfserr && nfserr != nfserr_rofs)342 if (resp->status && resp->status != nfserr_rofs)
329 goto out_unlock;343 goto out_unlock;
330 }344 }
331 } else345 } else
@@ -361,16 +375,17 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 29 unmodified lines
361 attr->ia_valid &= ~ATTR_SIZE;375 attr->ia_valid &= ~ATTR_SIZE;
362 376
363 /* Make sure the type and device matches */377 /* Make sure the type and device matches */
364 nfserr = nfserr_exist;378 resp->status = nfserr_exist;
365 if (inode && type != (inode->i_mode & S_IFMT))379 if (inode && type != (inode->i_mode & S_IFMT))
366 goto out_unlock;380 goto out_unlock;
367 }381 }
368 382
369 nfserr = 0;383 resp->status = nfs_ok;
370 if (!inode) {384 if (!inode) {
371 /* File doesn't exist. Create it and set attrs */385 /* File doesn't exist. Create it and set attrs */
372 nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name,386 resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
373 argp->len, attr, type, rdev, newfhp);387 argp->len, attr, type, rdev,
388 newfhp);
374 } else if (type == S_IFREG) {389 } else if (type == S_IFREG) {
375 dprintk("nfsd: existing %s, valid=%x, size=%ld\n",390 dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
376 argp->name, attr->ia_valid, (long) attr->ia_size);391 argp->name, attr->ia_valid, (long) attr->ia_size);
@@ -380,7 +395,8 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 3 unmodified lines
380 */395 */
381 attr->ia_valid &= ATTR_SIZE;396 attr->ia_valid &= ATTR_SIZE;
382 if (attr->ia_valid)397 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);
384 }400 }
385 401
386out_unlock:402out_unlock:
@@ -389,47 +405,52 @@ out_unlock: · 2 unmodified lines
389 fh_drop_write(dirfhp);405 fh_drop_write(dirfhp);
390done:406done:
391 fh_put(dirfhp);407 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);
411out:
412 return rpc_success;
393}413}
394 414
395static __be32415static __be32
396nfsd_proc_remove(struct svc_rqst *rqstp)416nfsd_proc_remove(struct svc_rqst *rqstp)
397{417{
398 struct nfsd_diropargs *argp = rqstp->rq_argp;418 struct nfsd_diropargs *argp = rqstp->rq_argp;
399 __be32 nfserr;419 struct nfsd_stat *resp = rqstp->rq_resp;
400 420
401 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh),421 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh),
402 argp->len, argp->name);422 argp->len, argp->name);
403 423
404 /* Unlink. -SIFDIR means file must not be a directory */424 /* 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);
406 fh_put(&argp->fh);427 fh_put(&argp->fh);
407 return nfserr;428 return rpc_success;
408}429}
409 430
410static __be32431static __be32
411nfsd_proc_rename(struct svc_rqst *rqstp)432nfsd_proc_rename(struct svc_rqst *rqstp)
412{433{
413 struct nfsd_renameargs *argp = rqstp->rq_argp;434 struct nfsd_renameargs *argp = rqstp->rq_argp;
414 __be32 nfserr;435 struct nfsd_stat *resp = rqstp->rq_resp;
415 436
416 dprintk("nfsd: RENAME %s %.*s -> \n",437 dprintk("nfsd: RENAME %s %.*s -> \n",
417 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);438 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
418 dprintk("nfsd: -> %s %.*s\n",439 dprintk("nfsd: -> %s %.*s\n",
419 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);440 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
420 441
421 nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,442 resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
422 &argp->tfh, argp->tname, argp->tlen);443 &argp->tfh, argp->tname, argp->tlen);
423 fh_put(&argp->ffh);444 fh_put(&argp->ffh);
424 fh_put(&argp->tfh);445 fh_put(&argp->tfh);
425 return nfserr;446 return rpc_success;
426}447}
427 448
428static __be32449static __be32
429nfsd_proc_link(struct svc_rqst *rqstp)450nfsd_proc_link(struct svc_rqst *rqstp)
430{451{
431 struct nfsd_linkargs *argp = rqstp->rq_argp;452 struct nfsd_linkargs *argp = rqstp->rq_argp;
432 __be32 nfserr;453 struct nfsd_stat *resp = rqstp->rq_resp;
433 454
434 dprintk("nfsd: LINK %s ->\n",455 dprintk("nfsd: LINK %s ->\n",
435 SVCFH_fmt(&argp->ffh));456 SVCFH_fmt(&argp->ffh));
@@ -438,41 +459,46 @@ nfsd_proc_link(struct svc_rqst *rqstp) · 2 unmodified lines
438 argp->tlen,459 argp->tlen,
439 argp->tname);460 argp->tname);
440 461
441 nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,462 resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
442 &argp->ffh);463 &argp->ffh);
443 fh_put(&argp->ffh);464 fh_put(&argp->ffh);
444 fh_put(&argp->tfh);465 fh_put(&argp->tfh);
445 return nfserr;466 return rpc_success;
446}467}
447 468
448static __be32469static __be32
449nfsd_proc_symlink(struct svc_rqst *rqstp)470nfsd_proc_symlink(struct svc_rqst *rqstp)
450{471{
451 struct nfsd_symlinkargs *argp = rqstp->rq_argp;472 struct nfsd_symlinkargs *argp = rqstp->rq_argp;
473 struct nfsd_stat *resp = rqstp->rq_resp;
452 struct svc_fh newfh;474 struct svc_fh newfh;
453 __be32 nfserr;
454 475
455 if (argp->tlen > NFS_MAXPATHLEN)476 if (argp->tlen > NFS_MAXPATHLEN) {
456 return nfserr_nametoolong;477 resp->status = nfserr_nametoolong;
478 goto out;
479 }
457 480
458 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,481 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
459 page_address(rqstp->rq_arg.pages[0]),482 page_address(rqstp->rq_arg.pages[0]),
460 argp->tlen);483 argp->tlen);
461 if (IS_ERR(argp->tname))484 if (IS_ERR(argp->tname)) {
462 return nfserrno(PTR_ERR(argp->tname));485 resp->status = nfserrno(PTR_ERR(argp->tname));
486 goto out;
487 }
463 488
464 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n",489 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n",
465 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,490 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
466 argp->tlen, argp->tname);491 argp->tlen, argp->tname);
467 492
468 fh_init(&newfh, NFS_FHSIZE);493 fh_init(&newfh, NFS_FHSIZE);
469 nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,494 resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
470 argp->tname, &newfh);495 argp->tname, &newfh);
471 496
472 kfree(argp->tname);497 kfree(argp->tname);
473 fh_put(&argp->ffh);498 fh_put(&argp->ffh);
474 fh_put(&newfh);499 fh_put(&newfh);
475 return nfserr;500out:
501 return rpc_success;
476}502}
477 503
478/*504/*
@@ -484,7 +510,6 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp) · 5 unmodified lines
484{510{
485 struct nfsd_createargs *argp = rqstp->rq_argp;511 struct nfsd_createargs *argp = rqstp->rq_argp;
486 struct nfsd_diropres *resp = rqstp->rq_resp;512 struct nfsd_diropres *resp = rqstp->rq_resp;
487 __be32 nfserr;
488 513
489 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);514 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
490 515
@@ -495,10 +520,15 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp) · 4 unmodified lines
495 520
496 argp->attrs.ia_valid &= ~ATTR_SIZE;521 argp->attrs.ia_valid &= ~ATTR_SIZE;
497 fh_init(&resp->fh, NFS_FHSIZE);522 fh_init(&resp->fh, NFS_FHSIZE);
498 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,523 resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
499 &argp->attrs, S_IFDIR, 0, &resp->fh);524 &argp->attrs, S_IFDIR, 0, &resp->fh);
500 fh_put(&argp->fh);525 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);
530out:
531 return rpc_success;
502}532}
503 533
504/*534/*
@@ -508,13 +538,14 @@ static __be32 · 3 unmodified lines
508nfsd_proc_rmdir(struct svc_rqst *rqstp)538nfsd_proc_rmdir(struct svc_rqst *rqstp)
509{539{
510 struct nfsd_diropargs *argp = rqstp->rq_argp;540 struct nfsd_diropargs *argp = rqstp->rq_argp;
511 __be32 nfserr;541 struct nfsd_stat *resp = rqstp->rq_resp;
512 542
513 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);543 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
514 544
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);
516 fh_put(&argp->fh);547 fh_put(&argp->fh);
517 return nfserr;548 return rpc_success;
518}549}
519 550
520/*551/*
@@ -526,7 +557,6 @@ nfsd_proc_readdir(struct svc_rqst *rqstp) · 5 unmodified lines
526 struct nfsd_readdirargs *argp = rqstp->rq_argp;557 struct nfsd_readdirargs *argp = rqstp->rq_argp;
527 struct nfsd_readdirres *resp = rqstp->rq_resp;558 struct nfsd_readdirres *resp = rqstp->rq_resp;
528 int count;559 int count;
529 __be32 nfserr;
530 loff_t offset;560 loff_t offset;
531 561
532 dprintk("nfsd: READDIR %s %d bytes at %d\n",562 dprintk("nfsd: READDIR %s %d bytes at %d\n",
@@ -547,15 +577,15 @@ nfsd_proc_readdir(struct svc_rqst *rqstp) · 14 unmodified lines
547 resp->common.err = nfs_ok;577 resp->common.err = nfs_ok;
548 /* Read directory and encode entries on the fly */578 /* Read directory and encode entries on the fly */
549 offset = argp->cookie;579 offset = argp->cookie;
550 nfserr = nfsd_readdir(rqstp, &argp->fh, &offset, 580 resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
551 &resp->common, nfssvc_encode_entry);581 &resp->common, nfssvc_encode_entry);
552 582
553 resp->count = resp->buffer - argp->buffer;583 resp->count = resp->buffer - argp->buffer;
554 if (resp->offset)584 if (resp->offset)
555 *resp->offset = htonl(offset);585 *resp->offset = htonl(offset);
556 586
557 fh_put(&argp->fh);587 fh_put(&argp->fh);
558 return nfserr;588 return rpc_success;
559}589}
560 590
561/*591/*
@@ -566,14 +596,13 @@ nfsd_proc_statfs(struct svc_rqst *rqstp) · 4 unmodified lines
566{596{
567 struct nfsd_fhandle *argp = rqstp->rq_argp;597 struct nfsd_fhandle *argp = rqstp->rq_argp;
568 struct nfsd_statfsres *resp = rqstp->rq_resp;598 struct nfsd_statfsres *resp = rqstp->rq_resp;
569 __be32 nfserr;
570 599
571 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));600 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
572 601
573 nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,602 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
574 NFSD_MAY_BYPASS_GSS_ON_ROOT);603 NFSD_MAY_BYPASS_GSS_ON_ROOT);
575 fh_put(&argp->fh);604 fh_put(&argp->fh);
576 return nfserr;605 return rpc_success;
577}606}
578 607
579/*608/*
@@ -594,13 +623,13 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 14 unmodified lines
594 .pc_argsize = sizeof(struct nfsd_void),623 .pc_argsize = sizeof(struct nfsd_void),
595 .pc_ressize = sizeof(struct nfsd_void),624 .pc_ressize = sizeof(struct nfsd_void),
596 .pc_cachetype = RC_NOCACHE,625 .pc_cachetype = RC_NOCACHE,
597 .pc_xdrressize = ST,626 .pc_xdrressize = 0,
598 },627 },
599 [NFSPROC_GETATTR] = {628 [NFSPROC_GETATTR] = {
600 .pc_func = nfsd_proc_getattr,629 .pc_func = nfsd_proc_getattr,
601 .pc_decode = nfssvc_decode_fhandle,630 .pc_decode = nfssvc_decode_fhandle,
602 .pc_encode = nfssvc_encode_attrstat,631 .pc_encode = nfssvc_encode_attrstat,
603 .pc_release = nfssvc_release_fhandle,632 .pc_release = nfssvc_release_attrstat,
604 .pc_argsize = sizeof(struct nfsd_fhandle),633 .pc_argsize = sizeof(struct nfsd_fhandle),
605 .pc_ressize = sizeof(struct nfsd_attrstat),634 .pc_ressize = sizeof(struct nfsd_attrstat),
606 .pc_cachetype = RC_NOCACHE,635 .pc_cachetype = RC_NOCACHE,
@@ -610,25 +639,26 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 3 unmodified lines
610 .pc_func = nfsd_proc_setattr,639 .pc_func = nfsd_proc_setattr,
611 .pc_decode = nfssvc_decode_sattrargs,640 .pc_decode = nfssvc_decode_sattrargs,
612 .pc_encode = nfssvc_encode_attrstat,641 .pc_encode = nfssvc_encode_attrstat,
613 .pc_release = nfssvc_release_fhandle,642 .pc_release = nfssvc_release_attrstat,
614 .pc_argsize = sizeof(struct nfsd_sattrargs),643 .pc_argsize = sizeof(struct nfsd_sattrargs),
615 .pc_ressize = sizeof(struct nfsd_attrstat),644 .pc_ressize = sizeof(struct nfsd_attrstat),
616 .pc_cachetype = RC_REPLBUFF,645 .pc_cachetype = RC_REPLBUFF,
617 .pc_xdrressize = ST+AT,646 .pc_xdrressize = ST+AT,
618 },647 },
619 [NFSPROC_ROOT] = {648 [NFSPROC_ROOT] = {
649 .pc_func = nfsd_proc_root,
620 .pc_decode = nfssvc_decode_void,650 .pc_decode = nfssvc_decode_void,
621 .pc_encode = nfssvc_encode_void,651 .pc_encode = nfssvc_encode_void,
622 .pc_argsize = sizeof(struct nfsd_void),652 .pc_argsize = sizeof(struct nfsd_void),
623 .pc_ressize = sizeof(struct nfsd_void),653 .pc_ressize = sizeof(struct nfsd_void),
624 .pc_cachetype = RC_NOCACHE,654 .pc_cachetype = RC_NOCACHE,
625 .pc_xdrressize = ST,655 .pc_xdrressize = 0,
626 },656 },
627 [NFSPROC_LOOKUP] = {657 [NFSPROC_LOOKUP] = {
628 .pc_func = nfsd_proc_lookup,658 .pc_func = nfsd_proc_lookup,
629 .pc_decode = nfssvc_decode_diropargs,659 .pc_decode = nfssvc_decode_diropargs,
630 .pc_encode = nfssvc_encode_diropres,660 .pc_encode = nfssvc_encode_diropres,
631 .pc_release = nfssvc_release_fhandle,661 .pc_release = nfssvc_release_diropres,
632 .pc_argsize = sizeof(struct nfsd_diropargs),662 .pc_argsize = sizeof(struct nfsd_diropargs),
633 .pc_ressize = sizeof(struct nfsd_diropres),663 .pc_ressize = sizeof(struct nfsd_diropres),
634 .pc_cachetype = RC_NOCACHE,664 .pc_cachetype = RC_NOCACHE,
@@ -647,25 +677,26 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 12 unmodified lines
647 .pc_func = nfsd_proc_read,677 .pc_func = nfsd_proc_read,
648 .pc_decode = nfssvc_decode_readargs,678 .pc_decode = nfssvc_decode_readargs,
649 .pc_encode = nfssvc_encode_readres,679 .pc_encode = nfssvc_encode_readres,
650 .pc_release = nfssvc_release_fhandle,680 .pc_release = nfssvc_release_readres,
651 .pc_argsize = sizeof(struct nfsd_readargs),681 .pc_argsize = sizeof(struct nfsd_readargs),
652 .pc_ressize = sizeof(struct nfsd_readres),682 .pc_ressize = sizeof(struct nfsd_readres),
653 .pc_cachetype = RC_NOCACHE,683 .pc_cachetype = RC_NOCACHE,
654 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,684 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
655 },685 },
656 [NFSPROC_WRITECACHE] = {686 [NFSPROC_WRITECACHE] = {
687 .pc_func = nfsd_proc_writecache,
657 .pc_decode = nfssvc_decode_void,688 .pc_decode = nfssvc_decode_void,
658 .pc_encode = nfssvc_encode_void,689 .pc_encode = nfssvc_encode_void,
659 .pc_argsize = sizeof(struct nfsd_void),690 .pc_argsize = sizeof(struct nfsd_void),
660 .pc_ressize = sizeof(struct nfsd_void),691 .pc_ressize = sizeof(struct nfsd_void),
661 .pc_cachetype = RC_NOCACHE,692 .pc_cachetype = RC_NOCACHE,
662 .pc_xdrressize = ST,693 .pc_xdrressize = 0,
663 },694 },
664 [NFSPROC_WRITE] = {695 [NFSPROC_WRITE] = {
665 .pc_func = nfsd_proc_write,696 .pc_func = nfsd_proc_write,
666 .pc_decode = nfssvc_decode_writeargs,697 .pc_decode = nfssvc_decode_writeargs,
667 .pc_encode = nfssvc_encode_attrstat,698 .pc_encode = nfssvc_encode_attrstat,
668 .pc_release = nfssvc_release_fhandle,699 .pc_release = nfssvc_release_attrstat,
669 .pc_argsize = sizeof(struct nfsd_writeargs),700 .pc_argsize = sizeof(struct nfsd_writeargs),
670 .pc_ressize = sizeof(struct nfsd_attrstat),701 .pc_ressize = sizeof(struct nfsd_attrstat),
671 .pc_cachetype = RC_REPLBUFF,702 .pc_cachetype = RC_REPLBUFF,
@@ -675,7 +706,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 3 unmodified lines
675 .pc_func = nfsd_proc_create,706 .pc_func = nfsd_proc_create,
676 .pc_decode = nfssvc_decode_createargs,707 .pc_decode = nfssvc_decode_createargs,
677 .pc_encode = nfssvc_encode_diropres,708 .pc_encode = nfssvc_encode_diropres,
678 .pc_release = nfssvc_release_fhandle,709 .pc_release = nfssvc_release_diropres,
679 .pc_argsize = sizeof(struct nfsd_createargs),710 .pc_argsize = sizeof(struct nfsd_createargs),
680 .pc_ressize = sizeof(struct nfsd_diropres),711 .pc_ressize = sizeof(struct nfsd_diropres),
681 .pc_cachetype = RC_REPLBUFF,712 .pc_cachetype = RC_REPLBUFF,
@@ -684,36 +715,36 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 2 unmodified lines
684 [NFSPROC_REMOVE] = {715 [NFSPROC_REMOVE] = {
685 .pc_func = nfsd_proc_remove,716 .pc_func = nfsd_proc_remove,
686 .pc_decode = nfssvc_decode_diropargs,717 .pc_decode = nfssvc_decode_diropargs,
687 .pc_encode = nfssvc_encode_void,718 .pc_encode = nfssvc_encode_stat,
688 .pc_argsize = sizeof(struct nfsd_diropargs),719 .pc_argsize = sizeof(struct nfsd_diropargs),
689 .pc_ressize = sizeof(struct nfsd_void),720 .pc_ressize = sizeof(struct nfsd_stat),
690 .pc_cachetype = RC_REPLSTAT,721 .pc_cachetype = RC_REPLSTAT,
691 .pc_xdrressize = ST,722 .pc_xdrressize = ST,
692 },723 },
693 [NFSPROC_RENAME] = {724 [NFSPROC_RENAME] = {
694 .pc_func = nfsd_proc_rename,725 .pc_func = nfsd_proc_rename,
695 .pc_decode = nfssvc_decode_renameargs,726 .pc_decode = nfssvc_decode_renameargs,
696 .pc_encode = nfssvc_encode_void,727 .pc_encode = nfssvc_encode_stat,
697 .pc_argsize = sizeof(struct nfsd_renameargs),728 .pc_argsize = sizeof(struct nfsd_renameargs),
698 .pc_ressize = sizeof(struct nfsd_void),729 .pc_ressize = sizeof(struct nfsd_stat),
699 .pc_cachetype = RC_REPLSTAT,730 .pc_cachetype = RC_REPLSTAT,
700 .pc_xdrressize = ST,731 .pc_xdrressize = ST,
701 },732 },
702 [NFSPROC_LINK] = {733 [NFSPROC_LINK] = {
703 .pc_func = nfsd_proc_link,734 .pc_func = nfsd_proc_link,
704 .pc_decode = nfssvc_decode_linkargs,735 .pc_decode = nfssvc_decode_linkargs,
705 .pc_encode = nfssvc_encode_void,736 .pc_encode = nfssvc_encode_stat,
706 .pc_argsize = sizeof(struct nfsd_linkargs),737 .pc_argsize = sizeof(struct nfsd_linkargs),
707 .pc_ressize = sizeof(struct nfsd_void),738 .pc_ressize = sizeof(struct nfsd_stat),
708 .pc_cachetype = RC_REPLSTAT,739 .pc_cachetype = RC_REPLSTAT,
709 .pc_xdrressize = ST,740 .pc_xdrressize = ST,
710 },741 },
711 [NFSPROC_SYMLINK] = {742 [NFSPROC_SYMLINK] = {
712 .pc_func = nfsd_proc_symlink,743 .pc_func = nfsd_proc_symlink,
713 .pc_decode = nfssvc_decode_symlinkargs,744 .pc_decode = nfssvc_decode_symlinkargs,
714 .pc_encode = nfssvc_encode_void,745 .pc_encode = nfssvc_encode_stat,
715 .pc_argsize = sizeof(struct nfsd_symlinkargs),746 .pc_argsize = sizeof(struct nfsd_symlinkargs),
716 .pc_ressize = sizeof(struct nfsd_void),747 .pc_ressize = sizeof(struct nfsd_stat),
717 .pc_cachetype = RC_REPLSTAT,748 .pc_cachetype = RC_REPLSTAT,
718 .pc_xdrressize = ST,749 .pc_xdrressize = ST,
719 },750 },
@@ -721,7 +752,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 1 unmodified line
721 .pc_func = nfsd_proc_mkdir,752 .pc_func = nfsd_proc_mkdir,
722 .pc_decode = nfssvc_decode_createargs,753 .pc_decode = nfssvc_decode_createargs,
723 .pc_encode = nfssvc_encode_diropres,754 .pc_encode = nfssvc_encode_diropres,
724 .pc_release = nfssvc_release_fhandle,755 .pc_release = nfssvc_release_diropres,
725 .pc_argsize = sizeof(struct nfsd_createargs),756 .pc_argsize = sizeof(struct nfsd_createargs),
726 .pc_ressize = sizeof(struct nfsd_diropres),757 .pc_ressize = sizeof(struct nfsd_diropres),
727 .pc_cachetype = RC_REPLBUFF,758 .pc_cachetype = RC_REPLBUFF,
@@ -730,9 +761,9 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 2 unmodified lines
730 [NFSPROC_RMDIR] = {761 [NFSPROC_RMDIR] = {
731 .pc_func = nfsd_proc_rmdir,762 .pc_func = nfsd_proc_rmdir,
732 .pc_decode = nfssvc_decode_diropargs,763 .pc_decode = nfssvc_decode_diropargs,
733 .pc_encode = nfssvc_encode_void,764 .pc_encode = nfssvc_encode_stat,
734 .pc_argsize = sizeof(struct nfsd_diropargs),765 .pc_argsize = sizeof(struct nfsd_diropargs),
735 .pc_ressize = sizeof(struct nfsd_void),766 .pc_ressize = sizeof(struct nfsd_stat),
736 .pc_cachetype = RC_REPLSTAT,767 .pc_cachetype = RC_REPLSTAT,
737 .pc_xdrressize = ST,768 .pc_xdrressize = ST,
738 },769 },
fs/nfsd/nfssvc.c+59−63
@@ -960,15 +960,6 @@ out: · 959 unmodified lines
960 return 0;960 return 0;
961}961}
962 962
963static __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
972/*963/*
973 * A write procedure can have a large argument, and a read procedure can964 * A write procedure can have a large argument, and a read procedure can
974 * have a large reply, but no NFSv2 or NFSv3 procedure has argument and965 * 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
1000 return rqstp->rq_arg.len > PAGE_SIZE;991 return rqstp->rq_arg.len > PAGE_SIZE;
1001}992}
1002 993
1003int994/**
1004nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)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 */
1005int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
1005{1006{
1006 const struct svc_procedure *proc;1007 const struct svc_procedure *proc = rqstp->rq_procinfo;
1007 __be32 nfserr;1008 struct kvec *argv = &rqstp->rq_arg.head[0];
1008 __be32 *nfserrp;1009 struct kvec *resv = &rqstp->rq_res.head[0];
1010 __be32 *p;
1009 1011
1010 dprintk("nfsd_dispatch: vers %d proc %d\n",1012 dprintk("nfsd_dispatch: vers %d proc %d\n",
1011 rqstp->rq_vers, rqstp->rq_proc);1013 rqstp->rq_vers, rqstp->rq_proc);
1012 proc = rqstp->rq_procinfo;
1013 1014
1014 if (nfs_request_too_big(rqstp, proc)) {1015 if (nfs_request_too_big(rqstp, proc))
1015 dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);1016 goto out_too_large;
1016 *statp = rpc_garbage_args;1017
1017 return 1;
1018 }
1019 rqstp->rq_lease_breaker = NULL;
1020 /*1018 /*
1021 * Give the xdr decoder a chance to change this if it wants1019 * Give the xdr decoder a chance to change this if it wants
1022 * (necessary in the NFSv4.0 compound case)1020 * (necessary in the NFSv4.0 compound case)
1023 */1021 */
1024 rqstp->rq_cachetype = proc->pc_cachetype;1022 rqstp->rq_cachetype = proc->pc_cachetype;
1025 /* Decode arguments */1023 if (!proc->pc_decode(rqstp, argv->iov_base))
1026 if (proc->pc_decode &&1024 goto out_decode_err;
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 }
1032 1025
1033 /* Check whether we have this call in the cache. */
1034 switch (nfsd_cache_lookup(rqstp)) {1026 switch (nfsd_cache_lookup(rqstp)) {
1035 case RC_DROPIT:1027 case RC_DOIT:
1036 return 0;1028 break;
1037 case RC_REPLY:1029 case RC_REPLY:
1038 return 1;1030 goto out_cached_reply;
1039 case RC_DOIT:;1031 case RC_DROPIT:
1040 /* do it */1032 goto out_dropit;
1041 }1033 }
1042 1034
1043 /* need to grab the location to store the status, as1035 /*
1044 * nfsv4 does some encoding while processing 1036 * Need to grab the location to store the status, as
1037 * NFSv4 does some encoding while processing
1045 */1038 */
1046 nfserrp = rqstp->rq_res.head[0].iov_base1039 p = resv->iov_base + resv->iov_len;
1047 + rqstp->rq_res.head[0].iov_len;1040 resv->iov_len += sizeof(__be32);
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 }
1058 1041
1059 if (rqstp->rq_proc != 0)1042 *statp = proc->pc_func(rqstp);
1060 *nfserrp++ = nfserr;1043 if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
1044 goto out_update_drop;
1061 1045
1062 /* Encode result.1046 if (!proc->pc_encode(rqstp, p))
1063 * For NFSv2, additional info is never returned in case of an error.1047 goto out_encode_err;
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 }
1074 1048
1075 /* Store reply in cache. */
1076 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);1049 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
1050out_cached_reply:
1051 return 1;
1052
1053out_too_large:
1054 dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
1055 *statp = rpc_garbage_args;
1056 return 1;
1057
1058out_decode_err:
1059 dprintk("nfsd: failed to decode arguments!\n");
1060 *statp = rpc_garbage_args;
1061 return 1;
1062
1063out_update_drop:
1064 dprintk("nfsd: Dropping request; may be revisited later\n");
1065 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
1066out_dropit:
1067 return 0;
1068
1069out_encode_err:
1070 dprintk("nfsd: failed to encode result!\n");
1071 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
1072 *statp = rpc_system_err;
1077 return 1;1073 return 1;
1078}1074}
1079 1075
fs/nfsd/nfsxdr.c+49−3
@@ -429,12 +429,25 @@ nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p) · 428 unmodified lines
429 return xdr_ressize_check(rqstp, p);429 return xdr_ressize_check(rqstp, p);
430}430}
431 431
432int
433nfssvc_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
432int441int
433nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)442nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
434{443{
435 struct nfsd_attrstat *resp = rqstp->rq_resp;444 struct nfsd_attrstat *resp = rqstp->rq_resp;
436 445
446 *p++ = resp->status;
447 if (resp->status != nfs_ok)
448 goto out;
437 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);449 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
450out:
438 return xdr_ressize_check(rqstp, p);451 return xdr_ressize_check(rqstp, p);
439}452}
440 453
@@ -443,8 +456,12 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p) · 2 unmodified lines
443{456{
444 struct nfsd_diropres *resp = rqstp->rq_resp;457 struct nfsd_diropres *resp = rqstp->rq_resp;
445 458
459 *p++ = resp->status;
460 if (resp->status != nfs_ok)
461 goto out;
446 p = encode_fh(p, &resp->fh);462 p = encode_fh(p, &resp->fh);
447 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);463 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
464out:
448 return xdr_ressize_check(rqstp, p);465 return xdr_ressize_check(rqstp, p);
449}466}
450 467
@@ -453,6 +470,10 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) · 2 unmodified lines
453{470{
454 struct nfsd_readlinkres *resp = rqstp->rq_resp;471 struct nfsd_readlinkres *resp = rqstp->rq_resp;
455 472
473 *p++ = resp->status;
474 if (resp->status != nfs_ok)
475 return xdr_ressize_check(rqstp, p);
476
456 *p++ = htonl(resp->len);477 *p++ = htonl(resp->len);
457 xdr_ressize_check(rqstp, p);478 xdr_ressize_check(rqstp, p);
458 rqstp->rq_res.page_len = resp->len;479 rqstp->rq_res.page_len = resp->len;
@@ -470,6 +491,10 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p) · 11 unmodified lines
470{491{
471 struct nfsd_readres *resp = rqstp->rq_resp;492 struct nfsd_readres *resp = rqstp->rq_resp;
472 493
494 *p++ = resp->status;
495 if (resp->status != nfs_ok)
496 return xdr_ressize_check(rqstp, p);
497
473 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);498 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
474 *p++ = htonl(resp->count);499 *p++ = htonl(resp->count);
475 xdr_ressize_check(rqstp, p);500 xdr_ressize_check(rqstp, p);
@@ -490,6 +515,10 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) · 14 unmodified lines
490{515{
491 struct nfsd_readdirres *resp = rqstp->rq_resp;516 struct nfsd_readdirres *resp = rqstp->rq_resp;
492 517
518 *p++ = resp->status;
519 if (resp->status != nfs_ok)
520 return xdr_ressize_check(rqstp, p);
521
493 xdr_ressize_check(rqstp, p);522 xdr_ressize_check(rqstp, p);
494 p = resp->buffer;523 p = resp->buffer;
495 *p++ = 0; /* no more entries */524 *p++ = 0; /* no more entries */
@@ -505,6 +534,10 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p) · 9 unmodified lines
505 struct nfsd_statfsres *resp = rqstp->rq_resp;534 struct nfsd_statfsres *resp = rqstp->rq_resp;
506 struct kstatfs *stat = &resp->stats;535 struct kstatfs *stat = &resp->stats;
507 536
537 *p++ = resp->status;
538 if (resp->status != nfs_ok)
539 return xdr_ressize_check(rqstp, p);
540
508 *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */541 *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */
509 *p++ = htonl(stat->f_bsize);542 *p++ = htonl(stat->f_bsize);
510 *p++ = htonl(stat->f_blocks);543 *p++ = htonl(stat->f_blocks);
@@ -561,10 +594,23 @@ nfssvc_encode_entry(void *ccdv, const char *name, · 50 unmodified lines
561/*594/*
562 * XDR release functions595 * XDR release functions
563 */596 */
564void597void nfssvc_release_attrstat(struct svc_rqst *rqstp)
565nfssvc_release_fhandle(struct svc_rqst *rqstp)
566{598{
567 struct nfsd_fhandle *resp = rqstp->rq_resp;599 struct nfsd_attrstat *resp = rqstp->rq_resp;
600
601 fh_put(&resp->fh);
602}
603
604void nfssvc_release_diropres(struct svc_rqst *rqstp)
605{
606 struct nfsd_diropres *resp = rqstp->rq_resp;
607
608 fh_put(&resp->fh);
609}
610
611void nfssvc_release_readres(struct svc_rqst *rqstp)
612{
613 struct nfsd_readres *resp = rqstp->rq_resp;
568 614
569 fh_put(&resp->fh);615 fh_put(&resp->fh);
570}616}
fs/nfsd/state.h+0−27
@@ -693,31 +693,4 @@ extern void nfsd4_client_record_remove(struct nfs4_client *clp); · 692 unmodified lines
693extern int nfsd4_client_record_check(struct nfs4_client *clp);693extern int nfsd4_client_record_check(struct nfs4_client *clp);
694extern void nfsd4_record_grace_done(struct nfsd_net *nn);694extern void nfsd4_record_grace_done(struct nfsd_net *nn);
695 695
696/* nfs fault injection functions */
697#ifdef CONFIG_NFSD_FAULT_INJECTION
698void nfsd_fault_inject_init(void);
699void nfsd_fault_inject_cleanup(void);
700
701u64 nfsd_inject_print_clients(void);
702u64 nfsd_inject_forget_client(struct sockaddr_storage *, size_t);
703u64 nfsd_inject_forget_clients(u64);
704
705u64 nfsd_inject_print_locks(void);
706u64 nfsd_inject_forget_client_locks(struct sockaddr_storage *, size_t);
707u64 nfsd_inject_forget_locks(u64);
708
709u64 nfsd_inject_print_openowners(void);
710u64 nfsd_inject_forget_client_openowners(struct sockaddr_storage *, size_t);
711u64 nfsd_inject_forget_openowners(u64);
712
713u64 nfsd_inject_print_delegations(void);
714u64 nfsd_inject_forget_client_delegations(struct sockaddr_storage *, size_t);
715u64 nfsd_inject_forget_delegations(u64);
716u64 nfsd_inject_recall_client_delegations(struct sockaddr_storage *, size_t);
717u64 nfsd_inject_recall_delegations(u64);
718#else /* CONFIG_NFSD_FAULT_INJECTION */
719static inline void nfsd_fault_inject_init(void) {}
720static inline void nfsd_fault_inject_cleanup(void) {}
721#endif /* CONFIG_NFSD_FAULT_INJECTION */
722
723#endif /* NFSD4_STATE_H */696#endif /* NFSD4_STATE_H */
fs/nfsd/trace.h+2−2
@@ -289,8 +289,8 @@ DEFINE_STATEID_EVENT(layout_recall_done); · 288 unmodified lines
289DEFINE_STATEID_EVENT(layout_recall_fail);289DEFINE_STATEID_EVENT(layout_recall_fail);
290DEFINE_STATEID_EVENT(layout_recall_release);290DEFINE_STATEID_EVENT(layout_recall_release);
291 291
292DEFINE_STATEID_EVENT(deleg_open);292DEFINE_STATEID_EVENT(open);
293DEFINE_STATEID_EVENT(deleg_none);293DEFINE_STATEID_EVENT(deleg_read);
294DEFINE_STATEID_EVENT(deleg_break);294DEFINE_STATEID_EVENT(deleg_break);
295DEFINE_STATEID_EVENT(deleg_recall);295DEFINE_STATEID_EVENT(deleg_recall);
296 296
fs/nfsd/vfs.c+4−2
@@ -2259,7 +2259,8 @@ out: · 2258 unmodified lines
2259__be322259__be32
2260nfsd_removexattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name)2260nfsd_removexattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name)
2261{2261{
2262 int err, ret;2262 __be32 err;
2263 int ret;
2263 2264
2264 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE);2265 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE);
2265 if (err)2266 if (err)
@@ -2283,7 +2284,8 @@ __be32 · 17 unmodified lines
2283nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,2284nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,
2284 void *buf, u32 len, u32 flags)2285 void *buf, u32 len, u32 flags)
2285{2286{
2286 int err, ret;2287 __be32 err;
2288 int ret;
2287 2289
2288 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE);2290 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE);
2289 if (err)2291 if (err)
fs/nfsd/xdr.h+15−1
@@ -82,27 +82,37 @@ struct nfsd_readdirargs { · 81 unmodified lines
82 __be32 * buffer;82 __be32 * buffer;
83};83};
84 84
85struct nfsd_stat {
86 __be32 status;
87};
88
85struct nfsd_attrstat {89struct nfsd_attrstat {
90 __be32 status;
86 struct svc_fh fh;91 struct svc_fh fh;
87 struct kstat stat;92 struct kstat stat;
88};93};
89 94
90struct nfsd_diropres {95struct nfsd_diropres {
96 __be32 status;
91 struct svc_fh fh;97 struct svc_fh fh;
92 struct kstat stat;98 struct kstat stat;
93};99};
94 100
95struct nfsd_readlinkres {101struct nfsd_readlinkres {
102 __be32 status;
96 int len;103 int len;
97};104};
98 105
99struct nfsd_readres {106struct nfsd_readres {
107 __be32 status;
100 struct svc_fh fh;108 struct svc_fh fh;
101 unsigned long count;109 unsigned long count;
102 struct kstat stat;110 struct kstat stat;
103};111};
104 112
105struct nfsd_readdirres {113struct nfsd_readdirres {
114 __be32 status;
115
106 int count;116 int count;
107 117
108 struct readdir_cd common;118 struct readdir_cd common;
@@ -112,6 +122,7 @@ struct nfsd_readdirres { · 3 unmodified lines
112};122};
113 123
114struct nfsd_statfsres {124struct nfsd_statfsres {
125 __be32 status;
115 struct kstatfs stats;126 struct kstatfs stats;
116};127};
117 128
@@ -146,6 +157,7 @@ int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *); · 28 unmodified lines
146int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *);157int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *);
147int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *);158int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *);
148int nfssvc_encode_void(struct svc_rqst *, __be32 *);159int nfssvc_encode_void(struct svc_rqst *, __be32 *);
160int nfssvc_encode_stat(struct svc_rqst *, __be32 *);
149int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *);161int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *);
150int nfssvc_encode_diropres(struct svc_rqst *, __be32 *);162int nfssvc_encode_diropres(struct svc_rqst *, __be32 *);
151int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *);163int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *);
@@ -156,7 +168,9 @@ int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *); · 4 unmodified lines
156int nfssvc_encode_entry(void *, const char *name,168int nfssvc_encode_entry(void *, const char *name,
157 int namlen, loff_t offset, u64 ino, unsigned int);169 int namlen, loff_t offset, u64 ino, unsigned int);
158 170
159void nfssvc_release_fhandle(struct svc_rqst *);171void nfssvc_release_attrstat(struct svc_rqst *rqstp);
172void nfssvc_release_diropres(struct svc_rqst *rqstp);
173void nfssvc_release_readres(struct svc_rqst *rqstp);
160 174
161/* Helper functions for NFSv2 ACL code */175/* Helper functions for NFSv2 ACL code */
162__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);176__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
273 273
274#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)274#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
275 275
276int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *);
276int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *);277int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *);
277int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);278int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);
278int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *);279int 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
781 781
782 782
783bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);783bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
784int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *);
784int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *);785int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *);
785int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *);786int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *);
786int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *);787int 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
12extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
13
14/*
15 * NFS_V4
16 */
17struct 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 */
26struct nfs_ssc_client_ops {
27 void (*sco_sb_deactive)(struct super_block *sb);
28};
29
30struct 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
35extern void nfs42_ssc_register_ops(void);
36extern void nfs42_ssc_unregister_ops(void);
37
38extern void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops);
39extern void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops);
40
41#ifdef CONFIG_NFSD_V4_2_INTER_SSC
42static 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
50static 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 */
60extern void nfs_ssc_register(const struct nfs_ssc_client_ops *ops);
61extern void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops);
62
63static 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
234extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,234extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
235 __be32 *p, struct rpc_rqst *rqst);235 __be32 *p, struct rpc_rqst *rqst);
236extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);236extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
237extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec,
238 size_t nbytes);
237extern void xdr_commit_encode(struct xdr_stream *xdr);239extern void xdr_commit_encode(struct xdr_stream *xdr);
238extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);240extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
239extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);241extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
include/uapi/linux/nfsacl.h+2−0
@@ -9,11 +9,13 @@ · 8 unmodified lines
9 9
10#define NFS_ACL_PROGRAM 10022710#define NFS_ACL_PROGRAM 100227
11 11
12#define ACLPROC2_NULL 0
12#define ACLPROC2_GETACL 113#define ACLPROC2_GETACL 1
13#define ACLPROC2_SETACL 214#define ACLPROC2_SETACL 2
14#define ACLPROC2_GETATTR 315#define ACLPROC2_GETATTR 3
15#define ACLPROC2_ACCESS 416#define ACLPROC2_ACCESS 4
16 17
18#define ACLPROC3_NULL 0
17#define ACLPROC3_GETACL 119#define ACLPROC3_GETACL 1
18#define ACLPROC3_SETACL 220#define ACLPROC3_SETACL 2
19 21
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
1147 struct gssp_in_token *in_token)1147 struct gssp_in_token *in_token)
1148{1148{
1149 struct kvec *argv = &rqstp->rq_arg.head[0];1149 struct kvec *argv = &rqstp->rq_arg.head[0];
1150 unsigned int page_base, length;1150 unsigned int length, pgto_offs, pgfrom_offs;
1151 int pages, i, res;1151 int pages, i, res, pgto, pgfrom;
1152 size_t inlen;1152 size_t inlen, to_offs, from_offs;
1153 1153
1154 res = gss_read_common_verf(gc, argv, authp, in_handle);1154 res = gss_read_common_verf(gc, argv, authp, in_handle);
1155 if (res)1155 if (res)
@@ -1177,17 +1177,24 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp, · 21 unmodified lines
1177 memcpy(page_address(in_token->pages[0]), argv->iov_base, length);1177 memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
1178 inlen -= length;1178 inlen -= length;
1179 1179
1180 i = 1;1180 to_offs = length;
1181 page_base = rqstp->rq_arg.page_base;1181 from_offs = rqstp->rq_arg.page_base;
1182 while (inlen) {1182 while (inlen) {
1183 length = min_t(unsigned int, inlen, PAGE_SIZE);1183 pgto = to_offs >> PAGE_SHIFT;
1184 memcpy(page_address(in_token->pages[i]),1184 pgfrom = from_offs >> PAGE_SHIFT;
1185 page_address(rqstp->rq_arg.pages[i]) + page_base,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,
1186 length);1193 length);
1187 1194
1195 to_offs += length;
1196 from_offs += length;
1188 inlen -= length;1197 inlen -= length;
1189 page_base = 0;
1190 i++;
1191 }1198 }
1192 return 0;1199 return 0;
1193}1200}
net/sunrpc/backchannel_rqst.c+1−1
@@ -111,7 +111,7 @@ out_free: · 110 unmodified lines
111 * by the backchannel. This function can be called multiple times111 * by the backchannel. This function can be called multiple times
112 * when creating new sessions that use the same rpc_xprt. The112 * when creating new sessions that use the same rpc_xprt. The
113 * preallocated buffers are added to the pool of resources used by113 * preallocated buffers are added to the pool of resources used by
114 * the rpc_xprt. Anyone of these resources may be used used by an114 * the rpc_xprt. Any one of these resources may be used by an
115 * incoming callback request. It's up to the higher levels in the115 * incoming callback request. It's up to the higher levels in the
116 * stack to enforce that the maximum number of session slots is not116 * stack to enforce that the maximum number of session slots is not
117 * being exceeded.117 * being exceeded.
net/sunrpc/cache.c+11−10
@@ -498,16 +498,17 @@ static int cache_clean(void) · 497 unmodified lines
498 */498 */
499static void do_cache_clean(struct work_struct *work)499static void do_cache_clean(struct work_struct *work)
500{500{
501 int delay = 5;501 int delay;
502 if (cache_clean() == -1)
503 delay = round_jiffies_relative(30*HZ);
504 502
505 if (list_empty(&cache_list))503 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;
507 510
508 if (delay)511 queue_delayed_work(system_power_efficient_wq, &cache_cleaner, delay);
509 queue_delayed_work(system_power_efficient_wq,
510 &cache_cleaner, delay);
511}512}
512 513
513 514
@@ -908,7 +909,7 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, · 394 unmodified lines
908static ssize_t cache_slow_downcall(const char __user *buf,909static ssize_t cache_slow_downcall(const char __user *buf,
909 size_t count, struct cache_detail *cd)910 size_t count, struct cache_detail *cd)
910{911{
911 static char write_buf[8192]; /* protected by queue_io_mutex */912 static char write_buf[32768]; /* protected by queue_io_mutex */
912 ssize_t ret = -EINVAL;913 ssize_t ret = -EINVAL;
913 914
914 if (count >= sizeof(write_buf))915 if (count >= sizeof(write_buf))
@@ -1436,10 +1437,10 @@ static int c_show(struct seq_file *m, void *p) · 521 unmodified lines
1436 cache_get(cp);1437 cache_get(cp);
1437 if (cache_check(cd, cp, NULL))1438 if (cache_check(cd, cp, NULL))
1438 /* cache_check does a cache_put on failure */1439 /* cache_check does a cache_put on failure */
1439 seq_printf(m, "# ");1440 seq_puts(m, "# ");
1440 else {1441 else {
1441 if (cache_is_expired(cd, cp))1442 if (cache_is_expired(cd, cp))
1442 seq_printf(m, "# ");1443 seq_puts(m, "# ");
1443 cache_put(cp, cd);1444 cache_put(cp, cd);
1444 }1445 }
1445 1446
net/sunrpc/sysctl.c+7−1
@@ -70,7 +70,13 @@ static int proc_do_xprt(struct ctl_table *table, int write, · 69 unmodified lines
70 return 0;70 return 0;
71 }71 }
72 len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));72 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;
74}80}
75 81
76static int82static 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
792}792}
793EXPORT_SYMBOL_GPL(xdr_reserve_space);793EXPORT_SYMBOL_GPL(xdr_reserve_space);
794 794
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 */
807int 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}
838EXPORT_SYMBOL_GPL(xdr_reserve_space_vec);
839
795/**840/**
796 * xdr_truncate_encode - truncate an encode buffer841 * xdr_truncate_encode - truncate an encode buffer
797 * @xdr: pointer to xdr_stream842 * @xdr: pointer to xdr_stream
@@ -802,7 +847,7 @@ EXPORT_SYMBOL_GPL(xdr_reserve_space); · 4 unmodified lines
802 * head, tail, and page lengths are adjusted to correspond.847 * head, tail, and page lengths are adjusted to correspond.
803 *848 *
804 * If this means moving xdr->p to a different buffer, we assume that849 * 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,
806 * except in the case of the head buffer when we assume the head851 * except in the case of the head buffer when we assume the head
807 * buffer's current length represents the end of the available buffer.852 * buffer's current length represents the end of the available buffer.
808 *853 *
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
137}137}
138 138
139/* A chunk context tracks all I/O for moving one Read or Write139/* 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 movement140 * chunk. This is a set of rdma_rw's that handle data movement
141 * for all segments of one chunk.141 * for all segments of one chunk.
142 *142 *
143 * These are small, acquired with a single allocator call, and143 * 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
638 while (remaining) {638 while (remaining) {
639 len = min_t(u32, PAGE_SIZE - pageoff, remaining);639 len = min_t(u32, PAGE_SIZE - pageoff, remaining);
640 640
641 memcpy(dst, page_address(*ppages), len);641 memcpy(dst, page_address(*ppages) + pageoff, len);
642 remaining -= len;642 remaining -= len;
643 dst += len;643 dst += len;
644 pageoff = 0;644 pageoff = 0;
645 ppages++;
645 }646 }
646 }647 }
647 648
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
9DEBUGFS=`cat /proc/mounts | grep debugfs`
10if [ "$DEBUGFS" == "" ]; then
11 echo "debugfs does not appear to be mounted!"
12 echo "Please mount debugfs and try again"
13 exit 1
14fi
15
16# Check that the fault injection directory exists
17DEBUGDIR=`echo $DEBUGFS | awk '{print $2}'`/nfsd
18if [ ! -d "$DEBUGDIR" ]; then
19 echo "$DEBUGDIR does not exist"
20 echo "Check that your .config selects CONFIG_NFSD_FAULT_INJECTION"
21 exit 1
22fi
23
24function help()
25{
26 echo "Usage $0 injection_type [count]"
27 echo ""
28 echo "Injection types are:"
29 ls $DEBUGDIR
30 exit 1
31}
32
33if [ $# == 0 ]; then
34 help
35elif [ ! -f $DEBUGDIR/$1 ]; then
36 help
37elif [ $# != 2 ]; then
38 COUNT=0
39else
40 COUNT=$2
41fi
42
43BEFORE=`mktemp`
44AFTER=`mktemp`
45dmesg > $BEFORE
46echo $COUNT > $DEBUGDIR/$1
47dmesg > $AFTER
48# Capture lines that only exist in the $AFTER file
49diff $BEFORE $AFTER | grep ">"
50rm -f $BEFORE $AFTER