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; |
