NFSv4: Unify synchronous and asynchronous error handling

They now only differ in the way we handle waiting, so let's unify.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
This commit is contained in:
Trond Myklebust 2015-09-20 15:51:00 -04:00
parent 4816fdadab
commit 037fc9808a

View file

@ -78,7 +78,6 @@ struct nfs4_opendata;
static int _nfs4_proc_open(struct nfs4_opendata *data);
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *, struct nfs4_state *, long *);
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label);
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
@ -466,6 +465,55 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
return ret;
}
static int
nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
int errorcode, struct nfs4_exception *exception)
{
struct nfs_client *clp = server->nfs_client;
int ret;
ret = nfs4_do_handle_exception(server, errorcode, exception);
if (exception->delay) {
rpc_delay(task, nfs4_update_delay(&exception->timeout));
goto out_retry;
}
if (exception->recovering) {
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
goto out_retry;
}
if (test_bit(NFS_MIG_FAILED, &server->mig_status))
ret = -EIO;
return ret;
out_retry:
if (ret == 0)
exception->retry = 1;
return ret;
}
static int
nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server,
struct nfs4_state *state, long *timeout)
{
struct nfs4_exception exception = {
.state = state,
};
if (task->tk_status >= 0)
return 0;
if (timeout)
exception.timeout = *timeout;
task->tk_status = nfs4_async_handle_exception(task, server,
task->tk_status,
&exception);
if (exception.delay && timeout)
*timeout = exception.timeout;
if (exception.retry)
return -EAGAIN;
return 0;
}
/*
* Return 'true' if 'clp' is using an rpc_client that is integrity protected
* or 'false' otherwise.
@ -4979,79 +5027,6 @@ nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
#endif /* CONFIG_NFS_V4_SECURITY_LABEL */
static int
nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server,
struct nfs4_state *state, long *timeout)
{
struct nfs_client *clp = server->nfs_client;
if (task->tk_status >= 0)
return 0;
switch(task->tk_status) {
case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_OPENMODE:
if (state == NULL)
break;
if (nfs4_schedule_stateid_recovery(server, state) < 0)
goto recovery_failed;
goto wait_on_recovery;
case -NFS4ERR_EXPIRED:
if (state != NULL) {
if (nfs4_schedule_stateid_recovery(server, state) < 0)
goto recovery_failed;
}
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_STALE_CLIENTID:
nfs4_schedule_lease_recovery(clp);
goto wait_on_recovery;
case -NFS4ERR_MOVED:
if (nfs4_schedule_migration_recovery(server) < 0)
goto recovery_failed;
goto wait_on_recovery;
case -NFS4ERR_LEASE_MOVED:
nfs4_schedule_lease_moved_recovery(clp);
goto wait_on_recovery;
#if defined(CONFIG_NFS_V4_1)
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
case -NFS4ERR_BAD_HIGH_SLOT:
case -NFS4ERR_DEADSESSION:
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
case -NFS4ERR_SEQ_FALSE_RETRY:
case -NFS4ERR_SEQ_MISORDERED:
dprintk("%s ERROR %d, Reset session\n", __func__,
task->tk_status);
nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
goto wait_on_recovery;
#endif /* CONFIG_NFS_V4_1 */
case -NFS4ERR_DELAY:
nfs_inc_server_stats(server, NFSIOS_DELAY);
rpc_delay(task, nfs4_update_delay(timeout));
goto restart_call;
case -NFS4ERR_GRACE:
rpc_delay(task, NFS4_POLL_RETRY_MAX);
case -NFS4ERR_RETRY_UNCACHED_REP:
case -NFS4ERR_OLD_STATEID:
goto restart_call;
}
task->tk_status = nfs4_map_errors(task->tk_status);
return 0;
recovery_failed:
task->tk_status = -EIO;
return 0;
wait_on_recovery:
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
if (test_bit(NFS_MIG_FAILED, &server->mig_status))
goto recovery_failed;
restart_call:
task->tk_status = 0;
return -EAGAIN;
}
static void nfs4_init_boot_verifier(const struct nfs_client *clp,
nfs4_verifier *bootverf)
{