summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2019-02-14 17:32:40 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2019-03-01 22:37:38 -0500
commit76c6690522bb3e335ce1e201360df8776cab4d2c (patch)
treeade5acb43b8b1a85e6c85f032e0c1632b1bf6eee
parent17aaec816751d77e443dee66d11d9e6ac00ac95c (diff)
NFS/flexfiles: Speed up read failover when DSes are down
If we notice that a DS may be down, we should attempt to read from the other mirrors first before we go back to retry the dead DS. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c74
-rw-r--r--fs/nfs/pnfs.h1
-rw-r--r--fs/nfs/pnfs_dev.c10
3 files changed, 73 insertions, 12 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 747ab2fafb69..44ccfce3784e 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -788,10 +788,28 @@ ff_layout_alloc_commit_info(struct pnfs_layout_segment *lseg,
788 } 788 }
789} 789}
790 790
791static void
792ff_layout_mark_ds_unreachable(struct pnfs_layout_segment *lseg, int idx)
793{
794 struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
795
796 if (devid)
797 nfs4_mark_deviceid_unavailable(devid);
798}
799
800static void
801ff_layout_mark_ds_reachable(struct pnfs_layout_segment *lseg, int idx)
802{
803 struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
804
805 if (devid)
806 nfs4_mark_deviceid_available(devid);
807}
808
791static struct nfs4_pnfs_ds * 809static struct nfs4_pnfs_ds *
792ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg, 810ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg,
793 int start_idx, 811 int start_idx, int *best_idx,
794 int *best_idx) 812 bool check_device)
795{ 813{
796 struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); 814 struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
797 struct nfs4_ff_layout_mirror *mirror; 815 struct nfs4_ff_layout_mirror *mirror;
@@ -799,25 +817,53 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
799 bool fail_return = false; 817 bool fail_return = false;
800 int idx; 818 int idx;
801 819
802 /* mirrors are sorted by efficiency */ 820 /* mirrors are initially sorted by efficiency */
803 for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) { 821 for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) {
804 if (idx+1 == fls->mirror_array_cnt) 822 if (idx+1 == fls->mirror_array_cnt)
805 fail_return = true; 823 fail_return = !check_device;
806 824
807 mirror = FF_LAYOUT_COMP(lseg, idx); 825 mirror = FF_LAYOUT_COMP(lseg, idx);
808 if (ff_layout_test_devid_unavailable(&mirror->mirror_ds->id_node)) 826 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, fail_return);
827 if (!ds)
809 continue; 828 continue;
810 829
811 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, fail_return); 830 if (check_device &&
812 if (ds) { 831 nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node))
813 *best_idx = idx; 832 continue;
814 return ds; 833
815 } 834 *best_idx = idx;
835 return ds;
816 } 836 }
817 837
818 return NULL; 838 return NULL;
819} 839}
820 840
841static struct nfs4_pnfs_ds *
842ff_layout_choose_any_ds_for_read(struct pnfs_layout_segment *lseg,
843 int start_idx, int *best_idx)
844{
845 return ff_layout_choose_ds_for_read(lseg, start_idx, best_idx, false);
846}
847
848static struct nfs4_pnfs_ds *
849ff_layout_choose_valid_ds_for_read(struct pnfs_layout_segment *lseg,
850 int start_idx, int *best_idx)
851{
852 return ff_layout_choose_ds_for_read(lseg, start_idx, best_idx, true);
853}
854
855static struct nfs4_pnfs_ds *
856ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
857 int start_idx, int *best_idx)
858{
859 struct nfs4_pnfs_ds *ds;
860
861 ds = ff_layout_choose_valid_ds_for_read(lseg, start_idx, best_idx);
862 if (ds)
863 return ds;
864 return ff_layout_choose_any_ds_for_read(lseg, start_idx, best_idx);
865}
866
821static void 867static void
822ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio, 868ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
823 struct nfs_page *req, 869 struct nfs_page *req,
@@ -1167,8 +1213,10 @@ static int ff_layout_async_handle_error(struct rpc_task *task,
1167{ 1213{
1168 int vers = clp->cl_nfs_mod->rpc_vers->number; 1214 int vers = clp->cl_nfs_mod->rpc_vers->number;
1169 1215
1170 if (task->tk_status >= 0) 1216 if (task->tk_status >= 0) {
1217 ff_layout_mark_ds_reachable(lseg, idx);
1171 return 0; 1218 return 0;
1219 }
1172 1220
1173 /* Handle the case of an invalid layout segment */ 1221 /* Handle the case of an invalid layout segment */
1174 if (!pnfs_is_valid_lseg(lseg)) 1222 if (!pnfs_is_valid_lseg(lseg))
@@ -1231,6 +1279,8 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
1231 err = ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout), 1279 err = ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
1232 mirror, offset, length, status, opnum, 1280 mirror, offset, length, status, opnum,
1233 GFP_NOIO); 1281 GFP_NOIO);
1282 if (status == NFS4ERR_NXIO)
1283 ff_layout_mark_ds_unreachable(lseg, idx);
1234 pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, lseg); 1284 pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, lseg);
1235 dprintk("%s: err %d op %d status %u\n", __func__, err, opnum, status); 1285 dprintk("%s: err %d op %d status %u\n", __func__, err, opnum, status);
1236} 1286}
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 56659ccce1d8..c0420b979d88 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -350,6 +350,7 @@ void nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *, const struct nf
350void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, struct nfs_server *, 350void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, struct nfs_server *,
351 const struct nfs4_deviceid *); 351 const struct nfs4_deviceid *);
352bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); 352bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
353void nfs4_mark_deviceid_available(struct nfs4_deviceid_node *node);
353void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node); 354void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node);
354bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node); 355bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node);
355void nfs4_deviceid_purge_client(const struct nfs_client *); 356void nfs4_deviceid_purge_client(const struct nfs_client *);
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index ec6b607ff1d7..537b80d693f1 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -284,6 +284,16 @@ nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)
284EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); 284EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node);
285 285
286void 286void
287nfs4_mark_deviceid_available(struct nfs4_deviceid_node *node)
288{
289 if (test_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags)) {
290 clear_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags);
291 smp_mb__after_atomic();
292 }
293}
294EXPORT_SYMBOL_GPL(nfs4_mark_deviceid_available);
295
296void
287nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node) 297nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node)
288{ 298{
289 node->timestamp_unavailable = jiffies; 299 node->timestamp_unavailable = jiffies;