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/nfs4state.c | |
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/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 59 |
1 files changed, 41 insertions, 18 deletions
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 | ||