diff options
author | Andy Adamson <andros@netapp.com> | 2012-03-07 10:49:41 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-07 10:53:55 -0500 |
commit | 9cb8196839ab4ec87710526e9c43ac7f5dba69d3 (patch) | |
tree | 97ea8225d7ea1b7ba45785f25d042a18263eaf8e /fs/nfs | |
parent | 4f1abd226d80ef763c50e3930b369b63dffbb312 (diff) |
NFSv4.1 handle DS stateid errors
Handle DS READ and WRITE stateid errors by recovering the stateid on the MDS.
NFS4ERR_OLD_STATEID is ignored as the client always sends a
state sequenceid of zero for DS READ and WRITE stateids.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/delegation.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 29 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 2 |
3 files changed, 31 insertions, 1 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 87f7544f3dce..97d53574bf53 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -474,6 +474,7 @@ void nfs_remove_bad_delegation(struct inode *inode) | |||
474 | nfs_free_delegation(delegation); | 474 | nfs_free_delegation(delegation); |
475 | } | 475 | } |
476 | } | 476 | } |
477 | EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation); | ||
477 | 478 | ||
478 | /** | 479 | /** |
479 | * nfs_expire_all_delegation_types | 480 | * nfs_expire_all_delegation_types |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 47e8f3435d38..b2d3bb5971bb 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/sunrpc/metrics.h> | 36 | #include <linux/sunrpc/metrics.h> |
37 | 37 | ||
38 | #include "internal.h" | 38 | #include "internal.h" |
39 | #include "delegation.h" | ||
39 | #include "nfs4filelayout.h" | 40 | #include "nfs4filelayout.h" |
40 | 41 | ||
41 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 42 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
@@ -86,12 +87,31 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
86 | struct nfs_client *clp, | 87 | struct nfs_client *clp, |
87 | int *reset) | 88 | int *reset) |
88 | { | 89 | { |
90 | struct nfs_server *mds_server = NFS_SERVER(state->inode); | ||
91 | struct nfs_client *mds_client = mds_server->nfs_client; | ||
92 | |||
89 | if (task->tk_status >= 0) | 93 | if (task->tk_status >= 0) |
90 | return 0; | 94 | return 0; |
91 | |||
92 | *reset = 0; | 95 | *reset = 0; |
93 | 96 | ||
94 | switch (task->tk_status) { | 97 | switch (task->tk_status) { |
98 | /* MDS state errors */ | ||
99 | case -NFS4ERR_DELEG_REVOKED: | ||
100 | case -NFS4ERR_ADMIN_REVOKED: | ||
101 | case -NFS4ERR_BAD_STATEID: | ||
102 | if (state != NULL) | ||
103 | nfs_remove_bad_delegation(state->inode); | ||
104 | case -NFS4ERR_OPENMODE: | ||
105 | if (state == NULL) | ||
106 | break; | ||
107 | nfs4_schedule_stateid_recovery(mds_server, state); | ||
108 | goto wait_on_recovery; | ||
109 | case -NFS4ERR_EXPIRED: | ||
110 | if (state != NULL) | ||
111 | nfs4_schedule_stateid_recovery(mds_server, state); | ||
112 | nfs4_schedule_lease_recovery(mds_client); | ||
113 | goto wait_on_recovery; | ||
114 | /* DS session errors */ | ||
95 | case -NFS4ERR_BADSESSION: | 115 | case -NFS4ERR_BADSESSION: |
96 | case -NFS4ERR_BADSLOT: | 116 | case -NFS4ERR_BADSLOT: |
97 | case -NFS4ERR_BAD_HIGH_SLOT: | 117 | case -NFS4ERR_BAD_HIGH_SLOT: |
@@ -117,8 +137,15 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
117 | *reset = 1; | 137 | *reset = 1; |
118 | break; | 138 | break; |
119 | } | 139 | } |
140 | out: | ||
120 | task->tk_status = 0; | 141 | task->tk_status = 0; |
121 | return -EAGAIN; | 142 | return -EAGAIN; |
143 | wait_on_recovery: | ||
144 | rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL); | ||
145 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0) | ||
146 | rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task); | ||
147 | goto out; | ||
148 | |||
122 | } | 149 | } |
123 | 150 | ||
124 | /* NFS_PROTO call done callback routines */ | 151 | /* NFS_PROTO call done callback routines */ |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 1dad5c53c7fa..a58d02a0c27d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1072,6 +1072,7 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) | |||
1072 | set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | 1072 | set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
1073 | nfs4_schedule_state_manager(clp); | 1073 | nfs4_schedule_state_manager(clp); |
1074 | } | 1074 | } |
1075 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); | ||
1075 | 1076 | ||
1076 | void nfs4_schedule_path_down_recovery(struct nfs_client *clp) | 1077 | void nfs4_schedule_path_down_recovery(struct nfs_client *clp) |
1077 | { | 1078 | { |
@@ -1109,6 +1110,7 @@ void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4 | |||
1109 | nfs4_state_mark_reclaim_nograce(clp, state); | 1110 | nfs4_state_mark_reclaim_nograce(clp, state); |
1110 | nfs4_schedule_state_manager(clp); | 1111 | nfs4_schedule_state_manager(clp); |
1111 | } | 1112 | } |
1113 | EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery); | ||
1112 | 1114 | ||
1113 | void nfs_inode_find_state_and_recover(struct inode *inode, | 1115 | void nfs_inode_find_state_and_recover(struct inode *inode, |
1114 | const nfs4_stateid *stateid) | 1116 | const nfs4_stateid *stateid) |