diff options
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 3 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 27 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 23 |
3 files changed, 28 insertions, 25 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 4ad5981f9375..1d4c5b339b4d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -38,7 +38,7 @@ struct idmap; | |||
| 38 | ((err) != NFSERR_NOFILEHANDLE)) | 38 | ((err) != NFSERR_NOFILEHANDLE)) |
| 39 | 39 | ||
| 40 | enum nfs4_client_state { | 40 | enum nfs4_client_state { |
| 41 | NFS4CLNT_OK = 0, | 41 | NFS4CLNT_STATE_RECOVER = 0, |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | /* | 44 | /* |
| @@ -76,7 +76,6 @@ struct nfs4_client { | |||
| 76 | struct work_struct cl_renewd; | 76 | struct work_struct cl_renewd; |
| 77 | struct work_struct cl_recoverd; | 77 | struct work_struct cl_recoverd; |
| 78 | 78 | ||
| 79 | wait_queue_head_t cl_waitq; | ||
| 80 | struct rpc_wait_queue cl_rpcwaitq; | 79 | struct rpc_wait_queue cl_rpcwaitq; |
| 81 | 80 | ||
| 82 | /* used for the setclientid verifier */ | 81 | /* used for the setclientid verifier */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 76d7d0259b6c..46623ac3ce86 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2736,7 +2736,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) | |||
| 2736 | case -NFS4ERR_EXPIRED: | 2736 | case -NFS4ERR_EXPIRED: |
| 2737 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL); | 2737 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL); |
| 2738 | nfs4_schedule_state_recovery(clp); | 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 | rpc_wake_up_task(task); | 2740 | rpc_wake_up_task(task); |
| 2741 | task->tk_status = 0; | 2741 | task->tk_status = 0; |
| 2742 | return -EAGAIN; | 2742 | return -EAGAIN; |
| @@ -2753,25 +2753,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) | |||
| 2753 | return 0; | 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 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) | 2764 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) |
| 2757 | { | 2765 | { |
| 2758 | DEFINE_WAIT(wait); | ||
| 2759 | sigset_t oldset; | 2766 | sigset_t oldset; |
| 2760 | int interruptible, res = 0; | 2767 | int res; |
| 2761 | 2768 | ||
| 2762 | might_sleep(); | 2769 | might_sleep(); |
| 2763 | 2770 | ||
| 2764 | rpc_clnt_sigmask(clnt, &oldset); | 2771 | rpc_clnt_sigmask(clnt, &oldset); |
| 2765 | interruptible = TASK_UNINTERRUPTIBLE; | 2772 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER, |
| 2766 | if (clnt->cl_intr) | 2773 | nfs4_wait_bit_interruptible, |
| 2767 | interruptible = TASK_INTERRUPTIBLE; | 2774 | 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); | ||
| 2775 | rpc_clnt_sigunmask(clnt, &oldset); | 2775 | rpc_clnt_sigunmask(clnt, &oldset); |
| 2776 | return res; | 2776 | return res; |
| 2777 | } | 2777 | } |
| @@ -2814,6 +2814,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct | |||
| 2814 | case -NFS4ERR_STALE_CLIENTID: | 2814 | case -NFS4ERR_STALE_CLIENTID: |
| 2815 | case -NFS4ERR_STALE_STATEID: | 2815 | case -NFS4ERR_STALE_STATEID: |
| 2816 | case -NFS4ERR_EXPIRED: | 2816 | case -NFS4ERR_EXPIRED: |
| 2817 | nfs4_schedule_state_recovery(clp); | ||
| 2817 | ret = nfs4_wait_clnt_recover(server->client, clp); | 2818 | ret = nfs4_wait_clnt_recover(server->client, clp); |
| 2818 | if (ret == 0) | 2819 | if (ret == 0) |
| 2819 | exception->retry = 1; | 2820 | exception->retry = 1; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 41a5f1a8a984..4ebf4df7f191 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -106,11 +106,10 @@ nfs4_alloc_client(struct in_addr *addr) | |||
| 106 | INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp); | 106 | INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp); |
| 107 | INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); | 107 | INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); |
| 108 | INIT_LIST_HEAD(&clp->cl_superblocks); | 108 | INIT_LIST_HEAD(&clp->cl_superblocks); |
| 109 | init_waitqueue_head(&clp->cl_waitq); | ||
| 110 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); | 109 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); |
| 111 | clp->cl_rpcclient = ERR_PTR(-EINVAL); | 110 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
| 112 | clp->cl_boot_time = CURRENT_TIME; | 111 | clp->cl_boot_time = CURRENT_TIME; |
| 113 | clp->cl_state = 1 << NFS4CLNT_OK; | 112 | clp->cl_state = 0; |
| 114 | return clp; | 113 | return clp; |
| 115 | } | 114 | } |
| 116 | 115 | ||
| @@ -193,7 +192,6 @@ nfs4_put_client(struct nfs4_client *clp) | |||
| 193 | list_del(&clp->cl_servers); | 192 | list_del(&clp->cl_servers); |
| 194 | spin_unlock(&state_spinlock); | 193 | spin_unlock(&state_spinlock); |
| 195 | BUG_ON(!list_empty(&clp->cl_superblocks)); | 194 | BUG_ON(!list_empty(&clp->cl_superblocks)); |
| 196 | wake_up_all(&clp->cl_waitq); | ||
| 197 | rpc_wake_up(&clp->cl_rpcwaitq); | 195 | rpc_wake_up(&clp->cl_rpcwaitq); |
| 198 | nfs4_kill_renewd(clp); | 196 | nfs4_kill_renewd(clp); |
| 199 | nfs4_free_client(clp); | 197 | nfs4_free_client(clp); |
| @@ -741,6 +739,15 @@ struct reclaimer_args { | |||
| 741 | struct completion complete; | 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 | * State recovery routine | 752 | * State recovery routine |
| 746 | */ | 753 | */ |
| @@ -760,9 +767,7 @@ nfs4_recover_state(void *data) | |||
| 760 | wait_for_completion(&args.complete); | 767 | wait_for_completion(&args.complete); |
| 761 | return; | 768 | return; |
| 762 | out_failed_clear: | 769 | out_failed_clear: |
| 763 | set_bit(NFS4CLNT_OK, &clp->cl_state); | 770 | nfs4_clear_recover_bit(clp); |
| 764 | wake_up_all(&clp->cl_waitq); | ||
| 765 | rpc_wake_up(&clp->cl_rpcwaitq); | ||
| 766 | } | 771 | } |
| 767 | 772 | ||
| 768 | /* | 773 | /* |
| @@ -773,7 +778,7 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp) | |||
| 773 | { | 778 | { |
| 774 | if (!clp) | 779 | if (!clp) |
| 775 | return; | 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 | schedule_work(&clp->cl_recoverd); | 782 | schedule_work(&clp->cl_recoverd); |
| 778 | } | 783 | } |
| 779 | 784 | ||
| @@ -943,13 +948,11 @@ restart_loop: | |||
| 943 | } | 948 | } |
| 944 | nfs_delegation_reap_unclaimed(clp); | 949 | nfs_delegation_reap_unclaimed(clp); |
| 945 | out: | 950 | out: |
| 946 | set_bit(NFS4CLNT_OK, &clp->cl_state); | ||
| 947 | up_write(&clp->cl_sem); | 951 | up_write(&clp->cl_sem); |
| 948 | unlock_kernel(); | 952 | unlock_kernel(); |
| 949 | wake_up_all(&clp->cl_waitq); | ||
| 950 | rpc_wake_up(&clp->cl_rpcwaitq); | ||
| 951 | if (status == -NFS4ERR_CB_PATH_DOWN) | 953 | if (status == -NFS4ERR_CB_PATH_DOWN) |
| 952 | nfs_handle_cb_pathdown(clp); | 954 | nfs_handle_cb_pathdown(clp); |
| 955 | nfs4_clear_recover_bit(clp); | ||
| 953 | nfs4_put_client(clp); | 956 | nfs4_put_client(clp); |
| 954 | return 0; | 957 | return 0; |
| 955 | out_error: | 958 | out_error: |
