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>
This commit is contained in:
Trond Myklebust 2010-01-26 15:42:47 -05:00
Родитель 03391693a9
Коммит a2c0b9e291
3 изменённых файлов: 33 добавлений и 14 удалений

Просмотреть файл

@ -278,6 +278,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
extern void nfs4_schedule_state_recovery(struct nfs_client *); extern void nfs4_schedule_state_recovery(struct nfs_client *);
extern void nfs4_schedule_state_manager(struct nfs_client *); extern void nfs4_schedule_state_manager(struct nfs_client *);
extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state);
extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);

Просмотреть файл

@ -249,14 +249,14 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
if (state == NULL) if (state == NULL)
break; break;
nfs4_state_mark_reclaim_nograce(clp, state); nfs4_state_mark_reclaim_nograce(clp, state);
case -NFS4ERR_STALE_CLIENTID: goto do_state_recovery;
case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_STATEID:
if (state == NULL)
break;
nfs4_state_mark_reclaim_reboot(clp, state);
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
nfs4_schedule_state_recovery(clp); goto do_state_recovery;
ret = nfs4_wait_clnt_recover(clp);
if (ret == 0)
exception->retry = 1;
break;
#if defined(CONFIG_NFS_V4_1) #if defined(CONFIG_NFS_V4_1)
case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT: case -NFS4ERR_BADSLOT:
@ -289,6 +289,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
} }
/* We failed to handle the error */ /* We failed to handle the error */
return nfs4_map_errors(ret); return nfs4_map_errors(ret);
do_state_recovery:
nfs4_schedule_state_recovery(clp);
ret = nfs4_wait_clnt_recover(clp);
if (ret == 0)
exception->retry = 1;
return ret;
} }
@ -3420,15 +3426,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
if (state == NULL) if (state == NULL)
break; break;
nfs4_state_mark_reclaim_nograce(clp, state); nfs4_state_mark_reclaim_nograce(clp, state);
case -NFS4ERR_STALE_CLIENTID: goto do_state_recovery;
case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_STATEID:
if (state == NULL)
break;
nfs4_state_mark_reclaim_reboot(clp, state);
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); goto do_state_recovery;
nfs4_schedule_state_recovery(clp);
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
task->tk_status = 0;
return -EAGAIN;
#if defined(CONFIG_NFS_V4_1) #if defined(CONFIG_NFS_V4_1)
case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT: case -NFS4ERR_BADSLOT:
@ -3456,6 +3461,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
} }
task->tk_status = nfs4_map_errors(task->tk_status); task->tk_status = nfs4_map_errors(task->tk_status);
return 0; return 0;
do_state_recovery:
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
nfs4_schedule_state_recovery(clp);
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
task->tk_status = 0;
return -EAGAIN;
} }
static int static int
@ -4099,6 +4111,12 @@ static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_
(lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
nfs4_state_mark_reclaim_nograce(clp, state); nfs4_state_mark_reclaim_nograce(clp, state);
lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
break;
case -NFS4ERR_STALE_STATEID:
if (new_lock_owner != 0 ||
(lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
nfs4_state_mark_reclaim_reboot(clp, state);
lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
}; };
} }

Просмотреть файл

@ -901,7 +901,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
nfs4_schedule_state_manager(clp); nfs4_schedule_state_manager(clp);
} }
static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
{ {
set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);