diff options
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.h | 13 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 1 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 |
4 files changed, 39 insertions, 4 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index eaaca897305c..474c6305afd9 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -182,6 +182,27 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
182 | break; | 182 | break; |
183 | case -NFS4ERR_RETRY_UNCACHED_REP: | 183 | case -NFS4ERR_RETRY_UNCACHED_REP: |
184 | break; | 184 | break; |
185 | /* Invalidate Layout errors */ | ||
186 | case -NFS4ERR_PNFS_NO_LAYOUT: | ||
187 | case -ESTALE: /* mapped NFS4ERR_STALE */ | ||
188 | case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */ | ||
189 | case -EISDIR: /* mapped NFS4ERR_ISDIR */ | ||
190 | case -NFS4ERR_FHEXPIRED: | ||
191 | case -NFS4ERR_WRONG_TYPE: | ||
192 | dprintk("%s Invalid layout error %d\n", __func__, | ||
193 | task->tk_status); | ||
194 | /* | ||
195 | * Destroy layout so new i/o will get a new layout. | ||
196 | * Layout will not be destroyed until all current lseg | ||
197 | * references are put. Mark layout as invalid to resend failed | ||
198 | * i/o and all i/o waiting on the slot table to the MDS until | ||
199 | * layout is destroyed and a new valid layout is obtained. | ||
200 | */ | ||
201 | set_bit(NFS_LAYOUT_INVALID, | ||
202 | &NFS_I(state->inode)->layout->plh_flags); | ||
203 | pnfs_destroy_layout(NFS_I(state->inode)); | ||
204 | rpc_wake_up(&tbl->slot_tbl_waitq); | ||
205 | goto reset; | ||
185 | /* RPC connection errors */ | 206 | /* RPC connection errors */ |
186 | case -ECONNREFUSED: | 207 | case -ECONNREFUSED: |
187 | case -EHOSTDOWN: | 208 | case -EHOSTDOWN: |
@@ -199,6 +220,7 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
199 | nfs4_ds_disconnect(clp); | 220 | nfs4_ds_disconnect(clp); |
200 | /* fall through */ | 221 | /* fall through */ |
201 | default: | 222 | default: |
223 | reset: | ||
202 | dprintk("%s Retry through MDS. Error %d\n", __func__, | 224 | dprintk("%s Retry through MDS. Error %d\n", __func__, |
203 | task->tk_status); | 225 | task->tk_status); |
204 | return -NFS4ERR_RESET_TO_MDS; | 226 | return -NFS4ERR_RESET_TO_MDS; |
@@ -263,9 +285,8 @@ filelayout_set_layoutcommit(struct nfs_write_data *wdata) | |||
263 | static void filelayout_read_prepare(struct rpc_task *task, void *data) | 285 | static void filelayout_read_prepare(struct rpc_task *task, void *data) |
264 | { | 286 | { |
265 | struct nfs_read_data *rdata = data; | 287 | struct nfs_read_data *rdata = data; |
266 | struct pnfs_layout_segment *lseg = rdata->header->lseg; | ||
267 | 288 | ||
268 | if (filelayout_test_devid_invalid(FILELAYOUT_DEVID_NODE(lseg))) { | 289 | if (filelayout_reset_to_mds(rdata->header->lseg)) { |
269 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); | 290 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); |
270 | filelayout_reset_read(rdata); | 291 | filelayout_reset_read(rdata); |
271 | rpc_exit(task, 0); | 292 | rpc_exit(task, 0); |
@@ -366,9 +387,8 @@ static int filelayout_commit_done_cb(struct rpc_task *task, | |||
366 | static void filelayout_write_prepare(struct rpc_task *task, void *data) | 387 | static void filelayout_write_prepare(struct rpc_task *task, void *data) |
367 | { | 388 | { |
368 | struct nfs_write_data *wdata = data; | 389 | struct nfs_write_data *wdata = data; |
369 | struct pnfs_layout_segment *lseg = wdata->header->lseg; | ||
370 | 390 | ||
371 | if (filelayout_test_devid_invalid(FILELAYOUT_DEVID_NODE(lseg))) { | 391 | if (filelayout_reset_to_mds(wdata->header->lseg)) { |
372 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); | 392 | dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); |
373 | filelayout_reset_write(wdata); | 393 | filelayout_reset_write(wdata); |
374 | rpc_exit(task, 0); | 394 | rpc_exit(task, 0); |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 95562ad43e12..43fe802dd678 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
@@ -129,11 +129,24 @@ filelayout_mark_devid_invalid(struct nfs4_deviceid_node *node) | |||
129 | } | 129 | } |
130 | 130 | ||
131 | static inline bool | 131 | static inline bool |
132 | filelayout_test_layout_invalid(struct pnfs_layout_hdr *lo) | ||
133 | { | ||
134 | return test_bit(NFS_LAYOUT_INVALID, &lo->plh_flags); | ||
135 | } | ||
136 | |||
137 | static inline bool | ||
132 | filelayout_test_devid_invalid(struct nfs4_deviceid_node *node) | 138 | filelayout_test_devid_invalid(struct nfs4_deviceid_node *node) |
133 | { | 139 | { |
134 | return test_bit(NFS_DEVICEID_INVALID, &node->flags); | 140 | return test_bit(NFS_DEVICEID_INVALID, &node->flags); |
135 | } | 141 | } |
136 | 142 | ||
143 | static inline bool | ||
144 | filelayout_reset_to_mds(struct pnfs_layout_segment *lseg) | ||
145 | { | ||
146 | return filelayout_test_devid_invalid(FILELAYOUT_DEVID_NODE(lseg)) || | ||
147 | filelayout_test_layout_invalid(lseg->pls_layout); | ||
148 | } | ||
149 | |||
137 | extern struct nfs_fh * | 150 | extern struct nfs_fh * |
138 | nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); | 151 | nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); |
139 | 152 | ||
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index e48017f67fe2..5d09a36b2cd8 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -455,6 +455,7 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) | |||
455 | spin_unlock(&nfsi->vfs_inode.i_lock); | 455 | spin_unlock(&nfsi->vfs_inode.i_lock); |
456 | pnfs_free_lseg_list(&tmp_list); | 456 | pnfs_free_lseg_list(&tmp_list); |
457 | } | 457 | } |
458 | EXPORT_SYMBOL_GPL(pnfs_destroy_layout); | ||
458 | 459 | ||
459 | /* | 460 | /* |
460 | * Called by the state manger to remove all layouts established under an | 461 | * Called by the state manger to remove all layouts established under an |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 9cf9ede8cc52..7980756b2f57 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -63,6 +63,7 @@ enum { | |||
63 | NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ | 63 | NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ |
64 | NFS_LAYOUT_ROC, /* some lseg had roc bit set */ | 64 | NFS_LAYOUT_ROC, /* some lseg had roc bit set */ |
65 | NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ | 65 | NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ |
66 | NFS_LAYOUT_INVALID, /* layout is being destroyed */ | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | enum layoutdriver_policy_flags { | 69 | enum layoutdriver_policy_flags { |