aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h3
-rw-r--r--fs/nfs/nfs4proc.c27
-rw-r--r--fs/nfs/nfs4state.c23
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
40enum nfs4_client_state { 40enum 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
2756static int nfs4_wait_bit_interruptible(void *word)
2757{
2758 if (signal_pending(current))
2759 return -ERESTARTSYS;
2760 schedule();
2761 return 0;
2762}
2763
2756static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) 2764static 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
742static 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;
762out_failed_clear: 769out_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);
945out: 950out:
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;
955out_error: 958out_error: