diff options
author | Andy Adamson <andros@netapp.com> | 2011-02-28 20:34:20 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-11 15:38:43 -0500 |
commit | cbdabc7f8bf14ca1d40ab1cb86f64b3bc09716e8 (patch) | |
tree | 16939b96996e8380d91d7e2743e811cf5c49f629 /fs/nfs/nfs4filelayout.c | |
parent | dc70d7b3189597f313df7bd2da849cfc39063b15 (diff) |
NFSv4.1: filelayout async error handler
Use our own async error handler.
Mark the layout as failed and retry i/o through the MDS on specified errors.
Update the mds_offset in nfs_readpage_retry so that a failed short-read retry
to a DS gets correctly resent through the MDS.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4filelayout.c')
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 3608411653dc..6a424c19abea 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -40,6 +40,8 @@ MODULE_LICENSE("GPL"); | |||
40 | MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>"); | 40 | MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>"); |
41 | MODULE_DESCRIPTION("The NFSv4 file layout driver"); | 41 | MODULE_DESCRIPTION("The NFSv4 file layout driver"); |
42 | 42 | ||
43 | #define FILELAYOUT_POLL_RETRY_MAX (15*HZ) | ||
44 | |||
43 | static int | 45 | static int |
44 | filelayout_set_layoutdriver(struct nfs_server *nfss) | 46 | filelayout_set_layoutdriver(struct nfs_server *nfss) |
45 | { | 47 | { |
@@ -100,6 +102,83 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset) | |||
100 | BUG(); | 102 | BUG(); |
101 | } | 103 | } |
102 | 104 | ||
105 | /* For data server errors we don't recover from */ | ||
106 | static void | ||
107 | filelayout_set_lo_fail(struct pnfs_layout_segment *lseg) | ||
108 | { | ||
109 | if (lseg->pls_range.iomode == IOMODE_RW) { | ||
110 | dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__); | ||
111 | set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); | ||
112 | } else { | ||
113 | dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__); | ||
114 | set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static int filelayout_async_handle_error(struct rpc_task *task, | ||
119 | struct nfs4_state *state, | ||
120 | struct nfs_client *clp, | ||
121 | int *reset) | ||
122 | { | ||
123 | if (task->tk_status >= 0) | ||
124 | return 0; | ||
125 | |||
126 | *reset = 0; | ||
127 | |||
128 | switch (task->tk_status) { | ||
129 | case -NFS4ERR_BADSESSION: | ||
130 | case -NFS4ERR_BADSLOT: | ||
131 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
132 | case -NFS4ERR_DEADSESSION: | ||
133 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
134 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
135 | case -NFS4ERR_SEQ_MISORDERED: | ||
136 | dprintk("%s ERROR %d, Reset session. Exchangeid " | ||
137 | "flags 0x%x\n", __func__, task->tk_status, | ||
138 | clp->cl_exchange_flags); | ||
139 | nfs4_schedule_session_recovery(clp->cl_session); | ||
140 | break; | ||
141 | case -NFS4ERR_DELAY: | ||
142 | case -NFS4ERR_GRACE: | ||
143 | case -EKEYEXPIRED: | ||
144 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); | ||
145 | break; | ||
146 | default: | ||
147 | dprintk("%s DS error. Retry through MDS %d\n", __func__, | ||
148 | task->tk_status); | ||
149 | *reset = 1; | ||
150 | break; | ||
151 | } | ||
152 | task->tk_status = 0; | ||
153 | return -EAGAIN; | ||
154 | } | ||
155 | |||
156 | /* NFS_PROTO call done callback routines */ | ||
157 | |||
158 | static int filelayout_read_done_cb(struct rpc_task *task, | ||
159 | struct nfs_read_data *data) | ||
160 | { | ||
161 | struct nfs_client *clp = data->ds_clp; | ||
162 | int reset = 0; | ||
163 | |||
164 | dprintk("%s DS read\n", __func__); | ||
165 | |||
166 | if (filelayout_async_handle_error(task, data->args.context->state, | ||
167 | data->ds_clp, &reset) == -EAGAIN) { | ||
168 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", | ||
169 | __func__, data->ds_clp, data->ds_clp->cl_session); | ||
170 | if (reset) { | ||
171 | filelayout_set_lo_fail(data->lseg); | ||
172 | nfs4_reset_read(task, data); | ||
173 | clp = NFS_SERVER(data->inode)->nfs_client; | ||
174 | } | ||
175 | nfs_restart_rpc(task, clp); | ||
176 | return -EAGAIN; | ||
177 | } | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
103 | /* | 182 | /* |
104 | * Call ops for the async read/write cases | 183 | * Call ops for the async read/write cases |
105 | * In the case of dense layouts, the offset needs to be reset to its | 184 | * In the case of dense layouts, the offset needs to be reset to its |
@@ -109,6 +188,8 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) | |||
109 | { | 188 | { |
110 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; | 189 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; |
111 | 190 | ||
191 | rdata->read_done_cb = filelayout_read_done_cb; | ||
192 | |||
112 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, | 193 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, |
113 | &rdata->args.seq_args, &rdata->res.seq_res, | 194 | &rdata->args.seq_args, &rdata->res.seq_res, |
114 | 0, task)) | 195 | 0, task)) |