aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRicardo Labiaga <Ricardo.Labiaga@netapp.com>2009-12-06 12:57:34 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-12-06 12:57:34 -0500
commit9dfdf404c99347e2e224e25f8626e7b6399a05cd (patch)
tree7bad4e6c06b5f12548dbd3ec91fab56877808400 /fs
parent9430fb6b5315f7bc94b05be915c64ebfefc55bbc (diff)
nfs41: Don't clear DRAINING flag on NFS4ERR_STALE_CLIENTID
If CREATE_SESSION fails with NFS4ERR_STALE_CLIENTID, don't clear the NFS4CLNT_SESSION_DRAINING flag and don't wake RPCs waiting for the session to be reestablished. We don't have a session yet, so there is no reason to wake other RPCs. This avoids sending spurious compounds with bogus sequenceID during session and state recovery. Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com> [Trond.Myklebust@netapp.com: cleaned up patch by adding the nfs41_begin/end_drain_session() helpers] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfs/nfs4state.c59
2 files changed, 43 insertions, 18 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4be036942569..fbae2c94dbc6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4586,10 +4586,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
4586 init_completion(&session->complete); 4586 init_completion(&session->complete);
4587 4587
4588 tbl = &session->fc_slot_table; 4588 tbl = &session->fc_slot_table;
4589 tbl->highest_used_slotid = -1;
4589 spin_lock_init(&tbl->slot_tbl_lock); 4590 spin_lock_init(&tbl->slot_tbl_lock);
4590 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); 4591 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
4591 4592
4592 tbl = &session->bc_slot_table; 4593 tbl = &session->bc_slot_table;
4594 tbl->highest_used_slotid = -1;
4593 spin_lock_init(&tbl->slot_tbl_lock); 4595 spin_lock_init(&tbl->slot_tbl_lock);
4594 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); 4596 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
4595 4597
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 9cfe6864d9ed..1b629cca7072 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -135,16 +135,43 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp)
135 return status; 135 return status;
136} 136}
137 137
138static void nfs41_end_drain_session(struct nfs_client *clp,
139 struct nfs4_session *ses)
140{
141 if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state))
142 rpc_wake_up(&ses->fc_slot_table.slot_tbl_waitq);
143}
144
145static int nfs41_begin_drain_session(struct nfs_client *clp,
146 struct nfs4_session *ses)
147{
148 struct nfs4_slot_table *tbl = &ses->fc_slot_table;
149
150 spin_lock(&tbl->slot_tbl_lock);
151 set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state);
152 if (tbl->highest_used_slotid != -1) {
153 INIT_COMPLETION(ses->complete);
154 spin_unlock(&tbl->slot_tbl_lock);
155 return wait_for_completion_interruptible(&ses->complete);
156 }
157 spin_unlock(&tbl->slot_tbl_lock);
158 return 0;
159}
160
138int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) 161int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
139{ 162{
140 int status; 163 int status;
141 164
165 status = nfs41_begin_drain_session(clp, clp->cl_session);
166 if (status != 0)
167 goto out;
142 status = nfs4_proc_exchange_id(clp, cred); 168 status = nfs4_proc_exchange_id(clp, cred);
143 if (status != 0) 169 if (status != 0)
144 goto out; 170 goto out;
145 status = nfs4_proc_create_session(clp); 171 status = nfs4_proc_create_session(clp);
146 if (status != 0) 172 if (status != 0)
147 goto out; 173 goto out;
174 nfs41_end_drain_session(clp, clp->cl_session);
148 nfs41_setup_state_renewal(clp); 175 nfs41_setup_state_renewal(clp);
149 nfs_mark_client_ready(clp, NFS_CS_READY); 176 nfs_mark_client_ready(clp, NFS_CS_READY);
150out: 177out:
@@ -1239,20 +1266,11 @@ static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err)
1239static int nfs4_reset_session(struct nfs_client *clp) 1266static int nfs4_reset_session(struct nfs_client *clp)
1240{ 1267{
1241 struct nfs4_session *ses = clp->cl_session; 1268 struct nfs4_session *ses = clp->cl_session;
1242 struct nfs4_slot_table *tbl = &ses->fc_slot_table;
1243 int status; 1269 int status;
1244 1270
1245 spin_lock(&tbl->slot_tbl_lock); 1271 status = nfs41_begin_drain_session(clp, ses);
1246 set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state); 1272 if (status != 0)
1247 if (tbl->highest_used_slotid != -1) { 1273 return status;
1248 INIT_COMPLETION(ses->complete);
1249 spin_unlock(&tbl->slot_tbl_lock);
1250 status = wait_for_completion_interruptible(&ses->complete);
1251 if (status) /* -ERESTARTSYS */
1252 goto out;
1253 } else {
1254 spin_unlock(&tbl->slot_tbl_lock);
1255 }
1256 1274
1257 status = nfs4_proc_destroy_session(clp->cl_session); 1275 status = nfs4_proc_destroy_session(clp->cl_session);
1258 if (status && status != -NFS4ERR_BADSESSION && 1276 if (status && status != -NFS4ERR_BADSESSION &&
@@ -1265,13 +1283,18 @@ static int nfs4_reset_session(struct nfs_client *clp)
1265 status = nfs4_proc_create_session(clp); 1283 status = nfs4_proc_create_session(clp);
1266 if (status) 1284 if (status)
1267 nfs4_session_recovery_handle_error(clp, status); 1285 nfs4_session_recovery_handle_error(clp, status);
1268 /* fall through*/ 1286
1269out: 1287out:
1270 /* Wake up the next rpc task even on error */ 1288 /*
1271 clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state); 1289 * Let the state manager reestablish state
1272 rpc_wake_up(&clp->cl_session->fc_slot_table.slot_tbl_waitq); 1290 * without waking other tasks yet.
1273 if (status == 0) 1291 */
1274 nfs41_setup_state_renewal(clp); 1292 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
1293 /* Wake up the next rpc task */
1294 nfs41_end_drain_session(clp, ses);
1295 if (status == 0)
1296 nfs41_setup_state_renewal(clp);
1297 }
1275 return status; 1298 return status;
1276} 1299}
1277 1300