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() ...
Unified · Split
| @@ -1,70 +0,0 @@ | |||
| 1 | =================== | ||
| 2 | NFS Fault Injection | ||
| 3 | =================== | ||
| 4 | |||
| 5 | Fault injection is a method for forcing errors that may not normally occur, or | ||
| 6 | may be difficult to reproduce. Forcing these errors in a controlled environment | ||
| 7 | can help the developer find and fix bugs before their code is shipped in a | ||
| 8 | production system. Injecting an error on the Linux NFS server will allow us to | ||
| 9 | observe how the client reacts and if it manages to recover its state correctly. | ||
| 10 | |||
| 11 | NFSD_FAULT_INJECTION must be selected when configuring the kernel to use this | ||
| 12 | feature. | ||
| 13 | |||
| 14 | |||
| 15 | Using Fault Injection | ||
| 16 | ===================== | ||
| 17 | On the client, mount the fault injection server through NFS v4.0+ and do some | ||
| 18 | work over NFS (open files, take locks, ...). | ||
| 19 | |||
| 20 | On the server, mount the debugfs filesystem to <debug_dir> and ls | ||
| 21 | <debug_dir>/nfsd. This will show a list of files that will be used for | ||
| 22 | injecting faults on the NFS server. As root, write a number n to the file | ||
| 23 | corresponding to the action you want the server to take. The server will then | ||
| 24 | process the first n items it finds. So if you want to forget 5 locks, echo '5' | ||
| 25 | to <debug_dir>/nfsd/forget_locks. A value of 0 will tell the server to forget | ||
| 26 | all corresponding items. A log message will be created containing the number | ||
| 27 | of items forgotten (check dmesg). | ||
| 28 | |||
| 29 | Go back to work on the client and check if the client recovered from the error | ||
| 30 | correctly. | ||
| 31 | |||
| 32 | |||
| 33 | Available Faults | ||
| 34 | ================ | ||
| 35 | forget_clients: | ||
| 36 | The NFS server keeps a list of clients that have placed a mount call. If | ||
| 37 | this list is cleared, the server will have no knowledge of who the client | ||
| 38 | is, forcing the client to reauthenticate with the server. | ||
| 39 | |||
| 40 | forget_openowners: | ||
| 41 | The NFS server keeps a list of what files are currently opened and who | ||
| 42 | they were opened by. Clearing this list will force the client to reopen | ||
| 43 | its files. | ||
| 44 | |||
| 45 | forget_locks: | ||
| 46 | The NFS server keeps a list of what files are currently locked in the VFS. | ||
| 47 | Clearing this list will force the client to reclaim its locks (files are | ||
| 48 | unlocked through the VFS as they are cleared from this list). | ||
| 49 | |||
| 50 | forget_delegations: | ||
| 51 | A delegation is used to assure the client that a file, or part of a file, | ||
| 52 | has not changed since the delegation was awarded. Clearing this list will | ||
| 53 | force the client to reacquire its delegation before accessing the file | ||
| 54 | again. | ||
| 55 | |||
| 56 | recall_delegations: | ||
| 57 | Delegations can be recalled by the server when another client attempts to | ||
| 58 | access a file. This test will notify the client that its delegation has | ||
| 59 | been revoked, forcing the client to reacquire the delegation before using | ||
| 60 | the file again. | ||
| 61 | |||
| 62 | |||
| 63 | tools/nfs/inject_faults.sh script | ||
| 64 | ================================= | ||
| 65 | This script has been created to ease the fault injection process. This script | ||
| 66 | will detect the mounted debugfs directory and write to the files located there | ||
| 67 | based on the arguments passed by the user. For example, running | ||
| 68 | `inject_faults.sh forget_locks 1` as root will instruct the server to forget | ||
| 69 | one lock. Running `inject_faults forget_locks` will instruct the server to | ||
| 70 | forgetall locks. | ||
| @@ -12,4 +12,3 @@ NFS · 11 unmodified lines | |||
| 12 | nfs-idmapper | 12 | nfs-idmapper |
| 13 | pnfs-block-server | 13 | pnfs-block-server |
| 14 | pnfs-scsi-server | 14 | pnfs-scsi-server |
| 15 | fault_injection | ||
| @@ -13,10 +13,9 @@ RPCGSS is specified in a few IETF documents: · 12 unmodified lines | |||
| 13 | - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt | 13 | - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt |
| 14 | - RFC5403 v2: https://tools.ietf.org/rfc/rfc5403.txt | 14 | - RFC5403 v2: https://tools.ietf.org/rfc/rfc5403.txt |
| 15 | 15 | ||
| 16 | and there is a 3rd version being proposed: | 16 | There is a third version that we don't currently implement: |
| 17 | 17 | ||
| 18 | - https://tools.ietf.org/id/draft-williams-rpcsecgssv3.txt | 18 | - RFC7861 v3: https://tools.ietf.org/rfc/rfc7861.txt |
| 19 | (At draft n. 02 at the time of writing) | ||
| 20 | 19 | ||
| 21 | Background | 20 | Background |
| 22 | ========== | 21 | ========== |
| @@ -9556,6 +9556,7 @@ F: include/linux/sunrpc/ · 9555 unmodified lines | |||
| 9556 | F: include/uapi/linux/nfsd/ | 9556 | F: include/uapi/linux/nfsd/ |
| 9557 | F: include/uapi/linux/sunrpc/ | 9557 | F: include/uapi/linux/sunrpc/ |
| 9558 | F: net/sunrpc/ | 9558 | F: net/sunrpc/ |
| 9559 | F: Documentation/filesystems/nfs/ | ||
| 9559 | 9560 | ||
| 9560 | KERNEL SELFTEST FRAMEWORK | 9561 | KERNEL SELFTEST FRAMEWORK |
| 9561 | M: Shuah Khan <shuah@kernel.org> | 9562 | M: Shuah Khan <shuah@kernel.org> |
| @@ -12337,6 +12338,7 @@ F: include/linux/sunrpc/ · 2775 unmodified lines | |||
| 12337 | F: include/uapi/linux/nfs* | 12338 | F: include/uapi/linux/nfs* |
| 12338 | F: include/uapi/linux/sunrpc/ | 12339 | F: include/uapi/linux/sunrpc/ |
| 12339 | F: net/sunrpc/ | 12340 | F: net/sunrpc/ |
| 12341 | F: Documentation/filesystems/nfs/ | ||
| 12340 | 12342 | ||
| 12341 | NILFS2 FILESYSTEM | 12343 | NILFS2 FILESYSTEM |
| 12342 | M: Ryusuke Konishi <konishi.ryusuke@gmail.com> | 12344 | M: Ryusuke Konishi <konishi.ryusuke@gmail.com> |
| @@ -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 | ||
| 489 | static __be32 | ||
| 490 | nlm4svc_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 | |||
| 508 | struct nlm_void { int dummy; }; | 500 | struct 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) */ |
| 523 | const struct svc_procedure nlmsvc_procedures4[] = { | ||
| 524 | PROC(null, void, void, void, void, 1), | ||
| 525 | PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg), | ||
| 526 | PROC(lock, lockargs, res, args, res, Ck+St), | ||
| 527 | PROC(cancel, cancargs, res, args, res, Ck+St), | ||
| 528 | PROC(unlock, unlockargs, res, args, res, Ck+St), | ||
| 529 | PROC(granted, testargs, res, args, res, Ck+St), | ||
| 530 | PROC(test_msg, testargs, norep, args, void, 1), | ||
| 531 | PROC(lock_msg, lockargs, norep, args, void, 1), | ||
| 532 | PROC(cancel_msg, cancargs, norep, args, void, 1), | ||
| 533 | PROC(unlock_msg, unlockargs, norep, args, void, 1), | ||
| 534 | PROC(granted_msg, testargs, norep, args, void, 1), | ||
| 535 | PROC(test_res, testres, norep, res, void, 1), | ||
| 536 | PROC(lock_res, lockres, norep, res, void, 1), | ||
| 537 | PROC(cancel_res, cancelres, norep, res, void, 1), | ||
| 538 | PROC(unlock_res, unlockres, norep, res, void, 1), | ||
| 539 | PROC(granted_res, res, norep, res, void, 1), | ||
| 540 | /* statd callback */ | ||
| 541 | PROC(sm_notify, reboot, void, reboot, void, 1), | ||
| 542 | PROC(none, void, void, void, void, 0), | ||
| 543 | PROC(none, void, void, void, void, 0), | ||
| 544 | PROC(none, void, void, void, void, 0), | ||
| 545 | PROC(share, shareargs, shareres, args, res, Ck+St+1), | ||
| 546 | PROC(unshare, shareargs, shareres, args, res, Ck+St+1), | ||
| 547 | PROC(nm_lock, lockargs, res, args, res, Ck+St), | ||
| 548 | PROC(free_all, notify, void, args, void, 1), | ||
| 549 | 506 | ||
| 507 | const struct svc_procedure nlmsvc_procedures4[24] = { | ||
| 508 | [NLMPROC_NULL] = { | ||
| 509 | .pc_func = nlm4svc_proc_null, | ||
| 510 | .pc_decode = nlm4svc_decode_void, | ||
| 511 | .pc_encode = nlm4svc_encode_void, | ||
| 512 | .pc_argsize = sizeof(struct nlm_void), | ||
| 513 | .pc_ressize = sizeof(struct nlm_void), | ||
| 514 | .pc_xdrressize = St, | ||
| 515 | }, | ||
| 516 | [NLMPROC_TEST] = { | ||
| 517 | .pc_func = nlm4svc_proc_test, | ||
| 518 | .pc_decode = nlm4svc_decode_testargs, | ||
| 519 | .pc_encode = nlm4svc_encode_testres, | ||
| 520 | .pc_argsize = sizeof(struct nlm_args), | ||
| 521 | .pc_ressize = sizeof(struct nlm_res), | ||
| 522 | .pc_xdrressize = Ck+St+2+No+Rg, | ||
| 523 | }, | ||
| 524 | [NLMPROC_LOCK] = { | ||
| 525 | .pc_func = nlm4svc_proc_lock, | ||
| 526 | .pc_decode = nlm4svc_decode_lockargs, | ||
| 527 | .pc_encode = nlm4svc_encode_res, | ||
| 528 | .pc_argsize = sizeof(struct nlm_args), | ||
| 529 | .pc_ressize = sizeof(struct nlm_res), | ||
| 530 | .pc_xdrressize = Ck+St, | ||
| 531 | }, | ||
| 532 | [NLMPROC_CANCEL] = { | ||
| 533 | .pc_func = nlm4svc_proc_cancel, | ||
| 534 | .pc_decode = nlm4svc_decode_cancargs, | ||
| 535 | .pc_encode = nlm4svc_encode_res, | ||
| 536 | .pc_argsize = sizeof(struct nlm_args), | ||
| 537 | .pc_ressize = sizeof(struct nlm_res), | ||
| 538 | .pc_xdrressize = Ck+St, | ||
| 539 | }, | ||
| 540 | [NLMPROC_UNLOCK] = { | ||
| 541 | .pc_func = nlm4svc_proc_unlock, | ||
| 542 | .pc_decode = nlm4svc_decode_unlockargs, | ||
| 543 | .pc_encode = nlm4svc_encode_res, | ||
| 544 | .pc_argsize = sizeof(struct nlm_args), | ||
| 545 | .pc_ressize = sizeof(struct nlm_res), | ||
| 546 | .pc_xdrressize = Ck+St, | ||
| 547 | }, | ||
| 548 | [NLMPROC_GRANTED] = { | ||
| 549 | .pc_func = nlm4svc_proc_granted, | ||
| 550 | .pc_decode = nlm4svc_decode_testargs, | ||
| 551 | .pc_encode = nlm4svc_encode_res, | ||
| 552 | .pc_argsize = sizeof(struct nlm_args), | ||
| 553 | .pc_ressize = sizeof(struct nlm_res), | ||
| 554 | .pc_xdrressize = Ck+St, | ||
| 555 | }, | ||
| 556 | [NLMPROC_TEST_MSG] = { | ||
| 557 | .pc_func = nlm4svc_proc_test_msg, | ||
| 558 | .pc_decode = nlm4svc_decode_testargs, | ||
| 559 | .pc_encode = nlm4svc_encode_void, | ||
| 560 | .pc_argsize = sizeof(struct nlm_args), | ||
| 561 | .pc_ressize = sizeof(struct nlm_void), | ||
| 562 | .pc_xdrressize = St, | ||
| 563 | }, | ||
| 564 | [NLMPROC_LOCK_MSG] = { | ||
| 565 | .pc_func = nlm4svc_proc_lock_msg, | ||
| 566 | .pc_decode = nlm4svc_decode_lockargs, | ||
| 567 | .pc_encode = nlm4svc_encode_void, | ||
| 568 | .pc_argsize = sizeof(struct nlm_args), | ||
| 569 | .pc_ressize = sizeof(struct nlm_void), | ||
| 570 | .pc_xdrressize = St, | ||
| 571 | }, | ||
| 572 | [NLMPROC_CANCEL_MSG] = { | ||
| 573 | .pc_func = nlm4svc_proc_cancel_msg, | ||
| 574 | .pc_decode = nlm4svc_decode_cancargs, | ||
| 575 | .pc_encode = nlm4svc_encode_void, | ||
| 576 | .pc_argsize = sizeof(struct nlm_args), | ||
| 577 | .pc_ressize = sizeof(struct nlm_void), | ||
| 578 | .pc_xdrressize = St, | ||
| 579 | }, | ||
| 580 | [NLMPROC_UNLOCK_MSG] = { | ||
| 581 | .pc_func = nlm4svc_proc_unlock_msg, | ||
| 582 | .pc_decode = nlm4svc_decode_unlockargs, | ||
| 583 | .pc_encode = nlm4svc_encode_void, | ||
| 584 | .pc_argsize = sizeof(struct nlm_args), | ||
| 585 | .pc_ressize = sizeof(struct nlm_void), | ||
| 586 | .pc_xdrressize = St, | ||
| 587 | }, | ||
| 588 | [NLMPROC_GRANTED_MSG] = { | ||
| 589 | .pc_func = nlm4svc_proc_granted_msg, | ||
| 590 | .pc_decode = nlm4svc_decode_testargs, | ||
| 591 | .pc_encode = nlm4svc_encode_void, | ||
| 592 | .pc_argsize = sizeof(struct nlm_args), | ||
| 593 | .pc_ressize = sizeof(struct nlm_void), | ||
| 594 | .pc_xdrressize = St, | ||
| 595 | }, | ||
| 596 | [NLMPROC_TEST_RES] = { | ||
| 597 | .pc_func = nlm4svc_proc_null, | ||
| 598 | .pc_decode = nlm4svc_decode_void, | ||
| 599 | .pc_encode = nlm4svc_encode_void, | ||
| 600 | .pc_argsize = sizeof(struct nlm_res), | ||
| 601 | .pc_ressize = sizeof(struct nlm_void), | ||
| 602 | .pc_xdrressize = St, | ||
| 603 | }, | ||
| 604 | [NLMPROC_LOCK_RES] = { | ||
| 605 | .pc_func = nlm4svc_proc_null, | ||
| 606 | .pc_decode = nlm4svc_decode_void, | ||
| 607 | .pc_encode = nlm4svc_encode_void, | ||
| 608 | .pc_argsize = sizeof(struct nlm_res), | ||
| 609 | .pc_ressize = sizeof(struct nlm_void), | ||
| 610 | .pc_xdrressize = St, | ||
| 611 | }, | ||
| 612 | [NLMPROC_CANCEL_RES] = { | ||
| 613 | .pc_func = nlm4svc_proc_null, | ||
| 614 | .pc_decode = nlm4svc_decode_void, | ||
| 615 | .pc_encode = nlm4svc_encode_void, | ||
| 616 | .pc_argsize = sizeof(struct nlm_res), | ||
| 617 | .pc_ressize = sizeof(struct nlm_void), | ||
| 618 | .pc_xdrressize = St, | ||
| 619 | }, | ||
| 620 | [NLMPROC_UNLOCK_RES] = { | ||
| 621 | .pc_func = nlm4svc_proc_null, | ||
| 622 | .pc_decode = nlm4svc_decode_void, | ||
| 623 | .pc_encode = nlm4svc_encode_void, | ||
| 624 | .pc_argsize = sizeof(struct nlm_res), | ||
| 625 | .pc_ressize = sizeof(struct nlm_void), | ||
| 626 | .pc_xdrressize = St, | ||
| 627 | }, | ||
| 628 | [NLMPROC_GRANTED_RES] = { | ||
| 629 | .pc_func = nlm4svc_proc_granted_res, | ||
| 630 | .pc_decode = nlm4svc_decode_res, | ||
| 631 | .pc_encode = nlm4svc_encode_void, | ||
| 632 | .pc_argsize = sizeof(struct nlm_res), | ||
| 633 | .pc_ressize = sizeof(struct nlm_void), | ||
| 634 | .pc_xdrressize = St, | ||
| 635 | }, | ||
| 636 | [NLMPROC_NSM_NOTIFY] = { | ||
| 637 | .pc_func = nlm4svc_proc_sm_notify, | ||
| 638 | .pc_decode = nlm4svc_decode_reboot, | ||
| 639 | .pc_encode = nlm4svc_encode_void, | ||
| 640 | .pc_argsize = sizeof(struct nlm_reboot), | ||
| 641 | .pc_ressize = sizeof(struct nlm_void), | ||
| 642 | .pc_xdrressize = St, | ||
| 643 | }, | ||
| 644 | [17] = { | ||
| 645 | .pc_func = nlm4svc_proc_unused, | ||
| 646 | .pc_decode = nlm4svc_decode_void, | ||
| 647 | .pc_encode = nlm4svc_encode_void, | ||
| 648 | .pc_argsize = sizeof(struct nlm_void), | ||
| 649 | .pc_ressize = sizeof(struct nlm_void), | ||
| 650 | .pc_xdrressize = 0, | ||
| 651 | }, | ||
| 652 | [18] = { | ||
| 653 | .pc_func = nlm4svc_proc_unused, | ||
| 654 | .pc_decode = nlm4svc_decode_void, | ||
| 655 | .pc_encode = nlm4svc_encode_void, | ||
| 656 | .pc_argsize = sizeof(struct nlm_void), | ||
| 657 | .pc_ressize = sizeof(struct nlm_void), | ||
| 658 | .pc_xdrressize = 0, | ||
| 659 | }, | ||
| 660 | [19] = { | ||
| 661 | .pc_func = nlm4svc_proc_unused, | ||
| 662 | .pc_decode = nlm4svc_decode_void, | ||
| 663 | .pc_encode = nlm4svc_encode_void, | ||
| 664 | .pc_argsize = sizeof(struct nlm_void), | ||
| 665 | .pc_ressize = sizeof(struct nlm_void), | ||
| 666 | .pc_xdrressize = 0, | ||
| 667 | }, | ||
| 668 | [NLMPROC_SHARE] = { | ||
| 669 | .pc_func = nlm4svc_proc_share, | ||
| 670 | .pc_decode = nlm4svc_decode_shareargs, | ||
| 671 | .pc_encode = nlm4svc_encode_shareres, | ||
| 672 | .pc_argsize = sizeof(struct nlm_args), | ||
| 673 | .pc_ressize = sizeof(struct nlm_res), | ||
| 674 | .pc_xdrressize = Ck+St+1, | ||
| 675 | }, | ||
| 676 | [NLMPROC_UNSHARE] = { | ||
| 677 | .pc_func = nlm4svc_proc_unshare, | ||
| 678 | .pc_decode = nlm4svc_decode_shareargs, | ||
| 679 | .pc_encode = nlm4svc_encode_shareres, | ||
| 680 | .pc_argsize = sizeof(struct nlm_args), | ||
| 681 | .pc_ressize = sizeof(struct nlm_res), | ||
| 682 | .pc_xdrressize = Ck+St+1, | ||
| 683 | }, | ||
| 684 | [NLMPROC_NM_LOCK] = { | ||
| 685 | .pc_func = nlm4svc_proc_nm_lock, | ||
| 686 | .pc_decode = nlm4svc_decode_lockargs, | ||
| 687 | .pc_encode = nlm4svc_encode_res, | ||
| 688 | .pc_argsize = sizeof(struct nlm_args), | ||
| 689 | .pc_ressize = sizeof(struct nlm_res), | ||
| 690 | .pc_xdrressize = Ck+St, | ||
| 691 | }, | ||
| 692 | [NLMPROC_FREE_ALL] = { | ||
| 693 | .pc_func = nlm4svc_proc_free_all, | ||
| 694 | .pc_decode = nlm4svc_decode_notify, | ||
| 695 | .pc_encode = nlm4svc_encode_void, | ||
| 696 | .pc_argsize = sizeof(struct nlm_args), | ||
| 697 | .pc_ressize = sizeof(struct nlm_void), | ||
| 698 | .pc_xdrressize = St, | ||
| 699 | }, | ||
| 550 | }; | 700 | }; |
| @@ -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 | ||
| 532 | static __be32 | ||
| 533 | nlmsvc_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 | |||
| 550 | struct nlm_void { int dummy; }; | 542 | struct 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 | ||
| 567 | const struct svc_procedure nlmsvc_procedures[] = { | 549 | const 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 | }; |
| @@ -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 | |||
| 315 | static int read_name_gen = 1; | 316 | static 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 | ||
| 318 | struct file * | 319 | static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt, |
| 319 | nfs42_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 | } |
| 402 | EXPORT_SYMBOL_GPL(nfs42_ssc_open); | 402 | |
| 403 | void nfs42_ssc_close(struct file *filep) | 403 | static 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 | } |
| 409 | EXPORT_SYMBOL_GPL(nfs42_ssc_close); | 409 | |
| 410 | static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = { | ||
| 411 | .sco_open = __nfs42_ssc_open, | ||
| 412 | .sco_close = __nfs42_ssc_close, | ||
| 413 | }; | ||
| 414 | |||
| 415 | /** | ||
| 416 | * nfs42_ssc_register_ops - Wrapper to register NFS_V4 ops in nfs_common | ||
| 417 | * | ||
| 418 | * Return values: | ||
| 419 | * None | ||
| 420 | */ | ||
| 421 | void nfs42_ssc_register_ops(void) | ||
| 422 | { | ||
| 423 | nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl); | ||
| 424 | } | ||
| 425 | |||
| 426 | /** | ||
| 427 | * nfs42_ssc_unregister_ops - wrapper to un-register NFS_V4 ops in nfs_common | ||
| 428 | * | ||
| 429 | * Return values: | ||
| 430 | * None. | ||
| 431 | */ | ||
| 432 | void nfs42_ssc_unregister_ops(void) | ||
| 433 | { | ||
| 434 | nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl); | ||
| 435 | } | ||
| 410 | #endif /* CONFIG_NFS_V4_2 */ | 436 | #endif /* CONFIG_NFS_V4_2 */ |
| 411 | 437 | ||
| 412 | const struct file_operations nfs4_file_operations = { | 438 | const struct file_operations nfs4_file_operations = { |
| @@ -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; |
| 284 | out2: | 288 | out2: |
| @@ -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_2 | 302 | #ifdef CONFIG_NFS_V4_2 |
| 299 | nfs4_xattr_cache_exit(); | 303 | nfs4_xattr_cache_exit(); |
| 304 | nfs42_ssc_unregister_ops(); | ||
| 300 | #endif | 305 | #endif |
| 301 | nfs4_unregister_sysctl(); | 306 | nfs4_unregister_sysctl(); |
| 302 | nfs_idmap_quit(); | 307 | nfs_idmap_quit(); |
| @@ -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 | }; |
| 86 | EXPORT_SYMBOL_GPL(nfs_sops); | 87 | EXPORT_SYMBOL_GPL(nfs_sops); |
| 87 | 88 | ||
| 89 | static 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) |
| 89 | static int __init register_nfs4_fs(void) | 94 | static int __init register_nfs4_fs(void) |
| 90 | { | 95 | { |
| @@ -106,6 +111,16 @@ static void unregister_nfs4_fs(void) · 15 unmodified lines | |||
| 106 | } | 111 | } |
| 107 | #endif | 112 | #endif |
| 108 | 113 | ||
| 114 | static void nfs_ssc_register_ops(void) | ||
| 115 | { | ||
| 116 | nfs_ssc_register(&nfs_ssc_clnt_ops_tbl); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void nfs_ssc_unregister_ops(void) | ||
| 120 | { | ||
| 121 | nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl); | ||
| 122 | } | ||
| 123 | |||
| 109 | static struct shrinker acl_shrinker = { | 124 | static 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; |
| 137 | error_3: | 153 | error_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 | ||
| @@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o · 6 unmodified lines | |||
| 7 | nfs_acl-objs := nfsacl.o | 7 | nfs_acl-objs := nfsacl.o |
| 8 | 8 | ||
| 9 | obj-$(CONFIG_GRACE_PERIOD) += grace.o | 9 | obj-$(CONFIG_GRACE_PERIOD) += grace.o |
| 10 | obj-$(CONFIG_GRACE_PERIOD) += nfs_ssc.o | ||
| @@ -0,0 +1,94 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * fs/nfs_common/nfs_ssc_comm.c | ||
| 4 | * | ||
| 5 | * Helper for knfsd's SSC to access ops in NFS client modules | ||
| 6 | * | ||
| 7 | * Author: Dai Ngo <dai.ngo@oracle.com> | ||
| 8 | * | ||
| 9 | * Copyright (c) 2020, Oracle and/or its affiliates. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/fs.h> | ||
| 14 | #include <linux/nfs_ssc.h> | ||
| 15 | #include "../nfs/nfs4_fs.h" | ||
| 16 | |||
| 17 | MODULE_LICENSE("GPL"); | ||
| 18 | |||
| 19 | struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl; | ||
| 20 | EXPORT_SYMBOL_GPL(nfs_ssc_client_tbl); | ||
| 21 | |||
| 22 | #ifdef CONFIG_NFS_V4_2 | ||
| 23 | /** | ||
| 24 | * nfs42_ssc_register - install the NFS_V4 client ops in the nfs_ssc_client_tbl | ||
| 25 | * @ops: NFS_V4 ops to be installed | ||
| 26 | * | ||
| 27 | * Return values: | ||
| 28 | * None | ||
| 29 | */ | ||
| 30 | void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops) | ||
| 31 | { | ||
| 32 | nfs_ssc_client_tbl.ssc_nfs4_ops = ops; | ||
| 33 | } | ||
| 34 | EXPORT_SYMBOL_GPL(nfs42_ssc_register); | ||
| 35 | |||
| 36 | /** | ||
| 37 | * nfs42_ssc_unregister - uninstall the NFS_V4 client ops from | ||
| 38 | * the nfs_ssc_client_tbl | ||
| 39 | * @ops: ops to be uninstalled | ||
| 40 | * | ||
| 41 | * Return values: | ||
| 42 | * None | ||
| 43 | */ | ||
| 44 | void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops) | ||
| 45 | { | ||
| 46 | if (nfs_ssc_client_tbl.ssc_nfs4_ops != ops) | ||
| 47 | return; | ||
| 48 | |||
| 49 | nfs_ssc_client_tbl.ssc_nfs4_ops = NULL; | ||
| 50 | } | ||
| 51 | EXPORT_SYMBOL_GPL(nfs42_ssc_unregister); | ||
| 52 | #endif /* CONFIG_NFS_V4_2 */ | ||
| 53 | |||
| 54 | #ifdef CONFIG_NFS_V4_2 | ||
| 55 | /** | ||
| 56 | * nfs_ssc_register - install the NFS_FS client ops in the nfs_ssc_client_tbl | ||
| 57 | * @ops: NFS_FS ops to be installed | ||
| 58 | * | ||
| 59 | * Return values: | ||
| 60 | * None | ||
| 61 | */ | ||
| 62 | void nfs_ssc_register(const struct nfs_ssc_client_ops *ops) | ||
| 63 | { | ||
| 64 | nfs_ssc_client_tbl.ssc_nfs_ops = ops; | ||
| 65 | } | ||
| 66 | EXPORT_SYMBOL_GPL(nfs_ssc_register); | ||
| 67 | |||
| 68 | /** | ||
| 69 | * nfs_ssc_unregister - uninstall the NFS_FS client ops from | ||
| 70 | * the nfs_ssc_client_tbl | ||
| 71 | * @ops: ops to be uninstalled | ||
| 72 | * | ||
| 73 | * Return values: | ||
| 74 | * None | ||
| 75 | */ | ||
| 76 | void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops) | ||
| 77 | { | ||
| 78 | if (nfs_ssc_client_tbl.ssc_nfs_ops != ops) | ||
| 79 | return; | ||
| 80 | nfs_ssc_client_tbl.ssc_nfs_ops = NULL; | ||
| 81 | } | ||
| 82 | EXPORT_SYMBOL_GPL(nfs_ssc_unregister); | ||
| 83 | |||
| 84 | #else | ||
| 85 | void nfs_ssc_register(const struct nfs_ssc_client_ops *ops) | ||
| 86 | { | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(nfs_ssc_register); | ||
| 89 | |||
| 90 | void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops) | ||
| 91 | { | ||
| 92 | } | ||
| 93 | EXPORT_SYMBOL_GPL(nfs_ssc_unregister); | ||
| 94 | #endif /* CONFIG_NFS_V4_2 */ | ||
| @@ -136,7 +136,7 @@ config NFSD_FLEXFILELAYOUT · 135 unmodified lines | |||
| 136 | 136 | ||
| 137 | config NFSD_V4_2_INTER_SSC | 137 | config 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=y | 139 | depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 |
| 140 | help | 140 | help |
| 141 | This option enables support for NFSv4.2 inter server to | 141 | This option enables support for NFSv4.2 inter server to |
| 142 | server copy where the destination server calls the NFSv4.2 | 142 | 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 or | 157 | 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 | |||
| 160 | config NFSD_FAULT_INJECTION | ||
| 161 | bool "NFS server manual fault injection" | ||
| 162 | depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS && BROKEN | ||
| 163 | help | ||
| 164 | This option enables support for manually injecting faults | ||
| 165 | into the NFS server. This is intended to be used for | ||
| 166 | testing error recovery on the NFS client. | ||
| 167 | |||
| 168 | If unsure, say N. | ||
| @@ -13,7 +13,6 @@ nfsd-y += trace.o · 12 unmodified lines | |||
| 13 | nfsd-y += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ | 13 | nfsd-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.o | 15 | stats.o filecache.o |
| 16 | nfsd-$(CONFIG_NFSD_FAULT_INJECTION) += fault_inject.o | ||
| 17 | nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o | 16 | nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o |
| 18 | nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o | 17 | nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o |
| 19 | nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o | 18 | nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o |
| @@ -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 | /* |
| @@ -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; |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | |||
| 14 | #include "vfs.h" | 14 | #include "vfs.h" |
| 15 | 15 | ||
| 16 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 16 | #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 | |||
| 22 | static __be32 | 21 | static __be32 |
| 23 | nfsacld_proc_null(struct svc_rqst *rqstp) | 22 | nfsacld_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); | 81 | out: |
| 82 | return rpc_success; | ||
| 82 | 83 | ||
| 83 | fail: | 84 | fail: |
| 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 | ||
| 129 | out: | 129 | out: |
| 130 | /* argp->acl_{access,default} may have been allocated in | 130 | /* 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 | |||
| 135 | out_drop_lock: | 136 | out_drop_lock: |
| 136 | fh_unlock(fh); | 137 | fh_unlock(fh); |
| 137 | fh_drop_write(fh); | 138 | fh_drop_write(fh); |
| 138 | out_errno: | 139 | out_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; | 159 | out: |
| 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; | 181 | out: |
| 182 | return rpc_success; | ||
| 181 | } | 183 | } |
| 182 | 184 | ||
| 183 | /* | 185 | /* |
| 184 | * XDR decode functions | 186 | * XDR decode functions |
| 185 | */ | 187 | */ |
| 188 | static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) | ||
| 189 | { | ||
| 190 | return 1; | ||
| 191 | } | ||
| 192 | |||
| 186 | static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p) | 193 | static 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 in | 283 | * 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); |
| 326 | out: | ||
| 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); |
| 341 | out: | ||
| 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 | ||
| 355 | struct nfsd3_voidargs { int dummy; }; | 371 | struct 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 | ||
| 374 | static const struct svc_procedure nfsd_acl_procedures2[] = { | 378 | static 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 | ||
| 382 | static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)]; | 430 | static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)]; |
| @@ -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 | */ |
| 21 | static __be32 | 19 | static __be32 |
| 22 | nfsd3_proc_null(struct svc_rqst *rqstp) | 20 | nfsd3_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); | 73 | out: |
| 74 | return rpc_success; | ||
| 75 | 75 | ||
| 76 | fail: | 76 | fail: |
| 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); |
| 115 | out_errno: | 114 | out_errno: |
| 116 | nfserr = nfserrno(error); | 115 | resp->status = nfserrno(error); |
| 117 | out: | 116 | out: |
| 118 | /* argp->acl_{access,default} may have been allocated in | 117 | /* 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 | ||
| 242 | struct nfsd3_voidargs { int dummy; }; | 238 | struct 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 | ||
| 261 | static const struct svc_procedure nfsd_acl_procedures3[] = { | 245 | static 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 | ||
| 267 | static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)]; | 277 | static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)]; |
| @@ -15,8 +15,6 @@ · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 16 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 17 | 17 | ||
| 18 | #define RETURN_STATUS(st) { resp->status = (st); return (st); } | ||
| 19 | |||
| 20 | static int nfs3_ftypes[] = { | 18 | static 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 | |||
| 34 | static __be32 | 32 | static __be32 |
| 35 | nfsd3_proc_null(struct svc_rqst *rqstp) | 33 | nfsd3_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 | 57 | out: | |
| 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); | 198 | out: |
| 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 | ||
| 275 | static __be32 | 263 | static __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); | 296 | out: |
| 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 | } else | 328 | 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); | 339 | out: |
| 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 | ||
| 387 | static __be32 | 386 | static __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 | ||
| 410 | static __be32 | 408 | static __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); | 553 | out: |
| 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 request | 600 | /* Check special features of the file system. May request |
| 607 | * different read/write sizes for file systems known to have | 601 | * 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 | 681 | out: | |
| 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 | |||
| 716 | static const struct svc_procedure nfsd_procedures3[22] = { | 709 | static 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), |
| @@ -304,6 +304,12 @@ void fill_post_wcc(struct svc_fh *fhp) · 303 unmodified lines | |||
| 304 | /* | 304 | /* |
| 305 | * XDR decode functions | 305 | * XDR decode functions |
| 306 | */ | 306 | */ |
| 307 | int | ||
| 308 | nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) | ||
| 309 | { | ||
| 310 | return 1; | ||
| 311 | } | ||
| 312 | |||
| 307 | int | 313 | int |
| 308 | nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) | 314 | nfs3svc_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 functions | 642 | * 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 | */ | ||
| 642 | int | 645 | int |
| 643 | nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) | 646 | nfs3svc_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) { |
| @@ -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 | |||
| 1247 | static void | 1248 | static void |
| 1248 | nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) | 1249 | nfsd4_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 | |||
| 2165 | static __be32 | 2166 | static __be32 |
| 2166 | nfsd4_proc_null(struct svc_rqst *rqstp) | 2167 | nfsd4_proc_null(struct svc_rqst *rqstp) |
| 2167 | { | 2168 | { |
| 2168 | return nfs_ok; | 2169 | return rpc_success; |
| 2169 | } | 2170 | } |
| 2170 | 2171 | ||
| 2171 | static inline void nfsd4_increment_op_stats(u32 opnum) | 2172 | static 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); |
| 2464 | out: | 2464 | out: |
| 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 | ||
| 2594 | static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | ||
| 2595 | { | ||
| 2596 | u32 maxcount = svc_max_payload(rqstp); | ||
| 2597 | u32 rlen = min(op->u.read.rd_length, maxcount); | ||
| 2598 | /* | ||
| 2599 | * If we detect that the file changed during hole encoding, then we | ||
| 2600 | * recover by encoding the remaining reply as data. This means we need | ||
| 2601 | * to set aside enough room to encode two data segments. | ||
| 2602 | */ | ||
| 2603 | u32 seg_len = 2 * (1 + 2 + 1); | ||
| 2604 | |||
| 2605 | return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32); | ||
| 2606 | } | ||
| 2607 | |||
| 2594 | static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 2608 | static 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 | |||
| 3279 | static const struct svc_procedure nfsd_procedures4[2] = { | 3300 | static 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), |
| @@ -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); |
| 5244 | nodeleg: | 5245 | nodeleg: |
| 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); |
| 5247 | out: | 5248 | out: |
| 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 | else | 5724 | 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 | ||
| 7257 | static inline void | ||
| 7258 | put_client(struct nfs4_client *clp) | ||
| 7259 | { | ||
| 7260 | atomic_dec(&clp->cl_rpc_users); | ||
| 7261 | } | ||
| 7262 | |||
| 7263 | static struct nfs4_client * | ||
| 7264 | nfsd_find_client(struct sockaddr_storage *addr, size_t addr_size) | ||
| 7265 | { | ||
| 7266 | struct nfs4_client *clp; | ||
| 7267 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7268 | nfsd_net_id); | ||
| 7269 | |||
| 7270 | if (!nfsd_netns_ready(nn)) | ||
| 7271 | return NULL; | ||
| 7272 | |||
| 7273 | list_for_each_entry(clp, &nn->client_lru, cl_lru) { | ||
| 7274 | if (memcmp(&clp->cl_addr, addr, addr_size) == 0) | ||
| 7275 | return clp; | ||
| 7276 | } | ||
| 7277 | return NULL; | ||
| 7278 | } | ||
| 7279 | |||
| 7280 | u64 | ||
| 7281 | nfsd_inject_print_clients(void) | ||
| 7282 | { | ||
| 7283 | struct nfs4_client *clp; | ||
| 7284 | u64 count = 0; | ||
| 7285 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7286 | nfsd_net_id); | ||
| 7287 | char buf[INET6_ADDRSTRLEN]; | ||
| 7288 | |||
| 7289 | if (!nfsd_netns_ready(nn)) | ||
| 7290 | return 0; | ||
| 7291 | |||
| 7292 | spin_lock(&nn->client_lock); | ||
| 7293 | list_for_each_entry(clp, &nn->client_lru, cl_lru) { | ||
| 7294 | rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf)); | ||
| 7295 | pr_info("NFS Client: %s\n", buf); | ||
| 7296 | ++count; | ||
| 7297 | } | ||
| 7298 | spin_unlock(&nn->client_lock); | ||
| 7299 | |||
| 7300 | return count; | ||
| 7301 | } | ||
| 7302 | |||
| 7303 | u64 | ||
| 7304 | nfsd_inject_forget_client(struct sockaddr_storage *addr, size_t addr_size) | ||
| 7305 | { | ||
| 7306 | u64 count = 0; | ||
| 7307 | struct nfs4_client *clp; | ||
| 7308 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7309 | nfsd_net_id); | ||
| 7310 | |||
| 7311 | if (!nfsd_netns_ready(nn)) | ||
| 7312 | return count; | ||
| 7313 | |||
| 7314 | spin_lock(&nn->client_lock); | ||
| 7315 | clp = nfsd_find_client(addr, addr_size); | ||
| 7316 | if (clp) { | ||
| 7317 | if (mark_client_expired_locked(clp) == nfs_ok) | ||
| 7318 | ++count; | ||
| 7319 | else | ||
| 7320 | clp = NULL; | ||
| 7321 | } | ||
| 7322 | spin_unlock(&nn->client_lock); | ||
| 7323 | |||
| 7324 | if (clp) | ||
| 7325 | expire_client(clp); | ||
| 7326 | |||
| 7327 | return count; | ||
| 7328 | } | ||
| 7329 | |||
| 7330 | u64 | ||
| 7331 | nfsd_inject_forget_clients(u64 max) | ||
| 7332 | { | ||
| 7333 | u64 count = 0; | ||
| 7334 | struct nfs4_client *clp, *next; | ||
| 7335 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7336 | nfsd_net_id); | ||
| 7337 | LIST_HEAD(reaplist); | ||
| 7338 | |||
| 7339 | if (!nfsd_netns_ready(nn)) | ||
| 7340 | return count; | ||
| 7341 | |||
| 7342 | spin_lock(&nn->client_lock); | ||
| 7343 | list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) { | ||
| 7344 | if (mark_client_expired_locked(clp) == nfs_ok) { | ||
| 7345 | list_add(&clp->cl_lru, &reaplist); | ||
| 7346 | if (max != 0 && ++count >= max) | ||
| 7347 | break; | ||
| 7348 | } | ||
| 7349 | } | ||
| 7350 | spin_unlock(&nn->client_lock); | ||
| 7351 | |||
| 7352 | list_for_each_entry_safe(clp, next, &reaplist, cl_lru) | ||
| 7353 | expire_client(clp); | ||
| 7354 | |||
| 7355 | return count; | ||
| 7356 | } | ||
| 7357 | |||
| 7358 | static void nfsd_print_count(struct nfs4_client *clp, unsigned int count, | ||
| 7359 | const char *type) | ||
| 7360 | { | ||
| 7361 | char buf[INET6_ADDRSTRLEN]; | ||
| 7362 | rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf)); | ||
| 7363 | printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type); | ||
| 7364 | } | ||
| 7365 | |||
| 7366 | static void | ||
| 7367 | nfsd_inject_add_lock_to_list(struct nfs4_ol_stateid *lst, | ||
| 7368 | struct list_head *collect) | ||
| 7369 | { | ||
| 7370 | struct nfs4_client *clp = lst->st_stid.sc_client; | ||
| 7371 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7372 | nfsd_net_id); | ||
| 7373 | |||
| 7374 | if (!collect) | ||
| 7375 | return; | ||
| 7376 | |||
| 7377 | lockdep_assert_held(&nn->client_lock); | ||
| 7378 | atomic_inc(&clp->cl_rpc_users); | ||
| 7379 | list_add(&lst->st_locks, collect); | ||
| 7380 | } | ||
| 7381 | |||
| 7382 | static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, | ||
| 7383 | struct list_head *collect, | ||
| 7384 | bool (*func)(struct nfs4_ol_stateid *)) | ||
| 7385 | { | ||
| 7386 | struct nfs4_openowner *oop; | ||
| 7387 | struct nfs4_ol_stateid *stp, *st_next; | ||
| 7388 | struct nfs4_ol_stateid *lst, *lst_next; | ||
| 7389 | u64 count = 0; | ||
| 7390 | |||
| 7391 | spin_lock(&clp->cl_lock); | ||
| 7392 | list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) { | ||
| 7393 | list_for_each_entry_safe(stp, st_next, | ||
| 7394 | &oop->oo_owner.so_stateids, st_perstateowner) { | ||
| 7395 | list_for_each_entry_safe(lst, lst_next, | ||
| 7396 | &stp->st_locks, st_locks) { | ||
| 7397 | if (func) { | ||
| 7398 | if (func(lst)) | ||
| 7399 | nfsd_inject_add_lock_to_list(lst, | ||
| 7400 | collect); | ||
| 7401 | } | ||
| 7402 | ++count; | ||
| 7403 | /* | ||
| 7404 | * Despite the fact that these functions deal | ||
| 7405 | * with 64-bit integers for "count", we must | ||
| 7406 | * ensure that it doesn't blow up the | ||
| 7407 | * clp->cl_rpc_users. Throw a warning if we | ||
| 7408 | * start to approach INT_MAX here. | ||
| 7409 | */ | ||
| 7410 | WARN_ON_ONCE(count == (INT_MAX / 2)); | ||
| 7411 | if (count == max) | ||
| 7412 | goto out; | ||
| 7413 | } | ||
| 7414 | } | ||
| 7415 | } | ||
| 7416 | out: | ||
| 7417 | spin_unlock(&clp->cl_lock); | ||
| 7418 | |||
| 7419 | return count; | ||
| 7420 | } | ||
| 7421 | |||
| 7422 | static u64 | ||
| 7423 | nfsd_collect_client_locks(struct nfs4_client *clp, struct list_head *collect, | ||
| 7424 | u64 max) | ||
| 7425 | { | ||
| 7426 | return nfsd_foreach_client_lock(clp, max, collect, unhash_lock_stateid); | ||
| 7427 | } | ||
| 7428 | |||
| 7429 | static u64 | ||
| 7430 | nfsd_print_client_locks(struct nfs4_client *clp) | ||
| 7431 | { | ||
| 7432 | u64 count = nfsd_foreach_client_lock(clp, 0, NULL, NULL); | ||
| 7433 | nfsd_print_count(clp, count, "locked files"); | ||
| 7434 | return count; | ||
| 7435 | } | ||
| 7436 | |||
| 7437 | u64 | ||
| 7438 | nfsd_inject_print_locks(void) | ||
| 7439 | { | ||
| 7440 | struct nfs4_client *clp; | ||
| 7441 | u64 count = 0; | ||
| 7442 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7443 | nfsd_net_id); | ||
| 7444 | |||
| 7445 | if (!nfsd_netns_ready(nn)) | ||
| 7446 | return 0; | ||
| 7447 | |||
| 7448 | spin_lock(&nn->client_lock); | ||
| 7449 | list_for_each_entry(clp, &nn->client_lru, cl_lru) | ||
| 7450 | count += nfsd_print_client_locks(clp); | ||
| 7451 | spin_unlock(&nn->client_lock); | ||
| 7452 | |||
| 7453 | return count; | ||
| 7454 | } | ||
| 7455 | |||
| 7456 | static void | ||
| 7457 | nfsd_reap_locks(struct list_head *reaplist) | ||
| 7458 | { | ||
| 7459 | struct nfs4_client *clp; | ||
| 7460 | struct nfs4_ol_stateid *stp, *next; | ||
| 7461 | |||
| 7462 | list_for_each_entry_safe(stp, next, reaplist, st_locks) { | ||
| 7463 | list_del_init(&stp->st_locks); | ||
| 7464 | clp = stp->st_stid.sc_client; | ||
| 7465 | nfs4_put_stid(&stp->st_stid); | ||
| 7466 | put_client(clp); | ||
| 7467 | } | ||
| 7468 | } | ||
| 7469 | |||
| 7470 | u64 | ||
| 7471 | nfsd_inject_forget_client_locks(struct sockaddr_storage *addr, size_t addr_size) | ||
| 7472 | { | ||
| 7473 | unsigned int count = 0; | ||
| 7474 | struct nfs4_client *clp; | ||
| 7475 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7476 | nfsd_net_id); | ||
| 7477 | LIST_HEAD(reaplist); | ||
| 7478 | |||
| 7479 | if (!nfsd_netns_ready(nn)) | ||
| 7480 | return count; | ||
| 7481 | |||
| 7482 | spin_lock(&nn->client_lock); | ||
| 7483 | clp = nfsd_find_client(addr, addr_size); | ||
| 7484 | if (clp) | ||
| 7485 | count = nfsd_collect_client_locks(clp, &reaplist, 0); | ||
| 7486 | spin_unlock(&nn->client_lock); | ||
| 7487 | nfsd_reap_locks(&reaplist); | ||
| 7488 | return count; | ||
| 7489 | } | ||
| 7490 | |||
| 7491 | u64 | ||
| 7492 | nfsd_inject_forget_locks(u64 max) | ||
| 7493 | { | ||
| 7494 | u64 count = 0; | ||
| 7495 | struct nfs4_client *clp; | ||
| 7496 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7497 | nfsd_net_id); | ||
| 7498 | LIST_HEAD(reaplist); | ||
| 7499 | |||
| 7500 | if (!nfsd_netns_ready(nn)) | ||
| 7501 | return count; | ||
| 7502 | |||
| 7503 | spin_lock(&nn->client_lock); | ||
| 7504 | list_for_each_entry(clp, &nn->client_lru, cl_lru) { | ||
| 7505 | count += nfsd_collect_client_locks(clp, &reaplist, max - count); | ||
| 7506 | if (max != 0 && count >= max) | ||
| 7507 | break; | ||
| 7508 | } | ||
| 7509 | spin_unlock(&nn->client_lock); | ||
| 7510 | nfsd_reap_locks(&reaplist); | ||
| 7511 | return count; | ||
| 7512 | } | ||
| 7513 | |||
| 7514 | static u64 | ||
| 7515 | nfsd_foreach_client_openowner(struct nfs4_client *clp, u64 max, | ||
| 7516 | struct list_head *collect, | ||
| 7517 | void (*func)(struct nfs4_openowner *)) | ||
| 7518 | { | ||
| 7519 | struct nfs4_openowner *oop, *next; | ||
| 7520 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7521 | nfsd_net_id); | ||
| 7522 | u64 count = 0; | ||
| 7523 | |||
| 7524 | lockdep_assert_held(&nn->client_lock); | ||
| 7525 | |||
| 7526 | spin_lock(&clp->cl_lock); | ||
| 7527 | list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) { | ||
| 7528 | if (func) { | ||
| 7529 | func(oop); | ||
| 7530 | if (collect) { | ||
| 7531 | atomic_inc(&clp->cl_rpc_users); | ||
| 7532 | list_add(&oop->oo_perclient, collect); | ||
| 7533 | } | ||
| 7534 | } | ||
| 7535 | ++count; | ||
| 7536 | /* | ||
| 7537 | * Despite the fact that these functions deal with | ||
| 7538 | * 64-bit integers for "count", we must ensure that | ||
| 7539 | * it doesn't blow up the clp->cl_rpc_users. Throw a | ||
| 7540 | * warning if we start to approach INT_MAX here. | ||
| 7541 | */ | ||
| 7542 | WARN_ON_ONCE(count == (INT_MAX / 2)); | ||
| 7543 | if (count == max) | ||
| 7544 | break; | ||
| 7545 | } | ||
| 7546 | spin_unlock(&clp->cl_lock); | ||
| 7547 | |||
| 7548 | return count; | ||
| 7549 | } | ||
| 7550 | |||
| 7551 | static u64 | ||
| 7552 | nfsd_print_client_openowners(struct nfs4_client *clp) | ||
| 7553 | { | ||
| 7554 | u64 count = nfsd_foreach_client_openowner(clp, 0, NULL, NULL); | ||
| 7555 | |||
| 7556 | nfsd_print_count(clp, count, "openowners"); | ||
| 7557 | return count; | ||
| 7558 | } | ||
| 7559 | |||
| 7560 | static u64 | ||
| 7561 | nfsd_collect_client_openowners(struct nfs4_client *clp, | ||
| 7562 | struct list_head *collect, u64 max) | ||
| 7563 | { | ||
| 7564 | return nfsd_foreach_client_openowner(clp, max, collect, | ||
| 7565 | unhash_openowner_locked); | ||
| 7566 | } | ||
| 7567 | |||
| 7568 | u64 | ||
| 7569 | nfsd_inject_print_openowners(void) | ||
| 7570 | { | ||
| 7571 | struct nfs4_client *clp; | ||
| 7572 | u64 count = 0; | ||
| 7573 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7574 | nfsd_net_id); | ||
| 7575 | |||
| 7576 | if (!nfsd_netns_ready(nn)) | ||
| 7577 | return 0; | ||
| 7578 | |||
| 7579 | spin_lock(&nn->client_lock); | ||
| 7580 | list_for_each_entry(clp, &nn->client_lru, cl_lru) | ||
| 7581 | count += nfsd_print_client_openowners(clp); | ||
| 7582 | spin_unlock(&nn->client_lock); | ||
| 7583 | |||
| 7584 | return count; | ||
| 7585 | } | ||
| 7586 | |||
| 7587 | static void | ||
| 7588 | nfsd_reap_openowners(struct list_head *reaplist) | ||
| 7589 | { | ||
| 7590 | struct nfs4_client *clp; | ||
| 7591 | struct nfs4_openowner *oop, *next; | ||
| 7592 | |||
| 7593 | list_for_each_entry_safe(oop, next, reaplist, oo_perclient) { | ||
| 7594 | list_del_init(&oop->oo_perclient); | ||
| 7595 | clp = oop->oo_owner.so_client; | ||
| 7596 | release_openowner(oop); | ||
| 7597 | put_client(clp); | ||
| 7598 | } | ||
| 7599 | } | ||
| 7600 | |||
| 7601 | u64 | ||
| 7602 | nfsd_inject_forget_client_openowners(struct sockaddr_storage *addr, | ||
| 7603 | size_t addr_size) | ||
| 7604 | { | ||
| 7605 | unsigned int count = 0; | ||
| 7606 | struct nfs4_client *clp; | ||
| 7607 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7608 | nfsd_net_id); | ||
| 7609 | LIST_HEAD(reaplist); | ||
| 7610 | |||
| 7611 | if (!nfsd_netns_ready(nn)) | ||
| 7612 | return count; | ||
| 7613 | |||
| 7614 | spin_lock(&nn->client_lock); | ||
| 7615 | clp = nfsd_find_client(addr, addr_size); | ||
| 7616 | if (clp) | ||
| 7617 | count = nfsd_collect_client_openowners(clp, &reaplist, 0); | ||
| 7618 | spin_unlock(&nn->client_lock); | ||
| 7619 | nfsd_reap_openowners(&reaplist); | ||
| 7620 | return count; | ||
| 7621 | } | ||
| 7622 | |||
| 7623 | u64 | ||
| 7624 | nfsd_inject_forget_openowners(u64 max) | ||
| 7625 | { | ||
| 7626 | u64 count = 0; | ||
| 7627 | struct nfs4_client *clp; | ||
| 7628 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7629 | nfsd_net_id); | ||
| 7630 | LIST_HEAD(reaplist); | ||
| 7631 | |||
| 7632 | if (!nfsd_netns_ready(nn)) | ||
| 7633 | return count; | ||
| 7634 | |||
| 7635 | spin_lock(&nn->client_lock); | ||
| 7636 | list_for_each_entry(clp, &nn->client_lru, cl_lru) { | ||
| 7637 | count += nfsd_collect_client_openowners(clp, &reaplist, | ||
| 7638 | max - count); | ||
| 7639 | if (max != 0 && count >= max) | ||
| 7640 | break; | ||
| 7641 | } | ||
| 7642 | spin_unlock(&nn->client_lock); | ||
| 7643 | nfsd_reap_openowners(&reaplist); | ||
| 7644 | return count; | ||
| 7645 | } | ||
| 7646 | |||
| 7647 | static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max, | ||
| 7648 | struct list_head *victims) | ||
| 7649 | { | ||
| 7650 | struct nfs4_delegation *dp, *next; | ||
| 7651 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7652 | nfsd_net_id); | ||
| 7653 | u64 count = 0; | ||
| 7654 | |||
| 7655 | lockdep_assert_held(&nn->client_lock); | ||
| 7656 | |||
| 7657 | spin_lock(&state_lock); | ||
| 7658 | list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) { | ||
| 7659 | if (victims) { | ||
| 7660 | /* | ||
| 7661 | * It's not safe to mess with delegations that have a | ||
| 7662 | * non-zero dl_time. They might have already been broken | ||
| 7663 | * and could be processed by the laundromat outside of | ||
| 7664 | * the state_lock. Just leave them be. | ||
| 7665 | */ | ||
| 7666 | if (dp->dl_time != 0) | ||
| 7667 | continue; | ||
| 7668 | |||
| 7669 | atomic_inc(&clp->cl_rpc_users); | ||
| 7670 | WARN_ON(!unhash_delegation_locked(dp)); | ||
| 7671 | list_add(&dp->dl_recall_lru, victims); | ||
| 7672 | } | ||
| 7673 | ++count; | ||
| 7674 | /* | ||
| 7675 | * Despite the fact that these functions deal with | ||
| 7676 | * 64-bit integers for "count", we must ensure that | ||
| 7677 | * it doesn't blow up the clp->cl_rpc_users. Throw a | ||
| 7678 | * warning if we start to approach INT_MAX here. | ||
| 7679 | */ | ||
| 7680 | WARN_ON_ONCE(count == (INT_MAX / 2)); | ||
| 7681 | if (count == max) | ||
| 7682 | break; | ||
| 7683 | } | ||
| 7684 | spin_unlock(&state_lock); | ||
| 7685 | return count; | ||
| 7686 | } | ||
| 7687 | |||
| 7688 | static u64 | ||
| 7689 | nfsd_print_client_delegations(struct nfs4_client *clp) | ||
| 7690 | { | ||
| 7691 | u64 count = nfsd_find_all_delegations(clp, 0, NULL); | ||
| 7692 | |||
| 7693 | nfsd_print_count(clp, count, "delegations"); | ||
| 7694 | return count; | ||
| 7695 | } | ||
| 7696 | |||
| 7697 | u64 | ||
| 7698 | nfsd_inject_print_delegations(void) | ||
| 7699 | { | ||
| 7700 | struct nfs4_client *clp; | ||
| 7701 | u64 count = 0; | ||
| 7702 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7703 | nfsd_net_id); | ||
| 7704 | |||
| 7705 | if (!nfsd_netns_ready(nn)) | ||
| 7706 | return 0; | ||
| 7707 | |||
| 7708 | spin_lock(&nn->client_lock); | ||
| 7709 | list_for_each_entry(clp, &nn->client_lru, cl_lru) | ||
| 7710 | count += nfsd_print_client_delegations(clp); | ||
| 7711 | spin_unlock(&nn->client_lock); | ||
| 7712 | |||
| 7713 | return count; | ||
| 7714 | } | ||
| 7715 | |||
| 7716 | static void | ||
| 7717 | nfsd_forget_delegations(struct list_head *reaplist) | ||
| 7718 | { | ||
| 7719 | struct nfs4_client *clp; | ||
| 7720 | struct nfs4_delegation *dp, *next; | ||
| 7721 | |||
| 7722 | list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) { | ||
| 7723 | list_del_init(&dp->dl_recall_lru); | ||
| 7724 | clp = dp->dl_stid.sc_client; | ||
| 7725 | revoke_delegation(dp); | ||
| 7726 | put_client(clp); | ||
| 7727 | } | ||
| 7728 | } | ||
| 7729 | |||
| 7730 | u64 | ||
| 7731 | nfsd_inject_forget_client_delegations(struct sockaddr_storage *addr, | ||
| 7732 | size_t addr_size) | ||
| 7733 | { | ||
| 7734 | u64 count = 0; | ||
| 7735 | struct nfs4_client *clp; | ||
| 7736 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7737 | nfsd_net_id); | ||
| 7738 | LIST_HEAD(reaplist); | ||
| 7739 | |||
| 7740 | if (!nfsd_netns_ready(nn)) | ||
| 7741 | return count; | ||
| 7742 | |||
| 7743 | spin_lock(&nn->client_lock); | ||
| 7744 | clp = nfsd_find_client(addr, addr_size); | ||
| 7745 | if (clp) | ||
| 7746 | count = nfsd_find_all_delegations(clp, 0, &reaplist); | ||
| 7747 | spin_unlock(&nn->client_lock); | ||
| 7748 | |||
| 7749 | nfsd_forget_delegations(&reaplist); | ||
| 7750 | return count; | ||
| 7751 | } | ||
| 7752 | |||
| 7753 | u64 | ||
| 7754 | nfsd_inject_forget_delegations(u64 max) | ||
| 7755 | { | ||
| 7756 | u64 count = 0; | ||
| 7757 | struct nfs4_client *clp; | ||
| 7758 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7759 | nfsd_net_id); | ||
| 7760 | LIST_HEAD(reaplist); | ||
| 7761 | |||
| 7762 | if (!nfsd_netns_ready(nn)) | ||
| 7763 | return count; | ||
| 7764 | |||
| 7765 | spin_lock(&nn->client_lock); | ||
| 7766 | list_for_each_entry(clp, &nn->client_lru, cl_lru) { | ||
| 7767 | count += nfsd_find_all_delegations(clp, max - count, &reaplist); | ||
| 7768 | if (max != 0 && count >= max) | ||
| 7769 | break; | ||
| 7770 | } | ||
| 7771 | spin_unlock(&nn->client_lock); | ||
| 7772 | nfsd_forget_delegations(&reaplist); | ||
| 7773 | return count; | ||
| 7774 | } | ||
| 7775 | |||
| 7776 | static void | ||
| 7777 | nfsd_recall_delegations(struct list_head *reaplist) | ||
| 7778 | { | ||
| 7779 | struct nfs4_client *clp; | ||
| 7780 | struct nfs4_delegation *dp, *next; | ||
| 7781 | |||
| 7782 | list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) { | ||
| 7783 | list_del_init(&dp->dl_recall_lru); | ||
| 7784 | clp = dp->dl_stid.sc_client; | ||
| 7785 | |||
| 7786 | trace_nfsd_deleg_recall(&dp->dl_stid.sc_stateid); | ||
| 7787 | |||
| 7788 | /* | ||
| 7789 | * We skipped all entries that had a zero dl_time before, | ||
| 7790 | * so we can now reset the dl_time back to 0. If a delegation | ||
| 7791 | * break comes in now, then it won't make any difference since | ||
| 7792 | * we're recalling it either way. | ||
| 7793 | */ | ||
| 7794 | spin_lock(&state_lock); | ||
| 7795 | dp->dl_time = 0; | ||
| 7796 | spin_unlock(&state_lock); | ||
| 7797 | nfsd_break_one_deleg(dp); | ||
| 7798 | put_client(clp); | ||
| 7799 | } | ||
| 7800 | } | ||
| 7801 | |||
| 7802 | u64 | ||
| 7803 | nfsd_inject_recall_client_delegations(struct sockaddr_storage *addr, | ||
| 7804 | size_t addr_size) | ||
| 7805 | { | ||
| 7806 | u64 count = 0; | ||
| 7807 | struct nfs4_client *clp; | ||
| 7808 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7809 | nfsd_net_id); | ||
| 7810 | LIST_HEAD(reaplist); | ||
| 7811 | |||
| 7812 | if (!nfsd_netns_ready(nn)) | ||
| 7813 | return count; | ||
| 7814 | |||
| 7815 | spin_lock(&nn->client_lock); | ||
| 7816 | clp = nfsd_find_client(addr, addr_size); | ||
| 7817 | if (clp) | ||
| 7818 | count = nfsd_find_all_delegations(clp, 0, &reaplist); | ||
| 7819 | spin_unlock(&nn->client_lock); | ||
| 7820 | |||
| 7821 | nfsd_recall_delegations(&reaplist); | ||
| 7822 | return count; | ||
| 7823 | } | ||
| 7824 | |||
| 7825 | u64 | ||
| 7826 | nfsd_inject_recall_delegations(u64 max) | ||
| 7827 | { | ||
| 7828 | u64 count = 0; | ||
| 7829 | struct nfs4_client *clp, *next; | ||
| 7830 | struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, | ||
| 7831 | nfsd_net_id); | ||
| 7832 | LIST_HEAD(reaplist); | ||
| 7833 | |||
| 7834 | if (!nfsd_netns_ready(nn)) | ||
| 7835 | return count; | ||
| 7836 | |||
| 7837 | spin_lock(&nn->client_lock); | ||
| 7838 | list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) { | ||
| 7839 | count += nfsd_find_all_delegations(clp, max - count, &reaplist); | ||
| 7840 | if (max != 0 && ++count >= max) | ||
| 7841 | break; | ||
| 7842 | } | ||
| 7843 | spin_unlock(&nn->client_lock); | ||
| 7844 | nfsd_recall_delegations(&reaplist); | ||
| 7845 | return count; | ||
| 7846 | } | ||
| 7847 | #endif /* CONFIG_NFSD_FAULT_INJECTION */ | ||
| 7848 | |||
| 7849 | /* | 7256 | /* |
| 7850 | * Since the lifetime of a delegation isn't limited to that of an open, a | 7257 | * 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 has | 7258 | * client may quite reasonably hang on to a delegation as long as it has |
| @@ -1855,7 +1855,7 @@ static __be32 · 1854 unmodified lines | |||
| 1855 | nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp, | 1855 | nfsd4_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 | } else | 2267 | } 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 somewhere | 3823 | 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 | |||
| 4603 | static __be32 | ||
| 4604 | nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, | ||
| 4605 | struct nfsd4_read *read, | ||
| 4606 | unsigned long *maxcount, u32 *eof, | ||
| 4607 | loff_t *pos) | ||
| 4608 | { | ||
| 4609 | struct xdr_stream *xdr = &resp->xdr; | ||
| 4610 | struct file *file = read->rd_nf->nf_file; | ||
| 4611 | int starting_len = xdr->buf->len; | ||
| 4612 | loff_t hole_pos; | ||
| 4613 | __be32 nfserr; | ||
| 4614 | __be32 *p, tmp; | ||
| 4615 | __be64 tmp64; | ||
| 4616 | |||
| 4617 | hole_pos = pos ? *pos : vfs_llseek(file, read->rd_offset, SEEK_HOLE); | ||
| 4618 | if (hole_pos > read->rd_offset) | ||
| 4619 | *maxcount = min_t(unsigned long, *maxcount, hole_pos - read->rd_offset); | ||
| 4620 | *maxcount = min_t(unsigned long, *maxcount, (xdr->buf->buflen - xdr->buf->len)); | ||
| 4621 | |||
| 4622 | /* Content type, offset, byte count */ | ||
| 4623 | p = xdr_reserve_space(xdr, 4 + 8 + 4); | ||
| 4624 | if (!p) | ||
| 4625 | return nfserr_resource; | ||
| 4626 | |||
| 4627 | read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, *maxcount); | ||
| 4628 | if (read->rd_vlen < 0) | ||
| 4629 | return nfserr_resource; | ||
| 4630 | |||
| 4631 | nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, | ||
| 4632 | resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof); | ||
| 4633 | if (nfserr) | ||
| 4634 | return nfserr; | ||
| 4635 | |||
| 4636 | tmp = htonl(NFS4_CONTENT_DATA); | ||
| 4637 | write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); | ||
| 4638 | tmp64 = cpu_to_be64(read->rd_offset); | ||
| 4639 | write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp64, 8); | ||
| 4640 | tmp = htonl(*maxcount); | ||
| 4641 | write_bytes_to_xdr_buf(xdr->buf, starting_len + 12, &tmp, 4); | ||
| 4642 | return nfs_ok; | ||
| 4643 | } | ||
| 4644 | |||
| 4645 | static __be32 | ||
| 4646 | nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, | ||
| 4647 | struct nfsd4_read *read, | ||
| 4648 | unsigned long *maxcount, u32 *eof) | ||
| 4649 | { | ||
| 4650 | struct file *file = read->rd_nf->nf_file; | ||
| 4651 | loff_t data_pos = vfs_llseek(file, read->rd_offset, SEEK_DATA); | ||
| 4652 | loff_t f_size = i_size_read(file_inode(file)); | ||
| 4653 | unsigned long count; | ||
| 4654 | __be32 *p; | ||
| 4655 | |||
| 4656 | if (data_pos == -ENXIO) | ||
| 4657 | data_pos = f_size; | ||
| 4658 | else if (data_pos <= read->rd_offset || (data_pos < f_size && data_pos % PAGE_SIZE)) | ||
| 4659 | return nfsd4_encode_read_plus_data(resp, read, maxcount, eof, &f_size); | ||
| 4660 | count = data_pos - read->rd_offset; | ||
| 4661 | |||
| 4662 | /* Content type, offset, byte count */ | ||
| 4663 | p = xdr_reserve_space(&resp->xdr, 4 + 8 + 8); | ||
| 4664 | if (!p) | ||
| 4665 | return nfserr_resource; | ||
| 4666 | |||
| 4667 | *p++ = htonl(NFS4_CONTENT_HOLE); | ||
| 4668 | p = xdr_encode_hyper(p, read->rd_offset); | ||
| 4669 | p = xdr_encode_hyper(p, count); | ||
| 4670 | |||
| 4671 | *eof = (read->rd_offset + count) >= f_size; | ||
| 4672 | *maxcount = min_t(unsigned long, count, *maxcount); | ||
| 4673 | return nfs_ok; | ||
| 4674 | } | ||
| 4675 | |||
| 4676 | static __be32 | ||
| 4677 | nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
| 4678 | struct nfsd4_read *read) | ||
| 4679 | { | ||
| 4680 | unsigned long maxcount, count; | ||
| 4681 | struct xdr_stream *xdr = &resp->xdr; | ||
| 4682 | struct file *file; | ||
| 4683 | int starting_len = xdr->buf->len; | ||
| 4684 | int last_segment = xdr->buf->len; | ||
| 4685 | int segments = 0; | ||
| 4686 | __be32 *p, tmp; | ||
| 4687 | bool is_data; | ||
| 4688 | loff_t pos; | ||
| 4689 | u32 eof; | ||
| 4690 | |||
| 4691 | if (nfserr) | ||
| 4692 | return nfserr; | ||
| 4693 | file = read->rd_nf->nf_file; | ||
| 4694 | |||
| 4695 | /* eof flag, segment count */ | ||
| 4696 | p = xdr_reserve_space(xdr, 4 + 4); | ||
| 4697 | if (!p) | ||
| 4698 | return nfserr_resource; | ||
| 4699 | xdr_commit_encode(xdr); | ||
| 4700 | |||
| 4701 | maxcount = svc_max_payload(resp->rqstp); | ||
| 4702 | maxcount = min_t(unsigned long, maxcount, | ||
| 4703 | (xdr->buf->buflen - xdr->buf->len)); | ||
| 4704 | maxcount = min_t(unsigned long, maxcount, read->rd_length); | ||
| 4705 | count = maxcount; | ||
| 4706 | |||
| 4707 | eof = read->rd_offset >= i_size_read(file_inode(file)); | ||
| 4708 | if (eof) | ||
| 4709 | goto out; | ||
| 4710 | |||
| 4711 | pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE); | ||
| 4712 | is_data = pos > read->rd_offset; | ||
| 4713 | |||
| 4714 | while (count > 0 && !eof) { | ||
| 4715 | maxcount = count; | ||
| 4716 | if (is_data) | ||
| 4717 | nfserr = nfsd4_encode_read_plus_data(resp, read, &maxcount, &eof, | ||
| 4718 | segments == 0 ? &pos : NULL); | ||
| 4719 | else | ||
| 4720 | nfserr = nfsd4_encode_read_plus_hole(resp, read, &maxcount, &eof); | ||
| 4721 | if (nfserr) | ||
| 4722 | goto out; | ||
| 4723 | count -= maxcount; | ||
| 4724 | read->rd_offset += maxcount; | ||
| 4725 | is_data = !is_data; | ||
| 4726 | last_segment = xdr->buf->len; | ||
| 4727 | segments++; | ||
| 4728 | } | ||
| 4729 | |||
| 4730 | out: | ||
| 4731 | if (nfserr && segments == 0) | ||
| 4732 | xdr_truncate_encode(xdr, starting_len); | ||
| 4733 | else { | ||
| 4734 | tmp = htonl(eof); | ||
| 4735 | write_bytes_to_xdr_buf(xdr->buf, starting_len, &tmp, 4); | ||
| 4736 | tmp = htonl(segments); | ||
| 4737 | write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4); | ||
| 4738 | if (nfserr) { | ||
| 4739 | xdr_truncate_encode(xdr, last_segment); | ||
| 4740 | nfserr = nfs_ok; | ||
| 4741 | } | ||
| 4742 | } | ||
| 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 | */ |
| 4682 | static int | 4803 | static __be32 |
| 4683 | nfsd4_vbuf_to_stream(struct xdr_stream *xdr, char *buf, u32 buflen) | 4804 | nfsd4_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); |
| 4893 | out: | 5014 | out: |
| 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 | ||
| 5280 | int | ||
| 5281 | nfs4svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) | ||
| 5282 | { | ||
| 5283 | return 1; | ||
| 5284 | } | ||
| 5285 | |||
| 5159 | int | 5286 | int |
| 5160 | nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p) | 5287 | nfs4svc_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 | |||
| 5183 | int | 5310 | int |
| 5184 | nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p) | 5311 | nfs4svc_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; |
| @@ -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); |
| @@ -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(); |
| 1556 | out_free_stat: | 1555 | out_free_stat: |
| 1557 | nfsd_stat_shutdown(); | 1556 | nfsd_stat_shutdown(); |
| 1558 | nfsd_fault_inject_cleanup(); | ||
| 1559 | nfsd4_exit_pnfs(); | 1557 | nfsd4_exit_pnfs(); |
| 1560 | out_free_slabs: | 1558 | out_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); |
| @@ -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 | ||
| 14 | typedef struct svc_rqst svc_rqst; | ||
| 15 | typedef struct svc_buf svc_buf; | ||
| 16 | |||
| 17 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 14 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 18 | 15 | ||
| 19 | |||
| 20 | static __be32 | 16 | static __be32 |
| 21 | nfsd_proc_null(struct svc_rqst *rqstp) | 17 | nfsd_proc_null(struct svc_rqst *rqstp) |
| 22 | { | 18 | { |
| 23 | return nfs_ok; | 19 | return rpc_success; |
| 24 | } | 20 | } |
| 25 | 21 | ||
| 26 | static __be32 | ||
| 27 | nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp) | ||
| 28 | { | ||
| 29 | if (err) return err; | ||
| 30 | return fh_getattr(&resp->fh, &resp->stat); | ||
| 31 | } | ||
| 32 | static __be32 | ||
| 33 | nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp) | ||
| 34 | { | ||
| 35 | if (err) return err; | ||
| 36 | return fh_getattr(&resp->fh, &resp->stat); | ||
| 37 | } | ||
| 38 | /* | 22 | /* |
| 39 | * Get a file's attributes | 23 | * Get a file's attributes |
| 40 | * N.B. After this call resp->fh needs an fh_put | 24 | * 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); | ||
| 40 | out: | ||
| 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); |
| 117 | done: | 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); | ||
| 108 | out: | ||
| 109 | return rpc_success; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* Obsolete, replaced by MNTPROC_MNT. */ | ||
| 113 | static __be32 | ||
| 114 | nfsd_proc_root(struct svc_rqst *rqstp) | ||
| 115 | { | ||
| 116 | return rpc_success; | ||
| 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); | ||
| 142 | out: | ||
| 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 */ | ||
| 208 | static __be32 | ||
| 209 | nfsd_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; | ||
| 244 | out: | ||
| 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 tell | 302 | * 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-pipe | 335 | * echo thing > device-special-file-or-pipe |
| 322 | * by doing a CREATE with type==0 | 336 | * 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 | } else | 345 | } 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 | ||
| 386 | out_unlock: | 402 | out_unlock: |
| @@ -389,47 +405,52 @@ out_unlock: · 2 unmodified lines | |||
| 389 | fh_drop_write(dirfhp); | 405 | fh_drop_write(dirfhp); |
| 390 | done: | 406 | done: |
| 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); | ||
| 411 | out: | ||
| 412 | return rpc_success; | ||
| 393 | } | 413 | } |
| 394 | 414 | ||
| 395 | static __be32 | 415 | static __be32 |
| 396 | nfsd_proc_remove(struct svc_rqst *rqstp) | 416 | nfsd_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 | ||
| 410 | static __be32 | 431 | static __be32 |
| 411 | nfsd_proc_rename(struct svc_rqst *rqstp) | 432 | nfsd_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 | ||
| 428 | static __be32 | 449 | static __be32 |
| 429 | nfsd_proc_link(struct svc_rqst *rqstp) | 450 | nfsd_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 | ||
| 448 | static __be32 | 469 | static __be32 |
| 449 | nfsd_proc_symlink(struct svc_rqst *rqstp) | 470 | nfsd_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; | 500 | out: |
| 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); | ||
| 530 | out: | ||
| 531 | return rpc_success; | ||
| 502 | } | 532 | } |
| 503 | 533 | ||
| 504 | /* | 534 | /* |
| @@ -508,13 +538,14 @@ static __be32 · 3 unmodified lines | |||
| 508 | nfsd_proc_rmdir(struct svc_rqst *rqstp) | 538 | nfsd_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 | }, |
| @@ -960,15 +960,6 @@ out: · 959 unmodified lines | |||
| 960 | return 0; | 960 | return 0; |
| 961 | } | 961 | } |
| 962 | 962 | ||
| 963 | static __be32 map_new_errors(u32 vers, __be32 nfserr) | ||
| 964 | { | ||
| 965 | if (nfserr == nfserr_jukebox && vers == 2) | ||
| 966 | return nfserr_dropit; | ||
| 967 | if (nfserr == nfserr_wrongsec && vers < 4) | ||
| 968 | return nfserr_acces; | ||
| 969 | return nfserr; | ||
| 970 | } | ||
| 971 | |||
| 972 | /* | 963 | /* |
| 973 | * A write procedure can have a large argument, and a read procedure can | 964 | * 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 and | 965 | * 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 | ||
| 1003 | int | 994 | /** |
| 1004 | nfsd_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 | */ | ||
| 1005 | int 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 wants | 1019 | * 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, as | 1035 | /* |
| 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_base | 1039 | 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); |
| 1050 | out_cached_reply: | ||
| 1051 | return 1; | ||
| 1052 | |||
| 1053 | out_too_large: | ||
| 1054 | dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers); | ||
| 1055 | *statp = rpc_garbage_args; | ||
| 1056 | return 1; | ||
| 1057 | |||
| 1058 | out_decode_err: | ||
| 1059 | dprintk("nfsd: failed to decode arguments!\n"); | ||
| 1060 | *statp = rpc_garbage_args; | ||
| 1061 | return 1; | ||
| 1062 | |||
| 1063 | out_update_drop: | ||
| 1064 | dprintk("nfsd: Dropping request; may be revisited later\n"); | ||
| 1065 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | ||
| 1066 | out_dropit: | ||
| 1067 | return 0; | ||
| 1068 | |||
| 1069 | out_encode_err: | ||
| 1070 | dprintk("nfsd: failed to encode result!\n"); | ||
| 1071 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | ||
| 1072 | *statp = rpc_system_err; | ||
| 1077 | return 1; | 1073 | return 1; |
| 1078 | } | 1074 | } |
| 1079 | 1075 | ||
| @@ -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 | ||
| 432 | int | ||
| 433 | nfssvc_encode_stat(struct svc_rqst *rqstp, __be32 *p) | ||
| 434 | { | ||
| 435 | struct nfsd_stat *resp = rqstp->rq_resp; | ||
| 436 | |||
| 437 | *p++ = resp->status; | ||
| 438 | return xdr_ressize_check(rqstp, p); | ||
| 439 | } | ||
| 440 | |||
| 432 | int | 441 | int |
| 433 | nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) | 442 | nfssvc_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); |
| 450 | out: | ||
| 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); |
| 464 | out: | ||
| 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 functions | 595 | * XDR release functions |
| 563 | */ | 596 | */ |
| 564 | void | 597 | void nfssvc_release_attrstat(struct svc_rqst *rqstp) |
| 565 | nfssvc_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 | |||
| 604 | void nfssvc_release_diropres(struct svc_rqst *rqstp) | ||
| 605 | { | ||
| 606 | struct nfsd_diropres *resp = rqstp->rq_resp; | ||
| 607 | |||
| 608 | fh_put(&resp->fh); | ||
| 609 | } | ||
| 610 | |||
| 611 | void nfssvc_release_readres(struct svc_rqst *rqstp) | ||
| 612 | { | ||
| 613 | struct nfsd_readres *resp = rqstp->rq_resp; | ||
| 568 | 614 | ||
| 569 | fh_put(&resp->fh); | 615 | fh_put(&resp->fh); |
| 570 | } | 616 | } |
| @@ -693,31 +693,4 @@ extern void nfsd4_client_record_remove(struct nfs4_client *clp); · 692 unmodified lines | |||
| 693 | extern int nfsd4_client_record_check(struct nfs4_client *clp); | 693 | extern int nfsd4_client_record_check(struct nfs4_client *clp); |
| 694 | extern void nfsd4_record_grace_done(struct nfsd_net *nn); | 694 | extern void nfsd4_record_grace_done(struct nfsd_net *nn); |
| 695 | 695 | ||
| 696 | /* nfs fault injection functions */ | ||
| 697 | #ifdef CONFIG_NFSD_FAULT_INJECTION | ||
| 698 | void nfsd_fault_inject_init(void); | ||
| 699 | void nfsd_fault_inject_cleanup(void); | ||
| 700 | |||
| 701 | u64 nfsd_inject_print_clients(void); | ||
| 702 | u64 nfsd_inject_forget_client(struct sockaddr_storage *, size_t); | ||
| 703 | u64 nfsd_inject_forget_clients(u64); | ||
| 704 | |||
| 705 | u64 nfsd_inject_print_locks(void); | ||
| 706 | u64 nfsd_inject_forget_client_locks(struct sockaddr_storage *, size_t); | ||
| 707 | u64 nfsd_inject_forget_locks(u64); | ||
| 708 | |||
| 709 | u64 nfsd_inject_print_openowners(void); | ||
| 710 | u64 nfsd_inject_forget_client_openowners(struct sockaddr_storage *, size_t); | ||
| 711 | u64 nfsd_inject_forget_openowners(u64); | ||
| 712 | |||
| 713 | u64 nfsd_inject_print_delegations(void); | ||
| 714 | u64 nfsd_inject_forget_client_delegations(struct sockaddr_storage *, size_t); | ||
| 715 | u64 nfsd_inject_forget_delegations(u64); | ||
| 716 | u64 nfsd_inject_recall_client_delegations(struct sockaddr_storage *, size_t); | ||
| 717 | u64 nfsd_inject_recall_delegations(u64); | ||
| 718 | #else /* CONFIG_NFSD_FAULT_INJECTION */ | ||
| 719 | static inline void nfsd_fault_inject_init(void) {} | ||
| 720 | static inline void nfsd_fault_inject_cleanup(void) {} | ||
| 721 | #endif /* CONFIG_NFSD_FAULT_INJECTION */ | ||
| 722 | |||
| 723 | #endif /* NFSD4_STATE_H */ | 696 | #endif /* NFSD4_STATE_H */ |
| @@ -289,8 +289,8 @@ DEFINE_STATEID_EVENT(layout_recall_done); · 288 unmodified lines | |||
| 289 | DEFINE_STATEID_EVENT(layout_recall_fail); | 289 | DEFINE_STATEID_EVENT(layout_recall_fail); |
| 290 | DEFINE_STATEID_EVENT(layout_recall_release); | 290 | DEFINE_STATEID_EVENT(layout_recall_release); |
| 291 | 291 | ||
| 292 | DEFINE_STATEID_EVENT(deleg_open); | 292 | DEFINE_STATEID_EVENT(open); |
| 293 | DEFINE_STATEID_EVENT(deleg_none); | 293 | DEFINE_STATEID_EVENT(deleg_read); |
| 294 | DEFINE_STATEID_EVENT(deleg_break); | 294 | DEFINE_STATEID_EVENT(deleg_break); |
| 295 | DEFINE_STATEID_EVENT(deleg_recall); | 295 | DEFINE_STATEID_EVENT(deleg_recall); |
| 296 | 296 | ||
| @@ -2259,7 +2259,8 @@ out: · 2258 unmodified lines | |||
| 2259 | __be32 | 2259 | __be32 |
| 2260 | nfsd_removexattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name) | 2260 | nfsd_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 | |||
| 2283 | nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name, | 2284 | nfsd_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) |
| @@ -82,27 +82,37 @@ struct nfsd_readdirargs { · 81 unmodified lines | |||
| 82 | __be32 * buffer; | 82 | __be32 * buffer; |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | struct nfsd_stat { | ||
| 86 | __be32 status; | ||
| 87 | }; | ||
| 88 | |||
| 85 | struct nfsd_attrstat { | 89 | struct 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 | ||
| 90 | struct nfsd_diropres { | 95 | struct 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 | ||
| 95 | struct nfsd_readlinkres { | 101 | struct nfsd_readlinkres { |
| 102 | __be32 status; | ||
| 96 | int len; | 103 | int len; |
| 97 | }; | 104 | }; |
| 98 | 105 | ||
| 99 | struct nfsd_readres { | 106 | struct 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 | ||
| 105 | struct nfsd_readdirres { | 113 | struct 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 | ||
| 114 | struct nfsd_statfsres { | 124 | struct 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 | |||
| 146 | int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *); | 157 | int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *); |
| 147 | int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *); | 158 | int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *); |
| 148 | int nfssvc_encode_void(struct svc_rqst *, __be32 *); | 159 | int nfssvc_encode_void(struct svc_rqst *, __be32 *); |
| 160 | int nfssvc_encode_stat(struct svc_rqst *, __be32 *); | ||
| 149 | int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *); | 161 | int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *); |
| 150 | int nfssvc_encode_diropres(struct svc_rqst *, __be32 *); | 162 | int nfssvc_encode_diropres(struct svc_rqst *, __be32 *); |
| 151 | int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *); | 163 | int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *); |
| @@ -156,7 +168,9 @@ int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *); · 4 unmodified lines | |||
| 156 | int nfssvc_encode_entry(void *, const char *name, | 168 | int 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 | ||
| 159 | void nfssvc_release_fhandle(struct svc_rqst *); | 171 | void nfssvc_release_attrstat(struct svc_rqst *rqstp); |
| 172 | void nfssvc_release_diropres(struct svc_rqst *rqstp); | ||
| 173 | void nfssvc_release_readres(struct svc_rqst *rqstp); | ||
| 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); |
| @@ -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 | ||
| 276 | int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *); | ||
| 276 | int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *); | 277 | int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *); |
| 277 | int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *); | 278 | int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *); |
| 278 | int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *); | 279 | int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *); |
| @@ -781,6 +781,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) · 780 unmodified lines | |||
| 781 | 781 | ||
| 782 | 782 | ||
| 783 | bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp); | 783 | bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp); |
| 784 | int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *); | ||
| 784 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *); | 785 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *); |
| 785 | int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *); | 786 | int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *); |
| 786 | int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *); | 787 | int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *); |
| @@ -0,0 +1,67 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * include/linux/nfs_ssc.h | ||
| 4 | * | ||
| 5 | * Author: Dai Ngo <dai.ngo@oracle.com> | ||
| 6 | * | ||
| 7 | * Copyright (c) 2020, Oracle and/or its affiliates. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/nfs_fs.h> | ||
| 11 | |||
| 12 | extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl; | ||
| 13 | |||
| 14 | /* | ||
| 15 | * NFS_V4 | ||
| 16 | */ | ||
| 17 | struct nfs4_ssc_client_ops { | ||
| 18 | struct file *(*sco_open)(struct vfsmount *ss_mnt, | ||
| 19 | struct nfs_fh *src_fh, nfs4_stateid *stateid); | ||
| 20 | void (*sco_close)(struct file *filep); | ||
| 21 | }; | ||
| 22 | |||
| 23 | /* | ||
| 24 | * NFS_FS | ||
| 25 | */ | ||
| 26 | struct nfs_ssc_client_ops { | ||
| 27 | void (*sco_sb_deactive)(struct super_block *sb); | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct nfs_ssc_client_ops_tbl { | ||
| 31 | const struct nfs4_ssc_client_ops *ssc_nfs4_ops; | ||
| 32 | const struct nfs_ssc_client_ops *ssc_nfs_ops; | ||
| 33 | }; | ||
| 34 | |||
| 35 | extern void nfs42_ssc_register_ops(void); | ||
| 36 | extern void nfs42_ssc_unregister_ops(void); | ||
| 37 | |||
| 38 | extern void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops); | ||
| 39 | extern void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops); | ||
| 40 | |||
| 41 | #ifdef CONFIG_NFSD_V4_2_INTER_SSC | ||
| 42 | static inline struct file *nfs42_ssc_open(struct vfsmount *ss_mnt, | ||
| 43 | struct nfs_fh *src_fh, nfs4_stateid *stateid) | ||
| 44 | { | ||
| 45 | if (nfs_ssc_client_tbl.ssc_nfs4_ops) | ||
| 46 | return (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_open)(ss_mnt, src_fh, stateid); | ||
| 47 | return ERR_PTR(-EIO); | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline void nfs42_ssc_close(struct file *filep) | ||
| 51 | { | ||
| 52 | if (nfs_ssc_client_tbl.ssc_nfs4_ops) | ||
| 53 | (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep); | ||
| 54 | } | ||
| 55 | #endif | ||
| 56 | |||
| 57 | /* | ||
| 58 | * NFS_FS | ||
| 59 | */ | ||
| 60 | extern void nfs_ssc_register(const struct nfs_ssc_client_ops *ops); | ||
| 61 | extern void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops); | ||
| 62 | |||
| 63 | static inline void nfs_do_sb_deactive(struct super_block *sb) | ||
| 64 | { | ||
| 65 | if (nfs_ssc_client_tbl.ssc_nfs_ops) | ||
| 66 | (*nfs_ssc_client_tbl.ssc_nfs_ops->sco_sb_deactive)(sb); | ||
| 67 | } | ||
| @@ -234,6 +234,8 @@ typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr, · 233 unmodified lines | |||
| 234 | extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, | 234 | extern 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); |
| 236 | extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); | 236 | extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); |
| 237 | extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, | ||
| 238 | size_t nbytes); | ||
| 237 | extern void xdr_commit_encode(struct xdr_stream *xdr); | 239 | extern void xdr_commit_encode(struct xdr_stream *xdr); |
| 238 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); | 240 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); |
| 239 | extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); | 241 | extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); |
| @@ -9,11 +9,13 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | #define NFS_ACL_PROGRAM 100227 | 10 | #define NFS_ACL_PROGRAM 100227 |
| 11 | 11 | ||
| 12 | #define ACLPROC2_NULL 0 | ||
| 12 | #define ACLPROC2_GETACL 1 | 13 | #define ACLPROC2_GETACL 1 |
| 13 | #define ACLPROC2_SETACL 2 | 14 | #define ACLPROC2_SETACL 2 |
| 14 | #define ACLPROC2_GETATTR 3 | 15 | #define ACLPROC2_GETATTR 3 |
| 15 | #define ACLPROC2_ACCESS 4 | 16 | #define ACLPROC2_ACCESS 4 |
| 16 | 17 | ||
| 18 | #define ACLPROC3_NULL 0 | ||
| 17 | #define ACLPROC3_GETACL 1 | 19 | #define ACLPROC3_GETACL 1 |
| 18 | #define ACLPROC3_SETACL 2 | 20 | #define ACLPROC3_SETACL 2 |
| 19 | 21 | ||
| @@ -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 | } |
| @@ -111,7 +111,7 @@ out_free: · 110 unmodified lines | |||
| 111 | * by the backchannel. This function can be called multiple times | 111 | * by the backchannel. This function can be called multiple times |
| 112 | * when creating new sessions that use the same rpc_xprt. The | 112 | * when creating new sessions that use the same rpc_xprt. The |
| 113 | * preallocated buffers are added to the pool of resources used by | 113 | * preallocated buffers are added to the pool of resources used by |
| 114 | * the rpc_xprt. Anyone of these resources may be used used by an | 114 | * the rpc_xprt. Any one of these resources may be used by an |
| 115 | * incoming callback request. It's up to the higher levels in the | 115 | * incoming callback request. It's up to the higher levels in the |
| 116 | * stack to enforce that the maximum number of session slots is not | 116 | * stack to enforce that the maximum number of session slots is not |
| 117 | * being exceeded. | 117 | * being exceeded. |
| @@ -498,16 +498,17 @@ static int cache_clean(void) · 497 unmodified lines | |||
| 498 | */ | 498 | */ |
| 499 | static void do_cache_clean(struct work_struct *work) | 499 | static 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 | |||
| 908 | static ssize_t cache_slow_downcall(const char __user *buf, | 909 | static 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 | ||
| @@ -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 | ||
| 76 | static int | 82 | static int |
| @@ -792,6 +792,51 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) · 791 unmodified lines | |||
| 792 | } | 792 | } |
| 793 | EXPORT_SYMBOL_GPL(xdr_reserve_space); | 793 | EXPORT_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 | */ | ||
| 807 | int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, size_t nbytes) | ||
| 808 | { | ||
| 809 | int thislen; | ||
| 810 | int v = 0; | ||
| 811 | __be32 *p; | ||
| 812 | |||
| 813 | /* | ||
| 814 | * svcrdma requires every READ payload to start somewhere | ||
| 815 | * in xdr->pages. | ||
| 816 | */ | ||
| 817 | if (xdr->iov == xdr->buf->head) { | ||
| 818 | xdr->iov = NULL; | ||
| 819 | xdr->end = xdr->p; | ||
| 820 | } | ||
| 821 | |||
| 822 | while (nbytes) { | ||
| 823 | thislen = xdr->buf->page_len % PAGE_SIZE; | ||
| 824 | thislen = min_t(size_t, nbytes, PAGE_SIZE - thislen); | ||
| 825 | |||
| 826 | p = xdr_reserve_space(xdr, thislen); | ||
| 827 | if (!p) | ||
| 828 | return -EIO; | ||
| 829 | |||
| 830 | vec[v].iov_base = p; | ||
| 831 | vec[v].iov_len = thislen; | ||
| 832 | v++; | ||
| 833 | nbytes -= thislen; | ||
| 834 | } | ||
| 835 | |||
| 836 | return v; | ||
| 837 | } | ||
| 838 | EXPORT_SYMBOL_GPL(xdr_reserve_space_vec); | ||
| 839 | |||
| 795 | /** | 840 | /** |
| 796 | * xdr_truncate_encode - truncate an encode buffer | 841 | * xdr_truncate_encode - truncate an encode buffer |
| 797 | * @xdr: pointer to xdr_stream | 842 | * @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 that | 849 | * 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 head | 851 | * 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 | * |
| @@ -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 Write | 139 | /* A chunk context tracks all I/O for moving one Read or Write |
| 140 | * chunk. This is a a set of rdma_rw's that handle data movement | 140 | * chunk. This is a set of rdma_rw's that handle data movement |
| 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, and | 143 | * These are small, acquired with a single allocator call, and |
| @@ -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 | ||
| @@ -1,50 +0,0 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | # | ||
| 4 | # Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com> | ||
| 5 | # | ||
| 6 | # Script for easier NFSD fault injection | ||
| 7 | |||
| 8 | # Check that debugfs has been mounted | ||
| 9 | DEBUGFS=`cat /proc/mounts | grep debugfs` | ||
| 10 | if [ "$DEBUGFS" == "" ]; then | ||
| 11 | echo "debugfs does not appear to be mounted!" | ||
| 12 | echo "Please mount debugfs and try again" | ||
| 13 | exit 1 | ||
| 14 | fi | ||
| 15 | |||
| 16 | # Check that the fault injection directory exists | ||
| 17 | DEBUGDIR=`echo $DEBUGFS | awk '{print $2}'`/nfsd | ||
| 18 | if [ ! -d "$DEBUGDIR" ]; then | ||
| 19 | echo "$DEBUGDIR does not exist" | ||
| 20 | echo "Check that your .config selects CONFIG_NFSD_FAULT_INJECTION" | ||
| 21 | exit 1 | ||
| 22 | fi | ||
| 23 | |||
| 24 | function help() | ||
| 25 | { | ||
| 26 | echo "Usage $0 injection_type [count]" | ||
| 27 | echo "" | ||
| 28 | echo "Injection types are:" | ||
| 29 | ls $DEBUGDIR | ||
| 30 | exit 1 | ||
| 31 | } | ||
| 32 | |||
| 33 | if [ $# == 0 ]; then | ||
| 34 | help | ||
| 35 | elif [ ! -f $DEBUGDIR/$1 ]; then | ||
| 36 | help | ||
| 37 | elif [ $# != 2 ]; then | ||
| 38 | COUNT=0 | ||
| 39 | else | ||
| 40 | COUNT=$2 | ||
| 41 | fi | ||
| 42 | |||
| 43 | BEFORE=`mktemp` | ||
| 44 | AFTER=`mktemp` | ||
| 45 | dmesg > $BEFORE | ||
| 46 | echo $COUNT > $DEBUGDIR/$1 | ||
| 47 | dmesg > $AFTER | ||
| 48 | # Capture lines that only exist in the $AFTER file | ||
| 49 | diff $BEFORE $AFTER | grep ">" | ||
| 50 | rm -f $BEFORE $AFTER | ||