diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:19:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:19:15 -0400 |
commit | bf97293eb878df3792d9de7213bd7b82135aea77 (patch) | |
tree | 16cb367bd78095b9eb8a54c800fcddfcccb618c7 /fs/nfs/nfs4proc.c | |
parent | 16d70e15295953b19ecf59e943723a181782b856 (diff) | |
parent | b1b3e136948a2bf4915326acb0d825d7d180753f (diff) |
Merge tag 'nfs-for-3.12-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Highlights include:
- Fix NFSv4 recovery so that it doesn't recover lost locks in cases
such as lease loss due to a network partition, where doing so may
result in data corruption. Add a kernel parameter to control
choice of legacy behaviour or not.
- Performance improvements when 2 processes are writing to the same
file.
- Flush data to disk when an RPCSEC_GSS session timeout is imminent.
- Implement NFSv4.1 SP4_MACH_CRED state protection to prevent other
NFS clients from being able to manipulate our lease and file
locking state.
- Allow sharing of RPCSEC_GSS caches between different rpc clients.
- Fix the broken NFSv4 security auto-negotiation between client and
server.
- Fix rmdir() to wait for outstanding sillyrename unlinks to complete
- Add a tracepoint framework for debugging NFSv4 state recovery
issues.
- Add tracing to the generic NFS layer.
- Add tracing for the SUNRPC socket connection state.
- Clean up the rpc_pipefs mount/umount event management.
- Merge more patches from Chuck in preparation for NFSv4 migration
support"
* tag 'nfs-for-3.12-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (107 commits)
NFSv4: use mach cred for SECINFO_NO_NAME w/ integrity
NFS: nfs_compare_super shouldn't check the auth flavour unless 'sec=' was set
NFSv4: Allow security autonegotiation for submounts
NFSv4: Disallow security negotiation for lookups when 'sec=' is specified
NFSv4: Fix security auto-negotiation
NFS: Clean up nfs_parse_security_flavors()
NFS: Clean up the auth flavour array mess
NFSv4.1 Use MDS auth flavor for data server connection
NFS: Don't check lock owner compatability unless file is locked (part 2)
NFS: Don't check lock owner compatibility in writes unless file is locked
nfs4: Map NFS4ERR_WRONG_CRED to EPERM
nfs4.1: Add SP4_MACH_CRED write and commit support
nfs4.1: Add SP4_MACH_CRED stateid support
nfs4.1: Add SP4_MACH_CRED secinfo support
nfs4.1: Add SP4_MACH_CRED cleanup support
nfs4.1: Add state protection handler
nfs4.1: Minimal SP4_MACH_CRED implementation
SUNRPC: Replace pointer values with task->tk_pid and rpc_clnt->cl_clid
SUNRPC: Add an identifier for struct rpc_clnt
SUNRPC: Ensure rpc_task->tk_pid is available for tracepoints
...
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 793 |
1 files changed, 618 insertions, 175 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 108a774095f7..39b6cf2d1683 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -66,6 +66,8 @@ | |||
66 | #include "nfs4session.h" | 66 | #include "nfs4session.h" |
67 | #include "fscache.h" | 67 | #include "fscache.h" |
68 | 68 | ||
69 | #include "nfs4trace.h" | ||
70 | |||
69 | #define NFSDBG_FACILITY NFSDBG_PROC | 71 | #define NFSDBG_FACILITY NFSDBG_PROC |
70 | 72 | ||
71 | #define NFS4_POLL_RETRY_MIN (HZ/10) | 73 | #define NFS4_POLL_RETRY_MIN (HZ/10) |
@@ -150,6 +152,7 @@ static int nfs4_map_errors(int err) | |||
150 | case -NFS4ERR_RECALLCONFLICT: | 152 | case -NFS4ERR_RECALLCONFLICT: |
151 | return -EREMOTEIO; | 153 | return -EREMOTEIO; |
152 | case -NFS4ERR_WRONGSEC: | 154 | case -NFS4ERR_WRONGSEC: |
155 | case -NFS4ERR_WRONG_CRED: | ||
153 | return -EPERM; | 156 | return -EPERM; |
154 | case -NFS4ERR_BADOWNER: | 157 | case -NFS4ERR_BADOWNER: |
155 | case -NFS4ERR_BADNAME: | 158 | case -NFS4ERR_BADNAME: |
@@ -433,6 +436,20 @@ wait_on_recovery: | |||
433 | return ret; | 436 | return ret; |
434 | } | 437 | } |
435 | 438 | ||
439 | /* | ||
440 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected | ||
441 | * or 'false' otherwise. | ||
442 | */ | ||
443 | static bool _nfs4_is_integrity_protected(struct nfs_client *clp) | ||
444 | { | ||
445 | rpc_authflavor_t flavor = clp->cl_rpcclient->cl_auth->au_flavor; | ||
446 | |||
447 | if (flavor == RPC_AUTH_GSS_KRB5I || | ||
448 | flavor == RPC_AUTH_GSS_KRB5P) | ||
449 | return true; | ||
450 | |||
451 | return false; | ||
452 | } | ||
436 | 453 | ||
437 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) | 454 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) |
438 | { | 455 | { |
@@ -447,6 +464,88 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp | |||
447 | do_renew_lease(server->nfs_client, timestamp); | 464 | do_renew_lease(server->nfs_client, timestamp); |
448 | } | 465 | } |
449 | 466 | ||
467 | struct nfs4_call_sync_data { | ||
468 | const struct nfs_server *seq_server; | ||
469 | struct nfs4_sequence_args *seq_args; | ||
470 | struct nfs4_sequence_res *seq_res; | ||
471 | }; | ||
472 | |||
473 | static void nfs4_init_sequence(struct nfs4_sequence_args *args, | ||
474 | struct nfs4_sequence_res *res, int cache_reply) | ||
475 | { | ||
476 | args->sa_slot = NULL; | ||
477 | args->sa_cache_this = cache_reply; | ||
478 | args->sa_privileged = 0; | ||
479 | |||
480 | res->sr_slot = NULL; | ||
481 | } | ||
482 | |||
483 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
484 | { | ||
485 | args->sa_privileged = 1; | ||
486 | } | ||
487 | |||
488 | static int nfs40_setup_sequence(const struct nfs_server *server, | ||
489 | struct nfs4_sequence_args *args, | ||
490 | struct nfs4_sequence_res *res, | ||
491 | struct rpc_task *task) | ||
492 | { | ||
493 | struct nfs4_slot_table *tbl = server->nfs_client->cl_slot_tbl; | ||
494 | struct nfs4_slot *slot; | ||
495 | |||
496 | /* slot already allocated? */ | ||
497 | if (res->sr_slot != NULL) | ||
498 | goto out_start; | ||
499 | |||
500 | spin_lock(&tbl->slot_tbl_lock); | ||
501 | if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) | ||
502 | goto out_sleep; | ||
503 | |||
504 | slot = nfs4_alloc_slot(tbl); | ||
505 | if (IS_ERR(slot)) { | ||
506 | if (slot == ERR_PTR(-ENOMEM)) | ||
507 | task->tk_timeout = HZ >> 2; | ||
508 | goto out_sleep; | ||
509 | } | ||
510 | spin_unlock(&tbl->slot_tbl_lock); | ||
511 | |||
512 | args->sa_slot = slot; | ||
513 | res->sr_slot = slot; | ||
514 | |||
515 | out_start: | ||
516 | rpc_call_start(task); | ||
517 | return 0; | ||
518 | |||
519 | out_sleep: | ||
520 | if (args->sa_privileged) | ||
521 | rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task, | ||
522 | NULL, RPC_PRIORITY_PRIVILEGED); | ||
523 | else | ||
524 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
525 | spin_unlock(&tbl->slot_tbl_lock); | ||
526 | return -EAGAIN; | ||
527 | } | ||
528 | |||
529 | static int nfs40_sequence_done(struct rpc_task *task, | ||
530 | struct nfs4_sequence_res *res) | ||
531 | { | ||
532 | struct nfs4_slot *slot = res->sr_slot; | ||
533 | struct nfs4_slot_table *tbl; | ||
534 | |||
535 | if (!RPC_WAS_SENT(task)) | ||
536 | goto out; | ||
537 | |||
538 | tbl = slot->table; | ||
539 | spin_lock(&tbl->slot_tbl_lock); | ||
540 | if (!nfs41_wake_and_assign_slot(tbl, slot)) | ||
541 | nfs4_free_slot(tbl, slot); | ||
542 | spin_unlock(&tbl->slot_tbl_lock); | ||
543 | |||
544 | res->sr_slot = NULL; | ||
545 | out: | ||
546 | return 1; | ||
547 | } | ||
548 | |||
450 | #if defined(CONFIG_NFS_V4_1) | 549 | #if defined(CONFIG_NFS_V4_1) |
451 | 550 | ||
452 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | 551 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) |
@@ -506,6 +605,7 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
506 | interrupted = true; | 605 | interrupted = true; |
507 | } | 606 | } |
508 | 607 | ||
608 | trace_nfs4_sequence_done(session, res); | ||
509 | /* Check the SEQUENCE operation status */ | 609 | /* Check the SEQUENCE operation status */ |
510 | switch (res->sr_status) { | 610 | switch (res->sr_status) { |
511 | case 0: | 611 | case 0: |
@@ -591,25 +691,11 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
591 | { | 691 | { |
592 | if (res->sr_slot == NULL) | 692 | if (res->sr_slot == NULL) |
593 | return 1; | 693 | return 1; |
694 | if (!res->sr_slot->table->session) | ||
695 | return nfs40_sequence_done(task, res); | ||
594 | return nfs41_sequence_done(task, res); | 696 | return nfs41_sequence_done(task, res); |
595 | } | 697 | } |
596 | 698 | ||
597 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, | ||
598 | struct nfs4_sequence_res *res, int cache_reply) | ||
599 | { | ||
600 | args->sa_slot = NULL; | ||
601 | args->sa_cache_this = 0; | ||
602 | args->sa_privileged = 0; | ||
603 | if (cache_reply) | ||
604 | args->sa_cache_this = 1; | ||
605 | res->sr_slot = NULL; | ||
606 | } | ||
607 | |||
608 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
609 | { | ||
610 | args->sa_privileged = 1; | ||
611 | } | ||
612 | |||
613 | int nfs41_setup_sequence(struct nfs4_session *session, | 699 | int nfs41_setup_sequence(struct nfs4_session *session, |
614 | struct nfs4_sequence_args *args, | 700 | struct nfs4_sequence_args *args, |
615 | struct nfs4_sequence_res *res, | 701 | struct nfs4_sequence_res *res, |
@@ -647,7 +733,7 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
647 | 733 | ||
648 | args->sa_slot = slot; | 734 | args->sa_slot = slot; |
649 | 735 | ||
650 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, | 736 | dprintk("<-- %s slotid=%u seqid=%u\n", __func__, |
651 | slot->slot_nr, slot->seq_nr); | 737 | slot->slot_nr, slot->seq_nr); |
652 | 738 | ||
653 | res->sr_slot = slot; | 739 | res->sr_slot = slot; |
@@ -658,6 +744,7 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
658 | * set to 1 if an rpc level failure occurs. | 744 | * set to 1 if an rpc level failure occurs. |
659 | */ | 745 | */ |
660 | res->sr_status = 1; | 746 | res->sr_status = 1; |
747 | trace_nfs4_setup_sequence(session, args); | ||
661 | out_success: | 748 | out_success: |
662 | rpc_call_start(task); | 749 | rpc_call_start(task); |
663 | return 0; | 750 | return 0; |
@@ -673,38 +760,30 @@ out_sleep: | |||
673 | } | 760 | } |
674 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | 761 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); |
675 | 762 | ||
676 | int nfs4_setup_sequence(const struct nfs_server *server, | 763 | static int nfs4_setup_sequence(const struct nfs_server *server, |
677 | struct nfs4_sequence_args *args, | 764 | struct nfs4_sequence_args *args, |
678 | struct nfs4_sequence_res *res, | 765 | struct nfs4_sequence_res *res, |
679 | struct rpc_task *task) | 766 | struct rpc_task *task) |
680 | { | 767 | { |
681 | struct nfs4_session *session = nfs4_get_session(server); | 768 | struct nfs4_session *session = nfs4_get_session(server); |
682 | int ret = 0; | 769 | int ret = 0; |
683 | 770 | ||
684 | if (session == NULL) { | 771 | if (!session) |
685 | rpc_call_start(task); | 772 | return nfs40_setup_sequence(server, args, res, task); |
686 | goto out; | ||
687 | } | ||
688 | 773 | ||
689 | dprintk("--> %s clp %p session %p sr_slot %d\n", | 774 | dprintk("--> %s clp %p session %p sr_slot %u\n", |
690 | __func__, session->clp, session, res->sr_slot ? | 775 | __func__, session->clp, session, res->sr_slot ? |
691 | res->sr_slot->slot_nr : -1); | 776 | res->sr_slot->slot_nr : NFS4_NO_SLOT); |
692 | 777 | ||
693 | ret = nfs41_setup_sequence(session, args, res, task); | 778 | ret = nfs41_setup_sequence(session, args, res, task); |
694 | out: | 779 | |
695 | dprintk("<-- %s status=%d\n", __func__, ret); | 780 | dprintk("<-- %s status=%d\n", __func__, ret); |
696 | return ret; | 781 | return ret; |
697 | } | 782 | } |
698 | 783 | ||
699 | struct nfs41_call_sync_data { | ||
700 | const struct nfs_server *seq_server; | ||
701 | struct nfs4_sequence_args *seq_args; | ||
702 | struct nfs4_sequence_res *seq_res; | ||
703 | }; | ||
704 | |||
705 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | 784 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) |
706 | { | 785 | { |
707 | struct nfs41_call_sync_data *data = calldata; | 786 | struct nfs4_call_sync_data *data = calldata; |
708 | struct nfs4_session *session = nfs4_get_session(data->seq_server); | 787 | struct nfs4_session *session = nfs4_get_session(data->seq_server); |
709 | 788 | ||
710 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); | 789 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); |
@@ -714,7 +793,7 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | |||
714 | 793 | ||
715 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | 794 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) |
716 | { | 795 | { |
717 | struct nfs41_call_sync_data *data = calldata; | 796 | struct nfs4_call_sync_data *data = calldata; |
718 | 797 | ||
719 | nfs41_sequence_done(task, data->seq_res); | 798 | nfs41_sequence_done(task, data->seq_res); |
720 | } | 799 | } |
@@ -724,6 +803,42 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { | |||
724 | .rpc_call_done = nfs41_call_sync_done, | 803 | .rpc_call_done = nfs41_call_sync_done, |
725 | }; | 804 | }; |
726 | 805 | ||
806 | #else /* !CONFIG_NFS_V4_1 */ | ||
807 | |||
808 | static int nfs4_setup_sequence(const struct nfs_server *server, | ||
809 | struct nfs4_sequence_args *args, | ||
810 | struct nfs4_sequence_res *res, | ||
811 | struct rpc_task *task) | ||
812 | { | ||
813 | return nfs40_setup_sequence(server, args, res, task); | ||
814 | } | ||
815 | |||
816 | static int nfs4_sequence_done(struct rpc_task *task, | ||
817 | struct nfs4_sequence_res *res) | ||
818 | { | ||
819 | return nfs40_sequence_done(task, res); | ||
820 | } | ||
821 | |||
822 | #endif /* !CONFIG_NFS_V4_1 */ | ||
823 | |||
824 | static void nfs40_call_sync_prepare(struct rpc_task *task, void *calldata) | ||
825 | { | ||
826 | struct nfs4_call_sync_data *data = calldata; | ||
827 | nfs4_setup_sequence(data->seq_server, | ||
828 | data->seq_args, data->seq_res, task); | ||
829 | } | ||
830 | |||
831 | static void nfs40_call_sync_done(struct rpc_task *task, void *calldata) | ||
832 | { | ||
833 | struct nfs4_call_sync_data *data = calldata; | ||
834 | nfs4_sequence_done(task, data->seq_res); | ||
835 | } | ||
836 | |||
837 | static const struct rpc_call_ops nfs40_call_sync_ops = { | ||
838 | .rpc_call_prepare = nfs40_call_sync_prepare, | ||
839 | .rpc_call_done = nfs40_call_sync_done, | ||
840 | }; | ||
841 | |||
727 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | 842 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, |
728 | struct nfs_server *server, | 843 | struct nfs_server *server, |
729 | struct rpc_message *msg, | 844 | struct rpc_message *msg, |
@@ -732,7 +847,8 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
732 | { | 847 | { |
733 | int ret; | 848 | int ret; |
734 | struct rpc_task *task; | 849 | struct rpc_task *task; |
735 | struct nfs41_call_sync_data data = { | 850 | struct nfs_client *clp = server->nfs_client; |
851 | struct nfs4_call_sync_data data = { | ||
736 | .seq_server = server, | 852 | .seq_server = server, |
737 | .seq_args = args, | 853 | .seq_args = args, |
738 | .seq_res = res, | 854 | .seq_res = res, |
@@ -740,7 +856,7 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
740 | struct rpc_task_setup task_setup = { | 856 | struct rpc_task_setup task_setup = { |
741 | .rpc_client = clnt, | 857 | .rpc_client = clnt, |
742 | .rpc_message = msg, | 858 | .rpc_message = msg, |
743 | .callback_ops = &nfs41_call_sync_ops, | 859 | .callback_ops = clp->cl_mvops->call_sync_ops, |
744 | .callback_data = &data | 860 | .callback_data = &data |
745 | }; | 861 | }; |
746 | 862 | ||
@@ -754,35 +870,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
754 | return ret; | 870 | return ret; |
755 | } | 871 | } |
756 | 872 | ||
757 | #else | ||
758 | static | ||
759 | void nfs41_init_sequence(struct nfs4_sequence_args *args, | ||
760 | struct nfs4_sequence_res *res, int cache_reply) | ||
761 | { | ||
762 | } | ||
763 | |||
764 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
765 | { | ||
766 | } | ||
767 | |||
768 | |||
769 | static int nfs4_sequence_done(struct rpc_task *task, | ||
770 | struct nfs4_sequence_res *res) | ||
771 | { | ||
772 | return 1; | ||
773 | } | ||
774 | #endif /* CONFIG_NFS_V4_1 */ | ||
775 | |||
776 | static | ||
777 | int _nfs4_call_sync(struct rpc_clnt *clnt, | ||
778 | struct nfs_server *server, | ||
779 | struct rpc_message *msg, | ||
780 | struct nfs4_sequence_args *args, | ||
781 | struct nfs4_sequence_res *res) | ||
782 | { | ||
783 | return rpc_call_sync(clnt, msg, 0); | ||
784 | } | ||
785 | |||
786 | static | 873 | static |
787 | int nfs4_call_sync(struct rpc_clnt *clnt, | 874 | int nfs4_call_sync(struct rpc_clnt *clnt, |
788 | struct nfs_server *server, | 875 | struct nfs_server *server, |
@@ -791,9 +878,8 @@ int nfs4_call_sync(struct rpc_clnt *clnt, | |||
791 | struct nfs4_sequence_res *res, | 878 | struct nfs4_sequence_res *res, |
792 | int cache_reply) | 879 | int cache_reply) |
793 | { | 880 | { |
794 | nfs41_init_sequence(args, res, cache_reply); | 881 | nfs4_init_sequence(args, res, cache_reply); |
795 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, | 882 | return nfs4_call_sync_sequence(clnt, server, msg, args, res); |
796 | args, res); | ||
797 | } | 883 | } |
798 | 884 | ||
799 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 885 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) |
@@ -933,7 +1019,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
933 | p->o_arg.fh = NFS_FH(dentry->d_inode); | 1019 | p->o_arg.fh = NFS_FH(dentry->d_inode); |
934 | } | 1020 | } |
935 | if (attrs != NULL && attrs->ia_valid != 0) { | 1021 | if (attrs != NULL && attrs->ia_valid != 0) { |
936 | __be32 verf[2]; | 1022 | __u32 verf[2]; |
937 | 1023 | ||
938 | p->o_arg.u.attrs = &p->attrs; | 1024 | p->o_arg.u.attrs = &p->attrs; |
939 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); | 1025 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); |
@@ -1103,7 +1189,7 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat | |||
1103 | goto no_delegation; | 1189 | goto no_delegation; |
1104 | 1190 | ||
1105 | spin_lock(&deleg_cur->lock); | 1191 | spin_lock(&deleg_cur->lock); |
1106 | if (nfsi->delegation != deleg_cur || | 1192 | if (rcu_dereference(nfsi->delegation) != deleg_cur || |
1107 | test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) || | 1193 | test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) || |
1108 | (deleg_cur->type & fmode) != fmode) | 1194 | (deleg_cur->type & fmode) != fmode) |
1109 | goto no_delegation_unlock; | 1195 | goto no_delegation_unlock; |
@@ -1440,6 +1526,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state | |||
1440 | int err; | 1526 | int err; |
1441 | do { | 1527 | do { |
1442 | err = _nfs4_do_open_reclaim(ctx, state); | 1528 | err = _nfs4_do_open_reclaim(ctx, state); |
1529 | trace_nfs4_open_reclaim(ctx, 0, err); | ||
1443 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) | 1530 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) |
1444 | continue; | 1531 | continue; |
1445 | if (err != -NFS4ERR_DELAY) | 1532 | if (err != -NFS4ERR_DELAY) |
@@ -1524,10 +1611,20 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1524 | return nfs4_handle_delegation_recall_error(server, state, stateid, err); | 1611 | return nfs4_handle_delegation_recall_error(server, state, stateid, err); |
1525 | } | 1612 | } |
1526 | 1613 | ||
1614 | static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | ||
1615 | { | ||
1616 | struct nfs4_opendata *data = calldata; | ||
1617 | |||
1618 | nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, | ||
1619 | &data->o_res.seq_res, task); | ||
1620 | } | ||
1621 | |||
1527 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1622 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
1528 | { | 1623 | { |
1529 | struct nfs4_opendata *data = calldata; | 1624 | struct nfs4_opendata *data = calldata; |
1530 | 1625 | ||
1626 | nfs40_sequence_done(task, &data->o_res.seq_res); | ||
1627 | |||
1531 | data->rpc_status = task->tk_status; | 1628 | data->rpc_status = task->tk_status; |
1532 | if (data->rpc_status == 0) { | 1629 | if (data->rpc_status == 0) { |
1533 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); | 1630 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); |
@@ -1556,6 +1653,7 @@ out_free: | |||
1556 | } | 1653 | } |
1557 | 1654 | ||
1558 | static const struct rpc_call_ops nfs4_open_confirm_ops = { | 1655 | static const struct rpc_call_ops nfs4_open_confirm_ops = { |
1656 | .rpc_call_prepare = nfs4_open_confirm_prepare, | ||
1559 | .rpc_call_done = nfs4_open_confirm_done, | 1657 | .rpc_call_done = nfs4_open_confirm_done, |
1560 | .rpc_release = nfs4_open_confirm_release, | 1658 | .rpc_release = nfs4_open_confirm_release, |
1561 | }; | 1659 | }; |
@@ -1583,6 +1681,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
1583 | }; | 1681 | }; |
1584 | int status; | 1682 | int status; |
1585 | 1683 | ||
1684 | nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1); | ||
1586 | kref_get(&data->kref); | 1685 | kref_get(&data->kref); |
1587 | data->rpc_done = 0; | 1686 | data->rpc_done = 0; |
1588 | data->rpc_status = 0; | 1687 | data->rpc_status = 0; |
@@ -1742,7 +1841,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | |||
1742 | }; | 1841 | }; |
1743 | int status; | 1842 | int status; |
1744 | 1843 | ||
1745 | nfs41_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); | 1844 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); |
1746 | kref_get(&data->kref); | 1845 | kref_get(&data->kref); |
1747 | data->rpc_done = 0; | 1846 | data->rpc_done = 0; |
1748 | data->rpc_status = 0; | 1847 | data->rpc_status = 0; |
@@ -1895,6 +1994,7 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state | |||
1895 | 1994 | ||
1896 | do { | 1995 | do { |
1897 | err = _nfs4_open_expired(ctx, state); | 1996 | err = _nfs4_open_expired(ctx, state); |
1997 | trace_nfs4_open_expired(ctx, 0, err); | ||
1898 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) | 1998 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) |
1899 | continue; | 1999 | continue; |
1900 | switch (err) { | 2000 | switch (err) { |
@@ -1944,6 +2044,7 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
1944 | cred = get_rpccred(delegation->cred); | 2044 | cred = get_rpccred(delegation->cred); |
1945 | rcu_read_unlock(); | 2045 | rcu_read_unlock(); |
1946 | status = nfs41_test_stateid(server, stateid, cred); | 2046 | status = nfs41_test_stateid(server, stateid, cred); |
2047 | trace_nfs4_test_delegation_stateid(state, NULL, status); | ||
1947 | } else | 2048 | } else |
1948 | rcu_read_unlock(); | 2049 | rcu_read_unlock(); |
1949 | 2050 | ||
@@ -1986,6 +2087,7 @@ static int nfs41_check_open_stateid(struct nfs4_state *state) | |||
1986 | return -NFS4ERR_BAD_STATEID; | 2087 | return -NFS4ERR_BAD_STATEID; |
1987 | 2088 | ||
1988 | status = nfs41_test_stateid(server, stateid, cred); | 2089 | status = nfs41_test_stateid(server, stateid, cred); |
2090 | trace_nfs4_test_open_stateid(state, NULL, status); | ||
1989 | if (status != NFS_OK) { | 2091 | if (status != NFS_OK) { |
1990 | /* Free the stateid unless the server explicitly | 2092 | /* Free the stateid unless the server explicitly |
1991 | * informs us the stateid is unrecognized. */ | 2093 | * informs us the stateid is unrecognized. */ |
@@ -2197,6 +2299,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
2197 | do { | 2299 | do { |
2198 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); | 2300 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); |
2199 | res = ctx->state; | 2301 | res = ctx->state; |
2302 | trace_nfs4_open_file(ctx, flags, status); | ||
2200 | if (status == 0) | 2303 | if (status == 0) |
2201 | break; | 2304 | break; |
2202 | /* NOTE: BAD_SEQID means the server and client disagree about the | 2305 | /* NOTE: BAD_SEQID means the server and client disagree about the |
@@ -2310,6 +2413,7 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2310 | int err; | 2413 | int err; |
2311 | do { | 2414 | do { |
2312 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel); | 2415 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel); |
2416 | trace_nfs4_setattr(inode, err); | ||
2313 | switch (err) { | 2417 | switch (err) { |
2314 | case -NFS4ERR_OPENMODE: | 2418 | case -NFS4ERR_OPENMODE: |
2315 | if (!(sattr->ia_valid & ATTR_SIZE)) { | 2419 | if (!(sattr->ia_valid & ATTR_SIZE)) { |
@@ -2387,6 +2491,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2387 | dprintk("%s: begin!\n", __func__); | 2491 | dprintk("%s: begin!\n", __func__); |
2388 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) | 2492 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) |
2389 | return; | 2493 | return; |
2494 | trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status); | ||
2390 | /* hmm. we are done with the inode, and in the process of freeing | 2495 | /* hmm. we are done with the inode, and in the process of freeing |
2391 | * the state_owner. we keep this around to process errors | 2496 | * the state_owner. we keep this around to process errors |
2392 | */ | 2497 | */ |
@@ -2511,10 +2616,13 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) | |||
2511 | }; | 2616 | }; |
2512 | int status = -ENOMEM; | 2617 | int status = -ENOMEM; |
2513 | 2618 | ||
2619 | nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_CLEANUP, | ||
2620 | &task_setup_data.rpc_client, &msg); | ||
2621 | |||
2514 | calldata = kzalloc(sizeof(*calldata), gfp_mask); | 2622 | calldata = kzalloc(sizeof(*calldata), gfp_mask); |
2515 | if (calldata == NULL) | 2623 | if (calldata == NULL) |
2516 | goto out; | 2624 | goto out; |
2517 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1); | 2625 | nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1); |
2518 | calldata->inode = state->inode; | 2626 | calldata->inode = state->inode; |
2519 | calldata->state = state; | 2627 | calldata->state = state; |
2520 | calldata->arg.fh = NFS_FH(state->inode); | 2628 | calldata->arg.fh = NFS_FH(state->inode); |
@@ -2690,6 +2798,7 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2690 | int err; | 2798 | int err; |
2691 | do { | 2799 | do { |
2692 | err = _nfs4_lookup_root(server, fhandle, info); | 2800 | err = _nfs4_lookup_root(server, fhandle, info); |
2801 | trace_nfs4_lookup_root(server, fhandle, info->fattr, err); | ||
2693 | switch (err) { | 2802 | switch (err) { |
2694 | case 0: | 2803 | case 0: |
2695 | case -NFS4ERR_WRONGSEC: | 2804 | case -NFS4ERR_WRONGSEC: |
@@ -2705,10 +2814,13 @@ out: | |||
2705 | static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | 2814 | static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, |
2706 | struct nfs_fsinfo *info, rpc_authflavor_t flavor) | 2815 | struct nfs_fsinfo *info, rpc_authflavor_t flavor) |
2707 | { | 2816 | { |
2817 | struct rpc_auth_create_args auth_args = { | ||
2818 | .pseudoflavor = flavor, | ||
2819 | }; | ||
2708 | struct rpc_auth *auth; | 2820 | struct rpc_auth *auth; |
2709 | int ret; | 2821 | int ret; |
2710 | 2822 | ||
2711 | auth = rpcauth_create(flavor, server->client); | 2823 | auth = rpcauth_create(&auth_args, server->client); |
2712 | if (IS_ERR(auth)) { | 2824 | if (IS_ERR(auth)) { |
2713 | ret = -EACCES; | 2825 | ret = -EACCES; |
2714 | goto out; | 2826 | goto out; |
@@ -2772,18 +2884,27 @@ static int nfs4_do_find_root_sec(struct nfs_server *server, | |||
2772 | * @server: initialized nfs_server handle | 2884 | * @server: initialized nfs_server handle |
2773 | * @fhandle: we fill in the pseudo-fs root file handle | 2885 | * @fhandle: we fill in the pseudo-fs root file handle |
2774 | * @info: we fill in an FSINFO struct | 2886 | * @info: we fill in an FSINFO struct |
2887 | * @auth_probe: probe the auth flavours | ||
2775 | * | 2888 | * |
2776 | * Returns zero on success, or a negative errno. | 2889 | * Returns zero on success, or a negative errno. |
2777 | */ | 2890 | */ |
2778 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, | 2891 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, |
2779 | struct nfs_fsinfo *info) | 2892 | struct nfs_fsinfo *info, |
2893 | bool auth_probe) | ||
2780 | { | 2894 | { |
2781 | int status; | 2895 | int status; |
2782 | 2896 | ||
2783 | status = nfs4_lookup_root(server, fhandle, info); | 2897 | switch (auth_probe) { |
2784 | if ((status == -NFS4ERR_WRONGSEC) && | 2898 | case false: |
2785 | !(server->flags & NFS_MOUNT_SECFLAVOUR)) | 2899 | status = nfs4_lookup_root(server, fhandle, info); |
2900 | if (status != -NFS4ERR_WRONGSEC) | ||
2901 | break; | ||
2902 | /* Did user force a 'sec=' mount option? */ | ||
2903 | if (server->flags & NFS_MOUNT_SECFLAVOUR) | ||
2904 | break; | ||
2905 | default: | ||
2786 | status = nfs4_do_find_root_sec(server, fhandle, info); | 2906 | status = nfs4_do_find_root_sec(server, fhandle, info); |
2907 | } | ||
2787 | 2908 | ||
2788 | if (status == 0) | 2909 | if (status == 0) |
2789 | status = nfs4_server_capabilities(server, fhandle); | 2910 | status = nfs4_server_capabilities(server, fhandle); |
@@ -2899,8 +3020,9 @@ static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2899 | struct nfs4_exception exception = { }; | 3020 | struct nfs4_exception exception = { }; |
2900 | int err; | 3021 | int err; |
2901 | do { | 3022 | do { |
2902 | err = nfs4_handle_exception(server, | 3023 | err = _nfs4_proc_getattr(server, fhandle, fattr, label); |
2903 | _nfs4_proc_getattr(server, fhandle, fattr, label), | 3024 | trace_nfs4_getattr(server, fhandle, fattr, err); |
3025 | err = nfs4_handle_exception(server, err, | ||
2904 | &exception); | 3026 | &exception); |
2905 | } while (exception.retry); | 3027 | } while (exception.retry); |
2906 | return err; | 3028 | return err; |
@@ -2940,10 +3062,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2940 | 3062 | ||
2941 | /* Deal with open(O_TRUNC) */ | 3063 | /* Deal with open(O_TRUNC) */ |
2942 | if (sattr->ia_valid & ATTR_OPEN) | 3064 | if (sattr->ia_valid & ATTR_OPEN) |
2943 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | 3065 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME); |
2944 | 3066 | ||
2945 | /* Optimization: if the end result is no change, don't RPC */ | 3067 | /* Optimization: if the end result is no change, don't RPC */ |
2946 | if ((sattr->ia_valid & ~(ATTR_FILE)) == 0) | 3068 | if ((sattr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0) |
2947 | return 0; | 3069 | return 0; |
2948 | 3070 | ||
2949 | /* Search for an existing open(O_WRITE) file */ | 3071 | /* Search for an existing open(O_WRITE) file */ |
@@ -3020,6 +3142,7 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |||
3020 | int err; | 3142 | int err; |
3021 | do { | 3143 | do { |
3022 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label); | 3144 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label); |
3145 | trace_nfs4_lookup(dir, name, err); | ||
3023 | switch (err) { | 3146 | switch (err) { |
3024 | case -NFS4ERR_BADNAME: | 3147 | case -NFS4ERR_BADNAME: |
3025 | err = -ENOENT; | 3148 | err = -ENOENT; |
@@ -3031,7 +3154,9 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |||
3031 | err = -EPERM; | 3154 | err = -EPERM; |
3032 | if (client != *clnt) | 3155 | if (client != *clnt) |
3033 | goto out; | 3156 | goto out; |
3034 | 3157 | /* No security negotiation if the user specified 'sec=' */ | |
3158 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_SECFLAVOUR) | ||
3159 | goto out; | ||
3035 | client = nfs4_create_sec_client(client, dir, name); | 3160 | client = nfs4_create_sec_client(client, dir, name); |
3036 | if (IS_ERR(client)) | 3161 | if (IS_ERR(client)) |
3037 | return PTR_ERR(client); | 3162 | return PTR_ERR(client); |
@@ -3134,8 +3259,9 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
3134 | struct nfs4_exception exception = { }; | 3259 | struct nfs4_exception exception = { }; |
3135 | int err; | 3260 | int err; |
3136 | do { | 3261 | do { |
3137 | err = nfs4_handle_exception(NFS_SERVER(inode), | 3262 | err = _nfs4_proc_access(inode, entry); |
3138 | _nfs4_proc_access(inode, entry), | 3263 | trace_nfs4_access(inode, err); |
3264 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
3139 | &exception); | 3265 | &exception); |
3140 | } while (exception.retry); | 3266 | } while (exception.retry); |
3141 | return err; | 3267 | return err; |
@@ -3188,8 +3314,9 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
3188 | struct nfs4_exception exception = { }; | 3314 | struct nfs4_exception exception = { }; |
3189 | int err; | 3315 | int err; |
3190 | do { | 3316 | do { |
3191 | err = nfs4_handle_exception(NFS_SERVER(inode), | 3317 | err = _nfs4_proc_readlink(inode, page, pgbase, pglen); |
3192 | _nfs4_proc_readlink(inode, page, pgbase, pglen), | 3318 | trace_nfs4_readlink(inode, err); |
3319 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
3193 | &exception); | 3320 | &exception); |
3194 | } while (exception.retry); | 3321 | } while (exception.retry); |
3195 | return err; | 3322 | return err; |
@@ -3253,8 +3380,9 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
3253 | struct nfs4_exception exception = { }; | 3380 | struct nfs4_exception exception = { }; |
3254 | int err; | 3381 | int err; |
3255 | do { | 3382 | do { |
3256 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3383 | err = _nfs4_proc_remove(dir, name); |
3257 | _nfs4_proc_remove(dir, name), | 3384 | trace_nfs4_remove(dir, name, err); |
3385 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
3258 | &exception); | 3386 | &exception); |
3259 | } while (exception.retry); | 3387 | } while (exception.retry); |
3260 | return err; | 3388 | return err; |
@@ -3268,7 +3396,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3268 | 3396 | ||
3269 | res->server = server; | 3397 | res->server = server; |
3270 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 3398 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
3271 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 3399 | nfs4_init_sequence(&args->seq_args, &res->seq_res, 1); |
3272 | 3400 | ||
3273 | nfs_fattr_init(res->dir_attr); | 3401 | nfs_fattr_init(res->dir_attr); |
3274 | } | 3402 | } |
@@ -3283,7 +3411,8 @@ static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlin | |||
3283 | 3411 | ||
3284 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 3412 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
3285 | { | 3413 | { |
3286 | struct nfs_removeres *res = task->tk_msg.rpc_resp; | 3414 | struct nfs_unlinkdata *data = task->tk_calldata; |
3415 | struct nfs_removeres *res = &data->res; | ||
3287 | 3416 | ||
3288 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3417 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3289 | return 0; | 3418 | return 0; |
@@ -3301,7 +3430,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | |||
3301 | 3430 | ||
3302 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; | 3431 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; |
3303 | res->server = server; | 3432 | res->server = server; |
3304 | nfs41_init_sequence(&arg->seq_args, &res->seq_res, 1); | 3433 | nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1); |
3305 | } | 3434 | } |
3306 | 3435 | ||
3307 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) | 3436 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) |
@@ -3315,7 +3444,8 @@ static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renam | |||
3315 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | 3444 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, |
3316 | struct inode *new_dir) | 3445 | struct inode *new_dir) |
3317 | { | 3446 | { |
3318 | struct nfs_renameres *res = task->tk_msg.rpc_resp; | 3447 | struct nfs_renamedata *data = task->tk_calldata; |
3448 | struct nfs_renameres *res = &data->res; | ||
3319 | 3449 | ||
3320 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3450 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3321 | return 0; | 3451 | return 0; |
@@ -3361,9 +3491,10 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
3361 | struct nfs4_exception exception = { }; | 3491 | struct nfs4_exception exception = { }; |
3362 | int err; | 3492 | int err; |
3363 | do { | 3493 | do { |
3364 | err = nfs4_handle_exception(NFS_SERVER(old_dir), | 3494 | err = _nfs4_proc_rename(old_dir, old_name, |
3365 | _nfs4_proc_rename(old_dir, old_name, | 3495 | new_dir, new_name); |
3366 | new_dir, new_name), | 3496 | trace_nfs4_rename(old_dir, old_name, new_dir, new_name, err); |
3497 | err = nfs4_handle_exception(NFS_SERVER(old_dir), err, | ||
3367 | &exception); | 3498 | &exception); |
3368 | } while (exception.retry); | 3499 | } while (exception.retry); |
3369 | return err; | 3500 | return err; |
@@ -3525,9 +3656,9 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3525 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | 3656 | label = nfs4_label_init_security(dir, dentry, sattr, &l); |
3526 | 3657 | ||
3527 | do { | 3658 | do { |
3528 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3659 | err = _nfs4_proc_symlink(dir, dentry, page, len, sattr, label); |
3529 | _nfs4_proc_symlink(dir, dentry, page, | 3660 | trace_nfs4_symlink(dir, &dentry->d_name, err); |
3530 | len, sattr, label), | 3661 | err = nfs4_handle_exception(NFS_SERVER(dir), err, |
3531 | &exception); | 3662 | &exception); |
3532 | } while (exception.retry); | 3663 | } while (exception.retry); |
3533 | 3664 | ||
@@ -3564,8 +3695,9 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3564 | 3695 | ||
3565 | sattr->ia_mode &= ~current_umask(); | 3696 | sattr->ia_mode &= ~current_umask(); |
3566 | do { | 3697 | do { |
3567 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3698 | err = _nfs4_proc_mkdir(dir, dentry, sattr, label); |
3568 | _nfs4_proc_mkdir(dir, dentry, sattr, label), | 3699 | trace_nfs4_mkdir(dir, &dentry->d_name, err); |
3700 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
3569 | &exception); | 3701 | &exception); |
3570 | } while (exception.retry); | 3702 | } while (exception.retry); |
3571 | nfs4_label_release_security(label); | 3703 | nfs4_label_release_security(label); |
@@ -3618,9 +3750,10 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
3618 | struct nfs4_exception exception = { }; | 3750 | struct nfs4_exception exception = { }; |
3619 | int err; | 3751 | int err; |
3620 | do { | 3752 | do { |
3621 | err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), | 3753 | err = _nfs4_proc_readdir(dentry, cred, cookie, |
3622 | _nfs4_proc_readdir(dentry, cred, cookie, | 3754 | pages, count, plus); |
3623 | pages, count, plus), | 3755 | trace_nfs4_readdir(dentry->d_inode, err); |
3756 | err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), err, | ||
3624 | &exception); | 3757 | &exception); |
3625 | } while (exception.retry); | 3758 | } while (exception.retry); |
3626 | return err; | 3759 | return err; |
@@ -3672,8 +3805,9 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3672 | 3805 | ||
3673 | sattr->ia_mode &= ~current_umask(); | 3806 | sattr->ia_mode &= ~current_umask(); |
3674 | do { | 3807 | do { |
3675 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3808 | err = _nfs4_proc_mknod(dir, dentry, sattr, label, rdev); |
3676 | _nfs4_proc_mknod(dir, dentry, sattr, label, rdev), | 3809 | trace_nfs4_mknod(dir, &dentry->d_name, err); |
3810 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
3677 | &exception); | 3811 | &exception); |
3678 | } while (exception.retry); | 3812 | } while (exception.retry); |
3679 | 3813 | ||
@@ -3741,6 +3875,7 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str | |||
3741 | 3875 | ||
3742 | do { | 3876 | do { |
3743 | err = _nfs4_do_fsinfo(server, fhandle, fsinfo); | 3877 | err = _nfs4_do_fsinfo(server, fhandle, fsinfo); |
3878 | trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err); | ||
3744 | if (err == 0) { | 3879 | if (err == 0) { |
3745 | struct nfs_client *clp = server->nfs_client; | 3880 | struct nfs_client *clp = server->nfs_client; |
3746 | 3881 | ||
@@ -3859,6 +3994,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) | |||
3859 | { | 3994 | { |
3860 | struct nfs_server *server = NFS_SERVER(data->header->inode); | 3995 | struct nfs_server *server = NFS_SERVER(data->header->inode); |
3861 | 3996 | ||
3997 | trace_nfs4_read(data, task->tk_status); | ||
3862 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3998 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3863 | rpc_restart_call_prepare(task); | 3999 | rpc_restart_call_prepare(task); |
3864 | return -EAGAIN; | 4000 | return -EAGAIN; |
@@ -3902,24 +4038,29 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3902 | data->timestamp = jiffies; | 4038 | data->timestamp = jiffies; |
3903 | data->read_done_cb = nfs4_read_done_cb; | 4039 | data->read_done_cb = nfs4_read_done_cb; |
3904 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | 4040 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; |
3905 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | 4041 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); |
3906 | } | 4042 | } |
3907 | 4043 | ||
3908 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 4044 | static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
3909 | { | 4045 | { |
3910 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 4046 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3911 | &data->args.seq_args, | 4047 | &data->args.seq_args, |
3912 | &data->res.seq_res, | 4048 | &data->res.seq_res, |
3913 | task)) | 4049 | task)) |
3914 | return; | 4050 | return 0; |
3915 | nfs4_set_rw_stateid(&data->args.stateid, data->args.context, | 4051 | if (nfs4_set_rw_stateid(&data->args.stateid, data->args.context, |
3916 | data->args.lock_context, FMODE_READ); | 4052 | data->args.lock_context, FMODE_READ) == -EIO) |
4053 | return -EIO; | ||
4054 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags))) | ||
4055 | return -EIO; | ||
4056 | return 0; | ||
3917 | } | 4057 | } |
3918 | 4058 | ||
3919 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 4059 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
3920 | { | 4060 | { |
3921 | struct inode *inode = data->header->inode; | 4061 | struct inode *inode = data->header->inode; |
3922 | 4062 | ||
4063 | trace_nfs4_write(data, task->tk_status); | ||
3923 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 4064 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3924 | rpc_restart_call_prepare(task); | 4065 | rpc_restart_call_prepare(task); |
3925 | return -EAGAIN; | 4066 | return -EAGAIN; |
@@ -3985,18 +4126,22 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3985 | data->timestamp = jiffies; | 4126 | data->timestamp = jiffies; |
3986 | 4127 | ||
3987 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; | 4128 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
3988 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4129 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
3989 | } | 4130 | } |
3990 | 4131 | ||
3991 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 4132 | static int nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
3992 | { | 4133 | { |
3993 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 4134 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3994 | &data->args.seq_args, | 4135 | &data->args.seq_args, |
3995 | &data->res.seq_res, | 4136 | &data->res.seq_res, |
3996 | task)) | 4137 | task)) |
3997 | return; | 4138 | return 0; |
3998 | nfs4_set_rw_stateid(&data->args.stateid, data->args.context, | 4139 | if (nfs4_set_rw_stateid(&data->args.stateid, data->args.context, |
3999 | data->args.lock_context, FMODE_WRITE); | 4140 | data->args.lock_context, FMODE_WRITE) == -EIO) |
4141 | return -EIO; | ||
4142 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags))) | ||
4143 | return -EIO; | ||
4144 | return 0; | ||
4000 | } | 4145 | } |
4001 | 4146 | ||
4002 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | 4147 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) |
@@ -4011,6 +4156,7 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *da | |||
4011 | { | 4156 | { |
4012 | struct inode *inode = data->inode; | 4157 | struct inode *inode = data->inode; |
4013 | 4158 | ||
4159 | trace_nfs4_commit(data, task->tk_status); | ||
4014 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 4160 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
4015 | rpc_restart_call_prepare(task); | 4161 | rpc_restart_call_prepare(task); |
4016 | return -EAGAIN; | 4162 | return -EAGAIN; |
@@ -4033,7 +4179,7 @@ static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess | |||
4033 | data->commit_done_cb = nfs4_commit_done_cb; | 4179 | data->commit_done_cb = nfs4_commit_done_cb; |
4034 | data->res.server = server; | 4180 | data->res.server = server; |
4035 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 4181 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
4036 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4182 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
4037 | } | 4183 | } |
4038 | 4184 | ||
4039 | struct nfs4_renewdata { | 4185 | struct nfs4_renewdata { |
@@ -4062,6 +4208,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) | |||
4062 | struct nfs_client *clp = data->client; | 4208 | struct nfs_client *clp = data->client; |
4063 | unsigned long timestamp = data->timestamp; | 4209 | unsigned long timestamp = data->timestamp; |
4064 | 4210 | ||
4211 | trace_nfs4_renew_async(clp, task->tk_status); | ||
4065 | if (task->tk_status < 0) { | 4212 | if (task->tk_status < 0) { |
4066 | /* Unless we're shutting down, schedule state recovery! */ | 4213 | /* Unless we're shutting down, schedule state recovery! */ |
4067 | if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0) | 4214 | if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0) |
@@ -4319,6 +4466,7 @@ static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bufl | |||
4319 | ssize_t ret; | 4466 | ssize_t ret; |
4320 | do { | 4467 | do { |
4321 | ret = __nfs4_get_acl_uncached(inode, buf, buflen); | 4468 | ret = __nfs4_get_acl_uncached(inode, buf, buflen); |
4469 | trace_nfs4_get_acl(inode, ret); | ||
4322 | if (ret >= 0) | 4470 | if (ret >= 0) |
4323 | break; | 4471 | break; |
4324 | ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); | 4472 | ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); |
@@ -4398,8 +4546,9 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
4398 | struct nfs4_exception exception = { }; | 4546 | struct nfs4_exception exception = { }; |
4399 | int err; | 4547 | int err; |
4400 | do { | 4548 | do { |
4401 | err = nfs4_handle_exception(NFS_SERVER(inode), | 4549 | err = __nfs4_proc_set_acl(inode, buf, buflen); |
4402 | __nfs4_proc_set_acl(inode, buf, buflen), | 4550 | trace_nfs4_set_acl(inode, err); |
4551 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
4403 | &exception); | 4552 | &exception); |
4404 | } while (exception.retry); | 4553 | } while (exception.retry); |
4405 | return err; | 4554 | return err; |
@@ -4452,8 +4601,9 @@ static int nfs4_get_security_label(struct inode *inode, void *buf, | |||
4452 | return -EOPNOTSUPP; | 4601 | return -EOPNOTSUPP; |
4453 | 4602 | ||
4454 | do { | 4603 | do { |
4455 | err = nfs4_handle_exception(NFS_SERVER(inode), | 4604 | err = _nfs4_get_security_label(inode, buf, buflen); |
4456 | _nfs4_get_security_label(inode, buf, buflen), | 4605 | trace_nfs4_get_security_label(inode, err); |
4606 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
4457 | &exception); | 4607 | &exception); |
4458 | } while (exception.retry); | 4608 | } while (exception.retry); |
4459 | return err; | 4609 | return err; |
@@ -4505,9 +4655,10 @@ static int nfs4_do_set_security_label(struct inode *inode, | |||
4505 | int err; | 4655 | int err; |
4506 | 4656 | ||
4507 | do { | 4657 | do { |
4508 | err = nfs4_handle_exception(NFS_SERVER(inode), | 4658 | err = _nfs4_do_set_security_label(inode, ilabel, |
4509 | _nfs4_do_set_security_label(inode, ilabel, | 4659 | fattr, olabel); |
4510 | fattr, olabel), | 4660 | trace_nfs4_set_security_label(inode, err); |
4661 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
4511 | &exception); | 4662 | &exception); |
4512 | } while (exception.retry); | 4663 | } while (exception.retry); |
4513 | return err; | 4664 | return err; |
@@ -4630,11 +4781,11 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, | |||
4630 | /* An impossible timestamp guarantees this value | 4781 | /* An impossible timestamp guarantees this value |
4631 | * will never match a generated boot time. */ | 4782 | * will never match a generated boot time. */ |
4632 | verf[0] = 0; | 4783 | verf[0] = 0; |
4633 | verf[1] = (__be32)(NSEC_PER_SEC + 1); | 4784 | verf[1] = cpu_to_be32(NSEC_PER_SEC + 1); |
4634 | } else { | 4785 | } else { |
4635 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); | 4786 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); |
4636 | verf[0] = (__be32)nn->boot_time.tv_sec; | 4787 | verf[0] = cpu_to_be32(nn->boot_time.tv_sec); |
4637 | verf[1] = (__be32)nn->boot_time.tv_nsec; | 4788 | verf[1] = cpu_to_be32(nn->boot_time.tv_nsec); |
4638 | } | 4789 | } |
4639 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); | 4790 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); |
4640 | } | 4791 | } |
@@ -4660,10 +4811,14 @@ static unsigned int | |||
4660 | nfs4_init_uniform_client_string(const struct nfs_client *clp, | 4811 | nfs4_init_uniform_client_string(const struct nfs_client *clp, |
4661 | char *buf, size_t len) | 4812 | char *buf, size_t len) |
4662 | { | 4813 | { |
4663 | char *nodename = clp->cl_rpcclient->cl_nodename; | 4814 | const char *nodename = clp->cl_rpcclient->cl_nodename; |
4664 | 4815 | ||
4665 | if (nfs4_client_id_uniquifier[0] != '\0') | 4816 | if (nfs4_client_id_uniquifier[0] != '\0') |
4666 | nodename = nfs4_client_id_uniquifier; | 4817 | return scnprintf(buf, len, "Linux NFSv%u.%u %s/%s", |
4818 | clp->rpc_ops->version, | ||
4819 | clp->cl_minorversion, | ||
4820 | nfs4_client_id_uniquifier, | ||
4821 | nodename); | ||
4667 | return scnprintf(buf, len, "Linux NFSv%u.%u %s", | 4822 | return scnprintf(buf, len, "Linux NFSv%u.%u %s", |
4668 | clp->rpc_ops->version, clp->cl_minorversion, | 4823 | clp->rpc_ops->version, clp->cl_minorversion, |
4669 | nodename); | 4824 | nodename); |
@@ -4724,6 +4879,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
4724 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | 4879 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
4725 | setclientid.sc_name_len, setclientid.sc_name); | 4880 | setclientid.sc_name_len, setclientid.sc_name); |
4726 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4881 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4882 | trace_nfs4_setclientid(clp, status); | ||
4727 | dprintk("NFS reply setclientid: %d\n", status); | 4883 | dprintk("NFS reply setclientid: %d\n", status); |
4728 | return status; | 4884 | return status; |
4729 | } | 4885 | } |
@@ -4751,6 +4907,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
4751 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | 4907 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
4752 | clp->cl_clientid); | 4908 | clp->cl_clientid); |
4753 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4909 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4910 | trace_nfs4_setclientid_confirm(clp, status); | ||
4754 | dprintk("NFS reply setclientid_confirm: %d\n", status); | 4911 | dprintk("NFS reply setclientid_confirm: %d\n", status); |
4755 | return status; | 4912 | return status; |
4756 | } | 4913 | } |
@@ -4772,6 +4929,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
4772 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | 4929 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
4773 | return; | 4930 | return; |
4774 | 4931 | ||
4932 | trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status); | ||
4775 | switch (task->tk_status) { | 4933 | switch (task->tk_status) { |
4776 | case -NFS4ERR_STALE_STATEID: | 4934 | case -NFS4ERR_STALE_STATEID: |
4777 | case -NFS4ERR_EXPIRED: | 4935 | case -NFS4ERR_EXPIRED: |
@@ -4793,7 +4951,6 @@ static void nfs4_delegreturn_release(void *calldata) | |||
4793 | kfree(calldata); | 4951 | kfree(calldata); |
4794 | } | 4952 | } |
4795 | 4953 | ||
4796 | #if defined(CONFIG_NFS_V4_1) | ||
4797 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | 4954 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) |
4798 | { | 4955 | { |
4799 | struct nfs4_delegreturndata *d_data; | 4956 | struct nfs4_delegreturndata *d_data; |
@@ -4805,12 +4962,9 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
4805 | &d_data->res.seq_res, | 4962 | &d_data->res.seq_res, |
4806 | task); | 4963 | task); |
4807 | } | 4964 | } |
4808 | #endif /* CONFIG_NFS_V4_1 */ | ||
4809 | 4965 | ||
4810 | static const struct rpc_call_ops nfs4_delegreturn_ops = { | 4966 | static const struct rpc_call_ops nfs4_delegreturn_ops = { |
4811 | #if defined(CONFIG_NFS_V4_1) | ||
4812 | .rpc_call_prepare = nfs4_delegreturn_prepare, | 4967 | .rpc_call_prepare = nfs4_delegreturn_prepare, |
4813 | #endif /* CONFIG_NFS_V4_1 */ | ||
4814 | .rpc_call_done = nfs4_delegreturn_done, | 4968 | .rpc_call_done = nfs4_delegreturn_done, |
4815 | .rpc_release = nfs4_delegreturn_release, | 4969 | .rpc_release = nfs4_delegreturn_release, |
4816 | }; | 4970 | }; |
@@ -4835,7 +4989,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
4835 | data = kzalloc(sizeof(*data), GFP_NOFS); | 4989 | data = kzalloc(sizeof(*data), GFP_NOFS); |
4836 | if (data == NULL) | 4990 | if (data == NULL) |
4837 | return -ENOMEM; | 4991 | return -ENOMEM; |
4838 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4992 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
4839 | data->args.fhandle = &data->fh; | 4993 | data->args.fhandle = &data->fh; |
4840 | data->args.stateid = &data->stateid; | 4994 | data->args.stateid = &data->stateid; |
4841 | data->args.bitmask = server->cache_consistency_bitmask; | 4995 | data->args.bitmask = server->cache_consistency_bitmask; |
@@ -4875,6 +5029,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 | |||
4875 | int err; | 5029 | int err; |
4876 | do { | 5030 | do { |
4877 | err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); | 5031 | err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); |
5032 | trace_nfs4_delegreturn(inode, err); | ||
4878 | switch (err) { | 5033 | switch (err) { |
4879 | case -NFS4ERR_STALE_STATEID: | 5034 | case -NFS4ERR_STALE_STATEID: |
4880 | case -NFS4ERR_EXPIRED: | 5035 | case -NFS4ERR_EXPIRED: |
@@ -4949,8 +5104,9 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
4949 | int err; | 5104 | int err; |
4950 | 5105 | ||
4951 | do { | 5106 | do { |
4952 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | 5107 | err = _nfs4_proc_getlk(state, cmd, request); |
4953 | _nfs4_proc_getlk(state, cmd, request), | 5108 | trace_nfs4_get_lock(request, state, cmd, err); |
5109 | err = nfs4_handle_exception(NFS_SERVER(state->inode), err, | ||
4954 | &exception); | 5110 | &exception); |
4955 | } while (exception.retry); | 5111 | } while (exception.retry); |
4956 | return err; | 5112 | return err; |
@@ -5087,6 +5243,9 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
5087 | .flags = RPC_TASK_ASYNC, | 5243 | .flags = RPC_TASK_ASYNC, |
5088 | }; | 5244 | }; |
5089 | 5245 | ||
5246 | nfs4_state_protect(NFS_SERVER(lsp->ls_state->inode)->nfs_client, | ||
5247 | NFS_SP4_MACH_CRED_CLEANUP, &task_setup_data.rpc_client, &msg); | ||
5248 | |||
5090 | /* Ensure this is an unlock - when canceling a lock, the | 5249 | /* Ensure this is an unlock - when canceling a lock, the |
5091 | * canceled lock is passed in, and it won't be an unlock. | 5250 | * canceled lock is passed in, and it won't be an unlock. |
5092 | */ | 5251 | */ |
@@ -5098,7 +5257,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
5098 | return ERR_PTR(-ENOMEM); | 5257 | return ERR_PTR(-ENOMEM); |
5099 | } | 5258 | } |
5100 | 5259 | ||
5101 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | 5260 | nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); |
5102 | msg.rpc_argp = &data->arg; | 5261 | msg.rpc_argp = &data->arg; |
5103 | msg.rpc_resp = &data->res; | 5262 | msg.rpc_resp = &data->res; |
5104 | task_setup_data.callback_data = data; | 5263 | task_setup_data.callback_data = data; |
@@ -5148,6 +5307,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
5148 | rpc_put_task(task); | 5307 | rpc_put_task(task); |
5149 | out: | 5308 | out: |
5150 | request->fl_flags = fl_flags; | 5309 | request->fl_flags = fl_flags; |
5310 | trace_nfs4_unlock(request, state, F_SETLK, status); | ||
5151 | return status; | 5311 | return status; |
5152 | } | 5312 | } |
5153 | 5313 | ||
@@ -5333,7 +5493,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
5333 | return -ENOMEM; | 5493 | return -ENOMEM; |
5334 | if (IS_SETLKW(cmd)) | 5494 | if (IS_SETLKW(cmd)) |
5335 | data->arg.block = 1; | 5495 | data->arg.block = 1; |
5336 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | 5496 | nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); |
5337 | msg.rpc_argp = &data->arg; | 5497 | msg.rpc_argp = &data->arg; |
5338 | msg.rpc_resp = &data->res; | 5498 | msg.rpc_resp = &data->res; |
5339 | task_setup_data.callback_data = data; | 5499 | task_setup_data.callback_data = data; |
@@ -5371,6 +5531,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
5371 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 5531 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
5372 | return 0; | 5532 | return 0; |
5373 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); | 5533 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); |
5534 | trace_nfs4_lock_reclaim(request, state, F_SETLK, err); | ||
5374 | if (err != -NFS4ERR_DELAY) | 5535 | if (err != -NFS4ERR_DELAY) |
5375 | break; | 5536 | break; |
5376 | nfs4_handle_exception(server, err, &exception); | 5537 | nfs4_handle_exception(server, err, &exception); |
@@ -5389,10 +5550,15 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
5389 | err = nfs4_set_lock_state(state, request); | 5550 | err = nfs4_set_lock_state(state, request); |
5390 | if (err != 0) | 5551 | if (err != 0) |
5391 | return err; | 5552 | return err; |
5553 | if (!recover_lost_locks) { | ||
5554 | set_bit(NFS_LOCK_LOST, &request->fl_u.nfs4_fl.owner->ls_flags); | ||
5555 | return 0; | ||
5556 | } | ||
5392 | do { | 5557 | do { |
5393 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 5558 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
5394 | return 0; | 5559 | return 0; |
5395 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED); | 5560 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED); |
5561 | trace_nfs4_lock_expired(request, state, F_SETLK, err); | ||
5396 | switch (err) { | 5562 | switch (err) { |
5397 | default: | 5563 | default: |
5398 | goto out; | 5564 | goto out; |
@@ -5428,6 +5594,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
5428 | status = nfs41_test_stateid(server, | 5594 | status = nfs41_test_stateid(server, |
5429 | &lsp->ls_stateid, | 5595 | &lsp->ls_stateid, |
5430 | cred); | 5596 | cred); |
5597 | trace_nfs4_test_lock_stateid(state, lsp, status); | ||
5431 | if (status != NFS_OK) { | 5598 | if (status != NFS_OK) { |
5432 | /* Free the stateid unless the server | 5599 | /* Free the stateid unless the server |
5433 | * informs us the stateid is unrecognized. */ | 5600 | * informs us the stateid is unrecognized. */ |
@@ -5515,6 +5682,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
5515 | 5682 | ||
5516 | do { | 5683 | do { |
5517 | err = _nfs4_proc_setlk(state, cmd, request); | 5684 | err = _nfs4_proc_setlk(state, cmd, request); |
5685 | trace_nfs4_set_lock(request, state, cmd, err); | ||
5518 | if (err == -NFS4ERR_DENIED) | 5686 | if (err == -NFS4ERR_DENIED) |
5519 | err = -EAGAIN; | 5687 | err = -EAGAIN; |
5520 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | 5688 | err = nfs4_handle_exception(NFS_SERVER(state->inode), |
@@ -5597,8 +5765,23 @@ struct nfs_release_lockowner_data { | |||
5597 | struct nfs4_lock_state *lsp; | 5765 | struct nfs4_lock_state *lsp; |
5598 | struct nfs_server *server; | 5766 | struct nfs_server *server; |
5599 | struct nfs_release_lockowner_args args; | 5767 | struct nfs_release_lockowner_args args; |
5768 | struct nfs4_sequence_args seq_args; | ||
5769 | struct nfs4_sequence_res seq_res; | ||
5600 | }; | 5770 | }; |
5601 | 5771 | ||
5772 | static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata) | ||
5773 | { | ||
5774 | struct nfs_release_lockowner_data *data = calldata; | ||
5775 | nfs40_setup_sequence(data->server, | ||
5776 | &data->seq_args, &data->seq_res, task); | ||
5777 | } | ||
5778 | |||
5779 | static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) | ||
5780 | { | ||
5781 | struct nfs_release_lockowner_data *data = calldata; | ||
5782 | nfs40_sequence_done(task, &data->seq_res); | ||
5783 | } | ||
5784 | |||
5602 | static void nfs4_release_lockowner_release(void *calldata) | 5785 | static void nfs4_release_lockowner_release(void *calldata) |
5603 | { | 5786 | { |
5604 | struct nfs_release_lockowner_data *data = calldata; | 5787 | struct nfs_release_lockowner_data *data = calldata; |
@@ -5607,6 +5790,8 @@ static void nfs4_release_lockowner_release(void *calldata) | |||
5607 | } | 5790 | } |
5608 | 5791 | ||
5609 | static const struct rpc_call_ops nfs4_release_lockowner_ops = { | 5792 | static const struct rpc_call_ops nfs4_release_lockowner_ops = { |
5793 | .rpc_call_prepare = nfs4_release_lockowner_prepare, | ||
5794 | .rpc_call_done = nfs4_release_lockowner_done, | ||
5610 | .rpc_release = nfs4_release_lockowner_release, | 5795 | .rpc_release = nfs4_release_lockowner_release, |
5611 | }; | 5796 | }; |
5612 | 5797 | ||
@@ -5619,14 +5804,17 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st | |||
5619 | 5804 | ||
5620 | if (server->nfs_client->cl_mvops->minor_version != 0) | 5805 | if (server->nfs_client->cl_mvops->minor_version != 0) |
5621 | return -EINVAL; | 5806 | return -EINVAL; |
5807 | |||
5622 | data = kmalloc(sizeof(*data), GFP_NOFS); | 5808 | data = kmalloc(sizeof(*data), GFP_NOFS); |
5623 | if (!data) | 5809 | if (!data) |
5624 | return -ENOMEM; | 5810 | return -ENOMEM; |
5811 | nfs4_init_sequence(&data->seq_args, &data->seq_res, 0); | ||
5625 | data->lsp = lsp; | 5812 | data->lsp = lsp; |
5626 | data->server = server; | 5813 | data->server = server; |
5627 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; | 5814 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; |
5628 | data->args.lock_owner.id = lsp->ls_seqid.owner_id; | 5815 | data->args.lock_owner.id = lsp->ls_seqid.owner_id; |
5629 | data->args.lock_owner.s_dev = server->s_dev; | 5816 | data->args.lock_owner.s_dev = server->s_dev; |
5817 | |||
5630 | msg.rpc_argp = &data->args; | 5818 | msg.rpc_argp = &data->args; |
5631 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); | 5819 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); |
5632 | return 0; | 5820 | return 0; |
@@ -5781,14 +5969,23 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
5781 | struct nfs4_exception exception = { }; | 5969 | struct nfs4_exception exception = { }; |
5782 | int err; | 5970 | int err; |
5783 | do { | 5971 | do { |
5784 | err = nfs4_handle_exception(NFS_SERVER(dir), | 5972 | err = _nfs4_proc_fs_locations(client, dir, name, |
5785 | _nfs4_proc_fs_locations(client, dir, name, fs_locations, page), | 5973 | fs_locations, page); |
5974 | trace_nfs4_get_fs_locations(dir, name, err); | ||
5975 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
5786 | &exception); | 5976 | &exception); |
5787 | } while (exception.retry); | 5977 | } while (exception.retry); |
5788 | return err; | 5978 | return err; |
5789 | } | 5979 | } |
5790 | 5980 | ||
5791 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | 5981 | /** |
5982 | * If 'use_integrity' is true and the state managment nfs_client | ||
5983 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient | ||
5984 | * and the machine credential as per RFC3530bis and RFC5661 Security | ||
5985 | * Considerations sections. Otherwise, just use the user cred with the | ||
5986 | * filesystem's rpc_client. | ||
5987 | */ | ||
5988 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors, bool use_integrity) | ||
5792 | { | 5989 | { |
5793 | int status; | 5990 | int status; |
5794 | struct nfs4_secinfo_arg args = { | 5991 | struct nfs4_secinfo_arg args = { |
@@ -5803,10 +6000,25 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct | |||
5803 | .rpc_argp = &args, | 6000 | .rpc_argp = &args, |
5804 | .rpc_resp = &res, | 6001 | .rpc_resp = &res, |
5805 | }; | 6002 | }; |
6003 | struct rpc_clnt *clnt = NFS_SERVER(dir)->client; | ||
6004 | |||
6005 | if (use_integrity) { | ||
6006 | clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient; | ||
6007 | msg.rpc_cred = nfs4_get_clid_cred(NFS_SERVER(dir)->nfs_client); | ||
6008 | } | ||
5806 | 6009 | ||
5807 | dprintk("NFS call secinfo %s\n", name->name); | 6010 | dprintk("NFS call secinfo %s\n", name->name); |
5808 | status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); | 6011 | |
6012 | nfs4_state_protect(NFS_SERVER(dir)->nfs_client, | ||
6013 | NFS_SP4_MACH_CRED_SECINFO, &clnt, &msg); | ||
6014 | |||
6015 | status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args, | ||
6016 | &res.seq_res, 0); | ||
5809 | dprintk("NFS reply secinfo: %d\n", status); | 6017 | dprintk("NFS reply secinfo: %d\n", status); |
6018 | |||
6019 | if (msg.rpc_cred) | ||
6020 | put_rpccred(msg.rpc_cred); | ||
6021 | |||
5810 | return status; | 6022 | return status; |
5811 | } | 6023 | } |
5812 | 6024 | ||
@@ -5816,8 +6028,23 @@ int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, | |||
5816 | struct nfs4_exception exception = { }; | 6028 | struct nfs4_exception exception = { }; |
5817 | int err; | 6029 | int err; |
5818 | do { | 6030 | do { |
5819 | err = nfs4_handle_exception(NFS_SERVER(dir), | 6031 | err = -NFS4ERR_WRONGSEC; |
5820 | _nfs4_proc_secinfo(dir, name, flavors), | 6032 | |
6033 | /* try to use integrity protection with machine cred */ | ||
6034 | if (_nfs4_is_integrity_protected(NFS_SERVER(dir)->nfs_client)) | ||
6035 | err = _nfs4_proc_secinfo(dir, name, flavors, true); | ||
6036 | |||
6037 | /* | ||
6038 | * if unable to use integrity protection, or SECINFO with | ||
6039 | * integrity protection returns NFS4ERR_WRONGSEC (which is | ||
6040 | * disallowed by spec, but exists in deployed servers) use | ||
6041 | * the current filesystem's rpc_client and the user cred. | ||
6042 | */ | ||
6043 | if (err == -NFS4ERR_WRONGSEC) | ||
6044 | err = _nfs4_proc_secinfo(dir, name, flavors, false); | ||
6045 | |||
6046 | trace_nfs4_secinfo(dir, name, err); | ||
6047 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
5821 | &exception); | 6048 | &exception); |
5822 | } while (exception.retry); | 6049 | } while (exception.retry); |
5823 | return err; | 6050 | return err; |
@@ -5881,6 +6108,7 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred | |||
5881 | } | 6108 | } |
5882 | 6109 | ||
5883 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6110 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6111 | trace_nfs4_bind_conn_to_session(clp, status); | ||
5884 | if (status == 0) { | 6112 | if (status == 0) { |
5885 | if (memcmp(res.session->sess_id.data, | 6113 | if (memcmp(res.session->sess_id.data, |
5886 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { | 6114 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { |
@@ -5909,16 +6137,124 @@ out: | |||
5909 | } | 6137 | } |
5910 | 6138 | ||
5911 | /* | 6139 | /* |
5912 | * nfs4_proc_exchange_id() | 6140 | * Minimum set of SP4_MACH_CRED operations from RFC 5661 in the enforce map |
6141 | * and operations we'd like to see to enable certain features in the allow map | ||
6142 | */ | ||
6143 | static const struct nfs41_state_protection nfs4_sp4_mach_cred_request = { | ||
6144 | .how = SP4_MACH_CRED, | ||
6145 | .enforce.u.words = { | ||
6146 | [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) | | ||
6147 | 1 << (OP_EXCHANGE_ID - 32) | | ||
6148 | 1 << (OP_CREATE_SESSION - 32) | | ||
6149 | 1 << (OP_DESTROY_SESSION - 32) | | ||
6150 | 1 << (OP_DESTROY_CLIENTID - 32) | ||
6151 | }, | ||
6152 | .allow.u.words = { | ||
6153 | [0] = 1 << (OP_CLOSE) | | ||
6154 | 1 << (OP_LOCKU), | ||
6155 | [1] = 1 << (OP_SECINFO - 32) | | ||
6156 | 1 << (OP_SECINFO_NO_NAME - 32) | | ||
6157 | 1 << (OP_TEST_STATEID - 32) | | ||
6158 | 1 << (OP_FREE_STATEID - 32) | ||
6159 | } | ||
6160 | }; | ||
6161 | |||
6162 | /* | ||
6163 | * Select the state protection mode for client `clp' given the server results | ||
6164 | * from exchange_id in `sp'. | ||
5913 | * | 6165 | * |
5914 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | 6166 | * Returns 0 on success, negative errno otherwise. |
6167 | */ | ||
6168 | static int nfs4_sp4_select_mode(struct nfs_client *clp, | ||
6169 | struct nfs41_state_protection *sp) | ||
6170 | { | ||
6171 | static const u32 supported_enforce[NFS4_OP_MAP_NUM_WORDS] = { | ||
6172 | [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) | | ||
6173 | 1 << (OP_EXCHANGE_ID - 32) | | ||
6174 | 1 << (OP_CREATE_SESSION - 32) | | ||
6175 | 1 << (OP_DESTROY_SESSION - 32) | | ||
6176 | 1 << (OP_DESTROY_CLIENTID - 32) | ||
6177 | }; | ||
6178 | unsigned int i; | ||
6179 | |||
6180 | if (sp->how == SP4_MACH_CRED) { | ||
6181 | /* Print state protect result */ | ||
6182 | dfprintk(MOUNT, "Server SP4_MACH_CRED support:\n"); | ||
6183 | for (i = 0; i <= LAST_NFS4_OP; i++) { | ||
6184 | if (test_bit(i, sp->enforce.u.longs)) | ||
6185 | dfprintk(MOUNT, " enforce op %d\n", i); | ||
6186 | if (test_bit(i, sp->allow.u.longs)) | ||
6187 | dfprintk(MOUNT, " allow op %d\n", i); | ||
6188 | } | ||
6189 | |||
6190 | /* make sure nothing is on enforce list that isn't supported */ | ||
6191 | for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) { | ||
6192 | if (sp->enforce.u.words[i] & ~supported_enforce[i]) { | ||
6193 | dfprintk(MOUNT, "sp4_mach_cred: disabled\n"); | ||
6194 | return -EINVAL; | ||
6195 | } | ||
6196 | } | ||
6197 | |||
6198 | /* | ||
6199 | * Minimal mode - state operations are allowed to use machine | ||
6200 | * credential. Note this already happens by default, so the | ||
6201 | * client doesn't have to do anything more than the negotiation. | ||
6202 | * | ||
6203 | * NOTE: we don't care if EXCHANGE_ID is in the list - | ||
6204 | * we're already using the machine cred for exchange_id | ||
6205 | * and will never use a different cred. | ||
6206 | */ | ||
6207 | if (test_bit(OP_BIND_CONN_TO_SESSION, sp->enforce.u.longs) && | ||
6208 | test_bit(OP_CREATE_SESSION, sp->enforce.u.longs) && | ||
6209 | test_bit(OP_DESTROY_SESSION, sp->enforce.u.longs) && | ||
6210 | test_bit(OP_DESTROY_CLIENTID, sp->enforce.u.longs)) { | ||
6211 | dfprintk(MOUNT, "sp4_mach_cred:\n"); | ||
6212 | dfprintk(MOUNT, " minimal mode enabled\n"); | ||
6213 | set_bit(NFS_SP4_MACH_CRED_MINIMAL, &clp->cl_sp4_flags); | ||
6214 | } else { | ||
6215 | dfprintk(MOUNT, "sp4_mach_cred: disabled\n"); | ||
6216 | return -EINVAL; | ||
6217 | } | ||
6218 | |||
6219 | if (test_bit(OP_CLOSE, sp->allow.u.longs) && | ||
6220 | test_bit(OP_LOCKU, sp->allow.u.longs)) { | ||
6221 | dfprintk(MOUNT, " cleanup mode enabled\n"); | ||
6222 | set_bit(NFS_SP4_MACH_CRED_CLEANUP, &clp->cl_sp4_flags); | ||
6223 | } | ||
6224 | |||
6225 | if (test_bit(OP_SECINFO, sp->allow.u.longs) && | ||
6226 | test_bit(OP_SECINFO_NO_NAME, sp->allow.u.longs)) { | ||
6227 | dfprintk(MOUNT, " secinfo mode enabled\n"); | ||
6228 | set_bit(NFS_SP4_MACH_CRED_SECINFO, &clp->cl_sp4_flags); | ||
6229 | } | ||
6230 | |||
6231 | if (test_bit(OP_TEST_STATEID, sp->allow.u.longs) && | ||
6232 | test_bit(OP_FREE_STATEID, sp->allow.u.longs)) { | ||
6233 | dfprintk(MOUNT, " stateid mode enabled\n"); | ||
6234 | set_bit(NFS_SP4_MACH_CRED_STATEID, &clp->cl_sp4_flags); | ||
6235 | } | ||
6236 | |||
6237 | if (test_bit(OP_WRITE, sp->allow.u.longs)) { | ||
6238 | dfprintk(MOUNT, " write mode enabled\n"); | ||
6239 | set_bit(NFS_SP4_MACH_CRED_WRITE, &clp->cl_sp4_flags); | ||
6240 | } | ||
6241 | |||
6242 | if (test_bit(OP_COMMIT, sp->allow.u.longs)) { | ||
6243 | dfprintk(MOUNT, " commit mode enabled\n"); | ||
6244 | set_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags); | ||
6245 | } | ||
6246 | } | ||
6247 | |||
6248 | return 0; | ||
6249 | } | ||
6250 | |||
6251 | /* | ||
6252 | * _nfs4_proc_exchange_id() | ||
5915 | * | 6253 | * |
5916 | * Since the clientid has expired, all compounds using sessions | 6254 | * Wrapper for EXCHANGE_ID operation. |
5917 | * associated with the stale clientid will be returning | ||
5918 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | ||
5919 | * be in some phase of session reset. | ||
5920 | */ | 6255 | */ |
5921 | int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | 6256 | static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, |
6257 | u32 sp4_how) | ||
5922 | { | 6258 | { |
5923 | nfs4_verifier verifier; | 6259 | nfs4_verifier verifier; |
5924 | struct nfs41_exchange_id_args args = { | 6260 | struct nfs41_exchange_id_args args = { |
@@ -5965,10 +6301,30 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5965 | goto out_server_scope; | 6301 | goto out_server_scope; |
5966 | } | 6302 | } |
5967 | 6303 | ||
6304 | switch (sp4_how) { | ||
6305 | case SP4_NONE: | ||
6306 | args.state_protect.how = SP4_NONE; | ||
6307 | break; | ||
6308 | |||
6309 | case SP4_MACH_CRED: | ||
6310 | args.state_protect = nfs4_sp4_mach_cred_request; | ||
6311 | break; | ||
6312 | |||
6313 | default: | ||
6314 | /* unsupported! */ | ||
6315 | WARN_ON_ONCE(1); | ||
6316 | status = -EINVAL; | ||
6317 | goto out_server_scope; | ||
6318 | } | ||
6319 | |||
5968 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6320 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6321 | trace_nfs4_exchange_id(clp, status); | ||
5969 | if (status == 0) | 6322 | if (status == 0) |
5970 | status = nfs4_check_cl_exchange_flags(res.flags); | 6323 | status = nfs4_check_cl_exchange_flags(res.flags); |
5971 | 6324 | ||
6325 | if (status == 0) | ||
6326 | status = nfs4_sp4_select_mode(clp, &res.state_protect); | ||
6327 | |||
5972 | if (status == 0) { | 6328 | if (status == 0) { |
5973 | clp->cl_clientid = res.clientid; | 6329 | clp->cl_clientid = res.clientid; |
5974 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); | 6330 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); |
@@ -6015,6 +6371,35 @@ out: | |||
6015 | return status; | 6371 | return status; |
6016 | } | 6372 | } |
6017 | 6373 | ||
6374 | /* | ||
6375 | * nfs4_proc_exchange_id() | ||
6376 | * | ||
6377 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | ||
6378 | * | ||
6379 | * Since the clientid has expired, all compounds using sessions | ||
6380 | * associated with the stale clientid will be returning | ||
6381 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | ||
6382 | * be in some phase of session reset. | ||
6383 | * | ||
6384 | * Will attempt to negotiate SP4_MACH_CRED if krb5i / krb5p auth is used. | ||
6385 | */ | ||
6386 | int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | ||
6387 | { | ||
6388 | rpc_authflavor_t authflavor = clp->cl_rpcclient->cl_auth->au_flavor; | ||
6389 | int status; | ||
6390 | |||
6391 | /* try SP4_MACH_CRED if krb5i/p */ | ||
6392 | if (authflavor == RPC_AUTH_GSS_KRB5I || | ||
6393 | authflavor == RPC_AUTH_GSS_KRB5P) { | ||
6394 | status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED); | ||
6395 | if (!status) | ||
6396 | return 0; | ||
6397 | } | ||
6398 | |||
6399 | /* try SP4_NONE */ | ||
6400 | return _nfs4_proc_exchange_id(clp, cred, SP4_NONE); | ||
6401 | } | ||
6402 | |||
6018 | static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, | 6403 | static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, |
6019 | struct rpc_cred *cred) | 6404 | struct rpc_cred *cred) |
6020 | { | 6405 | { |
@@ -6026,6 +6411,7 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, | |||
6026 | int status; | 6411 | int status; |
6027 | 6412 | ||
6028 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6413 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6414 | trace_nfs4_destroy_clientid(clp, status); | ||
6029 | if (status) | 6415 | if (status) |
6030 | dprintk("NFS: Got error %d from the server %s on " | 6416 | dprintk("NFS: Got error %d from the server %s on " |
6031 | "DESTROY_CLIENTID.", status, clp->cl_hostname); | 6417 | "DESTROY_CLIENTID.", status, clp->cl_hostname); |
@@ -6063,7 +6449,7 @@ int nfs4_destroy_clientid(struct nfs_client *clp) | |||
6063 | goto out; | 6449 | goto out; |
6064 | if (clp->cl_preserve_clid) | 6450 | if (clp->cl_preserve_clid) |
6065 | goto out; | 6451 | goto out; |
6066 | cred = nfs4_get_exchange_id_cred(clp); | 6452 | cred = nfs4_get_clid_cred(clp); |
6067 | ret = nfs4_proc_destroy_clientid(clp, cred); | 6453 | ret = nfs4_proc_destroy_clientid(clp, cred); |
6068 | if (cred) | 6454 | if (cred) |
6069 | put_rpccred(cred); | 6455 | put_rpccred(cred); |
@@ -6155,7 +6541,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
6155 | }; | 6541 | }; |
6156 | int status; | 6542 | int status; |
6157 | 6543 | ||
6158 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); | 6544 | nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); |
6159 | nfs4_set_sequence_privileged(&args.la_seq_args); | 6545 | nfs4_set_sequence_privileged(&args.la_seq_args); |
6160 | dprintk("--> %s\n", __func__); | 6546 | dprintk("--> %s\n", __func__); |
6161 | task = rpc_run_task(&task_setup); | 6547 | task = rpc_run_task(&task_setup); |
@@ -6289,6 +6675,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, | |||
6289 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); | 6675 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); |
6290 | 6676 | ||
6291 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6677 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6678 | trace_nfs4_create_session(clp, status); | ||
6292 | 6679 | ||
6293 | if (!status) { | 6680 | if (!status) { |
6294 | /* Verify the session's negotiated channel_attrs values */ | 6681 | /* Verify the session's negotiated channel_attrs values */ |
@@ -6352,6 +6739,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
6352 | return status; | 6739 | return status; |
6353 | 6740 | ||
6354 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6741 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6742 | trace_nfs4_destroy_session(session->clp, status); | ||
6355 | 6743 | ||
6356 | if (status) | 6744 | if (status) |
6357 | dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " | 6745 | dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " |
@@ -6401,6 +6789,7 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data) | |||
6401 | if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp)) | 6789 | if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp)) |
6402 | return; | 6790 | return; |
6403 | 6791 | ||
6792 | trace_nfs4_sequence(clp, task->tk_status); | ||
6404 | if (task->tk_status < 0) { | 6793 | if (task->tk_status < 0) { |
6405 | dprintk("%s ERROR %d\n", __func__, task->tk_status); | 6794 | dprintk("%s ERROR %d\n", __func__, task->tk_status); |
6406 | if (atomic_read(&clp->cl_count) == 1) | 6795 | if (atomic_read(&clp->cl_count) == 1) |
@@ -6458,7 +6847,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, | |||
6458 | nfs_put_client(clp); | 6847 | nfs_put_client(clp); |
6459 | return ERR_PTR(-ENOMEM); | 6848 | return ERR_PTR(-ENOMEM); |
6460 | } | 6849 | } |
6461 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); | 6850 | nfs4_init_sequence(&calldata->args, &calldata->res, 0); |
6462 | if (is_privileged) | 6851 | if (is_privileged) |
6463 | nfs4_set_sequence_privileged(&calldata->args); | 6852 | nfs4_set_sequence_privileged(&calldata->args); |
6464 | msg.rpc_argp = &calldata->args; | 6853 | msg.rpc_argp = &calldata->args; |
@@ -6553,6 +6942,7 @@ static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) | |||
6553 | if (!nfs41_sequence_done(task, res)) | 6942 | if (!nfs41_sequence_done(task, res)) |
6554 | return; | 6943 | return; |
6555 | 6944 | ||
6945 | trace_nfs4_reclaim_complete(clp, task->tk_status); | ||
6556 | if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) { | 6946 | if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) { |
6557 | rpc_restart_call_prepare(task); | 6947 | rpc_restart_call_prepare(task); |
6558 | return; | 6948 | return; |
@@ -6600,7 +6990,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp, | |||
6600 | calldata->clp = clp; | 6990 | calldata->clp = clp; |
6601 | calldata->arg.one_fs = 0; | 6991 | calldata->arg.one_fs = 0; |
6602 | 6992 | ||
6603 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); | 6993 | nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); |
6604 | nfs4_set_sequence_privileged(&calldata->arg.seq_args); | 6994 | nfs4_set_sequence_privileged(&calldata->arg.seq_args); |
6605 | msg.rpc_argp = &calldata->arg; | 6995 | msg.rpc_argp = &calldata->arg; |
6606 | msg.rpc_resp = &calldata->res; | 6996 | msg.rpc_resp = &calldata->res; |
@@ -6791,7 +7181,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6791 | 7181 | ||
6792 | lgp->res.layoutp = &lgp->args.layout; | 7182 | lgp->res.layoutp = &lgp->args.layout; |
6793 | lgp->res.seq_res.sr_slot = NULL; | 7183 | lgp->res.seq_res.sr_slot = NULL; |
6794 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 7184 | nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
6795 | 7185 | ||
6796 | /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ | 7186 | /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ |
6797 | pnfs_get_layout_hdr(NFS_I(inode)->layout); | 7187 | pnfs_get_layout_hdr(NFS_I(inode)->layout); |
@@ -6802,6 +7192,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6802 | status = nfs4_wait_for_completion_rpc_task(task); | 7192 | status = nfs4_wait_for_completion_rpc_task(task); |
6803 | if (status == 0) | 7193 | if (status == 0) |
6804 | status = task->tk_status; | 7194 | status = task->tk_status; |
7195 | trace_nfs4_layoutget(lgp->args.ctx, | ||
7196 | &lgp->args.range, | ||
7197 | &lgp->res.range, | ||
7198 | status); | ||
6805 | /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ | 7199 | /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ |
6806 | if (status == 0 && lgp->res.layoutp->len) | 7200 | if (status == 0 && lgp->res.layoutp->len) |
6807 | lseg = pnfs_layout_process(lgp); | 7201 | lseg = pnfs_layout_process(lgp); |
@@ -6874,7 +7268,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
6874 | .rpc_cred = lrp->cred, | 7268 | .rpc_cred = lrp->cred, |
6875 | }; | 7269 | }; |
6876 | struct rpc_task_setup task_setup_data = { | 7270 | struct rpc_task_setup task_setup_data = { |
6877 | .rpc_client = lrp->clp->cl_rpcclient, | 7271 | .rpc_client = NFS_SERVER(lrp->args.inode)->client, |
6878 | .rpc_message = &msg, | 7272 | .rpc_message = &msg, |
6879 | .callback_ops = &nfs4_layoutreturn_call_ops, | 7273 | .callback_ops = &nfs4_layoutreturn_call_ops, |
6880 | .callback_data = lrp, | 7274 | .callback_data = lrp, |
@@ -6882,11 +7276,12 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
6882 | int status; | 7276 | int status; |
6883 | 7277 | ||
6884 | dprintk("--> %s\n", __func__); | 7278 | dprintk("--> %s\n", __func__); |
6885 | nfs41_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); | 7279 | nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); |
6886 | task = rpc_run_task(&task_setup_data); | 7280 | task = rpc_run_task(&task_setup_data); |
6887 | if (IS_ERR(task)) | 7281 | if (IS_ERR(task)) |
6888 | return PTR_ERR(task); | 7282 | return PTR_ERR(task); |
6889 | status = task->tk_status; | 7283 | status = task->tk_status; |
7284 | trace_nfs4_layoutreturn(lrp->args.inode, status); | ||
6890 | dprintk("<-- %s status=%d\n", __func__, status); | 7285 | dprintk("<-- %s status=%d\n", __func__, status); |
6891 | rpc_put_task(task); | 7286 | rpc_put_task(task); |
6892 | return status; | 7287 | return status; |
@@ -7063,7 +7458,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
7063 | data->args.lastbytewritten, | 7458 | data->args.lastbytewritten, |
7064 | data->args.inode->i_ino); | 7459 | data->args.inode->i_ino); |
7065 | 7460 | ||
7066 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 7461 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
7067 | task = rpc_run_task(&task_setup_data); | 7462 | task = rpc_run_task(&task_setup_data); |
7068 | if (IS_ERR(task)) | 7463 | if (IS_ERR(task)) |
7069 | return PTR_ERR(task); | 7464 | return PTR_ERR(task); |
@@ -7073,15 +7468,21 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
7073 | if (status != 0) | 7468 | if (status != 0) |
7074 | goto out; | 7469 | goto out; |
7075 | status = task->tk_status; | 7470 | status = task->tk_status; |
7471 | trace_nfs4_layoutcommit(data->args.inode, status); | ||
7076 | out: | 7472 | out: |
7077 | dprintk("%s: status %d\n", __func__, status); | 7473 | dprintk("%s: status %d\n", __func__, status); |
7078 | rpc_put_task(task); | 7474 | rpc_put_task(task); |
7079 | return status; | 7475 | return status; |
7080 | } | 7476 | } |
7081 | 7477 | ||
7478 | /** | ||
7479 | * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if | ||
7480 | * possible) as per RFC3530bis and RFC5661 Security Considerations sections | ||
7481 | */ | ||
7082 | static int | 7482 | static int |
7083 | _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | 7483 | _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, |
7084 | struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) | 7484 | struct nfs_fsinfo *info, |
7485 | struct nfs4_secinfo_flavors *flavors, bool use_integrity) | ||
7085 | { | 7486 | { |
7086 | struct nfs41_secinfo_no_name_args args = { | 7487 | struct nfs41_secinfo_no_name_args args = { |
7087 | .style = SECINFO_STYLE_CURRENT_FH, | 7488 | .style = SECINFO_STYLE_CURRENT_FH, |
@@ -7094,7 +7495,23 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | |||
7094 | .rpc_argp = &args, | 7495 | .rpc_argp = &args, |
7095 | .rpc_resp = &res, | 7496 | .rpc_resp = &res, |
7096 | }; | 7497 | }; |
7097 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 7498 | struct rpc_clnt *clnt = server->client; |
7499 | int status; | ||
7500 | |||
7501 | if (use_integrity) { | ||
7502 | clnt = server->nfs_client->cl_rpcclient; | ||
7503 | msg.rpc_cred = nfs4_get_clid_cred(server->nfs_client); | ||
7504 | } | ||
7505 | |||
7506 | dprintk("--> %s\n", __func__); | ||
7507 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, | ||
7508 | &res.seq_res, 0); | ||
7509 | dprintk("<-- %s status=%d\n", __func__, status); | ||
7510 | |||
7511 | if (msg.rpc_cred) | ||
7512 | put_rpccred(msg.rpc_cred); | ||
7513 | |||
7514 | return status; | ||
7098 | } | 7515 | } |
7099 | 7516 | ||
7100 | static int | 7517 | static int |
@@ -7104,7 +7521,24 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | |||
7104 | struct nfs4_exception exception = { }; | 7521 | struct nfs4_exception exception = { }; |
7105 | int err; | 7522 | int err; |
7106 | do { | 7523 | do { |
7107 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); | 7524 | /* first try using integrity protection */ |
7525 | err = -NFS4ERR_WRONGSEC; | ||
7526 | |||
7527 | /* try to use integrity protection with machine cred */ | ||
7528 | if (_nfs4_is_integrity_protected(server->nfs_client)) | ||
7529 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, | ||
7530 | flavors, true); | ||
7531 | |||
7532 | /* | ||
7533 | * if unable to use integrity protection, or SECINFO with | ||
7534 | * integrity protection returns NFS4ERR_WRONGSEC (which is | ||
7535 | * disallowed by spec, but exists in deployed servers) use | ||
7536 | * the current filesystem's rpc_client and the user cred. | ||
7537 | */ | ||
7538 | if (err == -NFS4ERR_WRONGSEC) | ||
7539 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, | ||
7540 | flavors, false); | ||
7541 | |||
7108 | switch (err) { | 7542 | switch (err) { |
7109 | case 0: | 7543 | case 0: |
7110 | case -NFS4ERR_WRONGSEC: | 7544 | case -NFS4ERR_WRONGSEC: |
@@ -7174,11 +7608,15 @@ static int _nfs41_test_stateid(struct nfs_server *server, | |||
7174 | .rpc_resp = &res, | 7608 | .rpc_resp = &res, |
7175 | .rpc_cred = cred, | 7609 | .rpc_cred = cred, |
7176 | }; | 7610 | }; |
7611 | struct rpc_clnt *rpc_client = server->client; | ||
7612 | |||
7613 | nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID, | ||
7614 | &rpc_client, &msg); | ||
7177 | 7615 | ||
7178 | dprintk("NFS call test_stateid %p\n", stateid); | 7616 | dprintk("NFS call test_stateid %p\n", stateid); |
7179 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 7617 | nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); |
7180 | nfs4_set_sequence_privileged(&args.seq_args); | 7618 | nfs4_set_sequence_privileged(&args.seq_args); |
7181 | status = nfs4_call_sync_sequence(server->client, server, &msg, | 7619 | status = nfs4_call_sync_sequence(rpc_client, server, &msg, |
7182 | &args.seq_args, &res.seq_res); | 7620 | &args.seq_args, &res.seq_res); |
7183 | if (status != NFS_OK) { | 7621 | if (status != NFS_OK) { |
7184 | dprintk("NFS reply test_stateid: failed, %d\n", status); | 7622 | dprintk("NFS reply test_stateid: failed, %d\n", status); |
@@ -7247,7 +7685,7 @@ static void nfs41_free_stateid_release(void *calldata) | |||
7247 | kfree(calldata); | 7685 | kfree(calldata); |
7248 | } | 7686 | } |
7249 | 7687 | ||
7250 | const struct rpc_call_ops nfs41_free_stateid_ops = { | 7688 | static const struct rpc_call_ops nfs41_free_stateid_ops = { |
7251 | .rpc_call_prepare = nfs41_free_stateid_prepare, | 7689 | .rpc_call_prepare = nfs41_free_stateid_prepare, |
7252 | .rpc_call_done = nfs41_free_stateid_done, | 7690 | .rpc_call_done = nfs41_free_stateid_done, |
7253 | .rpc_release = nfs41_free_stateid_release, | 7691 | .rpc_release = nfs41_free_stateid_release, |
@@ -7270,6 +7708,9 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
7270 | }; | 7708 | }; |
7271 | struct nfs_free_stateid_data *data; | 7709 | struct nfs_free_stateid_data *data; |
7272 | 7710 | ||
7711 | nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID, | ||
7712 | &task_setup.rpc_client, &msg); | ||
7713 | |||
7273 | dprintk("NFS call free_stateid %p\n", stateid); | 7714 | dprintk("NFS call free_stateid %p\n", stateid); |
7274 | data = kmalloc(sizeof(*data), GFP_NOFS); | 7715 | data = kmalloc(sizeof(*data), GFP_NOFS); |
7275 | if (!data) | 7716 | if (!data) |
@@ -7281,7 +7722,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
7281 | 7722 | ||
7282 | msg.rpc_argp = &data->args; | 7723 | msg.rpc_argp = &data->args; |
7283 | msg.rpc_resp = &data->res; | 7724 | msg.rpc_resp = &data->res; |
7284 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | 7725 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); |
7285 | if (privileged) | 7726 | if (privileged) |
7286 | nfs4_set_sequence_privileged(&data->args.seq_args); | 7727 | nfs4_set_sequence_privileged(&data->args.seq_args); |
7287 | 7728 | ||
@@ -7357,7 +7798,6 @@ static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | |||
7357 | .recover_open = nfs4_open_reclaim, | 7798 | .recover_open = nfs4_open_reclaim, |
7358 | .recover_lock = nfs4_lock_reclaim, | 7799 | .recover_lock = nfs4_lock_reclaim, |
7359 | .establish_clid = nfs4_init_clientid, | 7800 | .establish_clid = nfs4_init_clientid, |
7360 | .get_clid_cred = nfs4_get_setclientid_cred, | ||
7361 | .detect_trunking = nfs40_discover_server_trunking, | 7801 | .detect_trunking = nfs40_discover_server_trunking, |
7362 | }; | 7802 | }; |
7363 | 7803 | ||
@@ -7368,7 +7808,6 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | |||
7368 | .recover_open = nfs4_open_reclaim, | 7808 | .recover_open = nfs4_open_reclaim, |
7369 | .recover_lock = nfs4_lock_reclaim, | 7809 | .recover_lock = nfs4_lock_reclaim, |
7370 | .establish_clid = nfs41_init_clientid, | 7810 | .establish_clid = nfs41_init_clientid, |
7371 | .get_clid_cred = nfs4_get_exchange_id_cred, | ||
7372 | .reclaim_complete = nfs41_proc_reclaim_complete, | 7811 | .reclaim_complete = nfs41_proc_reclaim_complete, |
7373 | .detect_trunking = nfs41_discover_server_trunking, | 7812 | .detect_trunking = nfs41_discover_server_trunking, |
7374 | }; | 7813 | }; |
@@ -7380,7 +7819,6 @@ static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { | |||
7380 | .recover_open = nfs4_open_expired, | 7819 | .recover_open = nfs4_open_expired, |
7381 | .recover_lock = nfs4_lock_expired, | 7820 | .recover_lock = nfs4_lock_expired, |
7382 | .establish_clid = nfs4_init_clientid, | 7821 | .establish_clid = nfs4_init_clientid, |
7383 | .get_clid_cred = nfs4_get_setclientid_cred, | ||
7384 | }; | 7822 | }; |
7385 | 7823 | ||
7386 | #if defined(CONFIG_NFS_V4_1) | 7824 | #if defined(CONFIG_NFS_V4_1) |
@@ -7390,7 +7828,6 @@ static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { | |||
7390 | .recover_open = nfs41_open_expired, | 7828 | .recover_open = nfs41_open_expired, |
7391 | .recover_lock = nfs41_lock_expired, | 7829 | .recover_lock = nfs41_lock_expired, |
7392 | .establish_clid = nfs41_init_clientid, | 7830 | .establish_clid = nfs41_init_clientid, |
7393 | .get_clid_cred = nfs4_get_exchange_id_cred, | ||
7394 | }; | 7831 | }; |
7395 | #endif /* CONFIG_NFS_V4_1 */ | 7832 | #endif /* CONFIG_NFS_V4_1 */ |
7396 | 7833 | ||
@@ -7414,10 +7851,12 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
7414 | | NFS_CAP_ATOMIC_OPEN | 7851 | | NFS_CAP_ATOMIC_OPEN |
7415 | | NFS_CAP_CHANGE_ATTR | 7852 | | NFS_CAP_CHANGE_ATTR |
7416 | | NFS_CAP_POSIX_LOCK, | 7853 | | NFS_CAP_POSIX_LOCK, |
7417 | .call_sync = _nfs4_call_sync, | 7854 | .init_client = nfs40_init_client, |
7855 | .shutdown_client = nfs40_shutdown_client, | ||
7418 | .match_stateid = nfs4_match_stateid, | 7856 | .match_stateid = nfs4_match_stateid, |
7419 | .find_root_sec = nfs4_find_root_sec, | 7857 | .find_root_sec = nfs4_find_root_sec, |
7420 | .free_lock_state = nfs4_release_lockowner, | 7858 | .free_lock_state = nfs4_release_lockowner, |
7859 | .call_sync_ops = &nfs40_call_sync_ops, | ||
7421 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, | 7860 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, |
7422 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, | 7861 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, |
7423 | .state_renewal_ops = &nfs40_state_renewal_ops, | 7862 | .state_renewal_ops = &nfs40_state_renewal_ops, |
@@ -7432,10 +7871,12 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
7432 | | NFS_CAP_POSIX_LOCK | 7871 | | NFS_CAP_POSIX_LOCK |
7433 | | NFS_CAP_STATEID_NFSV41 | 7872 | | NFS_CAP_STATEID_NFSV41 |
7434 | | NFS_CAP_ATOMIC_OPEN_V1, | 7873 | | NFS_CAP_ATOMIC_OPEN_V1, |
7435 | .call_sync = nfs4_call_sync_sequence, | 7874 | .init_client = nfs41_init_client, |
7875 | .shutdown_client = nfs41_shutdown_client, | ||
7436 | .match_stateid = nfs41_match_stateid, | 7876 | .match_stateid = nfs41_match_stateid, |
7437 | .find_root_sec = nfs41_find_root_sec, | 7877 | .find_root_sec = nfs41_find_root_sec, |
7438 | .free_lock_state = nfs41_free_lock_state, | 7878 | .free_lock_state = nfs41_free_lock_state, |
7879 | .call_sync_ops = &nfs41_call_sync_ops, | ||
7439 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 7880 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
7440 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 7881 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
7441 | .state_renewal_ops = &nfs41_state_renewal_ops, | 7882 | .state_renewal_ops = &nfs41_state_renewal_ops, |
@@ -7451,10 +7892,12 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
7451 | | NFS_CAP_POSIX_LOCK | 7892 | | NFS_CAP_POSIX_LOCK |
7452 | | NFS_CAP_STATEID_NFSV41 | 7893 | | NFS_CAP_STATEID_NFSV41 |
7453 | | NFS_CAP_ATOMIC_OPEN_V1, | 7894 | | NFS_CAP_ATOMIC_OPEN_V1, |
7454 | .call_sync = nfs4_call_sync_sequence, | 7895 | .init_client = nfs41_init_client, |
7896 | .shutdown_client = nfs41_shutdown_client, | ||
7455 | .match_stateid = nfs41_match_stateid, | 7897 | .match_stateid = nfs41_match_stateid, |
7456 | .find_root_sec = nfs41_find_root_sec, | 7898 | .find_root_sec = nfs41_find_root_sec, |
7457 | .free_lock_state = nfs41_free_lock_state, | 7899 | .free_lock_state = nfs41_free_lock_state, |
7900 | .call_sync_ops = &nfs41_call_sync_ops, | ||
7458 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 7901 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
7459 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 7902 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
7460 | .state_renewal_ops = &nfs41_state_renewal_ops, | 7903 | .state_renewal_ops = &nfs41_state_renewal_ops, |
@@ -7471,7 +7914,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | |||
7471 | #endif | 7914 | #endif |
7472 | }; | 7915 | }; |
7473 | 7916 | ||
7474 | const struct inode_operations nfs4_dir_inode_operations = { | 7917 | static const struct inode_operations nfs4_dir_inode_operations = { |
7475 | .create = nfs_create, | 7918 | .create = nfs_create, |
7476 | .lookup = nfs_lookup, | 7919 | .lookup = nfs_lookup, |
7477 | .atomic_open = nfs_atomic_open, | 7920 | .atomic_open = nfs_atomic_open, |