aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorPeng Tao <tao.peng@primarydata.com>2014-09-05 12:53:23 -0400
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:41 -0500
commit016256df3a7e9eeb3f4dea5ccd0e21a0b63841eb (patch)
tree98a9c9596f3febafdbaeff99e6912f8b295dd897 /fs/nfs
parentf40eb5d044e2eea3f866eeeeb45ca30753773cda (diff)
nfs41: add a helper to mark layout for return
It marks all matching layout segments as NFS_LSEG_LAYOUTRETURN, which is an indicator for pnfs_put_lseg() to send layoutreturn, and also prevents pnfs_update_layout() from using the returning segments. Once it is set, it never gets cleared. It also sets proper io failure bit so that pnfs path can be retried after PNFS_LAYOUTGET_RETRY_TIMEOUT second. Signed-off-by: Peng Tao <tao.peng@primarydata.com> Signed-off-by: Tom Haynes <Thomas.Haynes@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/pnfs.c55
-rw-r--r--fs/nfs/pnfs.h4
2 files changed, 59 insertions, 0 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 1b9720992608..0bd149baca71 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1479,6 +1479,61 @@ out_forget_reply:
1479 goto out; 1479 goto out;
1480} 1480}
1481 1481
1482static void
1483pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
1484 struct list_head *tmp_list,
1485 struct pnfs_layout_range *return_range)
1486{
1487 struct pnfs_layout_segment *lseg, *next;
1488
1489 dprintk("%s:Begin lo %p\n", __func__, lo);
1490
1491 if (list_empty(&lo->plh_segs))
1492 return;
1493
1494 list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
1495 if (should_free_lseg(&lseg->pls_range, return_range)) {
1496 dprintk("%s: marking lseg %p iomode %d "
1497 "offset %llu length %llu\n", __func__,
1498 lseg, lseg->pls_range.iomode,
1499 lseg->pls_range.offset,
1500 lseg->pls_range.length);
1501 set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
1502 mark_lseg_invalid(lseg, tmp_list);
1503 }
1504}
1505
1506void pnfs_error_mark_layout_for_return(struct inode *inode,
1507 struct pnfs_layout_segment *lseg)
1508{
1509 struct pnfs_layout_hdr *lo = NFS_I(inode)->layout;
1510 int iomode = pnfs_iomode_to_fail_bit(lseg->pls_range.iomode);
1511 struct pnfs_layout_range range = {
1512 .iomode = lseg->pls_range.iomode,
1513 .offset = 0,
1514 .length = NFS4_MAX_UINT64,
1515 };
1516 LIST_HEAD(free_me);
1517
1518 spin_lock(&inode->i_lock);
1519 /* set failure bit so that pnfs path will be retried later */
1520 pnfs_layout_set_fail_bit(lo, iomode);
1521 set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
1522 if (lo->plh_return_iomode == 0)
1523 lo->plh_return_iomode = range.iomode;
1524 else if (lo->plh_return_iomode != range.iomode)
1525 lo->plh_return_iomode = IOMODE_ANY;
1526 /*
1527 * mark all matching lsegs so that we are sure to have no live
1528 * segments at hand when sending layoutreturn. See pnfs_put_lseg()
1529 * for how it works.
1530 */
1531 pnfs_mark_matching_lsegs_return(lo, &free_me, &range);
1532 spin_unlock(&inode->i_lock);
1533 pnfs_free_lseg_list(&free_me);
1534}
1535EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
1536
1482void 1537void
1483pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 1538pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
1484{ 1539{
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 4cf0d54e14c3..bea2030eec74 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -38,6 +38,7 @@ enum {
38 NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ 38 NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */
39 NFS_LSEG_ROC, /* roc bit received from server */ 39 NFS_LSEG_ROC, /* roc bit received from server */
40 NFS_LSEG_LAYOUTCOMMIT, /* layoutcommit bit set for layoutcommit */ 40 NFS_LSEG_LAYOUTCOMMIT, /* layoutcommit bit set for layoutcommit */
41 NFS_LSEG_LAYOUTRETURN, /* layoutreturn bit set for layoutreturn */
41}; 42};
42 43
43/* Individual ip address */ 44/* Individual ip address */
@@ -184,6 +185,7 @@ struct pnfs_layout_hdr {
184 u32 plh_barrier; /* ignore lower seqids */ 185 u32 plh_barrier; /* ignore lower seqids */
185 unsigned long plh_retry_timestamp; 186 unsigned long plh_retry_timestamp;
186 unsigned long plh_flags; 187 unsigned long plh_flags;
188 enum pnfs_iomode plh_return_iomode;
187 loff_t plh_lwb; /* last write byte for layoutcommit */ 189 loff_t plh_lwb; /* last write byte for layoutcommit */
188 struct rpc_cred *plh_lc_cred; /* layoutcommit cred */ 190 struct rpc_cred *plh_lc_cred; /* layoutcommit cred */
189 struct inode *plh_inode; 191 struct inode *plh_inode;
@@ -274,6 +276,8 @@ void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp);
274int pnfs_read_done_resend_to_mds(struct nfs_pgio_header *); 276int pnfs_read_done_resend_to_mds(struct nfs_pgio_header *);
275int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *); 277int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *);
276struct nfs4_threshold *pnfs_mdsthreshold_alloc(void); 278struct nfs4_threshold *pnfs_mdsthreshold_alloc(void);
279void pnfs_error_mark_layout_for_return(struct inode *inode,
280 struct pnfs_layout_segment *lseg);
277 281
278/* nfs4_deviceid_flags */ 282/* nfs4_deviceid_flags */
279enum { 283enum {