NFSv4: State recovery cleanup
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 3 Jan 2006 08:55:22 +0000 (09:55 +0100)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 6 Jan 2006 19:58:45 +0000 (14:58 -0500)
 Use wait_on_bit() when waiting for state recovery to complete.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c

index 4ad5981f937511ca81e70eee0659c579bb801857..1d4c5b339b4d96792adb6d43286213d4af331d99 100644 (file)
@@ -38,7 +38,7 @@ struct idmap;
  ((err) != NFSERR_NOFILEHANDLE))
 
 enum nfs4_client_state {
-       NFS4CLNT_OK  = 0,
+       NFS4CLNT_STATE_RECOVER  = 0,
 };
 
 /*
@@ -76,7 +76,6 @@ struct nfs4_client {
        struct work_struct      cl_renewd;
        struct work_struct      cl_recoverd;
 
-       wait_queue_head_t       cl_waitq;
        struct rpc_wait_queue   cl_rpcwaitq;
 
        /* used for the setclientid verifier */
index 76d7d0259b6c19a3e7f14c40395c417d45379e7f..46623ac3ce862aa90284edd1a490b69478ee7637 100644 (file)
@@ -2736,7 +2736,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
                case -NFS4ERR_EXPIRED:
                        rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
                        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);
                        task->tk_status = 0;
                        return -EAGAIN;
@@ -2753,25 +2753,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
        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)
 {
-       DEFINE_WAIT(wait);
        sigset_t oldset;
-       int interruptible, res = 0;
+       int res;
 
        might_sleep();
 
        rpc_clnt_sigmask(clnt, &oldset);
-       interruptible = TASK_UNINTERRUPTIBLE;
-       if (clnt->cl_intr)
-               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);
+       res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
+                       nfs4_wait_bit_interruptible,
+                       TASK_INTERRUPTIBLE);
        rpc_clnt_sigunmask(clnt, &oldset);
        return res;
 }
@@ -2814,6 +2814,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_EXPIRED:
+                       nfs4_schedule_state_recovery(clp);
                        ret = nfs4_wait_clnt_recover(server->client, clp);
                        if (ret == 0)
                                exception->retry = 1;
index 41a5f1a8a984e7fdd9f0d4d13d1bde13613b8c02..4ebf4df7f191a17e6788811faa7cef2f7df84848 100644 (file)
@@ -106,11 +106,10 @@ nfs4_alloc_client(struct in_addr *addr)
        INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
        INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
        INIT_LIST_HEAD(&clp->cl_superblocks);
-       init_waitqueue_head(&clp->cl_waitq);
        rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
        clp->cl_rpcclient = ERR_PTR(-EINVAL);
        clp->cl_boot_time = CURRENT_TIME;
-       clp->cl_state = 1 << NFS4CLNT_OK;
+       clp->cl_state = 0;
        return clp;
 }
 
@@ -193,7 +192,6 @@ nfs4_put_client(struct nfs4_client *clp)
        list_del(&clp->cl_servers);
        spin_unlock(&state_spinlock);
        BUG_ON(!list_empty(&clp->cl_superblocks));
-       wake_up_all(&clp->cl_waitq);
        rpc_wake_up(&clp->cl_rpcwaitq);
        nfs4_kill_renewd(clp);
        nfs4_free_client(clp);
@@ -741,6 +739,15 @@ struct reclaimer_args {
        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
  */
@@ -760,9 +767,7 @@ nfs4_recover_state(void *data)
        wait_for_completion(&args.complete);
        return;
 out_failed_clear:
-       set_bit(NFS4CLNT_OK, &clp->cl_state);
-       wake_up_all(&clp->cl_waitq);
-       rpc_wake_up(&clp->cl_rpcwaitq);
+       nfs4_clear_recover_bit(clp);
 }
 
 /*
@@ -773,7 +778,7 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp)
 {
        if (!clp)
                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);
 }
 
@@ -943,13 +948,11 @@ restart_loop:
        }
        nfs_delegation_reap_unclaimed(clp);
 out:
-       set_bit(NFS4CLNT_OK, &clp->cl_state);
        up_write(&clp->cl_sem);
        unlock_kernel();
-       wake_up_all(&clp->cl_waitq);
-       rpc_wake_up(&clp->cl_rpcwaitq);
        if (status == -NFS4ERR_CB_PATH_DOWN)
                nfs_handle_cb_pathdown(clp);
+       nfs4_clear_recover_bit(clp);
        nfs4_put_client(clp);
        return 0;
 out_error: