Commit 433fbe4c8837e3cc2ba6a6374edf28737d01a2e9
1 parent
26e976a884
NFSv4: State recovery cleanup
Use wait_on_bit() when waiting for state recovery to complete. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 3 changed files with 28 additions and 25 deletions Side-by-side Diff
fs/nfs/nfs4_fs.h
... | ... | @@ -38,7 +38,7 @@ |
38 | 38 | ((err) != NFSERR_NOFILEHANDLE)) |
39 | 39 | |
40 | 40 | enum nfs4_client_state { |
41 | - NFS4CLNT_OK = 0, | |
41 | + NFS4CLNT_STATE_RECOVER = 0, | |
42 | 42 | }; |
43 | 43 | |
44 | 44 | /* |
... | ... | @@ -76,7 +76,6 @@ |
76 | 76 | struct work_struct cl_renewd; |
77 | 77 | struct work_struct cl_recoverd; |
78 | 78 | |
79 | - wait_queue_head_t cl_waitq; | |
80 | 79 | struct rpc_wait_queue cl_rpcwaitq; |
81 | 80 | |
82 | 81 | /* used for the setclientid verifier */ |
fs/nfs/nfs4proc.c
... | ... | @@ -2736,7 +2736,7 @@ |
2736 | 2736 | case -NFS4ERR_EXPIRED: |
2737 | 2737 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL); |
2738 | 2738 | nfs4_schedule_state_recovery(clp); |
2739 | - if (test_bit(NFS4CLNT_OK, &clp->cl_state)) | |
2739 | + if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) | |
2740 | 2740 | rpc_wake_up_task(task); |
2741 | 2741 | task->tk_status = 0; |
2742 | 2742 | return -EAGAIN; |
2743 | 2743 | |
2744 | 2744 | |
2745 | 2745 | |
... | ... | @@ -2753,25 +2753,25 @@ |
2753 | 2753 | return 0; |
2754 | 2754 | } |
2755 | 2755 | |
2756 | +static int nfs4_wait_bit_interruptible(void *word) | |
2757 | +{ | |
2758 | + if (signal_pending(current)) | |
2759 | + return -ERESTARTSYS; | |
2760 | + schedule(); | |
2761 | + return 0; | |
2762 | +} | |
2763 | + | |
2756 | 2764 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) |
2757 | 2765 | { |
2758 | - DEFINE_WAIT(wait); | |
2759 | 2766 | sigset_t oldset; |
2760 | - int interruptible, res = 0; | |
2767 | + int res; | |
2761 | 2768 | |
2762 | 2769 | might_sleep(); |
2763 | 2770 | |
2764 | 2771 | rpc_clnt_sigmask(clnt, &oldset); |
2765 | - interruptible = TASK_UNINTERRUPTIBLE; | |
2766 | - if (clnt->cl_intr) | |
2767 | - interruptible = TASK_INTERRUPTIBLE; | |
2768 | - prepare_to_wait(&clp->cl_waitq, &wait, interruptible); | |
2769 | - nfs4_schedule_state_recovery(clp); | |
2770 | - if (clnt->cl_intr && signalled()) | |
2771 | - res = -ERESTARTSYS; | |
2772 | - else if (!test_bit(NFS4CLNT_OK, &clp->cl_state)) | |
2773 | - schedule(); | |
2774 | - finish_wait(&clp->cl_waitq, &wait); | |
2772 | + res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER, | |
2773 | + nfs4_wait_bit_interruptible, | |
2774 | + TASK_INTERRUPTIBLE); | |
2775 | 2775 | rpc_clnt_sigunmask(clnt, &oldset); |
2776 | 2776 | return res; |
2777 | 2777 | } |
... | ... | @@ -2814,6 +2814,7 @@ |
2814 | 2814 | case -NFS4ERR_STALE_CLIENTID: |
2815 | 2815 | case -NFS4ERR_STALE_STATEID: |
2816 | 2816 | case -NFS4ERR_EXPIRED: |
2817 | + nfs4_schedule_state_recovery(clp); | |
2817 | 2818 | ret = nfs4_wait_clnt_recover(server->client, clp); |
2818 | 2819 | if (ret == 0) |
2819 | 2820 | exception->retry = 1; |
fs/nfs/nfs4state.c
... | ... | @@ -106,11 +106,10 @@ |
106 | 106 | INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp); |
107 | 107 | INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); |
108 | 108 | INIT_LIST_HEAD(&clp->cl_superblocks); |
109 | - init_waitqueue_head(&clp->cl_waitq); | |
110 | 109 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); |
111 | 110 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
112 | 111 | clp->cl_boot_time = CURRENT_TIME; |
113 | - clp->cl_state = 1 << NFS4CLNT_OK; | |
112 | + clp->cl_state = 0; | |
114 | 113 | return clp; |
115 | 114 | } |
116 | 115 | |
... | ... | @@ -193,7 +192,6 @@ |
193 | 192 | list_del(&clp->cl_servers); |
194 | 193 | spin_unlock(&state_spinlock); |
195 | 194 | BUG_ON(!list_empty(&clp->cl_superblocks)); |
196 | - wake_up_all(&clp->cl_waitq); | |
197 | 195 | rpc_wake_up(&clp->cl_rpcwaitq); |
198 | 196 | nfs4_kill_renewd(clp); |
199 | 197 | nfs4_free_client(clp); |
... | ... | @@ -741,6 +739,15 @@ |
741 | 739 | struct completion complete; |
742 | 740 | }; |
743 | 741 | |
742 | +static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) | |
743 | +{ | |
744 | + smp_mb__before_clear_bit(); | |
745 | + clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); | |
746 | + smp_mb__after_clear_bit(); | |
747 | + wake_up_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER); | |
748 | + rpc_wake_up(&clp->cl_rpcwaitq); | |
749 | +} | |
750 | + | |
744 | 751 | /* |
745 | 752 | * State recovery routine |
746 | 753 | */ |
... | ... | @@ -760,9 +767,7 @@ |
760 | 767 | wait_for_completion(&args.complete); |
761 | 768 | return; |
762 | 769 | out_failed_clear: |
763 | - set_bit(NFS4CLNT_OK, &clp->cl_state); | |
764 | - wake_up_all(&clp->cl_waitq); | |
765 | - rpc_wake_up(&clp->cl_rpcwaitq); | |
770 | + nfs4_clear_recover_bit(clp); | |
766 | 771 | } |
767 | 772 | |
768 | 773 | /* |
... | ... | @@ -773,7 +778,7 @@ |
773 | 778 | { |
774 | 779 | if (!clp) |
775 | 780 | return; |
776 | - if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state)) | |
781 | + if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) | |
777 | 782 | schedule_work(&clp->cl_recoverd); |
778 | 783 | } |
779 | 784 | |
780 | 785 | |
781 | 786 | |
... | ... | @@ -943,13 +948,11 @@ |
943 | 948 | } |
944 | 949 | nfs_delegation_reap_unclaimed(clp); |
945 | 950 | out: |
946 | - set_bit(NFS4CLNT_OK, &clp->cl_state); | |
947 | 951 | up_write(&clp->cl_sem); |
948 | 952 | unlock_kernel(); |
949 | - wake_up_all(&clp->cl_waitq); | |
950 | - rpc_wake_up(&clp->cl_rpcwaitq); | |
951 | 953 | if (status == -NFS4ERR_CB_PATH_DOWN) |
952 | 954 | nfs_handle_cb_pathdown(clp); |
955 | + nfs4_clear_recover_bit(clp); | |
953 | 956 | nfs4_put_client(clp); |
954 | 957 | return 0; |
955 | 958 | out_error: |