Skip to content

Commit 3dc1473

Browse files
committed
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: 446ca21 ("pNFS/flexfiles: When initing reads or writes, we...") Cc: [email protected] # v4.7+ Signed-off-by: Trond Myklebust <[email protected]>
1 parent d138027 commit 3dc1473

File tree

2 files changed

+28
-28
lines changed

2 files changed

+28
-28
lines changed

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -806,11 +806,14 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
806806
{
807807
struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
808808
struct nfs4_pnfs_ds *ds;
809+
bool fail_return = false;
809810
int idx;
810811

811812
/* mirrors are sorted by efficiency */
812813
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);
814817
if (ds) {
815818
*best_idx = idx;
816819
return ds;
@@ -859,6 +862,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
859862
struct nfs4_pnfs_ds *ds;
860863
int ds_idx;
861864

865+
retry:
862866
/* Use full layout for now */
863867
if (!pgio->pg_lseg)
864868
ff_layout_pg_get_read(pgio, req, false);
@@ -871,10 +875,13 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
871875

872876
ds = ff_layout_choose_best_ds_for_read(pgio->pg_lseg, 0, &ds_idx);
873877
if (!ds) {
874-
if (ff_layout_no_fallback_to_mds(pgio->pg_lseg))
875-
goto out_pnfs;
876-
else
878+
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
877879
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;
878885
}
879886

880887
mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx);
@@ -890,12 +897,6 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
890897
pnfs_put_lseg(pgio->pg_lseg);
891898
pgio->pg_lseg = NULL;
892899
nfs_pageio_reset_read_mds(pgio);
893-
return;
894-
895-
out_pnfs:
896-
pnfs_set_lo_fail(pgio->pg_lseg);
897-
pnfs_put_lseg(pgio->pg_lseg);
898-
pgio->pg_lseg = NULL;
899900
}
900901

901902
static void
@@ -909,6 +910,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
909910
int i;
910911
int status;
911912

913+
retry:
912914
if (!pgio->pg_lseg) {
913915
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
914916
req->wb_context,
@@ -940,10 +942,13 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
940942
for (i = 0; i < pgio->pg_mirror_count; i++) {
941943
ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, i, true);
942944
if (!ds) {
943-
if (ff_layout_no_fallback_to_mds(pgio->pg_lseg))
944-
goto out_pnfs;
945-
else
945+
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
946946
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;
947952
}
948953
pgm = &pgio->pg_mirrors[i];
949954
mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i);
@@ -956,12 +961,6 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
956961
pnfs_put_lseg(pgio->pg_lseg);
957962
pgio->pg_lseg = NULL;
958963
nfs_pageio_reset_write_mds(pgio);
959-
return;
960-
961-
out_pnfs:
962-
pnfs_set_lo_fail(pgio->pg_lseg);
963-
pnfs_put_lseg(pgio->pg_lseg);
964-
pgio->pg_lseg = NULL;
965964
}
966965

967966
static unsigned int

fs/nfs/flexfilelayout/flexfilelayoutdev.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
379379

380380
devid = &mirror->mirror_ds->id_node;
381381
if (ff_layout_test_devid_unavailable(devid))
382-
goto out;
382+
goto out_fail;
383383

384384
ds = mirror->mirror_ds->ds;
385385
/* 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,
405405
mirror->mirror_ds->ds_versions[0].rsize = max_payload;
406406
if (mirror->mirror_ds->ds_versions[0].wsize > max_payload)
407407
mirror->mirror_ds->ds_versions[0].wsize = max_payload;
408-
} else {
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;
408+
goto out;
416409
}
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);
414+
out_fail:
415+
if (fail_return || !ff_layout_has_available_ds(lseg))
416+
pnfs_error_mark_layout_for_return(ino, lseg);
417+
ds = NULL;
417418
out:
418419
return ds;
419420
}

0 commit comments

Comments
 (0)