diff options
author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-02-14 17:32:40 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-03-01 22:37:38 -0500 |
commit | 76c6690522bb3e335ce1e201360df8776cab4d2c (patch) | |
tree | ade5acb43b8b1a85e6c85f032e0c1632b1bf6eee | |
parent | 17aaec816751d77e443dee66d11d9e6ac00ac95c (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.c | 74 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 | ||||
-rw-r--r-- | fs/nfs/pnfs_dev.c | 10 |
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 | ||
791 | static void | ||
792 | ff_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 | |||
800 | static void | ||
801 | ff_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 | |||
791 | static struct nfs4_pnfs_ds * | 809 | static struct nfs4_pnfs_ds * |
792 | ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg, | 810 | ff_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 | ||
841 | static struct nfs4_pnfs_ds * | ||
842 | ff_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 | |||
848 | static struct nfs4_pnfs_ds * | ||
849 | ff_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 | |||
855 | static struct nfs4_pnfs_ds * | ||
856 | ff_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 | |||
821 | static void | 867 | static void |
822 | ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio, | 868 | ff_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 | |||
350 | void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, struct nfs_server *, | 350 | void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, struct nfs_server *, |
351 | const struct nfs4_deviceid *); | 351 | const struct nfs4_deviceid *); |
352 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); | 352 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); |
353 | void nfs4_mark_deviceid_available(struct nfs4_deviceid_node *node); | ||
353 | void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node); | 354 | void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node); |
354 | bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node); | 355 | bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node); |
355 | void nfs4_deviceid_purge_client(const struct nfs_client *); | 356 | void 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) | |||
284 | EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); | 284 | EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); |
285 | 285 | ||
286 | void | 286 | void |
287 | nfs4_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 | } | ||
294 | EXPORT_SYMBOL_GPL(nfs4_mark_deviceid_available); | ||
295 | |||
296 | void | ||
287 | nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node) | 297 | nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node) |
288 | { | 298 | { |
289 | node->timestamp_unavailable = jiffies; | 299 | node->timestamp_unavailable = jiffies; |