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 | 12 | nfs-idmapper |
| 13 | 13 | pnfs-block-server |
| 14 | 14 | pnfs-scsi-server |
| 15 | − fault_injection | |
| @@ -13,10 +13,9 @@ RPCGSS is specified in a few IETF documents: · 12 unmodified lines | ||
| 13 | 13 | - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt |
| 14 | 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 | |
| 19 | − (At draft n. 02 at the time of writing) | |
| 18 | + - RFC7861 v3: https://tools.ietf.org/rfc/rfc7861.txt | |
| 20 | 19 | |
| 21 | 20 | Background |
| 22 | 21 | ========== |
| @@ -9556,6 +9556,7 @@ F: include/linux/sunrpc/ · 9555 unmodified lines | ||
| 9556 | 9556 | F: include/uapi/linux/nfsd/ |
| 9557 | 9557 | F: include/uapi/linux/sunrpc/ |
| 9558 | 9558 | F: net/sunrpc/ |
| 9559 | +F: Documentation/filesystems/nfs/ | |
| 9559 | 9560 | |
| 9560 | 9561 | KERNEL SELFTEST FRAMEWORK |
| 9561 | 9562 | M: Shuah Khan <shuah@kernel.org> |
| @@ -12337,6 +12338,7 @@ F: include/linux/sunrpc/ · 2775 unmodified lines | ||
| 12337 | 12338 | F: include/uapi/linux/nfs* |
| 12338 | 12339 | F: include/uapi/linux/sunrpc/ |
| 12339 | 12340 | F: net/sunrpc/ |
| 12341 | +F: Documentation/filesystems/nfs/ | |
| 12340 | 12342 | |
| 12341 | 12343 | NILFS2 FILESYSTEM |
| 12342 | 12344 | M: Ryusuke Konishi <konishi.ryusuke@gmail.com> |
| @@ -486,65 +486,215 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp) · 485 unmodified lines | ||
| 486 | 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 | 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 | 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 | 502 | #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ |
| 520 | 503 | #define No (1+1024/4) /* netobj */ |
| 521 | 504 | #define St 1 /* status */ |
| 522 | 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 | 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 | 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 | 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 | 544 | #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ |
| 563 | 545 | #define St 1 /* status */ |
| 564 | 546 | #define No (1+1024/4) /* Net Obj */ |
| 565 | 547 | #define Rg 2 /* range - offset + size */ |
| 566 | 548 | |
| 567 | −const struct svc_procedure nlmsvc_procedures[] = { | |
| 568 | − PROC(null, void, void, void, void, 1), | |
| 569 | − PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg), | |
| 570 | − PROC(lock, lockargs, res, args, res, Ck+St), | |
| 571 | − PROC(cancel, cancargs, res, args, res, Ck+St), | |
| 572 | − PROC(unlock, unlockargs, res, args, res, Ck+St), | |
| 573 | − PROC(granted, testargs, res, args, res, Ck+St), | |
| 574 | − PROC(test_msg, testargs, norep, args, void, 1), | |
| 575 | − PROC(lock_msg, lockargs, norep, args, void, 1), | |
| 576 | − PROC(cancel_msg, cancargs, norep, args, void, 1), | |
| 577 | − PROC(unlock_msg, unlockargs, norep, args, void, 1), | |
| 578 | − PROC(granted_msg, testargs, norep, args, void, 1), | |
| 579 | − PROC(test_res, testres, norep, res, void, 1), | |
| 580 | − PROC(lock_res, lockres, norep, res, void, 1), | |
| 581 | − PROC(cancel_res, cancelres, norep, res, void, 1), | |
| 582 | − PROC(unlock_res, unlockres, norep, res, void, 1), | |
| 583 | − PROC(granted_res, res, norep, res, void, 1), | |
| 584 | − /* statd callback */ | |
| 585 | − PROC(sm_notify, reboot, void, reboot, void, 1), | |
| 586 | − PROC(none, void, void, void, void, 1), | |
| 587 | − PROC(none, void, void, void, void, 1), | |
| 588 | − PROC(none, void, void, void, void, 1), | |
| 589 | − PROC(share, shareargs, shareres, args, res, Ck+St+1), | |
| 590 | − PROC(unshare, shareargs, shareres, args, res, Ck+St+1), | |
| 591 | − PROC(nm_lock, lockargs, res, args, res, Ck+St), | |
| 592 | − PROC(free_all, notify, void, args, void, 0), | |
| 593 | − | |
| 549 | +const struct svc_procedure nlmsvc_procedures[24] = { | |
| 550 | + [NLMPROC_NULL] = { | |
| 551 | + .pc_func = nlmsvc_proc_null, | |
| 552 | + .pc_decode = nlmsvc_decode_void, | |
| 553 | + .pc_encode = nlmsvc_encode_void, | |
| 554 | + .pc_argsize = sizeof(struct nlm_void), | |
| 555 | + .pc_ressize = sizeof(struct nlm_void), | |
| 556 | + .pc_xdrressize = St, | |
| 557 | + }, | |
| 558 | + [NLMPROC_TEST] = { | |
| 559 | + .pc_func = nlmsvc_proc_test, | |
| 560 | + .pc_decode = nlmsvc_decode_testargs, | |
| 561 | + .pc_encode = nlmsvc_encode_testres, | |
| 562 | + .pc_argsize = sizeof(struct nlm_args), | |
| 563 | + .pc_ressize = sizeof(struct nlm_res), | |
| 564 | + .pc_xdrressize = Ck+St+2+No+Rg, | |
| 565 | + }, | |
| 566 | + [NLMPROC_LOCK] = { | |
| 567 | + .pc_func = nlmsvc_proc_lock, | |
| 568 | + .pc_decode = nlmsvc_decode_lockargs, | |
| 569 | + .pc_encode = nlmsvc_encode_res, | |
| 570 | + .pc_argsize = sizeof(struct nlm_args), | |
| 571 | + .pc_ressize = sizeof(struct nlm_res), | |
| 572 | + .pc_xdrressize = Ck+St, | |
| 573 | + }, | |
| 574 | + [NLMPROC_CANCEL] = { | |
| 575 | + .pc_func = nlmsvc_proc_cancel, | |
| 576 | + .pc_decode = nlmsvc_decode_cancargs, | |
| 577 | + .pc_encode = nlmsvc_encode_res, | |
| 578 | + .pc_argsize = sizeof(struct nlm_args), | |
| 579 | + .pc_ressize = sizeof(struct nlm_res), | |
| 580 | + .pc_xdrressize = Ck+St, | |
| 581 | + }, | |
| 582 | + [NLMPROC_UNLOCK] = { | |
| 583 | + .pc_func = nlmsvc_proc_unlock, | |
| 584 | + .pc_decode = nlmsvc_decode_unlockargs, | |
| 585 | + .pc_encode = nlmsvc_encode_res, | |
| 586 | + .pc_argsize = sizeof(struct nlm_args), | |
| 587 | + .pc_ressize = sizeof(struct nlm_res), | |
| 588 | + .pc_xdrressize = Ck+St, | |
| 589 | + }, | |
| 590 | + [NLMPROC_GRANTED] = { | |
| 591 | + .pc_func = nlmsvc_proc_granted, | |
| 592 | + .pc_decode = nlmsvc_decode_testargs, | |
| 593 | + .pc_encode = nlmsvc_encode_res, | |
| 594 | + .pc_argsize = sizeof(struct nlm_args), | |
| 595 | + .pc_ressize = sizeof(struct nlm_res), | |
| 596 | + .pc_xdrressize = Ck+St, | |
| 597 | + }, | |
| 598 | + [NLMPROC_TEST_MSG] = { | |
| 599 | + .pc_func = nlmsvc_proc_test_msg, | |
| 600 | + .pc_decode = nlmsvc_decode_testargs, | |
| 601 | + .pc_encode = nlmsvc_encode_void, | |
| 602 | + .pc_argsize = sizeof(struct nlm_args), | |
| 603 | + .pc_ressize = sizeof(struct nlm_void), | |
| 604 | + .pc_xdrressize = St, | |
| 605 | + }, | |
| 606 | + [NLMPROC_LOCK_MSG] = { | |
| 607 | + .pc_func = nlmsvc_proc_lock_msg, | |
| 608 | + .pc_decode = nlmsvc_decode_lockargs, | |
| 609 | + .pc_encode = nlmsvc_encode_void, | |
| 610 | + .pc_argsize = sizeof(struct nlm_args), | |
| 611 | + .pc_ressize = sizeof(struct nlm_void), | |
| 612 | + .pc_xdrressize = St, | |
| 613 | + }, | |
| 614 | + [NLMPROC_CANCEL_MSG] = { | |
| 615 | + .pc_func = nlmsvc_proc_cancel_msg, | |
| 616 | + .pc_decode = nlmsvc_decode_cancargs, | |
| 617 | + .pc_encode = nlmsvc_encode_void, | |
| 618 | + .pc_argsize = sizeof(struct nlm_args), | |
| 619 | + .pc_ressize = sizeof(struct nlm_void), | |
| 620 | + .pc_xdrressize = St, | |
| 621 | + }, | |
| 622 | + [NLMPROC_UNLOCK_MSG] = { | |
| 623 | + .pc_func = nlmsvc_proc_unlock_msg, | |
| 624 | + .pc_decode = nlmsvc_decode_unlockargs, | |
| 625 | + .pc_encode = nlmsvc_encode_void, | |
| 626 | + .pc_argsize = sizeof(struct nlm_args), | |
| 627 | + .pc_ressize = sizeof(struct nlm_void), | |
| 628 | + .pc_xdrressize = St, | |
| 629 | + }, | |
| 630 | + [NLMPROC_GRANTED_MSG] = { | |
| 631 | + .pc_func = nlmsvc_proc_granted_msg, | |
| 632 | + .pc_decode = nlmsvc_decode_testargs, | |
| 633 | + .pc_encode = nlmsvc_encode_void, | |
| 634 | + .pc_argsize = sizeof(struct nlm_args), | |
| 635 | + .pc_ressize = sizeof(struct nlm_void), | |
| 636 | + .pc_xdrressize = St, | |
| 637 | + }, | |
| 638 | + [NLMPROC_TEST_RES] = { | |
| 639 | + .pc_func = nlmsvc_proc_null, | |
| 640 | + .pc_decode = nlmsvc_decode_void, | |
| 641 | + .pc_encode = nlmsvc_encode_void, | |
| 642 | + .pc_argsize = sizeof(struct nlm_res), | |
| 643 | + .pc_ressize = sizeof(struct nlm_void), | |
| 644 | + .pc_xdrressize = St, | |
| 645 | + }, | |
| 646 | + [NLMPROC_LOCK_RES] = { | |
| 647 | + .pc_func = nlmsvc_proc_null, | |
| 648 | + .pc_decode = nlmsvc_decode_void, | |
| 649 | + .pc_encode = nlmsvc_encode_void, | |
| 650 | + .pc_argsize = sizeof(struct nlm_res), | |
| 651 | + .pc_ressize = sizeof(struct nlm_void), | |
| 652 | + .pc_xdrressize = St, | |
| 653 | + }, | |
| 654 | + [NLMPROC_CANCEL_RES] = { | |
| 655 | + .pc_func = nlmsvc_proc_null, | |
| 656 | + .pc_decode = nlmsvc_decode_void, | |
| 657 | + .pc_encode = nlmsvc_encode_void, | |
| 658 | + .pc_argsize = sizeof(struct nlm_res), | |
| 659 | + .pc_ressize = sizeof(struct nlm_void), | |
| 660 | + .pc_xdrressize = St, | |
| 661 | + }, | |
| 662 | + [NLMPROC_UNLOCK_RES] = { | |
| 663 | + .pc_func = nlmsvc_proc_null, | |
| 664 | + .pc_decode = nlmsvc_decode_void, | |
| 665 | + .pc_encode = nlmsvc_encode_void, | |
| 666 | + .pc_argsize = sizeof(struct nlm_res), | |
| 667 | + .pc_ressize = sizeof(struct nlm_void), | |
| 668 | + .pc_xdrressize = St, | |
| 669 | + }, | |
| 670 | + [NLMPROC_GRANTED_RES] = { | |
| 671 | + .pc_func = nlmsvc_proc_granted_res, | |
| 672 | + .pc_decode = nlmsvc_decode_res, | |
| 673 | + .pc_encode = nlmsvc_encode_void, | |
| 674 | + .pc_argsize = sizeof(struct nlm_res), | |
| 675 | + .pc_ressize = sizeof(struct nlm_void), | |
| 676 | + .pc_xdrressize = St, | |
| 677 | + }, | |
| 678 | + [NLMPROC_NSM_NOTIFY] = { | |
| 679 | + .pc_func = nlmsvc_proc_sm_notify, | |
| 680 | + .pc_decode = nlmsvc_decode_reboot, | |
| 681 | + .pc_encode = nlmsvc_encode_void, | |
| 682 | + .pc_argsize = sizeof(struct nlm_reboot), | |
| 683 | + .pc_ressize = sizeof(struct nlm_void), | |
| 684 | + .pc_xdrressize = St, | |
| 685 | + }, | |
| 686 | + [17] = { | |
| 687 | + .pc_func = nlmsvc_proc_unused, | |
| 688 | + .pc_decode = nlmsvc_decode_void, | |
| 689 | + .pc_encode = nlmsvc_encode_void, | |
| 690 | + .pc_argsize = sizeof(struct nlm_void), | |
| 691 | + .pc_ressize = sizeof(struct nlm_void), | |
| 692 | + .pc_xdrressize = St, | |
| 693 | + }, | |
| 694 | + [18] = { | |
| 695 | + .pc_func = nlmsvc_proc_unused, | |
| 696 | + .pc_decode = nlmsvc_decode_void, | |
| 697 | + .pc_encode = nlmsvc_encode_void, | |
| 698 | + .pc_argsize = sizeof(struct nlm_void), | |
| 699 | + .pc_ressize = sizeof(struct nlm_void), | |
| 700 | + .pc_xdrressize = St, | |
| 701 | + }, | |
| 702 | + [19] = { | |
| 703 | + .pc_func = nlmsvc_proc_unused, | |
| 704 | + .pc_decode = nlmsvc_decode_void, | |
| 705 | + .pc_encode = nlmsvc_encode_void, | |
| 706 | + .pc_argsize = sizeof(struct nlm_void), | |
| 707 | + .pc_ressize = sizeof(struct nlm_void), | |
| 708 | + .pc_xdrressize = St, | |
| 709 | + }, | |
| 710 | + [NLMPROC_SHARE] = { | |
| 711 | + .pc_func = nlmsvc_proc_share, | |
| 712 | + .pc_decode = nlmsvc_decode_shareargs, | |
| 713 | + .pc_encode = nlmsvc_encode_shareres, | |
| 714 | + .pc_argsize = sizeof(struct nlm_args), | |
| 715 | + .pc_ressize = sizeof(struct nlm_res), | |
| 716 | + .pc_xdrressize = Ck+St+1, | |
| 717 | + }, | |
| 718 | + [NLMPROC_UNSHARE] = { | |
| 719 | + .pc_func = nlmsvc_proc_unshare, | |
| 720 | + .pc_decode = nlmsvc_decode_shareargs, | |
| 721 | + .pc_encode = nlmsvc_encode_shareres, | |
| 722 | + .pc_argsize = sizeof(struct nlm_args), | |
| 723 | + .pc_ressize = sizeof(struct nlm_res), | |
| 724 | + .pc_xdrressize = Ck+St+1, | |
| 725 | + }, | |
| 726 | + [NLMPROC_NM_LOCK] = { | |
| 727 | + .pc_func = nlmsvc_proc_nm_lock, | |
| 728 | + .pc_decode = nlmsvc_decode_lockargs, | |
| 729 | + .pc_encode = nlmsvc_encode_res, | |
| 730 | + .pc_argsize = sizeof(struct nlm_args), | |
| 731 | + .pc_ressize = sizeof(struct nlm_res), | |
| 732 | + .pc_xdrressize = Ck+St, | |
| 733 | + }, | |
| 734 | + [NLMPROC_FREE_ALL] = { | |
| 735 | + .pc_func = nlmsvc_proc_free_all, | |
| 736 | + .pc_decode = nlmsvc_decode_notify, | |
| 737 | + .pc_encode = nlmsvc_encode_void, | |
| 738 | + .pc_argsize = sizeof(struct nlm_args), | |
| 739 | + .pc_ressize = sizeof(struct nlm_void), | |
| 740 | + .pc_xdrressize = 0, | |
| 741 | + }, | |
| 594 | 742 | }; |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/falloc.h> |
| 10 | 10 | #include <linux/mount.h> |
| 11 | 11 | #include <linux/nfs_fs.h> |
| 12 | +#include <linux/nfs_ssc.h> | |
| 12 | 13 | #include "delegation.h" |
| 13 | 14 | #include "internal.h" |
| 14 | 15 | #include "iostat.h" |
| @@ -315,9 +316,8 @@ out: · 300 unmodified lines | ||
| 315 | 316 | static int read_name_gen = 1; |
| 316 | 317 | #define SSC_READ_NAME_BODY "ssc_read_%d" |
| 317 | 318 | |
| 318 | −struct file * | |
| 319 | −nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, | |
| 320 | − nfs4_stateid *stateid) | |
| 319 | +static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt, | |
| 320 | + struct nfs_fh *src_fh, nfs4_stateid *stateid) | |
| 321 | 321 | { |
| 322 | 322 | struct nfs_fattr fattr; |
| 323 | 323 | struct file *filep, *res; |
| @@ -399,14 +399,40 @@ out_filep: · 75 unmodified lines | ||
| 399 | 399 | fput(filep); |
| 400 | 400 | goto out_free_name; |
| 401 | 401 | } |
| 402 | −EXPORT_SYMBOL_GPL(nfs42_ssc_open); | |
| 403 | −void nfs42_ssc_close(struct file *filep) | |
| 402 | + | |
| 403 | +static void __nfs42_ssc_close(struct file *filep) | |
| 404 | 404 | { |
| 405 | 405 | struct nfs_open_context *ctx = nfs_file_open_context(filep); |
| 406 | 406 | |
| 407 | 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 | 436 | #endif /* CONFIG_NFS_V4_2 */ |
| 411 | 437 | |
| 412 | 438 | const struct file_operations nfs4_file_operations = { |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/mount.h> |
| 8 | 8 | #include <linux/nfs4_mount.h> |
| 9 | 9 | #include <linux/nfs_fs.h> |
| 10 | +#include <linux/nfs_ssc.h> | |
| 10 | 11 | #include "delegation.h" |
| 11 | 12 | #include "internal.h" |
| 12 | 13 | #include "nfs4_fs.h" |
| @@ -279,6 +280,9 @@ static int __init init_nfs_v4(void) · 266 unmodified lines | ||
| 279 | 280 | if (err) |
| 280 | 281 | goto out2; |
| 281 | 282 | |
| 283 | +#ifdef CONFIG_NFS_V4_2 | |
| 284 | + nfs42_ssc_register_ops(); | |
| 285 | +#endif | |
| 282 | 286 | register_nfs_version(&nfs_v4); |
| 283 | 287 | return 0; |
| 284 | 288 | out2: |
| @@ -297,6 +301,7 @@ static void __exit exit_nfs_v4(void) · 12 unmodified lines | ||
| 297 | 301 | unregister_nfs_version(&nfs_v4); |
| 298 | 302 | #ifdef CONFIG_NFS_V4_2 |
| 299 | 303 | nfs4_xattr_cache_exit(); |
| 304 | + nfs42_ssc_unregister_ops(); | |
| 300 | 305 | #endif |
| 301 | 306 | nfs4_unregister_sysctl(); |
| 302 | 307 | nfs_idmap_quit(); |
| @@ -57,6 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | #include <linux/rcupdate.h> |
| 58 | 58 | |
| 59 | 59 | #include <linux/uaccess.h> |
| 60 | +#include <linux/nfs_ssc.h> | |
| 60 | 61 | |
| 61 | 62 | #include "nfs4_fs.h" |
| 62 | 63 | #include "callback.h" |
| @@ -85,6 +86,10 @@ const struct super_operations nfs_sops = { · 22 unmodified lines | ||
| 85 | 86 | }; |
| 86 | 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 | 93 | #if IS_ENABLED(CONFIG_NFS_V4) |
| 89 | 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 | 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 | 124 | static struct shrinker acl_shrinker = { |
| 110 | 125 | .count_objects = nfs_access_cache_count, |
| 111 | 126 | .scan_objects = nfs_access_cache_scan, |
| @@ -133,6 +148,7 @@ int __init register_nfs_fs(void) · 21 unmodified lines | ||
| 133 | 148 | ret = register_shrinker(&acl_shrinker); |
| 134 | 149 | if (ret < 0) |
| 135 | 150 | goto error_3; |
| 151 | + nfs_ssc_register_ops(); | |
| 136 | 152 | return 0; |
| 137 | 153 | error_3: |
| 138 | 154 | nfs_unregister_sysctl(); |
| @@ -152,6 +168,7 @@ void __exit unregister_nfs_fs(void) · 13 unmodified lines | ||
| 152 | 168 | unregister_shrinker(&acl_shrinker); |
| 153 | 169 | nfs_unregister_sysctl(); |
| 154 | 170 | unregister_nfs4_fs(); |
| 171 | + nfs_ssc_unregister_ops(); | |
| 155 | 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 | 7 | nfs_acl-objs := nfsacl.o |
| 8 | 8 | |
| 9 | 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 | 137 | config NFSD_V4_2_INTER_SSC |
| 138 | 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 | 140 | help |
| 141 | 141 | This option enables support for NFSv4.2 inter server to |
| 142 | 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 | 157 | If you do not wish to enable fine-grained security labels SELinux or |
| 158 | 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 | 13 | nfsd-y += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ |
| 14 | 14 | export.o auth.o lockd.o nfscache.o nfsxdr.o \ |
| 15 | 15 | stats.o filecache.o |
| 16 | −nfsd-$(CONFIG_NFSD_FAULT_INJECTION) += fault_inject.o | |
| 17 | 16 | nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o |
| 18 | 17 | nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o |
| 19 | 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 | 1002 | if (nfsd4_spo_must_allow(rqstp)) |
| 1003 | 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 | 890 | hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head, |
| 891 | 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 | 893 | continue; |
| 894 | 894 | if (nf->nf_inode != inode) |
| 895 | 895 | continue; |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include "vfs.h" |
| 15 | 15 | |
| 16 | 16 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 17 | −#define RETURN_STATUS(st) { resp->status = (st); return (st); } | |
| 18 | 17 | |
| 19 | 18 | /* |
| 20 | 19 | * NULL call. |
| @@ -22,7 +21,7 @@ · 1 unmodified line | ||
| 22 | 21 | static __be32 |
| 23 | 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 | 34 | struct posix_acl *acl; |
| 36 | 35 | struct inode *inode; |
| 37 | 36 | svc_fh *fh; |
| 38 | − __be32 nfserr = 0; | |
| 39 | 37 | |
| 40 | 38 | dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); |
| 41 | 39 | |
| 42 | 40 | fh = fh_copy(&resp->fh, &argp->fh); |
| 43 | − nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); | |
| 44 | − if (nfserr) | |
| 45 | − RETURN_STATUS(nfserr); | |
| 41 | + resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); | |
| 42 | + if (resp->status != nfs_ok) | |
| 43 | + goto out; | |
| 46 | 44 | |
| 47 | 45 | inode = d_inode(fh->fh_dentry); |
| 48 | 46 | |
| 49 | − if (argp->mask & ~NFS_ACL_MASK) | |
| 50 | − RETURN_STATUS(nfserr_inval); | |
| 47 | + if (argp->mask & ~NFS_ACL_MASK) { | |
| 48 | + resp->status = nfserr_inval; | |
| 49 | + goto out; | |
| 50 | + } | |
| 51 | 51 | resp->mask = argp->mask; |
| 52 | 52 | |
| 53 | − nfserr = fh_getattr(fh, &resp->stat); | |
| 54 | − if (nfserr) | |
| 55 | − RETURN_STATUS(nfserr); | |
| 53 | + resp->status = fh_getattr(fh, &resp->stat); | |
| 54 | + if (resp->status != nfs_ok) | |
| 55 | + goto out; | |
| 56 | 56 | |
| 57 | 57 | if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { |
| 58 | 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 | 61 | acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); |
| 62 | 62 | } |
| 63 | 63 | if (IS_ERR(acl)) { |
| 64 | − nfserr = nfserrno(PTR_ERR(acl)); | |
| 64 | + resp->status = nfserrno(PTR_ERR(acl)); | |
| 65 | 65 | goto fail; |
| 66 | 66 | } |
| 67 | 67 | resp->acl_access = acl; |
| @@ -71,19 +71,20 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines | ||
| 71 | 71 | of a non-directory! */ |
| 72 | 72 | acl = get_acl(inode, ACL_TYPE_DEFAULT); |
| 73 | 73 | if (IS_ERR(acl)) { |
| 74 | − nfserr = nfserrno(PTR_ERR(acl)); | |
| 74 | + resp->status = nfserrno(PTR_ERR(acl)); | |
| 75 | 75 | goto fail; |
| 76 | 76 | } |
| 77 | 77 | resp->acl_default = acl; |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | /* resp->acl_{access,default} are released in nfssvc_release_getacl. */ |
| 81 | − RETURN_STATUS(0); | |
| 81 | +out: | |
| 82 | + return rpc_success; | |
| 82 | 83 | |
| 83 | 84 | fail: |
| 84 | 85 | posix_acl_release(resp->acl_access); |
| 85 | 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 | 96 | struct nfsd_attrstat *resp = rqstp->rq_resp; |
| 96 | 97 | struct inode *inode; |
| 97 | 98 | svc_fh *fh; |
| 98 | − __be32 nfserr = 0; | |
| 99 | 99 | int error; |
| 100 | 100 | |
| 101 | 101 | dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); |
| 102 | 102 | |
| 103 | 103 | fh = fh_copy(&resp->fh, &argp->fh); |
| 104 | − nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); | |
| 105 | − if (nfserr) | |
| 104 | + resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); | |
| 105 | + if (resp->status != nfs_ok) | |
| 106 | 106 | goto out; |
| 107 | 107 | |
| 108 | 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 | 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 | 129 | out: |
| 130 | 130 | /* argp->acl_{access,default} may have been allocated in |
| 131 | 131 | nfssvc_decode_setaclargs. */ |
| 132 | 132 | posix_acl_release(argp->acl_access); |
| 133 | 133 | posix_acl_release(argp->acl_default); |
| 134 | − return nfserr; | |
| 134 | + return rpc_success; | |
| 135 | + | |
| 135 | 136 | out_drop_lock: |
| 136 | 137 | fh_unlock(fh); |
| 137 | 138 | fh_drop_write(fh); |
| 138 | 139 | out_errno: |
| 139 | − nfserr = nfserrno(error); | |
| 140 | + resp->status = nfserrno(error); | |
| 140 | 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 | 149 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 149 | 150 | struct nfsd_attrstat *resp = rqstp->rq_resp; |
| 150 | − __be32 nfserr; | |
| 151 | + | |
| 151 | 152 | dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); |
| 152 | 153 | |
| 153 | 154 | fh_copy(&resp->fh, &argp->fh); |
| 154 | − nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); | |
| 155 | − if (nfserr) | |
| 156 | − return nfserr; | |
| 157 | − nfserr = fh_getattr(&resp->fh, &resp->stat); | |
| 158 | − return nfserr; | |
| 155 | + resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); | |
| 156 | + if (resp->status != nfs_ok) | |
| 157 | + goto out; | |
| 158 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 159 | +out: | |
| 160 | + return rpc_success; | |
| 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 | 168 | struct nfsd3_accessargs *argp = rqstp->rq_argp; |
| 167 | 169 | struct nfsd3_accessres *resp = rqstp->rq_resp; |
| 168 | − __be32 nfserr; | |
| 169 | 170 | |
| 170 | 171 | dprintk("nfsd: ACCESS(2acl) %s 0x%x\n", |
| 171 | 172 | SVCFH_fmt(&argp->fh), |
| @@ -173,16 +174,22 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp) · 1 unmodified line | ||
| 173 | 174 | |
| 174 | 175 | fh_copy(&resp->fh, &argp->fh); |
| 175 | 176 | resp->access = argp->access; |
| 176 | − nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); | |
| 177 | − if (nfserr) | |
| 178 | − return nfserr; | |
| 179 | − nfserr = fh_getattr(&resp->fh, &resp->stat); | |
| 180 | − return nfserr; | |
| 177 | + resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); | |
| 178 | + if (resp->status != nfs_ok) | |
| 179 | + goto out; | |
| 180 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 181 | +out: | |
| 182 | + return rpc_success; | |
| 181 | 183 | } |
| 182 | 184 | |
| 183 | 185 | /* |
| 184 | 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 | 193 | static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p) |
| 187 | 194 | { |
| 188 | 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 | 275 | int n; |
| 269 | 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 | 283 | * Since this is version 2, the check for nfserr in |
| 273 | 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 | 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 | 325 | p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat); |
| 326 | +out: | |
| 311 | 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 | 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 | 339 | p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat); |
| 320 | 340 | *p++ = htonl(resp->access); |
| 341 | +out: | |
| 321 | 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 | 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 | 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 | 373 | #define ST 1 /* status*/ |
| 370 | 374 | #define AT 21 /* attributes */ |
| 371 | 375 | #define pAT (1+AT) /* post attributes - conditional */ |
| 372 | 376 | #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */ |
| 373 | 377 | |
| 374 | −static const struct svc_procedure nfsd_acl_procedures2[] = { | |
| 375 | − PROC(null, void, void, void, RC_NOCACHE, ST), | |
| 376 | − PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)), | |
| 377 | − PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT), | |
| 378 | − PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT), | |
| 379 | − PROC(access, access, access, access, RC_NOCACHE, ST+AT+1), | |
| 378 | +static const struct svc_procedure nfsd_acl_procedures2[5] = { | |
| 379 | + [ACLPROC2_NULL] = { | |
| 380 | + .pc_func = nfsacld_proc_null, | |
| 381 | + .pc_decode = nfsaclsvc_decode_voidarg, | |
| 382 | + .pc_encode = nfsaclsvc_encode_voidres, | |
| 383 | + .pc_argsize = sizeof(struct nfsd3_voidargs), | |
| 384 | + .pc_ressize = sizeof(struct nfsd3_voidargs), | |
| 385 | + .pc_cachetype = RC_NOCACHE, | |
| 386 | + .pc_xdrressize = ST, | |
| 387 | + }, | |
| 388 | + [ACLPROC2_GETACL] = { | |
| 389 | + .pc_func = nfsacld_proc_getacl, | |
| 390 | + .pc_decode = nfsaclsvc_decode_getaclargs, | |
| 391 | + .pc_encode = nfsaclsvc_encode_getaclres, | |
| 392 | + .pc_release = nfsaclsvc_release_getacl, | |
| 393 | + .pc_argsize = sizeof(struct nfsd3_getaclargs), | |
| 394 | + .pc_ressize = sizeof(struct nfsd3_getaclres), | |
| 395 | + .pc_cachetype = RC_NOCACHE, | |
| 396 | + .pc_xdrressize = ST+1+2*(1+ACL), | |
| 397 | + }, | |
| 398 | + [ACLPROC2_SETACL] = { | |
| 399 | + .pc_func = nfsacld_proc_setacl, | |
| 400 | + .pc_decode = nfsaclsvc_decode_setaclargs, | |
| 401 | + .pc_encode = nfsaclsvc_encode_attrstatres, | |
| 402 | + .pc_release = nfsaclsvc_release_attrstat, | |
| 403 | + .pc_argsize = sizeof(struct nfsd3_setaclargs), | |
| 404 | + .pc_ressize = sizeof(struct nfsd_attrstat), | |
| 405 | + .pc_cachetype = RC_NOCACHE, | |
| 406 | + .pc_xdrressize = ST+AT, | |
| 407 | + }, | |
| 408 | + [ACLPROC2_GETATTR] = { | |
| 409 | + .pc_func = nfsacld_proc_getattr, | |
| 410 | + .pc_decode = nfsaclsvc_decode_fhandleargs, | |
| 411 | + .pc_encode = nfsaclsvc_encode_attrstatres, | |
| 412 | + .pc_release = nfsaclsvc_release_attrstat, | |
| 413 | + .pc_argsize = sizeof(struct nfsd_fhandle), | |
| 414 | + .pc_ressize = sizeof(struct nfsd_attrstat), | |
| 415 | + .pc_cachetype = RC_NOCACHE, | |
| 416 | + .pc_xdrressize = ST+AT, | |
| 417 | + }, | |
| 418 | + [ACLPROC2_ACCESS] = { | |
| 419 | + .pc_func = nfsacld_proc_access, | |
| 420 | + .pc_decode = nfsaclsvc_decode_accessargs, | |
| 421 | + .pc_encode = nfsaclsvc_encode_accessres, | |
| 422 | + .pc_release = nfsaclsvc_release_access, | |
| 423 | + .pc_argsize = sizeof(struct nfsd3_accessargs), | |
| 424 | + .pc_ressize = sizeof(struct nfsd3_accessres), | |
| 425 | + .pc_cachetype = RC_NOCACHE, | |
| 426 | + .pc_xdrressize = ST+AT+1, | |
| 427 | + }, | |
| 380 | 428 | }; |
| 381 | 429 | |
| 382 | 430 | static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)]; |
| @@ -13,15 +13,13 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "xdr3.h" |
| 14 | 14 | #include "vfs.h" |
| 15 | 15 | |
| 16 | −#define RETURN_STATUS(st) { resp->status = (st); return (st); } | |
| 17 | − | |
| 18 | 16 | /* |
| 19 | 17 | * NULL call. |
| 20 | 18 | */ |
| 21 | 19 | static __be32 |
| 22 | 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 | 32 | struct posix_acl *acl; |
| 35 | 33 | struct inode *inode; |
| 36 | 34 | svc_fh *fh; |
| 37 | − __be32 nfserr = 0; | |
| 38 | 35 | |
| 39 | 36 | fh = fh_copy(&resp->fh, &argp->fh); |
| 40 | − nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); | |
| 41 | − if (nfserr) | |
| 42 | − RETURN_STATUS(nfserr); | |
| 37 | + resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); | |
| 38 | + if (resp->status != nfs_ok) | |
| 39 | + goto out; | |
| 43 | 40 | |
| 44 | 41 | inode = d_inode(fh->fh_dentry); |
| 45 | 42 | |
| 46 | − if (argp->mask & ~NFS_ACL_MASK) | |
| 47 | − RETURN_STATUS(nfserr_inval); | |
| 43 | + if (argp->mask & ~NFS_ACL_MASK) { | |
| 44 | + resp->status = nfserr_inval; | |
| 45 | + goto out; | |
| 46 | + } | |
| 48 | 47 | resp->mask = argp->mask; |
| 49 | 48 | |
| 50 | 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 | 53 | acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); |
| 55 | 54 | } |
| 56 | 55 | if (IS_ERR(acl)) { |
| 57 | − nfserr = nfserrno(PTR_ERR(acl)); | |
| 56 | + resp->status = nfserrno(PTR_ERR(acl)); | |
| 58 | 57 | goto fail; |
| 59 | 58 | } |
| 60 | 59 | resp->acl_access = acl; |
| @@ -64,19 +63,20 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp) · 3 unmodified lines | ||
| 64 | 63 | of a non-directory! */ |
| 65 | 64 | acl = get_acl(inode, ACL_TYPE_DEFAULT); |
| 66 | 65 | if (IS_ERR(acl)) { |
| 67 | − nfserr = nfserrno(PTR_ERR(acl)); | |
| 66 | + resp->status = nfserrno(PTR_ERR(acl)); | |
| 68 | 67 | goto fail; |
| 69 | 68 | } |
| 70 | 69 | resp->acl_default = acl; |
| 71 | 70 | } |
| 72 | 71 | |
| 73 | 72 | /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */ |
| 74 | − RETURN_STATUS(0); | |
| 73 | +out: | |
| 74 | + return rpc_success; | |
| 75 | 75 | |
| 76 | 76 | fail: |
| 77 | 77 | posix_acl_release(resp->acl_access); |
| 78 | 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 | 88 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 89 | 89 | struct inode *inode; |
| 90 | 90 | svc_fh *fh; |
| 91 | − __be32 nfserr = 0; | |
| 92 | 91 | int error; |
| 93 | 92 | |
| 94 | 93 | fh = fh_copy(&resp->fh, &argp->fh); |
| 95 | − nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); | |
| 96 | − if (nfserr) | |
| 94 | + resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR); | |
| 95 | + if (resp->status != nfs_ok) | |
| 97 | 96 | goto out; |
| 98 | 97 | |
| 99 | 98 | inode = d_inode(fh->fh_dentry); |
| @@ -113,13 +112,13 @@ out_drop_lock: · 13 unmodified lines | ||
| 113 | 112 | fh_unlock(fh); |
| 114 | 113 | fh_drop_write(fh); |
| 115 | 114 | out_errno: |
| 116 | − nfserr = nfserrno(error); | |
| 115 | + resp->status = nfserrno(error); | |
| 117 | 116 | out: |
| 118 | 117 | /* argp->acl_{access,default} may have been allocated in |
| 119 | 118 | nfs3svc_decode_setaclargs. */ |
| 120 | 119 | posix_acl_release(argp->acl_access); |
| 121 | 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 | 173 | struct nfsd3_getaclres *resp = rqstp->rq_resp; |
| 175 | 174 | struct dentry *dentry = resp->fh.fh_dentry; |
| 176 | 175 | |
| 176 | + *p++ = resp->status; | |
| 177 | 177 | p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); |
| 178 | 178 | if (resp->status == 0 && dentry && d_really_is_positive(dentry)) { |
| 179 | 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 | 219 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 220 | 220 | |
| 221 | + *p++ = resp->status; | |
| 221 | 222 | p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); |
| 222 | − | |
| 223 | 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 | 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 | 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 | 240 | #define ST 1 /* status*/ |
| 257 | 241 | #define AT 21 /* attributes */ |
| 258 | 242 | #define pAT (1+AT) /* post attributes - conditional */ |
| 259 | 243 | #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */ |
| 260 | 244 | |
| 261 | −static const struct svc_procedure nfsd_acl_procedures3[] = { | |
| 262 | − PROC(null, void, void, void, RC_NOCACHE, ST), | |
| 263 | − PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)), | |
| 264 | − PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT), | |
| 245 | +static const struct svc_procedure nfsd_acl_procedures3[3] = { | |
| 246 | + [ACLPROC3_NULL] = { | |
| 247 | + .pc_func = nfsd3_proc_null, | |
| 248 | + .pc_decode = nfs3svc_decode_voidarg, | |
| 249 | + .pc_encode = nfs3svc_encode_voidres, | |
| 250 | + .pc_argsize = sizeof(struct nfsd3_voidargs), | |
| 251 | + .pc_ressize = sizeof(struct nfsd3_voidargs), | |
| 252 | + .pc_cachetype = RC_NOCACHE, | |
| 253 | + .pc_xdrressize = ST, | |
| 254 | + }, | |
| 255 | + [ACLPROC3_GETACL] = { | |
| 256 | + .pc_func = nfsd3_proc_getacl, | |
| 257 | + .pc_decode = nfs3svc_decode_getaclargs, | |
| 258 | + .pc_encode = nfs3svc_encode_getaclres, | |
| 259 | + .pc_release = nfs3svc_release_getacl, | |
| 260 | + .pc_argsize = sizeof(struct nfsd3_getaclargs), | |
| 261 | + .pc_ressize = sizeof(struct nfsd3_getaclres), | |
| 262 | + .pc_cachetype = RC_NOCACHE, | |
| 263 | + .pc_xdrressize = ST+1+2*(1+ACL), | |
| 264 | + }, | |
| 265 | + [ACLPROC3_SETACL] = { | |
| 266 | + .pc_func = nfsd3_proc_setacl, | |
| 267 | + .pc_decode = nfs3svc_decode_setaclargs, | |
| 268 | + .pc_encode = nfs3svc_encode_setaclres, | |
| 269 | + .pc_release = nfs3svc_release_fhandle, | |
| 270 | + .pc_argsize = sizeof(struct nfsd3_setaclargs), | |
| 271 | + .pc_ressize = sizeof(struct nfsd3_attrstat), | |
| 272 | + .pc_cachetype = RC_NOCACHE, | |
| 273 | + .pc_xdrressize = ST+pAT, | |
| 274 | + }, | |
| 265 | 275 | }; |
| 266 | 276 | |
| 267 | 277 | static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)]; |
| @@ -15,8 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 17 | 17 | |
| 18 | −#define RETURN_STATUS(st) { resp->status = (st); return (st); } | |
| 19 | − | |
| 20 | 18 | static int nfs3_ftypes[] = { |
| 21 | 19 | 0, /* NF3NON */ |
| 22 | 20 | S_IFREG, /* NF3REG */ |
| @@ -34,7 +32,7 @@ static int nfs3_ftypes[] = { · 11 unmodified lines | ||
| 34 | 32 | static __be32 |
| 35 | 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 | 44 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 47 | 45 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 48 | − __be32 nfserr; | |
| 49 | 46 | |
| 50 | 47 | dprintk("nfsd: GETATTR(3) %s\n", |
| 51 | 48 | SVCFH_fmt(&argp->fh)); |
| 52 | 49 | |
| 53 | 50 | fh_copy(&resp->fh, &argp->fh); |
| 54 | − nfserr = fh_verify(rqstp, &resp->fh, 0, | |
| 55 | − NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 56 | − if (nfserr) | |
| 57 | − RETURN_STATUS(nfserr); | |
| 58 | − | |
| 59 | − nfserr = fh_getattr(&resp->fh, &resp->stat); | |
| 60 | − | |
| 61 | − RETURN_STATUS(nfserr); | |
| 51 | + resp->status = fh_verify(rqstp, &resp->fh, 0, | |
| 52 | + NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 53 | + if (resp->status != nfs_ok) | |
| 54 | + goto out; | |
| 55 | + | |
| 56 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 57 | +out: | |
| 58 | + return rpc_success; | |
| 62 | 59 | } |
| 63 | 60 | |
| 64 | 61 | /* |
| @@ -69,15 +66,14 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 69 | 66 | { |
| 70 | 67 | struct nfsd3_sattrargs *argp = rqstp->rq_argp; |
| 71 | 68 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 72 | − __be32 nfserr; | |
| 73 | 69 | |
| 74 | 70 | dprintk("nfsd: SETATTR(3) %s\n", |
| 75 | 71 | SVCFH_fmt(&argp->fh)); |
| 76 | 72 | |
| 77 | 73 | fh_copy(&resp->fh, &argp->fh); |
| 78 | − nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs, | |
| 79 | − argp->check_guard, argp->guardtime); | |
| 80 | − RETURN_STATUS(nfserr); | |
| 74 | + resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs, | |
| 75 | + argp->check_guard, argp->guardtime); | |
| 76 | + return rpc_success; | |
| 81 | 77 | } |
| 82 | 78 | |
| 83 | 79 | /* |
| @@ -88,7 +84,6 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 88 | 84 | { |
| 89 | 85 | struct nfsd3_diropargs *argp = rqstp->rq_argp; |
| 90 | 86 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 91 | − __be32 nfserr; | |
| 92 | 87 | |
| 93 | 88 | dprintk("nfsd: LOOKUP(3) %s %.*s\n", |
| 94 | 89 | SVCFH_fmt(&argp->fh), |
| @@ -98,11 +93,10 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp) · 3 unmodified lines | ||
| 98 | 93 | fh_copy(&resp->dirfh, &argp->fh); |
| 99 | 94 | fh_init(&resp->fh, NFS3_FHSIZE); |
| 100 | 95 | |
| 101 | − nfserr = nfsd_lookup(rqstp, &resp->dirfh, | |
| 102 | − argp->name, | |
| 103 | − argp->len, | |
| 104 | − &resp->fh); | |
| 105 | − RETURN_STATUS(nfserr); | |
| 96 | + resp->status = nfsd_lookup(rqstp, &resp->dirfh, | |
| 97 | + argp->name, argp->len, | |
| 98 | + &resp->fh); | |
| 99 | + return rpc_success; | |
| 106 | 100 | } |
| 107 | 101 | |
| 108 | 102 | /* |
| @@ -113,7 +107,6 @@ nfsd3_proc_access(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 113 | 107 | { |
| 114 | 108 | struct nfsd3_accessargs *argp = rqstp->rq_argp; |
| 115 | 109 | struct nfsd3_accessres *resp = rqstp->rq_resp; |
| 116 | − __be32 nfserr; | |
| 117 | 110 | |
| 118 | 111 | dprintk("nfsd: ACCESS(3) %s 0x%x\n", |
| 119 | 112 | SVCFH_fmt(&argp->fh), |
| @@ -121,8 +114,8 @@ nfsd3_proc_access(struct svc_rqst *rqstp) · 1 unmodified line | ||
| 121 | 114 | |
| 122 | 115 | fh_copy(&resp->fh, &argp->fh); |
| 123 | 116 | resp->access = argp->access; |
| 124 | − nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); | |
| 125 | − RETURN_STATUS(nfserr); | |
| 117 | + resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); | |
| 118 | + return rpc_success; | |
| 126 | 119 | } |
| 127 | 120 | |
| 128 | 121 | /* |
| @@ -133,15 +126,14 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 133 | 126 | { |
| 134 | 127 | struct nfsd3_readlinkargs *argp = rqstp->rq_argp; |
| 135 | 128 | struct nfsd3_readlinkres *resp = rqstp->rq_resp; |
| 136 | − __be32 nfserr; | |
| 137 | 129 | |
| 138 | 130 | dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh)); |
| 139 | 131 | |
| 140 | 132 | /* Read the symlink. */ |
| 141 | 133 | fh_copy(&resp->fh, &argp->fh); |
| 142 | 134 | resp->len = NFS3_MAXPATHLEN; |
| 143 | − nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len); | |
| 144 | − RETURN_STATUS(nfserr); | |
| 135 | + resp->status = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len); | |
| 136 | + return rpc_success; | |
| 145 | 137 | } |
| 146 | 138 | |
| 147 | 139 | /* |
| @@ -152,7 +144,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 152 | 144 | { |
| 153 | 145 | struct nfsd3_readargs *argp = rqstp->rq_argp; |
| 154 | 146 | struct nfsd3_readres *resp = rqstp->rq_resp; |
| 155 | − __be32 nfserr; | |
| 156 | 147 | u32 max_blocksize = svc_max_payload(rqstp); |
| 157 | 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 | 160 | svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); |
| 170 | 161 | |
| 171 | 162 | fh_copy(&resp->fh, &argp->fh); |
| 172 | − nfserr = nfsd_read(rqstp, &resp->fh, | |
| 173 | − argp->offset, | |
| 174 | − rqstp->rq_vec, argp->vlen, | |
| 175 | − &resp->count, | |
| 176 | − &resp->eof); | |
| 177 | − RETURN_STATUS(nfserr); | |
| 163 | + resp->status = nfsd_read(rqstp, &resp->fh, argp->offset, | |
| 164 | + rqstp->rq_vec, argp->vlen, &resp->count, | |
| 165 | + &resp->eof); | |
| 166 | + return rpc_success; | |
| 178 | 167 | } |
| 179 | 168 | |
| 180 | 169 | /* |
| @@ -185,7 +174,6 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 185 | 174 | { |
| 186 | 175 | struct nfsd3_writeargs *argp = rqstp->rq_argp; |
| 187 | 176 | struct nfsd3_writeres *resp = rqstp->rq_resp; |
| 188 | − __be32 nfserr; | |
| 189 | 177 | unsigned long cnt = argp->len; |
| 190 | 178 | unsigned int nvecs; |
| 191 | 179 | |
| @@ -199,13 +187,16 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 7 unmodified lines | ||
| 199 | 187 | resp->committed = argp->stable; |
| 200 | 188 | nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages, |
| 201 | 189 | &argp->first, cnt); |
| 202 | − if (!nvecs) | |
| 203 | − RETURN_STATUS(nfserr_io); | |
| 204 | − nfserr = nfsd_write(rqstp, &resp->fh, argp->offset, | |
| 205 | − rqstp->rq_vec, nvecs, &cnt, | |
| 206 | − resp->committed, resp->verf); | |
| 190 | + if (!nvecs) { | |
| 191 | + resp->status = nfserr_io; | |
| 192 | + goto out; | |
| 193 | + } | |
| 194 | + resp->status = nfsd_write(rqstp, &resp->fh, argp->offset, | |
| 195 | + rqstp->rq_vec, nvecs, &cnt, | |
| 196 | + resp->committed, resp->verf); | |
| 207 | 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 | 211 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 221 | 212 | svc_fh *dirfhp, *newfhp = NULL; |
| 222 | 213 | struct iattr *attr; |
| 223 | − __be32 nfserr; | |
| 224 | 214 | |
| 225 | 215 | dprintk("nfsd: CREATE(3) %s %.*s\n", |
| 226 | 216 | SVCFH_fmt(&argp->fh), |
| @@ -241,11 +231,10 @@ nfsd3_proc_create(struct svc_rqst *rqstp) · 14 unmodified lines | ||
| 241 | 231 | } |
| 242 | 232 | |
| 243 | 233 | /* Now create the file and set attributes */ |
| 244 | − nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, | |
| 245 | − attr, newfhp, | |
| 246 | − argp->createmode, (u32 *)argp->verf, NULL, NULL); | |
| 247 | − | |
| 248 | − RETURN_STATUS(nfserr); | |
| 234 | + resp->status = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, | |
| 235 | + attr, newfhp, argp->createmode, | |
| 236 | + (u32 *)argp->verf, NULL, NULL); | |
| 237 | + return rpc_success; | |
| 249 | 238 | } |
| 250 | 239 | |
| 251 | 240 | /* |
| @@ -256,7 +245,6 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 256 | 245 | { |
| 257 | 246 | struct nfsd3_createargs *argp = rqstp->rq_argp; |
| 258 | 247 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 259 | − __be32 nfserr; | |
| 260 | 248 | |
| 261 | 249 | dprintk("nfsd: MKDIR(3) %s %.*s\n", |
| 262 | 250 | SVCFH_fmt(&argp->fh), |
| @@ -266,10 +254,10 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) · 3 unmodified lines | ||
| 266 | 254 | argp->attrs.ia_valid &= ~ATTR_SIZE; |
| 267 | 255 | fh_copy(&resp->dirfh, &argp->fh); |
| 268 | 256 | fh_init(&resp->fh, NFS3_FHSIZE); |
| 269 | − nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, | |
| 270 | − &argp->attrs, S_IFDIR, 0, &resp->fh); | |
| 257 | + resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, | |
| 258 | + &argp->attrs, S_IFDIR, 0, &resp->fh); | |
| 271 | 259 | fh_unlock(&resp->dirfh); |
| 272 | − RETURN_STATUS(nfserr); | |
| 260 | + return rpc_success; | |
| 273 | 261 | } |
| 274 | 262 | |
| 275 | 263 | static __be32 |
| @@ -277,18 +265,23 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) · 1 unmodified line | ||
| 277 | 265 | { |
| 278 | 266 | struct nfsd3_symlinkargs *argp = rqstp->rq_argp; |
| 279 | 267 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 280 | − __be32 nfserr; | |
| 281 | 268 | |
| 282 | − if (argp->tlen == 0) | |
| 283 | − RETURN_STATUS(nfserr_inval); | |
| 284 | − if (argp->tlen > NFS3_MAXPATHLEN) | |
| 285 | − RETURN_STATUS(nfserr_nametoolong); | |
| 269 | + if (argp->tlen == 0) { | |
| 270 | + resp->status = nfserr_inval; | |
| 271 | + goto out; | |
| 272 | + } | |
| 273 | + if (argp->tlen > NFS3_MAXPATHLEN) { | |
| 274 | + resp->status = nfserr_nametoolong; | |
| 275 | + goto out; | |
| 276 | + } | |
| 286 | 277 | |
| 287 | 278 | argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first, |
| 288 | 279 | page_address(rqstp->rq_arg.pages[0]), |
| 289 | 280 | argp->tlen); |
| 290 | − if (IS_ERR(argp->tname)) | |
| 291 | − RETURN_STATUS(nfserrno(PTR_ERR(argp->tname))); | |
| 281 | + if (IS_ERR(argp->tname)) { | |
| 282 | + resp->status = nfserrno(PTR_ERR(argp->tname)); | |
| 283 | + goto out; | |
| 284 | + } | |
| 292 | 285 | |
| 293 | 286 | dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n", |
| 294 | 287 | SVCFH_fmt(&argp->ffh), |
| @@ -297,10 +290,11 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) · 2 unmodified lines | ||
| 297 | 290 | |
| 298 | 291 | fh_copy(&resp->dirfh, &argp->ffh); |
| 299 | 292 | fh_init(&resp->fh, NFS3_FHSIZE); |
| 300 | − nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen, | |
| 301 | − argp->tname, &resp->fh); | |
| 293 | + resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, | |
| 294 | + argp->flen, argp->tname, &resp->fh); | |
| 302 | 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 | 306 | struct nfsd3_mknodargs *argp = rqstp->rq_argp; |
| 313 | 307 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 314 | − __be32 nfserr; | |
| 315 | 308 | int type; |
| 316 | 309 | dev_t rdev = 0; |
| 317 | 310 | |
| @@ -323,22 +316,28 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) · 5 unmodified lines | ||
| 323 | 316 | fh_copy(&resp->dirfh, &argp->fh); |
| 324 | 317 | fh_init(&resp->fh, NFS3_FHSIZE); |
| 325 | 318 | |
| 326 | − if (argp->ftype == 0 || argp->ftype >= NF3BAD) | |
| 327 | − RETURN_STATUS(nfserr_inval); | |
| 319 | + if (argp->ftype == 0 || argp->ftype >= NF3BAD) { | |
| 320 | + resp->status = nfserr_inval; | |
| 321 | + goto out; | |
| 322 | + } | |
| 328 | 323 | if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) { |
| 329 | 324 | rdev = MKDEV(argp->major, argp->minor); |
| 330 | 325 | if (MAJOR(rdev) != argp->major || |
| 331 | − MINOR(rdev) != argp->minor) | |
| 332 | − RETURN_STATUS(nfserr_inval); | |
| 333 | − } else | |
| 334 | − if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) | |
| 335 | − RETURN_STATUS(nfserr_inval); | |
| 326 | + MINOR(rdev) != argp->minor) { | |
| 327 | + resp->status = nfserr_inval; | |
| 328 | + goto out; | |
| 329 | + } | |
| 330 | + } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) { | |
| 331 | + resp->status = nfserr_inval; | |
| 332 | + goto out; | |
| 333 | + } | |
| 336 | 334 | |
| 337 | 335 | type = nfs3_ftypes[argp->ftype]; |
| 338 | − nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, | |
| 339 | − &argp->attrs, type, rdev, &resp->fh); | |
| 336 | + resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, | |
| 337 | + &argp->attrs, type, rdev, &resp->fh); | |
| 340 | 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 | 349 | struct nfsd3_diropargs *argp = rqstp->rq_argp; |
| 351 | 350 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 352 | − __be32 nfserr; | |
| 353 | 351 | |
| 354 | 352 | dprintk("nfsd: REMOVE(3) %s %.*s\n", |
| 355 | 353 | SVCFH_fmt(&argp->fh), |
| @@ -358,9 +356,10 @@ nfsd3_proc_remove(struct svc_rqst *rqstp) · 2 unmodified lines | ||
| 358 | 356 | |
| 359 | 357 | /* Unlink. -S_IFDIR means file must not be a directory */ |
| 360 | 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 | 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 | 371 | struct nfsd3_diropargs *argp = rqstp->rq_argp; |
| 373 | 372 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 374 | − __be32 nfserr; | |
| 375 | 373 | |
| 376 | 374 | dprintk("nfsd: RMDIR(3) %s %.*s\n", |
| 377 | 375 | SVCFH_fmt(&argp->fh), |
| @@ -379,9 +377,10 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp) · 1 unmodified line | ||
| 379 | 377 | argp->name); |
| 380 | 378 | |
| 381 | 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 | 382 | fh_unlock(&resp->fh); |
| 384 | − RETURN_STATUS(nfserr); | |
| 383 | + return rpc_success; | |
| 385 | 384 | } |
| 386 | 385 | |
| 387 | 386 | static __be32 |
| @@ -389,7 +388,6 @@ nfsd3_proc_rename(struct svc_rqst *rqstp) · 1 unmodified line | ||
| 389 | 388 | { |
| 390 | 389 | struct nfsd3_renameargs *argp = rqstp->rq_argp; |
| 391 | 390 | struct nfsd3_renameres *resp = rqstp->rq_resp; |
| 392 | − __be32 nfserr; | |
| 393 | 391 | |
| 394 | 392 | dprintk("nfsd: RENAME(3) %s %.*s ->\n", |
| 395 | 393 | SVCFH_fmt(&argp->ffh), |
| @@ -402,9 +400,9 @@ nfsd3_proc_rename(struct svc_rqst *rqstp) · 6 unmodified lines | ||
| 402 | 400 | |
| 403 | 401 | fh_copy(&resp->ffh, &argp->ffh); |
| 404 | 402 | fh_copy(&resp->tfh, &argp->tfh); |
| 405 | − nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen, | |
| 406 | − &resp->tfh, argp->tname, argp->tlen); | |
| 407 | − RETURN_STATUS(nfserr); | |
| 403 | + resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen, | |
| 404 | + &resp->tfh, argp->tname, argp->tlen); | |
| 405 | + return rpc_success; | |
| 408 | 406 | } |
| 409 | 407 | |
| 410 | 408 | static __be32 |
| @@ -412,7 +410,6 @@ nfsd3_proc_link(struct svc_rqst *rqstp) · 1 unmodified line | ||
| 412 | 410 | { |
| 413 | 411 | struct nfsd3_linkargs *argp = rqstp->rq_argp; |
| 414 | 412 | struct nfsd3_linkres *resp = rqstp->rq_resp; |
| 415 | − __be32 nfserr; | |
| 416 | 413 | |
| 417 | 414 | dprintk("nfsd: LINK(3) %s ->\n", |
| 418 | 415 | SVCFH_fmt(&argp->ffh)); |
| @@ -423,9 +420,9 @@ nfsd3_proc_link(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 423 | 420 | |
| 424 | 421 | fh_copy(&resp->fh, &argp->ffh); |
| 425 | 422 | fh_copy(&resp->tfh, &argp->tfh); |
| 426 | − nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen, | |
| 427 | − &resp->fh); | |
| 428 | − RETURN_STATUS(nfserr); | |
| 423 | + resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen, | |
| 424 | + &resp->fh); | |
| 425 | + return rpc_success; | |
| 429 | 426 | } |
| 430 | 427 | |
| 431 | 428 | /* |
| @@ -436,7 +433,6 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 4 unmodified lines | ||
| 436 | 433 | { |
| 437 | 434 | struct nfsd3_readdirargs *argp = rqstp->rq_argp; |
| 438 | 435 | struct nfsd3_readdirres *resp = rqstp->rq_resp; |
| 439 | − __be32 nfserr; | |
| 440 | 436 | int count = 0; |
| 441 | 437 | struct page **p; |
| 442 | 438 | caddr_t page_addr = NULL; |
| @@ -456,8 +452,8 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp) · 13 unmodified lines | ||
| 456 | 452 | resp->common.err = nfs_ok; |
| 457 | 453 | resp->buffer = argp->buffer; |
| 458 | 454 | resp->rqstp = rqstp; |
| 459 | − nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, | |
| 460 | − &resp->common, nfs3svc_encode_entry); | |
| 455 | + resp->status = nfsd_readdir(rqstp, &resp->fh, (loff_t *)&argp->cookie, | |
| 456 | + &resp->common, nfs3svc_encode_entry); | |
| 461 | 457 | memcpy(resp->verf, argp->verf, 8); |
| 462 | 458 | count = 0; |
| 463 | 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 | 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 | 494 | struct nfsd3_readdirargs *argp = rqstp->rq_argp; |
| 499 | 495 | struct nfsd3_readdirres *resp = rqstp->rq_resp; |
| 500 | − __be32 nfserr; | |
| 501 | 496 | int count = 0; |
| 502 | 497 | loff_t offset; |
| 503 | 498 | struct page **p; |
| @@ -520,17 +515,17 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 16 unmodified lines | ||
| 520 | 515 | resp->rqstp = rqstp; |
| 521 | 516 | offset = argp->cookie; |
| 522 | 517 | |
| 523 | − nfserr = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP); | |
| 524 | − if (nfserr) | |
| 525 | − RETURN_STATUS(nfserr); | |
| 518 | + resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP); | |
| 519 | + if (resp->status != nfs_ok) | |
| 520 | + goto out; | |
| 526 | 521 | |
| 527 | − if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) | |
| 528 | − RETURN_STATUS(nfserr_notsupp); | |
| 522 | + if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) { | |
| 523 | + resp->status = nfserr_notsupp; | |
| 524 | + goto out; | |
| 525 | + } | |
| 529 | 526 | |
| 530 | − nfserr = nfsd_readdir(rqstp, &resp->fh, | |
| 531 | − &offset, | |
| 532 | − &resp->common, | |
| 533 | − nfs3svc_encode_entry_plus); | |
| 527 | + resp->status = nfsd_readdir(rqstp, &resp->fh, &offset, | |
| 528 | + &resp->common, nfs3svc_encode_entry_plus); | |
| 534 | 529 | memcpy(resp->verf, argp->verf, 8); |
| 535 | 530 | for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) { |
| 536 | 531 | page_addr = page_address(*p); |
| @@ -555,7 +550,8 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp) · 18 unmodified lines | ||
| 555 | 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 | 563 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 568 | 564 | struct nfsd3_fsstatres *resp = rqstp->rq_resp; |
| 569 | − __be32 nfserr; | |
| 570 | 565 | |
| 571 | 566 | dprintk("nfsd: FSSTAT(3) %s\n", |
| 572 | 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 | 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 | 580 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 586 | 581 | struct nfsd3_fsinfores *resp = rqstp->rq_resp; |
| 587 | − __be32 nfserr; | |
| 588 | 582 | u32 max_blocksize = svc_max_payload(rqstp); |
| 589 | 583 | |
| 590 | 584 | dprintk("nfsd: FSINFO(3) %s\n", |
| @@ -600,13 +594,13 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp) · 9 unmodified lines | ||
| 600 | 594 | resp->f_maxfilesize = ~(u32) 0; |
| 601 | 595 | resp->f_properties = NFS3_FSF_DEFAULT; |
| 602 | 596 | |
| 603 | − nfserr = fh_verify(rqstp, &argp->fh, 0, | |
| 604 | − NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 597 | + resp->status = fh_verify(rqstp, &argp->fh, 0, | |
| 598 | + NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 605 | 599 | |
| 606 | 600 | /* Check special features of the file system. May request |
| 607 | 601 | * different read/write sizes for file systems known to have |
| 608 | 602 | * problems with large blocks */ |
| 609 | − if (nfserr == 0) { | |
| 603 | + if (resp->status == nfs_ok) { | |
| 610 | 604 | struct super_block *sb = argp->fh.fh_dentry->d_sb; |
| 611 | 605 | |
| 612 | 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 | 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 | 623 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 630 | 624 | struct nfsd3_pathconfres *resp = rqstp->rq_resp; |
| 631 | − __be32 nfserr; | |
| 632 | 625 | |
| 633 | 626 | dprintk("nfsd: PATHCONF(3) %s\n", |
| 634 | 627 | SVCFH_fmt(&argp->fh)); |
| @@ -641,9 +634,9 @@ nfsd3_proc_pathconf(struct svc_rqst *rqstp) · 6 unmodified lines | ||
| 641 | 634 | resp->p_case_insensitive = 0; |
| 642 | 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 | 640 | struct super_block *sb = argp->fh.fh_dentry->d_sb; |
| 648 | 641 | |
| 649 | 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 | 655 | fh_put(&argp->fh); |
| 663 | − RETURN_STATUS(nfserr); | |
| 656 | + return rpc_success; | |
| 664 | 657 | } |
| 665 | 658 | |
| 666 | − | |
| 667 | 659 | /* |
| 668 | 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 | 665 | struct nfsd3_commitargs *argp = rqstp->rq_argp; |
| 674 | 666 | struct nfsd3_commitres *resp = rqstp->rq_resp; |
| 675 | − __be32 nfserr; | |
| 676 | 667 | |
| 677 | 668 | dprintk("nfsd: COMMIT(3) %s %u@%Lu\n", |
| 678 | 669 | SVCFH_fmt(&argp->fh), |
| 679 | 670 | argp->count, |
| 680 | 671 | (unsigned long long) argp->offset); |
| 681 | 672 | |
| 682 | − if (argp->offset > NFS_OFFSET_MAX) | |
| 683 | − RETURN_STATUS(nfserr_inval); | |
| 673 | + if (argp->offset > NFS_OFFSET_MAX) { | |
| 674 | + resp->status = nfserr_inval; | |
| 675 | + goto out; | |
| 676 | + } | |
| 684 | 677 | |
| 685 | 678 | fh_copy(&resp->fh, &argp->fh); |
| 686 | − nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count, | |
| 687 | − resp->verf); | |
| 688 | − | |
| 689 | − RETURN_STATUS(nfserr); | |
| 679 | + resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset, | |
| 680 | + argp->count, resp->verf); | |
| 681 | +out: | |
| 682 | + return rpc_success; | |
| 690 | 683 | } |
| 691 | 684 | |
| 692 | 685 | |
| @@ -716,6 +709,7 @@ struct nfsd3_voidargs { int dummy; }; · 23 unmodified lines | ||
| 716 | 709 | static const struct svc_procedure nfsd_procedures3[22] = { |
| 717 | 710 | [NFS3PROC_NULL] = { |
| 718 | 711 | .pc_func = nfsd3_proc_null, |
| 712 | + .pc_decode = nfs3svc_decode_voidarg, | |
| 719 | 713 | .pc_encode = nfs3svc_encode_voidres, |
| 720 | 714 | .pc_argsize = sizeof(struct nfsd3_voidargs), |
| 721 | 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 | 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 | 313 | int |
| 308 | 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 | 642 | * XDR encode functions |
| 637 | 643 | */ |
| 638 | −/* | |
| 639 | − * There must be an encoding function for void results so svc_process | |
| 640 | − * will work properly. | |
| 641 | − */ | |
| 644 | + | |
| 642 | 645 | int |
| 643 | 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 | 655 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 653 | 656 | |
| 657 | + *p++ = resp->status; | |
| 654 | 658 | if (resp->status == 0) { |
| 655 | 659 | lease_get_mtime(d_inode(resp->fh.fh_dentry), |
| 656 | 660 | &resp->stat.mtime); |
| @@ -665,6 +669,7 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p) · 8 unmodified lines | ||
| 665 | 669 | { |
| 666 | 670 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
| 667 | 671 | |
| 672 | + *p++ = resp->status; | |
| 668 | 673 | p = encode_wcc_data(rqstp, p, &resp->fh); |
| 669 | 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 | 681 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 677 | 682 | |
| 683 | + *p++ = resp->status; | |
| 678 | 684 | if (resp->status == 0) { |
| 679 | 685 | p = encode_fh(p, &resp->fh); |
| 680 | 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 | 696 | struct nfsd3_accessres *resp = rqstp->rq_resp; |
| 691 | 697 | |
| 698 | + *p++ = resp->status; | |
| 692 | 699 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
| 693 | 700 | if (resp->status == 0) |
| 694 | 701 | *p++ = htonl(resp->access); |
| @@ -701,6 +708,7 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) · 6 unmodified lines | ||
| 701 | 708 | { |
| 702 | 709 | struct nfsd3_readlinkres *resp = rqstp->rq_resp; |
| 703 | 710 | |
| 711 | + *p++ = resp->status; | |
| 704 | 712 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
| 705 | 713 | if (resp->status == 0) { |
| 706 | 714 | *p++ = htonl(resp->len); |
| @@ -723,6 +731,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p) · 16 unmodified lines | ||
| 723 | 731 | { |
| 724 | 732 | struct nfsd3_readres *resp = rqstp->rq_resp; |
| 725 | 733 | |
| 734 | + *p++ = resp->status; | |
| 726 | 735 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
| 727 | 736 | if (resp->status == 0) { |
| 728 | 737 | *p++ = htonl(resp->count); |
| @@ -748,6 +757,7 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) · 19 unmodified lines | ||
| 748 | 757 | { |
| 749 | 758 | struct nfsd3_writeres *resp = rqstp->rq_resp; |
| 750 | 759 | |
| 760 | + *p++ = resp->status; | |
| 751 | 761 | p = encode_wcc_data(rqstp, p, &resp->fh); |
| 752 | 762 | if (resp->status == 0) { |
| 753 | 763 | *p++ = htonl(resp->count); |
| @@ -764,6 +774,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p) · 10 unmodified lines | ||
| 764 | 774 | { |
| 765 | 775 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
| 766 | 776 | |
| 777 | + *p++ = resp->status; | |
| 767 | 778 | if (resp->status == 0) { |
| 768 | 779 | *p++ = xdr_one; |
| 769 | 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 | 791 | struct nfsd3_renameres *resp = rqstp->rq_resp; |
| 781 | 792 | |
| 793 | + *p++ = resp->status; | |
| 782 | 794 | p = encode_wcc_data(rqstp, p, &resp->ffh); |
| 783 | 795 | p = encode_wcc_data(rqstp, p, &resp->tfh); |
| 784 | 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 | 803 | struct nfsd3_linkres *resp = rqstp->rq_resp; |
| 792 | 804 | |
| 805 | + *p++ = resp->status; | |
| 793 | 806 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
| 794 | 807 | p = encode_wcc_data(rqstp, p, &resp->tfh); |
| 795 | 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 | 815 | struct nfsd3_readdirres *resp = rqstp->rq_resp; |
| 803 | 816 | |
| 817 | + *p++ = resp->status; | |
| 804 | 818 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
| 805 | 819 | |
| 806 | 820 | if (resp->status == 0) { |
| @@ -1053,6 +1067,7 @@ nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p) · 246 unmodified lines | ||
| 1053 | 1067 | struct kstatfs *s = &resp->stats; |
| 1054 | 1068 | u64 bs = s->f_bsize; |
| 1055 | 1069 | |
| 1070 | + *p++ = resp->status; | |
| 1056 | 1071 | *p++ = xdr_zero; /* no post_op_attr */ |
| 1057 | 1072 | |
| 1058 | 1073 | if (resp->status == 0) { |
| @@ -1073,6 +1088,7 @@ nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p) · 14 unmodified lines | ||
| 1073 | 1088 | { |
| 1074 | 1089 | struct nfsd3_fsinfores *resp = rqstp->rq_resp; |
| 1075 | 1090 | |
| 1091 | + *p++ = resp->status; | |
| 1076 | 1092 | *p++ = xdr_zero; /* no post_op_attr */ |
| 1077 | 1093 | |
| 1078 | 1094 | if (resp->status == 0) { |
| @@ -1118,6 +1134,7 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) · 39 unmodified lines | ||
| 1118 | 1134 | { |
| 1119 | 1135 | struct nfsd3_commitres *resp = rqstp->rq_resp; |
| 1120 | 1136 | |
| 1137 | + *p++ = resp->status; | |
| 1121 | 1138 | p = encode_wcc_data(rqstp, p, &resp->fh); |
| 1122 | 1139 | /* Write verifier */ |
| 1123 | 1140 | if (resp->status == 0) { |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <linux/slab.h> |
| 39 | 39 | #include <linux/kthread.h> |
| 40 | 40 | #include <linux/sunrpc/addr.h> |
| 41 | +#include <linux/nfs_ssc.h> | |
| 41 | 42 | |
| 42 | 43 | #include "idmap.h" |
| 43 | 44 | #include "cache.h" |
| @@ -1247,7 +1248,7 @@ out_err: · 1203 unmodified lines | ||
| 1247 | 1248 | static void |
| 1248 | 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 | 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 | 2166 | static __be32 |
| 2166 | 2167 | nfsd4_proc_null(struct svc_rqst *rqstp) |
| 2167 | 2168 | { |
| 2168 | − return nfs_ok; | |
| 2169 | + return rpc_success; | |
| 2169 | 2170 | } |
| 2170 | 2171 | |
| 2171 | 2172 | static inline void nfsd4_increment_op_stats(u32 opnum) |
| @@ -2457,15 +2458,14 @@ encode_op: · 285 unmodified lines | ||
| 2457 | 2458 | nfsd4_increment_op_stats(op->opnum); |
| 2458 | 2459 | } |
| 2459 | 2460 | |
| 2460 | − cstate->status = status; | |
| 2461 | 2461 | fh_put(current_fh); |
| 2462 | 2462 | fh_put(save_fh); |
| 2463 | 2463 | BUG_ON(cstate->replay_owner); |
| 2464 | 2464 | out: |
| 2465 | + cstate->status = status; | |
| 2465 | 2466 | /* Reset deferral mechanism for RPC deferrals */ |
| 2466 | 2467 | set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); |
| 2467 | − dprintk("nfsv4 compound returned %d\n", ntohl(status)); | |
| 2468 | − return status; | |
| 2468 | + return rpc_success; | |
| 2469 | 2469 | } |
| 2470 | 2470 | |
| 2471 | 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 | 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 | 2608 | static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) |
| 2595 | 2609 | { |
| 2596 | 2610 | u32 maxcount = 0, rlen = 0; |
| @@ -3163,6 +3177,13 @@ static const struct nfsd4_operation nfsd4_ops[] = { · 566 unmodified lines | ||
| 3163 | 3177 | .op_name = "OP_COPY", |
| 3164 | 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 | 3187 | [OP_SEEK] = { |
| 3167 | 3188 | .op_func = nfsd4_seek, |
| 3168 | 3189 | .op_name = "OP_SEEK", |
| @@ -3231,7 +3252,7 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) · 62 unmodified lines | ||
| 3231 | 3252 | if (!cstate->minorversion) |
| 3232 | 3253 | return false; |
| 3233 | 3254 | |
| 3234 | − if (cstate->spo_must_allowed == true) | |
| 3255 | + if (cstate->spo_must_allowed) | |
| 3235 | 3256 | return true; |
| 3236 | 3257 | |
| 3237 | 3258 | opiter = resp->opcnt; |
| @@ -3279,6 +3300,7 @@ struct nfsd4_voidargs { int dummy; }; · 41 unmodified lines | ||
| 3279 | 3300 | static const struct svc_procedure nfsd_procedures4[2] = { |
| 3280 | 3301 | [NFSPROC4_NULL] = { |
| 3281 | 3302 | .pc_func = nfsd4_proc_null, |
| 3303 | + .pc_decode = nfs4svc_decode_voidarg, | |
| 3282 | 3304 | .pc_encode = nfs4svc_encode_voidres, |
| 3283 | 3305 | .pc_argsize = sizeof(struct nfsd4_voidargs), |
| 3284 | 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 | 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 | 4518 | return 1; |
| 4518 | 4519 | |
| 4519 | 4520 | switch (task->tk_status) { |
| @@ -4597,7 +4598,8 @@ static bool nfsd_breaker_owns_lease(struct file_lock *fl) · 77 unmodified lines | ||
| 4597 | 4598 | if (!i_am_nfsd()) |
| 4598 | 4599 | return NULL; |
| 4599 | 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 | 4603 | return NULL; |
| 4602 | 4604 | clp = *(rqst->rq_lease_breaker); |
| 4603 | 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 | 4956 | writes--; |
| 4955 | 4957 | if (fp->fi_fds[O_RDWR]) |
| 4956 | 4958 | writes--; |
| 4957 | − WARN_ON_ONCE(writes < 0); | |
| 4958 | 4959 | if (writes > 0) |
| 4959 | 4960 | return -EAGAIN; |
| 4960 | 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 | 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 | 5131 | open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; |
| 5131 | 5132 | nfs4_put_stid(&dp->dl_stid); |
| 5132 | 5133 | return; |
| @@ -5243,7 +5244,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf · 110 unmodified lines | ||
| 5243 | 5244 | nfs4_open_delegation(current_fh, open, stp); |
| 5244 | 5245 | nodeleg: |
| 5245 | 5246 | status = nfs_ok; |
| 5246 | − trace_nfsd_deleg_none(&stp->st_stid.sc_stateid); | |
| 5247 | + trace_nfsd_open(&stp->st_stid.sc_stateid); | |
| 5247 | 5248 | out: |
| 5248 | 5249 | /* 4.1 client trying to upgrade/downgrade delegation? */ |
| 5249 | 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 | 5723 | return find_readable_file(s->sc_file); |
| 5723 | 5724 | else |
| 5724 | 5725 | return find_writeable_file(s->sc_file); |
| 5725 | − break; | |
| 5726 | 5726 | } |
| 5727 | 5727 | |
| 5728 | 5728 | return NULL; |
| @@ -7253,599 +7253,6 @@ nfs4_check_open_reclaim(clientid_t *clid, · 1524 unmodified lines | ||
| 7253 | 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 | 7257 | * Since the lifetime of a delegation isn't limited to that of an open, a |
| 7851 | 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 | 1855 | nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp, |
| 1856 | 1856 | struct nfsd4_copy_notify *cn) |
| 1857 | 1857 | { |
| 1858 | − int status; | |
| 1858 | + __be32 status; | |
| 1859 | 1859 | |
| 1860 | 1860 | status = nfsd4_decode_stateid(argp, &cn->cpn_src_stateid); |
| 1861 | 1861 | if (status) |
| @@ -2173,7 +2173,7 @@ static const nfsd4_dec nfsd4_dec_ops[] = { · 311 unmodified lines | ||
| 2173 | 2173 | [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 2174 | 2174 | [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_offload_status, |
| 2175 | 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 | 2177 | [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek, |
| 2178 | 2178 | [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 2179 | 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 | 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 | 2265 | readcount++; |
| 2266 | 2266 | readbytes += nfsd4_max_reply(argp->rqstp, op); |
| 2267 | 2267 | } else |
| @@ -3814,36 +3814,14 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, · 1546 unmodified lines | ||
| 3814 | 3814 | { |
| 3815 | 3815 | struct xdr_stream *xdr = &resp->xdr; |
| 3816 | 3816 | u32 eof; |
| 3817 | − int v; | |
| 3818 | 3817 | int starting_len = xdr->buf->len - 8; |
| 3819 | − long len; | |
| 3820 | − int thislen; | |
| 3821 | 3818 | __be32 nfserr; |
| 3822 | 3819 | __be32 tmp; |
| 3823 | − __be32 *p; | |
| 3824 | 3820 | int pad; |
| 3825 | 3821 | |
| 3826 | − /* | |
| 3827 | − * svcrdma requires every READ payload to start somewhere | |
| 3828 | − * in xdr->pages. | |
| 3829 | − */ | |
| 3830 | − if (xdr->iov == xdr->buf->head) { | |
| 3831 | − xdr->iov = NULL; | |
| 3832 | − xdr->end = xdr->p; | |
| 3833 | − } | |
| 3834 | − | |
| 3835 | − len = maxcount; | |
| 3836 | − v = 0; | |
| 3837 | − while (len) { | |
| 3838 | − thislen = min_t(long, len, PAGE_SIZE); | |
| 3839 | − p = xdr_reserve_space(xdr, thislen); | |
| 3840 | − WARN_ON_ONCE(!p); | |
| 3841 | − resp->rqstp->rq_vec[v].iov_base = p; | |
| 3842 | − resp->rqstp->rq_vec[v].iov_len = thislen; | |
| 3843 | − v++; | |
| 3844 | − len -= thislen; | |
| 3845 | − } | |
| 3846 | − read->rd_vlen = v; | |
| 3822 | + read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount); | |
| 3823 | + if (read->rd_vlen < 0) | |
| 3824 | + return nfserr_resource; | |
| 3847 | 3825 | |
| 3848 | 3826 | nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, |
| 3849 | 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 | 4597 | return nfserr_resource; |
| 4620 | 4598 | p = xdr_encode_hyper(p, os->count); |
| 4621 | 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 | 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 | 4801 | * Encode kmalloc-ed buffer in to XDR stream. |
| 4681 | 4802 | */ |
| 4682 | −static int | |
| 4803 | +static __be32 | |
| 4683 | 4804 | nfsd4_vbuf_to_stream(struct xdr_stream *xdr, char *buf, u32 buflen) |
| 4684 | 4805 | { |
| 4685 | 4806 | u32 cplen; |
| @@ -4795,7 +4916,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 109 unmodified lines | ||
| 4795 | 4916 | u32 xdrlen, offset; |
| 4796 | 4917 | u64 cookie; |
| 4797 | 4918 | char *sp; |
| 4798 | − __be32 status; | |
| 4919 | + __be32 status, tmp; | |
| 4799 | 4920 | __be32 *p; |
| 4800 | 4921 | u32 nuser; |
| 4801 | 4922 | |
| @@ -4828,7 +4949,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 26 unmodified lines | ||
| 4828 | 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 | 4954 | if (strncmp(sp, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) |
| 4834 | 4955 | goto contloop; |
| @@ -4859,7 +4980,7 @@ nfsd4_encode_listxattrs(struct nfsd4_compoundres *resp, __be32 nfserr, · 24 unmodified lines | ||
| 4859 | 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 | 4985 | xdrleft -= xdrlen; |
| 4865 | 4986 | count++; |
| @@ -4888,8 +5009,8 @@ wreof: · 22 unmodified lines | ||
| 4888 | 5009 | cookie = offset + count; |
| 4889 | 5010 | |
| 4890 | 5011 | write_bytes_to_xdr_buf(xdr->buf, cookie_offset, &cookie, 8); |
| 4891 | − count = htonl(count); | |
| 4892 | − write_bytes_to_xdr_buf(xdr->buf, count_offset, &count, 4); | |
| 5012 | + tmp = cpu_to_be32(count); | |
| 5013 | + write_bytes_to_xdr_buf(xdr->buf, count_offset, &tmp, 4); | |
| 4893 | 5014 | out: |
| 4894 | 5015 | if (listxattrs->lsxa_len) |
| 4895 | 5016 | kvfree(listxattrs->lsxa_buf); |
| @@ -4996,7 +5117,7 @@ static const nfsd4_enc nfsd4_enc_ops[] = { · 100 unmodified lines | ||
| 4996 | 5117 | [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop, |
| 4997 | 5118 | [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop, |
| 4998 | 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 | 5121 | [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek, |
| 5001 | 5122 | [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop, |
| 5002 | 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 | 5286 | int |
| 5160 | 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 | 5310 | int |
| 5184 | 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 | 5313 | struct nfsd4_compoundres *resp = rqstp->rq_resp; |
| 5190 | 5314 | struct xdr_buf *buf = resp->xdr.buf; |
| 5191 | 5315 | |
| 5192 | 5316 | WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len + |
| 5193 | 5317 | buf->tail[0].iov_len); |
| 5194 | 5318 | |
| 5319 | + *p = resp->cstate.status; | |
| 5320 | + | |
| 5195 | 5321 | rqstp->rq_next_page = resp->xdr.page_ptr + 1; |
| 5196 | 5322 | |
| 5197 | 5323 | p = resp->tagp; |
| @@ -172,14 +172,10 @@ int nfsd_reply_cache_init(struct nfsd_net *nn) · 171 unmodified lines | ||
| 172 | 172 | if (status) |
| 173 | 173 | goto out_nomem; |
| 174 | 174 | |
| 175 | − nn->drc_hashtbl = kcalloc(hashsize, | |
| 176 | − sizeof(*nn->drc_hashtbl), GFP_KERNEL); | |
| 177 | − if (!nn->drc_hashtbl) { | |
| 178 | − nn->drc_hashtbl = vzalloc(array_size(hashsize, | |
| 179 | − sizeof(*nn->drc_hashtbl))); | |
| 180 | − if (!nn->drc_hashtbl) | |
| 181 | − goto out_shrinker; | |
| 182 | − } | |
| 175 | + nn->drc_hashtbl = kvzalloc(array_size(hashsize, | |
| 176 | + sizeof(*nn->drc_hashtbl)), GFP_KERNEL); | |
| 177 | + if (!nn->drc_hashtbl) | |
| 178 | + goto out_shrinker; | |
| 183 | 179 | |
| 184 | 180 | for (i = 0; i < hashsize; i++) { |
| 185 | 181 | INIT_LIST_HEAD(&nn->drc_hashtbl[i].lru_head); |
| @@ -1534,7 +1534,6 @@ static int __init init_nfsd(void) · 1533 unmodified lines | ||
| 1534 | 1534 | retval = nfsd4_init_pnfs(); |
| 1535 | 1535 | if (retval) |
| 1536 | 1536 | goto out_free_slabs; |
| 1537 | − nfsd_fault_inject_init(); /* nfsd fault injection controls */ | |
| 1538 | 1537 | nfsd_stat_init(); /* Statistics */ |
| 1539 | 1538 | retval = nfsd_drc_slab_create(); |
| 1540 | 1539 | if (retval) |
| @@ -1555,7 +1554,6 @@ out_free_lockd: · 14 unmodified lines | ||
| 1555 | 1554 | nfsd_drc_slab_free(); |
| 1556 | 1555 | out_free_stat: |
| 1557 | 1556 | nfsd_stat_shutdown(); |
| 1558 | − nfsd_fault_inject_cleanup(); | |
| 1559 | 1557 | nfsd4_exit_pnfs(); |
| 1560 | 1558 | out_free_slabs: |
| 1561 | 1559 | nfsd4_free_slabs(); |
| @@ -1575,7 +1573,6 @@ static void __exit exit_nfsd(void) · 13 unmodified lines | ||
| 1575 | 1573 | nfsd_lockd_shutdown(); |
| 1576 | 1574 | nfsd4_free_slabs(); |
| 1577 | 1575 | nfsd4_exit_pnfs(); |
| 1578 | − nfsd_fault_inject_cleanup(); | |
| 1579 | 1576 | unregister_filesystem(&nfsd_fs_type); |
| 1580 | 1577 | unregister_cld_notifier(); |
| 1581 | 1578 | unregister_pernet_subsys(&nfsd_net_ops); |
| @@ -11,30 +11,14 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "xdr.h" |
| 12 | 12 | #include "vfs.h" |
| 13 | 13 | |
| 14 | −typedef struct svc_rqst svc_rqst; | |
| 15 | −typedef struct svc_buf svc_buf; | |
| 16 | − | |
| 17 | 14 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 18 | 15 | |
| 19 | − | |
| 20 | 16 | static __be32 |
| 21 | 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 | 23 | * Get a file's attributes |
| 40 | 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 | 29 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 46 | 30 | struct nfsd_attrstat *resp = rqstp->rq_resp; |
| 47 | − __be32 nfserr; | |
| 31 | + | |
| 48 | 32 | dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); |
| 49 | 33 | |
| 50 | 34 | fh_copy(&resp->fh, &argp->fh); |
| 51 | − nfserr = fh_verify(rqstp, &resp->fh, 0, | |
| 52 | − NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 53 | − return nfsd_return_attrs(nfserr, resp); | |
| 35 | + resp->status = fh_verify(rqstp, &resp->fh, 0, | |
| 36 | + NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 37 | + if (resp->status != nfs_ok) | |
| 38 | + goto out; | |
| 39 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 40 | +out: | |
| 41 | + return rpc_success; | |
| 54 | 42 | } |
| 55 | 43 | |
| 56 | 44 | /* |
| @@ -64,7 +52,6 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 7 unmodified lines | ||
| 64 | 52 | struct nfsd_attrstat *resp = rqstp->rq_resp; |
| 65 | 53 | struct iattr *iap = &argp->attrs; |
| 66 | 54 | struct svc_fh *fhp; |
| 67 | − __be32 nfserr; | |
| 68 | 55 | |
| 69 | 56 | dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", |
| 70 | 57 | SVCFH_fmt(&argp->fh), |
| @@ -96,9 +83,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) · 25 unmodified lines | ||
| 96 | 83 | */ |
| 97 | 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); | |
| 100 | − if (nfserr) | |
| 101 | − goto done; | |
| 86 | + resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP); | |
| 87 | + if (resp->status != nfs_ok) | |
| 88 | + goto out; | |
| 102 | 89 | |
| 103 | 90 | if (delta < 0) |
| 104 | 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); | |
| 117 | −done: | |
| 118 | − return nfsd_return_attrs(nfserr, resp); | |
| 103 | + resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0); | |
| 104 | + if (resp->status != nfs_ok) | |
| 105 | + goto out; | |
| 106 | + | |
| 107 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 108 | +out: | |
| 109 | + return rpc_success; | |
| 110 | +} | |
| 111 | + | |
| 112 | +/* Obsolete, replaced by MNTPROC_MNT. */ | |
| 113 | +static __be32 | |
| 114 | +nfsd_proc_root(struct svc_rqst *rqstp) | |
| 115 | +{ | |
| 116 | + return rpc_success; | |
| 119 | 117 | } |
| 120 | 118 | |
| 121 | 119 | /* |
| @@ -129,17 +127,20 @@ nfsd_proc_lookup(struct svc_rqst *rqstp) · 7 unmodified lines | ||
| 129 | 127 | { |
| 130 | 128 | struct nfsd_diropargs *argp = rqstp->rq_argp; |
| 131 | 129 | struct nfsd_diropres *resp = rqstp->rq_resp; |
| 132 | − __be32 nfserr; | |
| 133 | 130 | |
| 134 | 131 | dprintk("nfsd: LOOKUP %s %.*s\n", |
| 135 | 132 | SVCFH_fmt(&argp->fh), argp->len, argp->name); |
| 136 | 133 | |
| 137 | 134 | fh_init(&resp->fh, NFS_FHSIZE); |
| 138 | − nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len, | |
| 139 | − &resp->fh); | |
| 140 | − | |
| 135 | + resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len, | |
| 136 | + &resp->fh); | |
| 141 | 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 | 152 | struct nfsd_readlinkargs *argp = rqstp->rq_argp; |
| 152 | 153 | struct nfsd_readlinkres *resp = rqstp->rq_resp; |
| 153 | − __be32 nfserr; | |
| 154 | 154 | |
| 155 | 155 | dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh)); |
| 156 | 156 | |
| 157 | 157 | /* Read the symlink. */ |
| 158 | 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 | 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 | 172 | struct nfsd_readargs *argp = rqstp->rq_argp; |
| 173 | 173 | struct nfsd_readres *resp = rqstp->rq_resp; |
| 174 | − __be32 nfserr; | |
| 175 | 174 | u32 eof; |
| 176 | 175 | |
| 177 | 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 | 192 | svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); |
| 194 | 193 | |
| 195 | 194 | resp->count = argp->count; |
| 196 | − nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), | |
| 197 | − argp->offset, | |
| 198 | − rqstp->rq_vec, argp->vlen, | |
| 199 | − &resp->count, | |
| 200 | − &eof); | |
| 201 | − | |
| 202 | − if (nfserr) return nfserr; | |
| 203 | − return fh_getattr(&resp->fh, &resp->stat); | |
| 195 | + resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), | |
| 196 | + argp->offset, | |
| 197 | + rqstp->rq_vec, argp->vlen, | |
| 198 | + &resp->count, | |
| 199 | + &eof); | |
| 200 | + if (resp->status == nfs_ok) | |
| 201 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 202 | + else if (resp->status == nfserr_jukebox) | |
| 203 | + return rpc_drop_reply; | |
| 204 | + return rpc_success; | |
| 205 | +} | |
| 206 | + | |
| 207 | +/* Reserved */ | |
| 208 | +static __be32 | |
| 209 | +nfsd_proc_writecache(struct svc_rqst *rqstp) | |
| 210 | +{ | |
| 211 | + return rpc_success; | |
| 204 | 212 | } |
| 205 | 213 | |
| 206 | 214 | /* |
| @@ -212,7 +220,6 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 5 unmodified lines | ||
| 212 | 220 | { |
| 213 | 221 | struct nfsd_writeargs *argp = rqstp->rq_argp; |
| 214 | 222 | struct nfsd_attrstat *resp = rqstp->rq_resp; |
| 215 | − __be32 nfserr; | |
| 216 | 223 | unsigned long cnt = argp->len; |
| 217 | 224 | unsigned int nvecs; |
| 218 | 225 | |
| @@ -222,12 +229,20 @@ nfsd_proc_write(struct svc_rqst *rqstp) · 3 unmodified lines | ||
| 222 | 229 | |
| 223 | 230 | nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages, |
| 224 | 231 | &argp->first, cnt); |
| 225 | − if (!nvecs) | |
| 226 | − return nfserr_io; | |
| 227 | − nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), | |
| 228 | − argp->offset, rqstp->rq_vec, nvecs, | |
| 229 | − &cnt, NFS_DATA_SYNC, NULL); | |
| 230 | − return nfsd_return_attrs(nfserr, resp); | |
| 232 | + if (!nvecs) { | |
| 233 | + resp->status = nfserr_io; | |
| 234 | + goto out; | |
| 235 | + } | |
| 236 | + | |
| 237 | + resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), | |
| 238 | + argp->offset, rqstp->rq_vec, nvecs, | |
| 239 | + &cnt, NFS_DATA_SYNC, NULL); | |
| 240 | + if (resp->status == nfs_ok) | |
| 241 | + resp->status = fh_getattr(&resp->fh, &resp->stat); | |
| 242 | + else if (resp->status == nfserr_jukebox) | |
| 243 | + return rpc_drop_reply; | |
| 244 | +out: | |
| 245 | + return rpc_success; | |
| 231 | 246 | } |
| 232 | 247 | |
| 233 | 248 | /* |
| @@ -247,7 +262,6 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 13 unmodified lines | ||
| 247 | 262 | struct inode *inode; |
| 248 | 263 | struct dentry *dchild; |
| 249 | 264 | int type, mode; |
| 250 | − __be32 nfserr; | |
| 251 | 265 | int hosterr; |
| 252 | 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 | 269 | SVCFH_fmt(dirfhp), argp->len, argp->name); |
| 256 | 270 | |
| 257 | 271 | /* First verify the parent file handle */ |
| 258 | − nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC); | |
| 259 | − if (nfserr) | |
| 272 | + resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC); | |
| 273 | + if (resp->status != nfs_ok) | |
| 260 | 274 | goto done; /* must fh_put dirfhp even on error */ |
| 261 | 275 | |
| 262 | 276 | /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */ |
| 263 | 277 | |
| 264 | − nfserr = nfserr_exist; | |
| 278 | + resp->status = nfserr_exist; | |
| 265 | 279 | if (isdotent(argp->name, argp->len)) |
| 266 | 280 | goto done; |
| 267 | 281 | hosterr = fh_want_write(dirfhp); |
| 268 | 282 | if (hosterr) { |
| 269 | − nfserr = nfserrno(hosterr); | |
| 283 | + resp->status = nfserrno(hosterr); | |
| 270 | 284 | goto done; |
| 271 | 285 | } |
| 272 | 286 | |
| 273 | 287 | fh_lock_nested(dirfhp, I_MUTEX_PARENT); |
| 274 | 288 | dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); |
| 275 | 289 | if (IS_ERR(dchild)) { |
| 276 | − nfserr = nfserrno(PTR_ERR(dchild)); | |
| 290 | + resp->status = nfserrno(PTR_ERR(dchild)); | |
| 277 | 291 | goto out_unlock; |
| 278 | 292 | } |
| 279 | 293 | fh_init(newfhp, NFS_FHSIZE); |
| 280 | − nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp); | |
| 281 | − if (!nfserr && d_really_is_negative(dchild)) | |
| 282 | − nfserr = nfserr_noent; | |
| 294 | + resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp); | |
| 295 | + if (!resp->status && d_really_is_negative(dchild)) | |
| 296 | + resp->status = nfserr_noent; | |
| 283 | 297 | dput(dchild); |
| 284 | − if (nfserr) { | |
| 285 | − if (nfserr != nfserr_noent) | |
| 298 | + if (resp->status) { | |
| 299 | + if (resp->status != nfserr_noent) | |
| 286 | 300 | goto out_unlock; |
| 287 | 301 | /* |
| 288 | 302 | * If the new file handle wasn't verified, we can't tell |
| 289 | 303 | * whether the file exists or not. Time to bail ... |
| 290 | 304 | */ |
| 291 | − nfserr = nfserr_acces; | |
| 305 | + resp->status = nfserr_acces; | |
| 292 | 306 | if (!newfhp->fh_dentry) { |
| 293 | 307 | printk(KERN_WARNING |
| 294 | 308 | "nfsd_proc_create: file handle not verified\n"); |
| @@ -321,11 +335,11 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 26 unmodified lines | ||
| 321 | 335 | * echo thing > device-special-file-or-pipe |
| 322 | 336 | * by doing a CREATE with type==0 |
| 323 | 337 | */ |
| 324 | − nfserr = nfsd_permission(rqstp, | |
| 338 | + resp->status = nfsd_permission(rqstp, | |
| 325 | 339 | newfhp->fh_export, |
| 326 | 340 | newfhp->fh_dentry, |
| 327 | 341 | NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS); |
| 328 | − if (nfserr && nfserr != nfserr_rofs) | |
| 342 | + if (resp->status && resp->status != nfserr_rofs) | |
| 329 | 343 | goto out_unlock; |
| 330 | 344 | } |
| 331 | 345 | } else |
| @@ -361,16 +375,17 @@ nfsd_proc_create(struct svc_rqst *rqstp) · 29 unmodified lines | ||
| 361 | 375 | attr->ia_valid &= ~ATTR_SIZE; |
| 362 | 376 | |
| 363 | 377 | /* Make sure the type and device matches */ |
| 364 | − nfserr = nfserr_exist; | |
| 378 | + resp->status = nfserr_exist; | |
| 365 | 379 | if (inode && type != (inode->i_mode & S_IFMT)) |
| 366 | 380 | goto out_unlock; |
| 367 | 381 | } |
| 368 | 382 | |
| 369 | − nfserr = 0; | |
| 383 | + resp->status = nfs_ok; | |
| 370 | 384 | if (!inode) { |
| 371 | 385 | /* File doesn't exist. Create it and set attrs */ |
| 372 | − nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name, | |
| 373 | − argp->len, attr, type, rdev, newfhp); | |
| 386 | + resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name, | |
| 387 | + argp->len, attr, type, rdev, | |
| 388 | + newfhp); | |
| 374 | 389 | } else if (type == S_IFREG) { |
| 375 | 390 | dprintk("nfsd: existing %s, valid=%x, size=%ld\n", |
| 376 | 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 | 396 | attr->ia_valid &= ATTR_SIZE; |
| 382 | 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 | 402 | out_unlock: |
| @@ -389,47 +405,52 @@ out_unlock: · 2 unmodified lines | ||
| 389 | 405 | fh_drop_write(dirfhp); |
| 390 | 406 | done: |
| 391 | 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 | 415 | static __be32 |
| 396 | 416 | nfsd_proc_remove(struct svc_rqst *rqstp) |
| 397 | 417 | { |
| 398 | 418 | struct nfsd_diropargs *argp = rqstp->rq_argp; |
| 399 | − __be32 nfserr; | |
| 419 | + struct nfsd_stat *resp = rqstp->rq_resp; | |
| 400 | 420 | |
| 401 | 421 | dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh), |
| 402 | 422 | argp->len, argp->name); |
| 403 | 423 | |
| 404 | 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 | 427 | fh_put(&argp->fh); |
| 407 | − return nfserr; | |
| 428 | + return rpc_success; | |
| 408 | 429 | } |
| 409 | 430 | |
| 410 | 431 | static __be32 |
| 411 | 432 | nfsd_proc_rename(struct svc_rqst *rqstp) |
| 412 | 433 | { |
| 413 | 434 | struct nfsd_renameargs *argp = rqstp->rq_argp; |
| 414 | − __be32 nfserr; | |
| 435 | + struct nfsd_stat *resp = rqstp->rq_resp; | |
| 415 | 436 | |
| 416 | 437 | dprintk("nfsd: RENAME %s %.*s -> \n", |
| 417 | 438 | SVCFH_fmt(&argp->ffh), argp->flen, argp->fname); |
| 418 | 439 | dprintk("nfsd: -> %s %.*s\n", |
| 419 | 440 | SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname); |
| 420 | 441 | |
| 421 | − nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, | |
| 422 | − &argp->tfh, argp->tname, argp->tlen); | |
| 442 | + resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, | |
| 443 | + &argp->tfh, argp->tname, argp->tlen); | |
| 423 | 444 | fh_put(&argp->ffh); |
| 424 | 445 | fh_put(&argp->tfh); |
| 425 | − return nfserr; | |
| 446 | + return rpc_success; | |
| 426 | 447 | } |
| 427 | 448 | |
| 428 | 449 | static __be32 |
| 429 | 450 | nfsd_proc_link(struct svc_rqst *rqstp) |
| 430 | 451 | { |
| 431 | 452 | struct nfsd_linkargs *argp = rqstp->rq_argp; |
| 432 | − __be32 nfserr; | |
| 453 | + struct nfsd_stat *resp = rqstp->rq_resp; | |
| 433 | 454 | |
| 434 | 455 | dprintk("nfsd: LINK %s ->\n", |
| 435 | 456 | SVCFH_fmt(&argp->ffh)); |
| @@ -438,41 +459,46 @@ nfsd_proc_link(struct svc_rqst *rqstp) · 2 unmodified lines | ||
| 438 | 459 | argp->tlen, |
| 439 | 460 | argp->tname); |
| 440 | 461 | |
| 441 | − nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, | |
| 442 | − &argp->ffh); | |
| 462 | + resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, | |
| 463 | + &argp->ffh); | |
| 443 | 464 | fh_put(&argp->ffh); |
| 444 | 465 | fh_put(&argp->tfh); |
| 445 | − return nfserr; | |
| 466 | + return rpc_success; | |
| 446 | 467 | } |
| 447 | 468 | |
| 448 | 469 | static __be32 |
| 449 | 470 | nfsd_proc_symlink(struct svc_rqst *rqstp) |
| 450 | 471 | { |
| 451 | 472 | struct nfsd_symlinkargs *argp = rqstp->rq_argp; |
| 473 | + struct nfsd_stat *resp = rqstp->rq_resp; | |
| 452 | 474 | struct svc_fh newfh; |
| 453 | − __be32 nfserr; | |
| 454 | 475 | |
| 455 | − if (argp->tlen > NFS_MAXPATHLEN) | |
| 456 | − return nfserr_nametoolong; | |
| 476 | + if (argp->tlen > NFS_MAXPATHLEN) { | |
| 477 | + resp->status = nfserr_nametoolong; | |
| 478 | + goto out; | |
| 479 | + } | |
| 457 | 480 | |
| 458 | 481 | argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first, |
| 459 | 482 | page_address(rqstp->rq_arg.pages[0]), |
| 460 | 483 | argp->tlen); |
| 461 | − if (IS_ERR(argp->tname)) | |
| 462 | − return nfserrno(PTR_ERR(argp->tname)); | |
| 484 | + if (IS_ERR(argp->tname)) { | |
| 485 | + resp->status = nfserrno(PTR_ERR(argp->tname)); | |
| 486 | + goto out; | |
| 487 | + } | |
| 463 | 488 | |
| 464 | 489 | dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n", |
| 465 | 490 | SVCFH_fmt(&argp->ffh), argp->flen, argp->fname, |
| 466 | 491 | argp->tlen, argp->tname); |
| 467 | 492 | |
| 468 | 493 | fh_init(&newfh, NFS_FHSIZE); |
| 469 | − nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, | |
| 470 | − argp->tname, &newfh); | |
| 494 | + resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, | |
| 495 | + argp->tname, &newfh); | |
| 471 | 496 | |
| 472 | 497 | kfree(argp->tname); |
| 473 | 498 | fh_put(&argp->ffh); |
| 474 | 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 | 511 | struct nfsd_createargs *argp = rqstp->rq_argp; |
| 486 | 512 | struct nfsd_diropres *resp = rqstp->rq_resp; |
| 487 | − __be32 nfserr; | |
| 488 | 513 | |
| 489 | 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 | 521 | argp->attrs.ia_valid &= ~ATTR_SIZE; |
| 497 | 522 | fh_init(&resp->fh, NFS_FHSIZE); |
| 498 | − nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, | |
| 499 | − &argp->attrs, S_IFDIR, 0, &resp->fh); | |
| 523 | + resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, | |
| 524 | + &argp->attrs, S_IFDIR, 0, &resp->fh); | |
| 500 | 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 | 538 | nfsd_proc_rmdir(struct svc_rqst *rqstp) |
| 509 | 539 | { |
| 510 | 540 | struct nfsd_diropargs *argp = rqstp->rq_argp; |
| 511 | − __be32 nfserr; | |
| 541 | + struct nfsd_stat *resp = rqstp->rq_resp; | |
| 512 | 542 | |
| 513 | 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 | 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 | 557 | struct nfsd_readdirargs *argp = rqstp->rq_argp; |
| 527 | 558 | struct nfsd_readdirres *resp = rqstp->rq_resp; |
| 528 | 559 | int count; |
| 529 | − __be32 nfserr; | |
| 530 | 560 | loff_t offset; |
| 531 | 561 | |
| 532 | 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 | 577 | resp->common.err = nfs_ok; |
| 548 | 578 | /* Read directory and encode entries on the fly */ |
| 549 | 579 | offset = argp->cookie; |
| 550 | − nfserr = nfsd_readdir(rqstp, &argp->fh, &offset, | |
| 551 | − &resp->common, nfssvc_encode_entry); | |
| 580 | + resp->status = nfsd_readdir(rqstp, &argp->fh, &offset, | |
| 581 | + &resp->common, nfssvc_encode_entry); | |
| 552 | 582 | |
| 553 | 583 | resp->count = resp->buffer - argp->buffer; |
| 554 | 584 | if (resp->offset) |
| 555 | 585 | *resp->offset = htonl(offset); |
| 556 | 586 | |
| 557 | 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 | 597 | struct nfsd_fhandle *argp = rqstp->rq_argp; |
| 568 | 598 | struct nfsd_statfsres *resp = rqstp->rq_resp; |
| 569 | − __be32 nfserr; | |
| 570 | 599 | |
| 571 | 600 | dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh)); |
| 572 | 601 | |
| 573 | − nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, | |
| 574 | − NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 602 | + resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, | |
| 603 | + NFSD_MAY_BYPASS_GSS_ON_ROOT); | |
| 575 | 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 | 623 | .pc_argsize = sizeof(struct nfsd_void), |
| 595 | 624 | .pc_ressize = sizeof(struct nfsd_void), |
| 596 | 625 | .pc_cachetype = RC_NOCACHE, |
| 597 | − .pc_xdrressize = ST, | |
| 626 | + .pc_xdrressize = 0, | |
| 598 | 627 | }, |
| 599 | 628 | [NFSPROC_GETATTR] = { |
| 600 | 629 | .pc_func = nfsd_proc_getattr, |
| 601 | 630 | .pc_decode = nfssvc_decode_fhandle, |
| 602 | 631 | .pc_encode = nfssvc_encode_attrstat, |
| 603 | − .pc_release = nfssvc_release_fhandle, | |
| 632 | + .pc_release = nfssvc_release_attrstat, | |
| 604 | 633 | .pc_argsize = sizeof(struct nfsd_fhandle), |
| 605 | 634 | .pc_ressize = sizeof(struct nfsd_attrstat), |
| 606 | 635 | .pc_cachetype = RC_NOCACHE, |
| @@ -610,25 +639,26 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 3 unmodified lines | ||
| 610 | 639 | .pc_func = nfsd_proc_setattr, |
| 611 | 640 | .pc_decode = nfssvc_decode_sattrargs, |
| 612 | 641 | .pc_encode = nfssvc_encode_attrstat, |
| 613 | − .pc_release = nfssvc_release_fhandle, | |
| 642 | + .pc_release = nfssvc_release_attrstat, | |
| 614 | 643 | .pc_argsize = sizeof(struct nfsd_sattrargs), |
| 615 | 644 | .pc_ressize = sizeof(struct nfsd_attrstat), |
| 616 | 645 | .pc_cachetype = RC_REPLBUFF, |
| 617 | 646 | .pc_xdrressize = ST+AT, |
| 618 | 647 | }, |
| 619 | 648 | [NFSPROC_ROOT] = { |
| 649 | + .pc_func = nfsd_proc_root, | |
| 620 | 650 | .pc_decode = nfssvc_decode_void, |
| 621 | 651 | .pc_encode = nfssvc_encode_void, |
| 622 | 652 | .pc_argsize = sizeof(struct nfsd_void), |
| 623 | 653 | .pc_ressize = sizeof(struct nfsd_void), |
| 624 | 654 | .pc_cachetype = RC_NOCACHE, |
| 625 | − .pc_xdrressize = ST, | |
| 655 | + .pc_xdrressize = 0, | |
| 626 | 656 | }, |
| 627 | 657 | [NFSPROC_LOOKUP] = { |
| 628 | 658 | .pc_func = nfsd_proc_lookup, |
| 629 | 659 | .pc_decode = nfssvc_decode_diropargs, |
| 630 | 660 | .pc_encode = nfssvc_encode_diropres, |
| 631 | − .pc_release = nfssvc_release_fhandle, | |
| 661 | + .pc_release = nfssvc_release_diropres, | |
| 632 | 662 | .pc_argsize = sizeof(struct nfsd_diropargs), |
| 633 | 663 | .pc_ressize = sizeof(struct nfsd_diropres), |
| 634 | 664 | .pc_cachetype = RC_NOCACHE, |
| @@ -647,25 +677,26 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 12 unmodified lines | ||
| 647 | 677 | .pc_func = nfsd_proc_read, |
| 648 | 678 | .pc_decode = nfssvc_decode_readargs, |
| 649 | 679 | .pc_encode = nfssvc_encode_readres, |
| 650 | − .pc_release = nfssvc_release_fhandle, | |
| 680 | + .pc_release = nfssvc_release_readres, | |
| 651 | 681 | .pc_argsize = sizeof(struct nfsd_readargs), |
| 652 | 682 | .pc_ressize = sizeof(struct nfsd_readres), |
| 653 | 683 | .pc_cachetype = RC_NOCACHE, |
| 654 | 684 | .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4, |
| 655 | 685 | }, |
| 656 | 686 | [NFSPROC_WRITECACHE] = { |
| 687 | + .pc_func = nfsd_proc_writecache, | |
| 657 | 688 | .pc_decode = nfssvc_decode_void, |
| 658 | 689 | .pc_encode = nfssvc_encode_void, |
| 659 | 690 | .pc_argsize = sizeof(struct nfsd_void), |
| 660 | 691 | .pc_ressize = sizeof(struct nfsd_void), |
| 661 | 692 | .pc_cachetype = RC_NOCACHE, |
| 662 | − .pc_xdrressize = ST, | |
| 693 | + .pc_xdrressize = 0, | |
| 663 | 694 | }, |
| 664 | 695 | [NFSPROC_WRITE] = { |
| 665 | 696 | .pc_func = nfsd_proc_write, |
| 666 | 697 | .pc_decode = nfssvc_decode_writeargs, |
| 667 | 698 | .pc_encode = nfssvc_encode_attrstat, |
| 668 | − .pc_release = nfssvc_release_fhandle, | |
| 699 | + .pc_release = nfssvc_release_attrstat, | |
| 669 | 700 | .pc_argsize = sizeof(struct nfsd_writeargs), |
| 670 | 701 | .pc_ressize = sizeof(struct nfsd_attrstat), |
| 671 | 702 | .pc_cachetype = RC_REPLBUFF, |
| @@ -675,7 +706,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 3 unmodified lines | ||
| 675 | 706 | .pc_func = nfsd_proc_create, |
| 676 | 707 | .pc_decode = nfssvc_decode_createargs, |
| 677 | 708 | .pc_encode = nfssvc_encode_diropres, |
| 678 | − .pc_release = nfssvc_release_fhandle, | |
| 709 | + .pc_release = nfssvc_release_diropres, | |
| 679 | 710 | .pc_argsize = sizeof(struct nfsd_createargs), |
| 680 | 711 | .pc_ressize = sizeof(struct nfsd_diropres), |
| 681 | 712 | .pc_cachetype = RC_REPLBUFF, |
| @@ -684,36 +715,36 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 2 unmodified lines | ||
| 684 | 715 | [NFSPROC_REMOVE] = { |
| 685 | 716 | .pc_func = nfsd_proc_remove, |
| 686 | 717 | .pc_decode = nfssvc_decode_diropargs, |
| 687 | − .pc_encode = nfssvc_encode_void, | |
| 718 | + .pc_encode = nfssvc_encode_stat, | |
| 688 | 719 | .pc_argsize = sizeof(struct nfsd_diropargs), |
| 689 | − .pc_ressize = sizeof(struct nfsd_void), | |
| 720 | + .pc_ressize = sizeof(struct nfsd_stat), | |
| 690 | 721 | .pc_cachetype = RC_REPLSTAT, |
| 691 | 722 | .pc_xdrressize = ST, |
| 692 | 723 | }, |
| 693 | 724 | [NFSPROC_RENAME] = { |
| 694 | 725 | .pc_func = nfsd_proc_rename, |
| 695 | 726 | .pc_decode = nfssvc_decode_renameargs, |
| 696 | − .pc_encode = nfssvc_encode_void, | |
| 727 | + .pc_encode = nfssvc_encode_stat, | |
| 697 | 728 | .pc_argsize = sizeof(struct nfsd_renameargs), |
| 698 | − .pc_ressize = sizeof(struct nfsd_void), | |
| 729 | + .pc_ressize = sizeof(struct nfsd_stat), | |
| 699 | 730 | .pc_cachetype = RC_REPLSTAT, |
| 700 | 731 | .pc_xdrressize = ST, |
| 701 | 732 | }, |
| 702 | 733 | [NFSPROC_LINK] = { |
| 703 | 734 | .pc_func = nfsd_proc_link, |
| 704 | 735 | .pc_decode = nfssvc_decode_linkargs, |
| 705 | − .pc_encode = nfssvc_encode_void, | |
| 736 | + .pc_encode = nfssvc_encode_stat, | |
| 706 | 737 | .pc_argsize = sizeof(struct nfsd_linkargs), |
| 707 | − .pc_ressize = sizeof(struct nfsd_void), | |
| 738 | + .pc_ressize = sizeof(struct nfsd_stat), | |
| 708 | 739 | .pc_cachetype = RC_REPLSTAT, |
| 709 | 740 | .pc_xdrressize = ST, |
| 710 | 741 | }, |
| 711 | 742 | [NFSPROC_SYMLINK] = { |
| 712 | 743 | .pc_func = nfsd_proc_symlink, |
| 713 | 744 | .pc_decode = nfssvc_decode_symlinkargs, |
| 714 | − .pc_encode = nfssvc_encode_void, | |
| 745 | + .pc_encode = nfssvc_encode_stat, | |
| 715 | 746 | .pc_argsize = sizeof(struct nfsd_symlinkargs), |
| 716 | − .pc_ressize = sizeof(struct nfsd_void), | |
| 747 | + .pc_ressize = sizeof(struct nfsd_stat), | |
| 717 | 748 | .pc_cachetype = RC_REPLSTAT, |
| 718 | 749 | .pc_xdrressize = ST, |
| 719 | 750 | }, |
| @@ -721,7 +752,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 1 unmodified line | ||
| 721 | 752 | .pc_func = nfsd_proc_mkdir, |
| 722 | 753 | .pc_decode = nfssvc_decode_createargs, |
| 723 | 754 | .pc_encode = nfssvc_encode_diropres, |
| 724 | − .pc_release = nfssvc_release_fhandle, | |
| 755 | + .pc_release = nfssvc_release_diropres, | |
| 725 | 756 | .pc_argsize = sizeof(struct nfsd_createargs), |
| 726 | 757 | .pc_ressize = sizeof(struct nfsd_diropres), |
| 727 | 758 | .pc_cachetype = RC_REPLBUFF, |
| @@ -730,9 +761,9 @@ static const struct svc_procedure nfsd_procedures2[18] = { · 2 unmodified lines | ||
| 730 | 761 | [NFSPROC_RMDIR] = { |
| 731 | 762 | .pc_func = nfsd_proc_rmdir, |
| 732 | 763 | .pc_decode = nfssvc_decode_diropargs, |
| 733 | − .pc_encode = nfssvc_encode_void, | |
| 764 | + .pc_encode = nfssvc_encode_stat, | |
| 734 | 765 | .pc_argsize = sizeof(struct nfsd_diropargs), |
| 735 | − .pc_ressize = sizeof(struct nfsd_void), | |
| 766 | + .pc_ressize = sizeof(struct nfsd_stat), | |
| 736 | 767 | .pc_cachetype = RC_REPLSTAT, |
| 737 | 768 | .pc_xdrressize = ST, |
| 738 | 769 | }, |
| @@ -960,15 +960,6 @@ out: · 959 unmodified lines | ||
| 960 | 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 | 964 | * A write procedure can have a large argument, and a read procedure can |
| 974 | 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 | 991 | return rqstp->rq_arg.len > PAGE_SIZE; |
| 1001 | 992 | } |
| 1002 | 993 | |
| 1003 | −int | |
| 1004 | −nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |
| 994 | +/** | |
| 995 | + * nfsd_dispatch - Process an NFS or NFSACL Request | |
| 996 | + * @rqstp: incoming request | |
| 997 | + * @statp: pointer to location of accept_stat field in RPC Reply buffer | |
| 998 | + * | |
| 999 | + * This RPC dispatcher integrates the NFS server's duplicate reply cache. | |
| 1000 | + * | |
| 1001 | + * Return values: | |
| 1002 | + * %0: Processing complete; do not send a Reply | |
| 1003 | + * %1: Processing complete; send Reply in rqstp->rq_res | |
| 1004 | + */ | |
| 1005 | +int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |
| 1005 | 1006 | { |
| 1006 | − const struct svc_procedure *proc; | |
| 1007 | − __be32 nfserr; | |
| 1008 | − __be32 *nfserrp; | |
| 1007 | + const struct svc_procedure *proc = rqstp->rq_procinfo; | |
| 1008 | + struct kvec *argv = &rqstp->rq_arg.head[0]; | |
| 1009 | + struct kvec *resv = &rqstp->rq_res.head[0]; | |
| 1010 | + __be32 *p; | |
| 1009 | 1011 | |
| 1010 | 1012 | dprintk("nfsd_dispatch: vers %d proc %d\n", |
| 1011 | 1013 | rqstp->rq_vers, rqstp->rq_proc); |
| 1012 | − proc = rqstp->rq_procinfo; | |
| 1013 | 1014 | |
| 1014 | − if (nfs_request_too_big(rqstp, proc)) { | |
| 1015 | − dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers); | |
| 1016 | − *statp = rpc_garbage_args; | |
| 1017 | − return 1; | |
| 1018 | − } | |
| 1019 | − rqstp->rq_lease_breaker = NULL; | |
| 1015 | + if (nfs_request_too_big(rqstp, proc)) | |
| 1016 | + goto out_too_large; | |
| 1017 | + | |
| 1020 | 1018 | /* |
| 1021 | 1019 | * Give the xdr decoder a chance to change this if it wants |
| 1022 | 1020 | * (necessary in the NFSv4.0 compound case) |
| 1023 | 1021 | */ |
| 1024 | 1022 | rqstp->rq_cachetype = proc->pc_cachetype; |
| 1025 | − /* Decode arguments */ | |
| 1026 | − if (proc->pc_decode && | |
| 1027 | − !proc->pc_decode(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base)) { | |
| 1028 | − dprintk("nfsd: failed to decode arguments!\n"); | |
| 1029 | − *statp = rpc_garbage_args; | |
| 1030 | − return 1; | |
| 1031 | − } | |
| 1023 | + if (!proc->pc_decode(rqstp, argv->iov_base)) | |
| 1024 | + goto out_decode_err; | |
| 1032 | 1025 | |
| 1033 | − /* Check whether we have this call in the cache. */ | |
| 1034 | 1026 | switch (nfsd_cache_lookup(rqstp)) { |
| 1035 | − case RC_DROPIT: | |
| 1036 | − return 0; | |
| 1027 | + case RC_DOIT: | |
| 1028 | + break; | |
| 1037 | 1029 | case RC_REPLY: |
| 1038 | − return 1; | |
| 1039 | − case RC_DOIT:; | |
| 1040 | − /* do it */ | |
| 1030 | + goto out_cached_reply; | |
| 1031 | + case RC_DROPIT: | |
| 1032 | + goto out_dropit; | |
| 1041 | 1033 | } |
| 1042 | 1034 | |
| 1043 | − /* need to grab the location to store the status, as | |
| 1044 | − * nfsv4 does some encoding while processing | |
| 1035 | + /* | |
| 1036 | + * Need to grab the location to store the status, as | |
| 1037 | + * NFSv4 does some encoding while processing | |
| 1045 | 1038 | */ |
| 1046 | − nfserrp = rqstp->rq_res.head[0].iov_base | |
| 1047 | − + rqstp->rq_res.head[0].iov_len; | |
| 1048 | − rqstp->rq_res.head[0].iov_len += sizeof(__be32); | |
| 1049 | − | |
| 1050 | − /* Now call the procedure handler, and encode NFS status. */ | |
| 1051 | − nfserr = proc->pc_func(rqstp); | |
| 1052 | − nfserr = map_new_errors(rqstp->rq_vers, nfserr); | |
| 1053 | − if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) { | |
| 1054 | − dprintk("nfsd: Dropping request; may be revisited later\n"); | |
| 1055 | − nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | |
| 1056 | − return 0; | |
| 1057 | − } | |
| 1039 | + p = resv->iov_base + resv->iov_len; | |
| 1040 | + resv->iov_len += sizeof(__be32); | |
| 1058 | 1041 | |
| 1059 | − if (rqstp->rq_proc != 0) | |
| 1060 | − *nfserrp++ = nfserr; | |
| 1042 | + *statp = proc->pc_func(rqstp); | |
| 1043 | + if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags)) | |
| 1044 | + goto out_update_drop; | |
| 1061 | 1045 | |
| 1062 | − /* Encode result. | |
| 1063 | − * For NFSv2, additional info is never returned in case of an error. | |
| 1064 | − */ | |
| 1065 | − if (!(nfserr && rqstp->rq_vers == 2)) { | |
| 1066 | − if (proc->pc_encode && !proc->pc_encode(rqstp, nfserrp)) { | |
| 1067 | − /* Failed to encode result. Release cache entry */ | |
| 1068 | − dprintk("nfsd: failed to encode result!\n"); | |
| 1069 | − nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | |
| 1070 | − *statp = rpc_system_err; | |
| 1071 | − return 1; | |
| 1072 | − } | |
| 1073 | − } | |
| 1046 | + if (!proc->pc_encode(rqstp, p)) | |
| 1047 | + goto out_encode_err; | |
| 1074 | 1048 | |
| 1075 | − /* Store reply in cache. */ | |
| 1076 | 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 | 1073 | return 1; |
| 1078 | 1074 | } |
| 1079 | 1075 | |
| @@ -429,12 +429,25 @@ nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p) · 428 unmodified lines | ||
| 429 | 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 | 441 | int |
| 433 | 442 | nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) |
| 434 | 443 | { |
| 435 | 444 | struct nfsd_attrstat *resp = rqstp->rq_resp; |
| 436 | 445 | |
| 446 | + *p++ = resp->status; | |
| 447 | + if (resp->status != nfs_ok) | |
| 448 | + goto out; | |
| 437 | 449 | p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); |
| 450 | +out: | |
| 438 | 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 | 457 | struct nfsd_diropres *resp = rqstp->rq_resp; |
| 445 | 458 | |
| 459 | + *p++ = resp->status; | |
| 460 | + if (resp->status != nfs_ok) | |
| 461 | + goto out; | |
| 446 | 462 | p = encode_fh(p, &resp->fh); |
| 447 | 463 | p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); |
| 464 | +out: | |
| 448 | 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 | 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 | 477 | *p++ = htonl(resp->len); |
| 457 | 478 | xdr_ressize_check(rqstp, p); |
| 458 | 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 | 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 | 498 | p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); |
| 474 | 499 | *p++ = htonl(resp->count); |
| 475 | 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 | 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 | 522 | xdr_ressize_check(rqstp, p); |
| 494 | 523 | p = resp->buffer; |
| 495 | 524 | *p++ = 0; /* no more entries */ |
| @@ -505,6 +534,10 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p) · 9 unmodified lines | ||
| 505 | 534 | struct nfsd_statfsres *resp = rqstp->rq_resp; |
| 506 | 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 | 541 | *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */ |
| 509 | 542 | *p++ = htonl(stat->f_bsize); |
| 510 | 543 | *p++ = htonl(stat->f_blocks); |
| @@ -561,10 +594,23 @@ nfssvc_encode_entry(void *ccdv, const char *name, · 50 unmodified lines | ||
| 561 | 594 | /* |
| 562 | 595 | * XDR release functions |
| 563 | 596 | */ |
| 564 | −void | |
| 565 | −nfssvc_release_fhandle(struct svc_rqst *rqstp) | |
| 597 | +void nfssvc_release_attrstat(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 | 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 | 693 | extern int nfsd4_client_record_check(struct nfs4_client *clp); |
| 694 | 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 | 696 | #endif /* NFSD4_STATE_H */ |
| @@ -289,8 +289,8 @@ DEFINE_STATEID_EVENT(layout_recall_done); · 288 unmodified lines | ||
| 289 | 289 | DEFINE_STATEID_EVENT(layout_recall_fail); |
| 290 | 290 | DEFINE_STATEID_EVENT(layout_recall_release); |
| 291 | 291 | |
| 292 | −DEFINE_STATEID_EVENT(deleg_open); | |
| 293 | −DEFINE_STATEID_EVENT(deleg_none); | |
| 292 | +DEFINE_STATEID_EVENT(open); | |
| 293 | +DEFINE_STATEID_EVENT(deleg_read); | |
| 294 | 294 | DEFINE_STATEID_EVENT(deleg_break); |
| 295 | 295 | DEFINE_STATEID_EVENT(deleg_recall); |
| 296 | 296 | |
| @@ -2259,7 +2259,8 @@ out: · 2258 unmodified lines | ||
| 2259 | 2259 | __be32 |
| 2260 | 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 | 2265 | err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE); |
| 2265 | 2266 | if (err) |
| @@ -2283,7 +2284,8 @@ __be32 · 17 unmodified lines | ||
| 2283 | 2284 | nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name, |
| 2284 | 2285 | void *buf, u32 len, u32 flags) |
| 2285 | 2286 | { |
| 2286 | − int err, ret; | |
| 2287 | + __be32 err; | |
| 2288 | + int ret; | |
| 2287 | 2289 | |
| 2288 | 2290 | err = fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE); |
| 2289 | 2291 | if (err) |
| @@ -82,27 +82,37 @@ struct nfsd_readdirargs { · 81 unmodified lines | ||
| 82 | 82 | __be32 * buffer; |
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | +struct nfsd_stat { | |
| 86 | + __be32 status; | |
| 87 | +}; | |
| 88 | + | |
| 85 | 89 | struct nfsd_attrstat { |
| 90 | + __be32 status; | |
| 86 | 91 | struct svc_fh fh; |
| 87 | 92 | struct kstat stat; |
| 88 | 93 | }; |
| 89 | 94 | |
| 90 | 95 | struct nfsd_diropres { |
| 96 | + __be32 status; | |
| 91 | 97 | struct svc_fh fh; |
| 92 | 98 | struct kstat stat; |
| 93 | 99 | }; |
| 94 | 100 | |
| 95 | 101 | struct nfsd_readlinkres { |
| 102 | + __be32 status; | |
| 96 | 103 | int len; |
| 97 | 104 | }; |
| 98 | 105 | |
| 99 | 106 | struct nfsd_readres { |
| 107 | + __be32 status; | |
| 100 | 108 | struct svc_fh fh; |
| 101 | 109 | unsigned long count; |
| 102 | 110 | struct kstat stat; |
| 103 | 111 | }; |
| 104 | 112 | |
| 105 | 113 | struct nfsd_readdirres { |
| 114 | + __be32 status; | |
| 115 | + | |
| 106 | 116 | int count; |
| 107 | 117 | |
| 108 | 118 | struct readdir_cd common; |
| @@ -112,6 +122,7 @@ struct nfsd_readdirres { · 3 unmodified lines | ||
| 112 | 122 | }; |
| 113 | 123 | |
| 114 | 124 | struct nfsd_statfsres { |
| 125 | + __be32 status; | |
| 115 | 126 | struct kstatfs stats; |
| 116 | 127 | }; |
| 117 | 128 | |
| @@ -146,6 +157,7 @@ int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *); · 28 unmodified lines | ||
| 146 | 157 | int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *); |
| 147 | 158 | int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *); |
| 148 | 159 | int nfssvc_encode_void(struct svc_rqst *, __be32 *); |
| 160 | +int nfssvc_encode_stat(struct svc_rqst *, __be32 *); | |
| 149 | 161 | int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *); |
| 150 | 162 | int nfssvc_encode_diropres(struct svc_rqst *, __be32 *); |
| 151 | 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 | 168 | int nfssvc_encode_entry(void *, const char *name, |
| 157 | 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 | 175 | /* Helper functions for NFSv2 ACL code */ |
| 162 | 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 | 274 | #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) |
| 275 | 275 | |
| 276 | +int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *); | |
| 276 | 277 | int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *); |
| 277 | 278 | int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *); |
| 278 | 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 | 783 | bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp); |
| 784 | +int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *); | |
| 784 | 785 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *); |
| 785 | 786 | int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *); |
| 786 | 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 | 234 | extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, |
| 235 | 235 | __be32 *p, struct rpc_rqst *rqst); |
| 236 | 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 | 239 | extern void xdr_commit_encode(struct xdr_stream *xdr); |
| 238 | 240 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); |
| 239 | 241 | extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); |
| @@ -9,11 +9,13 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #define NFS_ACL_PROGRAM 100227 |
| 11 | 11 | |
| 12 | +#define ACLPROC2_NULL 0 | |
| 12 | 13 | #define ACLPROC2_GETACL 1 |
| 13 | 14 | #define ACLPROC2_SETACL 2 |
| 14 | 15 | #define ACLPROC2_GETATTR 3 |
| 15 | 16 | #define ACLPROC2_ACCESS 4 |
| 16 | 17 | |
| 18 | +#define ACLPROC3_NULL 0 | |
| 17 | 19 | #define ACLPROC3_GETACL 1 |
| 18 | 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 | 1147 | struct gssp_in_token *in_token) |
| 1148 | 1148 | { |
| 1149 | 1149 | struct kvec *argv = &rqstp->rq_arg.head[0]; |
| 1150 | − unsigned int page_base, length; | |
| 1151 | − int pages, i, res; | |
| 1152 | − size_t inlen; | |
| 1150 | + unsigned int length, pgto_offs, pgfrom_offs; | |
| 1151 | + int pages, i, res, pgto, pgfrom; | |
| 1152 | + size_t inlen, to_offs, from_offs; | |
| 1153 | 1153 | |
| 1154 | 1154 | res = gss_read_common_verf(gc, argv, authp, in_handle); |
| 1155 | 1155 | if (res) |
| @@ -1177,17 +1177,24 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp, · 21 unmodified lines | ||
| 1177 | 1177 | memcpy(page_address(in_token->pages[0]), argv->iov_base, length); |
| 1178 | 1178 | inlen -= length; |
| 1179 | 1179 | |
| 1180 | − i = 1; | |
| 1181 | − page_base = rqstp->rq_arg.page_base; | |
| 1180 | + to_offs = length; | |
| 1181 | + from_offs = rqstp->rq_arg.page_base; | |
| 1182 | 1182 | while (inlen) { |
| 1183 | − length = min_t(unsigned int, inlen, PAGE_SIZE); | |
| 1184 | − memcpy(page_address(in_token->pages[i]), | |
| 1185 | − page_address(rqstp->rq_arg.pages[i]) + page_base, | |
| 1183 | + pgto = to_offs >> PAGE_SHIFT; | |
| 1184 | + pgfrom = from_offs >> PAGE_SHIFT; | |
| 1185 | + pgto_offs = to_offs & ~PAGE_MASK; | |
| 1186 | + pgfrom_offs = from_offs & ~PAGE_MASK; | |
| 1187 | + | |
| 1188 | + length = min_t(unsigned int, inlen, | |
| 1189 | + min_t(unsigned int, PAGE_SIZE - pgto_offs, | |
| 1190 | + PAGE_SIZE - pgfrom_offs)); | |
| 1191 | + memcpy(page_address(in_token->pages[pgto]) + pgto_offs, | |
| 1192 | + page_address(rqstp->rq_arg.pages[pgfrom]) + pgfrom_offs, | |
| 1186 | 1193 | length); |
| 1187 | 1194 | |
| 1195 | + to_offs += length; | |
| 1196 | + from_offs += length; | |
| 1188 | 1197 | inlen -= length; |
| 1189 | − page_base = 0; | |
| 1190 | − i++; | |
| 1191 | 1198 | } |
| 1192 | 1199 | return 0; |
| 1193 | 1200 | } |
| @@ -111,7 +111,7 @@ out_free: · 110 unmodified lines | ||
| 111 | 111 | * by the backchannel. This function can be called multiple times |
| 112 | 112 | * when creating new sessions that use the same rpc_xprt. The |
| 113 | 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 | 115 | * incoming callback request. It's up to the higher levels in the |
| 116 | 116 | * stack to enforce that the maximum number of session slots is not |
| 117 | 117 | * being exceeded. |
| @@ -498,16 +498,17 @@ static int cache_clean(void) · 497 unmodified lines | ||
| 498 | 498 | */ |
| 499 | 499 | static void do_cache_clean(struct work_struct *work) |
| 500 | 500 | { |
| 501 | − int delay = 5; | |
| 502 | − if (cache_clean() == -1) | |
| 503 | − delay = round_jiffies_relative(30*HZ); | |
| 501 | + int delay; | |
| 504 | 502 | |
| 505 | 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) | |
| 509 | − queue_delayed_work(system_power_efficient_wq, | |
| 510 | − &cache_cleaner, delay); | |
| 511 | + queue_delayed_work(system_power_efficient_wq, &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 | 909 | static ssize_t cache_slow_downcall(const char __user *buf, |
| 909 | 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 | 913 | ssize_t ret = -EINVAL; |
| 913 | 914 | |
| 914 | 915 | if (count >= sizeof(write_buf)) |
| @@ -1436,10 +1437,10 @@ static int c_show(struct seq_file *m, void *p) · 521 unmodified lines | ||
| 1436 | 1437 | cache_get(cp); |
| 1437 | 1438 | if (cache_check(cd, cp, NULL)) |
| 1438 | 1439 | /* cache_check does a cache_put on failure */ |
| 1439 | − seq_printf(m, "# "); | |
| 1440 | + seq_puts(m, "# "); | |
| 1440 | 1441 | else { |
| 1441 | 1442 | if (cache_is_expired(cd, cp)) |
| 1442 | − seq_printf(m, "# "); | |
| 1443 | + seq_puts(m, "# "); | |
| 1443 | 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 | 70 | return 0; |
| 71 | 71 | } |
| 72 | 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 | 82 | static int |
| @@ -792,6 +792,51 @@ __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) · 791 unmodified lines | ||
| 792 | 792 | } |
| 793 | 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 | 841 | * xdr_truncate_encode - truncate an encode buffer |
| 797 | 842 | * @xdr: pointer to xdr_stream |
| @@ -802,7 +847,7 @@ EXPORT_SYMBOL_GPL(xdr_reserve_space); · 4 unmodified lines | ||
| 802 | 847 | * head, tail, and page lengths are adjusted to correspond. |
| 803 | 848 | * |
| 804 | 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 | 851 | * except in the case of the head buffer when we assume the head |
| 807 | 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 | 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 | 141 | * for all segments of one chunk. |
| 142 | 142 | * |
| 143 | 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 | 638 | while (remaining) { |
| 639 | 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 | 642 | remaining -= len; |
| 643 | 643 | dst += len; |
| 644 | 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 | |