diff options
| author | Ricardo Labiaga <Ricardo.Labiaga@netapp.com> | 2009-12-06 12:57:34 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-06 12:57:34 -0500 |
| commit | 9dfdf404c99347e2e224e25f8626e7b6399a05cd (patch) | |
| tree | 7bad4e6c06b5f12548dbd3ec91fab56877808400 /fs/nfs | |
| parent | 9430fb6b5315f7bc94b05be915c64ebfefc55bbc (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/nfs')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 59 |
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 | ||
| 138 | static 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 | |||
| 145 | static 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 | |||
| 138 | int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 161 | int 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); |
| 150 | out: | 177 | out: |
| @@ -1239,20 +1266,11 @@ static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err) | |||
| 1239 | static int nfs4_reset_session(struct nfs_client *clp) | 1266 | static 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 | |
| 1269 | out: | 1287 | out: |
| 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 | ||
