nfs41: nfs41: fix state manager deadlock in session reset
[linux-2.6-block.git] / fs / nfs / nfs4state.c
index f56f6be5e3145c8ae64c03d9b22af944b001c7ce..3c1433598b60296e847f61549c82a4213068e1ea 100644 (file)
@@ -1181,8 +1181,23 @@ static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err)
 
 static int nfs4_reset_session(struct nfs_client *clp)
 {
+       struct nfs4_session *ses = clp->cl_session;
+       struct nfs4_slot_table *tbl = &ses->fc_slot_table;
        int status;
 
+       INIT_COMPLETION(ses->complete);
+       spin_lock(&tbl->slot_tbl_lock);
+       if (tbl->highest_used_slotid != -1) {
+               set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state);
+               spin_unlock(&tbl->slot_tbl_lock);
+               status = wait_for_completion_interruptible(&ses->complete);
+               clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state);
+               if (status) /* -ERESTARTSYS */
+                       goto out;
+       } else {
+               spin_unlock(&tbl->slot_tbl_lock);
+       }
+
        status = nfs4_proc_destroy_session(clp->cl_session);
        if (status && status != -NFS4ERR_BADSESSION &&
            status != -NFS4ERR_DEADSESSION) {