aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-08-02 14:46:52 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-08-04 11:55:35 -0400
commit910ac68a2b80c7de95bc8488734067b1bb15d583 (patch)
treeb9f7e2af9c35fcee44eb33c7cbde276885b3285c
parent55a673990ec04cf63005318bcf08c2b0046e5778 (diff)
NFSv4.1: Return NFS4ERR_BADSESSION to callbacks during session resets
If the client is in the process of resetting the session when it receives a callback, then returning NFS4ERR_DELAY may cause a deadlock with the DESTROY_SESSION call. Basically, if the client returns NFS4ERR_DELAY in response to the CB_SEQUENCE call, then the server is entitled to believe that the client is busy because it is already processing that call. In that case, the server is perfectly entitled to respond with a NFS4ERR_BACK_CHAN_BUSY to any DESTROY_SESSION call. Fix this by having the client reply with a NFS4ERR_BADSESSION in response to the callback if it is resetting the session. Cc: stable@kernel.org [2.6.38+] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/callback_proc.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 0ab82020f5d..43926add945 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -452,6 +452,11 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
spin_unlock(&tbl->slot_tbl_lock);
status = htonl(NFS4ERR_DELAY);
+ /* Return NFS4ERR_BADSESSION if we're draining the session
+ * in order to reset it.
+ */
+ if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
+ status = htonl(NFS4ERR_BADSESSION);
goto out;
}