diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-01-26 15:42:47 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-01-26 15:42:47 -0500 |
commit | a2c0b9e291208f65221a0ad8a0c80a377707d480 (patch) | |
tree | 31bec606e1d33f97c160448e03bace4a63a2d2fb /fs/nfs | |
parent | 03391693a95900875b0973569d2d73ff3aa8972e (diff) |
NFS: Ensure that we handle NFS4ERR_STALE_STATEID correctly
Even if the server is crazy, we should be able to mark the stateid as being
bad, to ensure it gets recovered.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 44 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 2 |
3 files changed, 33 insertions, 14 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ea2f41b26aea..0c6fda33d66e 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -278,6 +278,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); | |||
278 | extern void nfs4_schedule_state_recovery(struct nfs_client *); | 278 | extern void nfs4_schedule_state_recovery(struct nfs_client *); |
279 | extern void nfs4_schedule_state_manager(struct nfs_client *); | 279 | extern void nfs4_schedule_state_manager(struct nfs_client *); |
280 | extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); | 280 | extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); |
281 | extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); | ||
281 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); | 282 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); |
282 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 283 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
283 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 284 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index afbfe673489b..375f0fae2c6a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -249,14 +249,14 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
249 | if (state == NULL) | 249 | if (state == NULL) |
250 | break; | 250 | break; |
251 | nfs4_state_mark_reclaim_nograce(clp, state); | 251 | nfs4_state_mark_reclaim_nograce(clp, state); |
252 | case -NFS4ERR_STALE_CLIENTID: | 252 | goto do_state_recovery; |
253 | case -NFS4ERR_STALE_STATEID: | 253 | case -NFS4ERR_STALE_STATEID: |
254 | if (state == NULL) | ||
255 | break; | ||
256 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
257 | case -NFS4ERR_STALE_CLIENTID: | ||
254 | case -NFS4ERR_EXPIRED: | 258 | case -NFS4ERR_EXPIRED: |
255 | nfs4_schedule_state_recovery(clp); | 259 | goto do_state_recovery; |
256 | ret = nfs4_wait_clnt_recover(clp); | ||
257 | if (ret == 0) | ||
258 | exception->retry = 1; | ||
259 | break; | ||
260 | #if defined(CONFIG_NFS_V4_1) | 260 | #if defined(CONFIG_NFS_V4_1) |
261 | case -NFS4ERR_BADSESSION: | 261 | case -NFS4ERR_BADSESSION: |
262 | case -NFS4ERR_BADSLOT: | 262 | case -NFS4ERR_BADSLOT: |
@@ -289,6 +289,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
289 | } | 289 | } |
290 | /* We failed to handle the error */ | 290 | /* We failed to handle the error */ |
291 | return nfs4_map_errors(ret); | 291 | return nfs4_map_errors(ret); |
292 | do_state_recovery: | ||
293 | nfs4_schedule_state_recovery(clp); | ||
294 | ret = nfs4_wait_clnt_recover(clp); | ||
295 | if (ret == 0) | ||
296 | exception->retry = 1; | ||
297 | return ret; | ||
292 | } | 298 | } |
293 | 299 | ||
294 | 300 | ||
@@ -3420,15 +3426,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3420 | if (state == NULL) | 3426 | if (state == NULL) |
3421 | break; | 3427 | break; |
3422 | nfs4_state_mark_reclaim_nograce(clp, state); | 3428 | nfs4_state_mark_reclaim_nograce(clp, state); |
3423 | case -NFS4ERR_STALE_CLIENTID: | 3429 | goto do_state_recovery; |
3424 | case -NFS4ERR_STALE_STATEID: | 3430 | case -NFS4ERR_STALE_STATEID: |
3431 | if (state == NULL) | ||
3432 | break; | ||
3433 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
3434 | case -NFS4ERR_STALE_CLIENTID: | ||
3425 | case -NFS4ERR_EXPIRED: | 3435 | case -NFS4ERR_EXPIRED: |
3426 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | 3436 | goto do_state_recovery; |
3427 | nfs4_schedule_state_recovery(clp); | ||
3428 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
3429 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
3430 | task->tk_status = 0; | ||
3431 | return -EAGAIN; | ||
3432 | #if defined(CONFIG_NFS_V4_1) | 3437 | #if defined(CONFIG_NFS_V4_1) |
3433 | case -NFS4ERR_BADSESSION: | 3438 | case -NFS4ERR_BADSESSION: |
3434 | case -NFS4ERR_BADSLOT: | 3439 | case -NFS4ERR_BADSLOT: |
@@ -3456,6 +3461,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3456 | } | 3461 | } |
3457 | task->tk_status = nfs4_map_errors(task->tk_status); | 3462 | task->tk_status = nfs4_map_errors(task->tk_status); |
3458 | return 0; | 3463 | return 0; |
3464 | do_state_recovery: | ||
3465 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | ||
3466 | nfs4_schedule_state_recovery(clp); | ||
3467 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
3468 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
3469 | task->tk_status = 0; | ||
3470 | return -EAGAIN; | ||
3459 | } | 3471 | } |
3460 | 3472 | ||
3461 | static int | 3473 | static int |
@@ -4099,6 +4111,12 @@ static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_ | |||
4099 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | 4111 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) |
4100 | nfs4_state_mark_reclaim_nograce(clp, state); | 4112 | nfs4_state_mark_reclaim_nograce(clp, state); |
4101 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | 4113 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; |
4114 | break; | ||
4115 | case -NFS4ERR_STALE_STATEID: | ||
4116 | if (new_lock_owner != 0 || | ||
4117 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | ||
4118 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
4119 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | ||
4102 | }; | 4120 | }; |
4103 | } | 4121 | } |
4104 | 4122 | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 6d263ed79e92..c1e2733f4fa4 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -901,7 +901,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp) | |||
901 | nfs4_schedule_state_manager(clp); | 901 | nfs4_schedule_state_manager(clp); |
902 | } | 902 | } |
903 | 903 | ||
904 | static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) | 904 | int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) |
905 | { | 905 | { |
906 | 906 | ||
907 | set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); | 907 | set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); |