aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4filelayout.c28
-rw-r--r--fs/nfs/nfs4filelayout.h13
-rw-r--r--fs/nfs/pnfs.c1
-rw-r--r--fs/nfs/pnfs.h1
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:
223reset:
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)
263static void filelayout_read_prepare(struct rpc_task *task, void *data) 285static 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,
366static void filelayout_write_prepare(struct rpc_task *task, void *data) 387static 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
131static inline bool 131static inline bool
132filelayout_test_layout_invalid(struct pnfs_layout_hdr *lo)
133{
134 return test_bit(NFS_LAYOUT_INVALID, &lo->plh_flags);
135}
136
137static inline bool
132filelayout_test_devid_invalid(struct nfs4_deviceid_node *node) 138filelayout_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
143static inline bool
144filelayout_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
137extern struct nfs_fh * 150extern struct nfs_fh *
138nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); 151nfs4_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}
458EXPORT_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
68enum layoutdriver_policy_flags { 69enum layoutdriver_policy_flags {