aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-08-29 15:12:54 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-08-29 15:21:16 -0400
commit3dc147359e3dcdf0648f1e2c11f62cfae3160df0 (patch)
tree1282ac36c201cdc5fab01357fe5910d234403e87 /fs
parentd138027a8256a3e9d7657c8d0dae84c08ef2cfe1 (diff)
pNFS/flexfiles: Fix an Oopsable condition when connection to the DS fails
If the attempt to connect to a DS fails inside ff_layout_pg_init_read or ff_layout_pg_init_write, then we currently end up clearing the layout segment carried by the struct nfs_pageio_descriptor, causing an Oops when we later call into ff_layout_read_pagelist/ff_layout_write_pagelist. The fix is to ensure we return the layout and then retry. Fixes: 446ca2195303 ("pNFS/flexfiles: When initing reads or writes, we...") Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c37
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c19
2 files changed, 28 insertions, 28 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index ee1c94c7614c..51b51369704c 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -806,11 +806,14 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
806{ 806{
807 struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); 807 struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
808 struct nfs4_pnfs_ds *ds; 808 struct nfs4_pnfs_ds *ds;
809 bool fail_return = false;
809 int idx; 810 int idx;
810 811
811 /* mirrors are sorted by efficiency */ 812 /* mirrors are sorted by efficiency */
812 for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) { 813 for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) {
813 ds = nfs4_ff_layout_prepare_ds(lseg, idx, false); 814 if (idx+1 == fls->mirror_array_cnt)
815 fail_return = true;
816 ds = nfs4_ff_layout_prepare_ds(lseg, idx, fail_return);
814 if (ds) { 817 if (ds) {
815 *best_idx = idx; 818 *best_idx = idx;
816 return ds; 819 return ds;
@@ -859,6 +862,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
859 struct nfs4_pnfs_ds *ds; 862 struct nfs4_pnfs_ds *ds;
860 int ds_idx; 863 int ds_idx;
861 864
865retry:
862 /* Use full layout for now */ 866 /* Use full layout for now */
863 if (!pgio->pg_lseg) 867 if (!pgio->pg_lseg)
864 ff_layout_pg_get_read(pgio, req, false); 868 ff_layout_pg_get_read(pgio, req, false);
@@ -871,10 +875,13 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
871 875
872 ds = ff_layout_choose_best_ds_for_read(pgio->pg_lseg, 0, &ds_idx); 876 ds = ff_layout_choose_best_ds_for_read(pgio->pg_lseg, 0, &ds_idx);
873 if (!ds) { 877 if (!ds) {
874 if (ff_layout_no_fallback_to_mds(pgio->pg_lseg)) 878 if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
875 goto out_pnfs;
876 else
877 goto out_mds; 879 goto out_mds;
880 pnfs_put_lseg(pgio->pg_lseg);
881 pgio->pg_lseg = NULL;
882 /* Sleep for 1 second before retrying */
883 ssleep(1);
884 goto retry;
878 } 885 }
879 886
880 mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx); 887 mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx);
@@ -890,12 +897,6 @@ out_mds:
890 pnfs_put_lseg(pgio->pg_lseg); 897 pnfs_put_lseg(pgio->pg_lseg);
891 pgio->pg_lseg = NULL; 898 pgio->pg_lseg = NULL;
892 nfs_pageio_reset_read_mds(pgio); 899 nfs_pageio_reset_read_mds(pgio);
893 return;
894
895out_pnfs:
896 pnfs_set_lo_fail(pgio->pg_lseg);
897 pnfs_put_lseg(pgio->pg_lseg);
898 pgio->pg_lseg = NULL;
899} 900}
900 901
901static void 902static void
@@ -909,6 +910,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
909 int i; 910 int i;
910 int status; 911 int status;
911 912
913retry:
912 if (!pgio->pg_lseg) { 914 if (!pgio->pg_lseg) {
913 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 915 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
914 req->wb_context, 916 req->wb_context,
@@ -940,10 +942,13 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
940 for (i = 0; i < pgio->pg_mirror_count; i++) { 942 for (i = 0; i < pgio->pg_mirror_count; i++) {
941 ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, i, true); 943 ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, i, true);
942 if (!ds) { 944 if (!ds) {
943 if (ff_layout_no_fallback_to_mds(pgio->pg_lseg)) 945 if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
944 goto out_pnfs;
945 else
946 goto out_mds; 946 goto out_mds;
947 pnfs_put_lseg(pgio->pg_lseg);
948 pgio->pg_lseg = NULL;
949 /* Sleep for 1 second before retrying */
950 ssleep(1);
951 goto retry;
947 } 952 }
948 pgm = &pgio->pg_mirrors[i]; 953 pgm = &pgio->pg_mirrors[i];
949 mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i); 954 mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i);
@@ -956,12 +961,6 @@ out_mds:
956 pnfs_put_lseg(pgio->pg_lseg); 961 pnfs_put_lseg(pgio->pg_lseg);
957 pgio->pg_lseg = NULL; 962 pgio->pg_lseg = NULL;
958 nfs_pageio_reset_write_mds(pgio); 963 nfs_pageio_reset_write_mds(pgio);
959 return;
960
961out_pnfs:
962 pnfs_set_lo_fail(pgio->pg_lseg);
963 pnfs_put_lseg(pgio->pg_lseg);
964 pgio->pg_lseg = NULL;
965} 964}
966 965
967static unsigned int 966static unsigned int
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index 970efba05ae1..f7a3f6b05369 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -379,7 +379,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
379 379
380 devid = &mirror->mirror_ds->id_node; 380 devid = &mirror->mirror_ds->id_node;
381 if (ff_layout_test_devid_unavailable(devid)) 381 if (ff_layout_test_devid_unavailable(devid))
382 goto out; 382 goto out_fail;
383 383
384 ds = mirror->mirror_ds->ds; 384 ds = mirror->mirror_ds->ds;
385 /* matching smp_wmb() in _nfs4_pnfs_v3/4_ds_connect */ 385 /* matching smp_wmb() in _nfs4_pnfs_v3/4_ds_connect */
@@ -405,15 +405,16 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
405 mirror->mirror_ds->ds_versions[0].rsize = max_payload; 405 mirror->mirror_ds->ds_versions[0].rsize = max_payload;
406 if (mirror->mirror_ds->ds_versions[0].wsize > max_payload) 406 if (mirror->mirror_ds->ds_versions[0].wsize > max_payload)
407 mirror->mirror_ds->ds_versions[0].wsize = max_payload; 407 mirror->mirror_ds->ds_versions[0].wsize = max_payload;
408 } else { 408 goto out;
409 ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
410 mirror, lseg->pls_range.offset,
411 lseg->pls_range.length, NFS4ERR_NXIO,
412 OP_ILLEGAL, GFP_NOIO);
413 if (fail_return || !ff_layout_has_available_ds(lseg))
414 pnfs_error_mark_layout_for_return(ino, lseg);
415 ds = NULL;
416 } 409 }
410 ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
411 mirror, lseg->pls_range.offset,
412 lseg->pls_range.length, NFS4ERR_NXIO,
413 OP_ILLEGAL, GFP_NOIO);
414out_fail:
415 if (fail_return || !ff_layout_has_available_ds(lseg))
416 pnfs_error_mark_layout_for_return(ino, lseg);
417 ds = NULL;
417out: 418out:
418 return ds; 419 return ds;
419} 420}