aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2011-02-28 20:34:22 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:43 -0500
commit568e8c494ded95a28c5dd8b79b4d3ffb95b6d845 (patch)
tree00e71f79575635c0ddfcd1210e263088cc121da2 /fs/nfs
parentea8eecdd11ee6becd09c095c8efa88aa7df95961 (diff)
NFSv4.1: turn off pNFS on ds connection failure
If a data server is unavailable, go through MDS. Mark the deviceid containing the data server as a negative cache entry. Do not try to connect to any data server on a deviceid marked as a negative cache entry. Mark any layout that tries to use the marked deviceid as failed. Inodes with a layout marked as fails will not use the layout for I/O, and will not perform any more layoutgets. Inodes without a layout will still do layoutget, but the layout will get marked immediately. 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/nfs4filelayout.c4
-rw-r--r--fs/nfs/nfs4filelayout.h4
-rw-r--r--fs/nfs/nfs4filelayoutdev.c28
-rw-r--r--fs/nfs/pnfs.c9
4 files changed, 36 insertions, 9 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index a922e75af42..0040a5ee620 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -214,7 +214,9 @@ filelayout_read_pagelist(struct nfs_read_data *data)
214 idx = nfs4_fl_calc_ds_index(lseg, j); 214 idx = nfs4_fl_calc_ds_index(lseg, j);
215 ds = nfs4_fl_prepare_ds(lseg, idx); 215 ds = nfs4_fl_prepare_ds(lseg, idx);
216 if (!ds) { 216 if (!ds) {
217 printk(KERN_ERR "%s: prepare_ds failed, use MDS\n", __func__); 217 /* Either layout fh index faulty, or ds connect failed */
218 set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
219 set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
218 return PNFS_NOT_ATTEMPTED; 220 return PNFS_NOT_ATTEMPTED;
219 } 221 }
220 dprintk("%s USE DS:ip %x %hu\n", __func__, 222 dprintk("%s USE DS:ip %x %hu\n", __func__,
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 23f1e1e2a0f..ee0c907742b 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -55,10 +55,14 @@ struct nfs4_pnfs_ds {
55 atomic_t ds_count; 55 atomic_t ds_count;
56}; 56};
57 57
58/* nfs4_file_layout_dsaddr flags */
59#define NFS4_DEVICE_ID_NEG_ENTRY 0x00000001
60
58struct nfs4_file_layout_dsaddr { 61struct nfs4_file_layout_dsaddr {
59 struct hlist_node node; 62 struct hlist_node node;
60 struct nfs4_deviceid deviceid; 63 struct nfs4_deviceid deviceid;
61 atomic_t ref; 64 atomic_t ref;
65 unsigned long flags;
62 u32 stripe_count; 66 u32 stripe_count;
63 u8 *stripe_indices; 67 u8 *stripe_indices;
64 u32 ds_num; 68 u32 ds_num;
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index f594ca35a99..68143c162e3 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -606,6 +606,21 @@ nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
606 return flseg->fh_array[i]; 606 return flseg->fh_array[i];
607} 607}
608 608
609static void
610filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr,
611 int err, u32 ds_addr)
612{
613 u32 *p = (u32 *)&dsaddr->deviceid;
614
615 printk(KERN_ERR "NFS: data server %x connection error %d."
616 " Deviceid [%x%x%x%x] marked out of use.\n",
617 ds_addr, err, p[0], p[1], p[2], p[3]);
618
619 spin_lock(&filelayout_deviceid_lock);
620 dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY;
621 spin_unlock(&filelayout_deviceid_lock);
622}
623
609struct nfs4_pnfs_ds * 624struct nfs4_pnfs_ds *
610nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) 625nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
611{ 626{
@@ -619,13 +634,18 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
619 } 634 }
620 635
621 if (!ds->ds_clp) { 636 if (!ds->ds_clp) {
637 struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
622 int err; 638 int err;
623 639
624 err = nfs4_ds_connect(NFS_SERVER(lseg->pls_layout->plh_inode), 640 if (dsaddr->flags & NFS4_DEVICE_ID_NEG_ENTRY) {
625 dsaddr->ds_list[ds_idx]); 641 /* Already tried to connect, don't try again */
642 dprintk("%s Deviceid marked out of use\n", __func__);
643 return NULL;
644 }
645 err = nfs4_ds_connect(s, ds);
626 if (err) { 646 if (err) {
627 printk(KERN_ERR "%s nfs4_ds_connect error %d\n", 647 filelayout_mark_devid_negative(dsaddr, err,
628 __func__, err); 648 ntohl(ds->ds_ip_addr));
629 return NULL; 649 return NULL;
630 } 650 }
631 } 651 }
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 1f4c153441a..3e545144a0b 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -739,15 +739,16 @@ pnfs_update_layout(struct inode *ino,
739 dprintk("%s matches recall, use MDS\n", __func__); 739 dprintk("%s matches recall, use MDS\n", __func__);
740 goto out_unlock; 740 goto out_unlock;
741 } 741 }
742 /* Check to see if the layout for the given range already exists */
743 lseg = pnfs_find_lseg(lo, iomode);
744 if (lseg)
745 goto out_unlock;
746 742
747 /* if LAYOUTGET already failed once we don't try again */ 743 /* if LAYOUTGET already failed once we don't try again */
748 if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags)) 744 if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags))
749 goto out_unlock; 745 goto out_unlock;
750 746
747 /* Check to see if the layout for the given range already exists */
748 lseg = pnfs_find_lseg(lo, iomode);
749 if (lseg)
750 goto out_unlock;
751
751 if (pnfs_layoutgets_blocked(lo, NULL, 0)) 752 if (pnfs_layoutgets_blocked(lo, NULL, 0))
752 goto out_unlock; 753 goto out_unlock;
753 atomic_inc(&lo->plh_outstanding); 754 atomic_inc(&lo->plh_outstanding);