Commit 433fbe4c authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: State recovery cleanup

 Use wait_on_bit() when waiting for state recovery to complete.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 26e976a8
...@@ -38,7 +38,7 @@ struct idmap; ...@@ -38,7 +38,7 @@ struct idmap;
((err) != NFSERR_NOFILEHANDLE)) ((err) != NFSERR_NOFILEHANDLE))
enum nfs4_client_state { enum nfs4_client_state {
NFS4CLNT_OK = 0, NFS4CLNT_STATE_RECOVER = 0,
}; };
/* /*
...@@ -76,7 +76,6 @@ struct nfs4_client { ...@@ -76,7 +76,6 @@ struct nfs4_client {
struct work_struct cl_renewd; struct work_struct cl_renewd;
struct work_struct cl_recoverd; struct work_struct cl_recoverd;
wait_queue_head_t cl_waitq;
struct rpc_wait_queue cl_rpcwaitq; struct rpc_wait_queue cl_rpcwaitq;
/* used for the setclientid verifier */ /* used for the setclientid verifier */
......
...@@ -2736,7 +2736,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) ...@@ -2736,7 +2736,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL); rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
nfs4_schedule_state_recovery(clp); nfs4_schedule_state_recovery(clp);
if (test_bit(NFS4CLNT_OK, &clp->cl_state)) if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
rpc_wake_up_task(task); rpc_wake_up_task(task);
task->tk_status = 0; task->tk_status = 0;
return -EAGAIN; return -EAGAIN;
...@@ -2753,25 +2753,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) ...@@ -2753,25 +2753,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
return 0; return 0;
} }
static int nfs4_wait_bit_interruptible(void *word)
{
if (signal_pending(current))
return -ERESTARTSYS;
schedule();
return 0;
}
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
{ {
DEFINE_WAIT(wait);
sigset_t oldset; sigset_t oldset;
int interruptible, res = 0; int res;
might_sleep(); might_sleep();
rpc_clnt_sigmask(clnt, &oldset); rpc_clnt_sigmask(clnt, &oldset);
interruptible = TASK_UNINTERRUPTIBLE; res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
if (clnt->cl_intr) nfs4_wait_bit_interruptible,
interruptible = TASK_INTERRUPTIBLE; TASK_INTERRUPTIBLE);
prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
nfs4_schedule_state_recovery(clp);
if (clnt->cl_intr && signalled())
res = -ERESTARTSYS;
else if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
schedule();
finish_wait(&clp->cl_waitq, &wait);
rpc_clnt_sigunmask(clnt, &oldset); rpc_clnt_sigunmask(clnt, &oldset);
return res; return res;
} }
...@@ -2814,6 +2814,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct ...@@ -2814,6 +2814,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
nfs4_schedule_state_recovery(clp);
ret = nfs4_wait_clnt_recover(server->client, clp); ret = nfs4_wait_clnt_recover(server->client, clp);
if (ret == 0) if (ret == 0)
exception->retry = 1; exception->retry = 1;
......
...@@ -106,11 +106,10 @@ nfs4_alloc_client(struct in_addr *addr) ...@@ -106,11 +106,10 @@ nfs4_alloc_client(struct in_addr *addr)
INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp); INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
INIT_LIST_HEAD(&clp->cl_superblocks); INIT_LIST_HEAD(&clp->cl_superblocks);
init_waitqueue_head(&clp->cl_waitq);
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
clp->cl_rpcclient = ERR_PTR(-EINVAL); clp->cl_rpcclient = ERR_PTR(-EINVAL);
clp->cl_boot_time = CURRENT_TIME; clp->cl_boot_time = CURRENT_TIME;
clp->cl_state = 1 << NFS4CLNT_OK; clp->cl_state = 0;
return clp; return clp;
} }
...@@ -193,7 +192,6 @@ nfs4_put_client(struct nfs4_client *clp) ...@@ -193,7 +192,6 @@ nfs4_put_client(struct nfs4_client *clp)
list_del(&clp->cl_servers); list_del(&clp->cl_servers);
spin_unlock(&state_spinlock); spin_unlock(&state_spinlock);
BUG_ON(!list_empty(&clp->cl_superblocks)); BUG_ON(!list_empty(&clp->cl_superblocks));
wake_up_all(&clp->cl_waitq);
rpc_wake_up(&clp->cl_rpcwaitq); rpc_wake_up(&clp->cl_rpcwaitq);
nfs4_kill_renewd(clp); nfs4_kill_renewd(clp);
nfs4_free_client(clp); nfs4_free_client(clp);
...@@ -741,6 +739,15 @@ struct reclaimer_args { ...@@ -741,6 +739,15 @@ struct reclaimer_args {
struct completion complete; struct completion complete;
}; };
static inline void nfs4_clear_recover_bit(struct nfs4_client *clp)
{
smp_mb__before_clear_bit();
clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state);
smp_mb__after_clear_bit();
wake_up_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER);
rpc_wake_up(&clp->cl_rpcwaitq);
}
/* /*
* State recovery routine * State recovery routine
*/ */
...@@ -760,9 +767,7 @@ nfs4_recover_state(void *data) ...@@ -760,9 +767,7 @@ nfs4_recover_state(void *data)
wait_for_completion(&args.complete); wait_for_completion(&args.complete);
return; return;
out_failed_clear: out_failed_clear:
set_bit(NFS4CLNT_OK, &clp->cl_state); nfs4_clear_recover_bit(clp);
wake_up_all(&clp->cl_waitq);
rpc_wake_up(&clp->cl_rpcwaitq);
} }
/* /*
...@@ -773,7 +778,7 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp) ...@@ -773,7 +778,7 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp)
{ {
if (!clp) if (!clp)
return; return;
if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state)) if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
schedule_work(&clp->cl_recoverd); schedule_work(&clp->cl_recoverd);
} }
...@@ -943,13 +948,11 @@ static int reclaimer(void *ptr) ...@@ -943,13 +948,11 @@ static int reclaimer(void *ptr)
} }
nfs_delegation_reap_unclaimed(clp); nfs_delegation_reap_unclaimed(clp);
out: out:
set_bit(NFS4CLNT_OK, &clp->cl_state);
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
unlock_kernel(); unlock_kernel();
wake_up_all(&clp->cl_waitq);
rpc_wake_up(&clp->cl_rpcwaitq);
if (status == -NFS4ERR_CB_PATH_DOWN) if (status == -NFS4ERR_CB_PATH_DOWN)
nfs_handle_cb_pathdown(clp); nfs_handle_cb_pathdown(clp);
nfs4_clear_recover_bit(clp);
nfs4_put_client(clp); nfs4_put_client(clp);
return 0; return 0;
out_error: out_error:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment