diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-09-20 15:51:00 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-10-08 10:45:53 -0400 |
commit | 037fc9808a777f6fb6a54c6510b9656716e0c8c8 (patch) | |
tree | 8301d284d71794be52b24b4e791a1f4360a8405d | |
parent | 4816fdadab9ff874ec1a4138dad43b636c7d220b (diff) |
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>
-rw-r--r-- | fs/nfs/nfs4proc.c | 123 |
1 files changed, 49 insertions, 74 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2a155ec05f6d..e32b7e93f253 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -78,7 +78,6 @@ struct nfs4_opendata; | |||
78 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 78 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
79 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 79 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
80 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 80 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
81 | static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *, struct nfs4_state *, long *); | ||
82 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 81 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
83 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); | 82 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); |
84 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); | 83 | 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 @@ out_retry: | |||
466 | return ret; | 465 | return ret; |
467 | } | 466 | } |
468 | 467 | ||
468 | static int | ||
469 | nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server, | ||
470 | int errorcode, struct nfs4_exception *exception) | ||
471 | { | ||
472 | struct nfs_client *clp = server->nfs_client; | ||
473 | int ret; | ||
474 | |||
475 | ret = nfs4_do_handle_exception(server, errorcode, exception); | ||
476 | if (exception->delay) { | ||
477 | rpc_delay(task, nfs4_update_delay(&exception->timeout)); | ||
478 | goto out_retry; | ||
479 | } | ||
480 | if (exception->recovering) { | ||
481 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | ||
482 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
483 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
484 | goto out_retry; | ||
485 | } | ||
486 | if (test_bit(NFS_MIG_FAILED, &server->mig_status)) | ||
487 | ret = -EIO; | ||
488 | return ret; | ||
489 | out_retry: | ||
490 | if (ret == 0) | ||
491 | exception->retry = 1; | ||
492 | return ret; | ||
493 | } | ||
494 | |||
495 | static int | ||
496 | nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server, | ||
497 | struct nfs4_state *state, long *timeout) | ||
498 | { | ||
499 | struct nfs4_exception exception = { | ||
500 | .state = state, | ||
501 | }; | ||
502 | |||
503 | if (task->tk_status >= 0) | ||
504 | return 0; | ||
505 | if (timeout) | ||
506 | exception.timeout = *timeout; | ||
507 | task->tk_status = nfs4_async_handle_exception(task, server, | ||
508 | task->tk_status, | ||
509 | &exception); | ||
510 | if (exception.delay && timeout) | ||
511 | *timeout = exception.timeout; | ||
512 | if (exception.retry) | ||
513 | return -EAGAIN; | ||
514 | return 0; | ||
515 | } | ||
516 | |||
469 | /* | 517 | /* |
470 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected | 518 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected |
471 | * or 'false' otherwise. | 519 | * or 'false' otherwise. |
@@ -4979,79 +5027,6 @@ out: | |||
4979 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | 5027 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ |
4980 | 5028 | ||
4981 | 5029 | ||
4982 | static int | ||
4983 | nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server, | ||
4984 | struct nfs4_state *state, long *timeout) | ||
4985 | { | ||
4986 | struct nfs_client *clp = server->nfs_client; | ||
4987 | |||
4988 | if (task->tk_status >= 0) | ||
4989 | return 0; | ||
4990 | switch(task->tk_status) { | ||
4991 | case -NFS4ERR_DELEG_REVOKED: | ||
4992 | case -NFS4ERR_ADMIN_REVOKED: | ||
4993 | case -NFS4ERR_BAD_STATEID: | ||
4994 | case -NFS4ERR_OPENMODE: | ||
4995 | if (state == NULL) | ||
4996 | break; | ||
4997 | if (nfs4_schedule_stateid_recovery(server, state) < 0) | ||
4998 | goto recovery_failed; | ||
4999 | goto wait_on_recovery; | ||
5000 | case -NFS4ERR_EXPIRED: | ||
5001 | if (state != NULL) { | ||
5002 | if (nfs4_schedule_stateid_recovery(server, state) < 0) | ||
5003 | goto recovery_failed; | ||
5004 | } | ||
5005 | case -NFS4ERR_STALE_STATEID: | ||
5006 | case -NFS4ERR_STALE_CLIENTID: | ||
5007 | nfs4_schedule_lease_recovery(clp); | ||
5008 | goto wait_on_recovery; | ||
5009 | case -NFS4ERR_MOVED: | ||
5010 | if (nfs4_schedule_migration_recovery(server) < 0) | ||
5011 | goto recovery_failed; | ||
5012 | goto wait_on_recovery; | ||
5013 | case -NFS4ERR_LEASE_MOVED: | ||
5014 | nfs4_schedule_lease_moved_recovery(clp); | ||
5015 | goto wait_on_recovery; | ||
5016 | #if defined(CONFIG_NFS_V4_1) | ||
5017 | case -NFS4ERR_BADSESSION: | ||
5018 | case -NFS4ERR_BADSLOT: | ||
5019 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
5020 | case -NFS4ERR_DEADSESSION: | ||
5021 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
5022 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
5023 | case -NFS4ERR_SEQ_MISORDERED: | ||
5024 | dprintk("%s ERROR %d, Reset session\n", __func__, | ||
5025 | task->tk_status); | ||
5026 | nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); | ||
5027 | goto wait_on_recovery; | ||
5028 | #endif /* CONFIG_NFS_V4_1 */ | ||
5029 | case -NFS4ERR_DELAY: | ||
5030 | nfs_inc_server_stats(server, NFSIOS_DELAY); | ||
5031 | rpc_delay(task, nfs4_update_delay(timeout)); | ||
5032 | goto restart_call; | ||
5033 | case -NFS4ERR_GRACE: | ||
5034 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | ||
5035 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
5036 | case -NFS4ERR_OLD_STATEID: | ||
5037 | goto restart_call; | ||
5038 | } | ||
5039 | task->tk_status = nfs4_map_errors(task->tk_status); | ||
5040 | return 0; | ||
5041 | recovery_failed: | ||
5042 | task->tk_status = -EIO; | ||
5043 | return 0; | ||
5044 | wait_on_recovery: | ||
5045 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | ||
5046 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
5047 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
5048 | if (test_bit(NFS_MIG_FAILED, &server->mig_status)) | ||
5049 | goto recovery_failed; | ||
5050 | restart_call: | ||
5051 | task->tk_status = 0; | ||
5052 | return -EAGAIN; | ||
5053 | } | ||
5054 | |||
5055 | static void nfs4_init_boot_verifier(const struct nfs_client *clp, | 5030 | static void nfs4_init_boot_verifier(const struct nfs_client *clp, |
5056 | nfs4_verifier *bootverf) | 5031 | nfs4_verifier *bootverf) |
5057 | { | 5032 | { |