Skip to content

Commit 563c53e

Browse files
author
Trond Myklebust
committed
NFS: Fix flexfiles read failover
The current mirrored read failover code is correctly resetting the mirror index between failed reads, however it is not able to actually flip the RPC call over to the next RPC client. The end result is that we keep resending the RPC call to the same client over and over. The fix is to use the pnfs_read_resend_pnfs() mechanism to schedule a new RPC call, but we need to add the ability to pass in a mirror index so that we always retry the next mirror in the list. Fixes: 166bd5b ("pNFS/flexfiles: Fix layoutstats handling during read failovers") Signed-off-by: Trond Myklebust <[email protected]>
1 parent a503291 commit 563c53e

File tree

3 files changed

+40
-16
lines changed

3 files changed

+40
-16
lines changed

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,19 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
790790
return ff_layout_choose_any_ds_for_read(lseg, start_idx, best_idx);
791791
}
792792

793+
static struct nfs4_pnfs_ds *
794+
ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio, int *best_idx)
795+
{
796+
struct pnfs_layout_segment *lseg = pgio->pg_lseg;
797+
struct nfs4_pnfs_ds *ds;
798+
799+
ds = ff_layout_choose_best_ds_for_read(lseg, pgio->pg_mirror_idx,
800+
best_idx);
801+
if (ds || !pgio->pg_mirror_idx)
802+
return ds;
803+
return ff_layout_choose_best_ds_for_read(lseg, 0, best_idx);
804+
}
805+
793806
static void
794807
ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
795808
struct nfs_page *req,
@@ -840,7 +853,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
840853
goto out_nolseg;
841854
}
842855

843-
ds = ff_layout_choose_best_ds_for_read(pgio->pg_lseg, 0, &ds_idx);
856+
ds = ff_layout_get_ds_for_read(pgio, &ds_idx);
844857
if (!ds) {
845858
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
846859
goto out_mds;
@@ -1022,11 +1035,24 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
10221035
}
10231036
}
10241037

1038+
static void ff_layout_resend_pnfs_read(struct nfs_pgio_header *hdr)
1039+
{
1040+
u32 idx = hdr->pgio_mirror_idx + 1;
1041+
int new_idx = 0;
1042+
1043+
if (ff_layout_choose_any_ds_for_read(hdr->lseg, idx + 1, &new_idx))
1044+
ff_layout_send_layouterror(hdr->lseg);
1045+
else
1046+
pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg);
1047+
pnfs_read_resend_pnfs(hdr, new_idx);
1048+
}
1049+
10251050
static void ff_layout_reset_read(struct nfs_pgio_header *hdr)
10261051
{
10271052
struct rpc_task *task = &hdr->task;
10281053

10291054
pnfs_layoutcommit_inode(hdr->inode, false);
1055+
pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg);
10301056

10311057
if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
10321058
dprintk("%s Reset task %5u for i/o through MDS "
@@ -1228,6 +1254,12 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
12281254
break;
12291255
case NFS4ERR_NXIO:
12301256
ff_layout_mark_ds_unreachable(lseg, idx);
1257+
/*
1258+
* Don't return the layout if this is a read and we still
1259+
* have layouts to try
1260+
*/
1261+
if (opnum == OP_READ)
1262+
break;
12311263
/* Fallthrough */
12321264
default:
12331265
pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode,
@@ -1241,7 +1273,6 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
12411273
static int ff_layout_read_done_cb(struct rpc_task *task,
12421274
struct nfs_pgio_header *hdr)
12431275
{
1244-
int new_idx = hdr->pgio_mirror_idx;
12451276
int err;
12461277

12471278
if (task->tk_status < 0) {
@@ -1261,10 +1292,6 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
12611292
clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
12621293
switch (err) {
12631294
case -NFS4ERR_RESET_TO_PNFS:
1264-
if (ff_layout_choose_best_ds_for_read(hdr->lseg,
1265-
hdr->pgio_mirror_idx + 1,
1266-
&new_idx))
1267-
goto out_layouterror;
12681295
set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
12691296
return task->tk_status;
12701297
case -NFS4ERR_RESET_TO_MDS:
@@ -1275,10 +1302,6 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
12751302
}
12761303

12771304
return 0;
1278-
out_layouterror:
1279-
ff_layout_read_record_layoutstats_done(task, hdr);
1280-
ff_layout_send_layouterror(hdr->lseg);
1281-
hdr->pgio_mirror_idx = new_idx;
12821305
out_eagain:
12831306
rpc_restart_call_prepare(task);
12841307
return -EAGAIN;
@@ -1405,10 +1428,9 @@ static void ff_layout_read_release(void *data)
14051428
struct nfs_pgio_header *hdr = data;
14061429

14071430
ff_layout_read_record_layoutstats_done(&hdr->task, hdr);
1408-
if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags)) {
1409-
ff_layout_send_layouterror(hdr->lseg);
1410-
pnfs_read_resend_pnfs(hdr);
1411-
} else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
1431+
if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
1432+
ff_layout_resend_pnfs_read(hdr);
1433+
else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
14121434
ff_layout_reset_read(hdr);
14131435
pnfs_generic_rw_release(data);
14141436
}

fs/nfs/pnfs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2939,7 +2939,8 @@ pnfs_try_to_read_data(struct nfs_pgio_header *hdr,
29392939
}
29402940

29412941
/* Resend all requests through pnfs. */
2942-
void pnfs_read_resend_pnfs(struct nfs_pgio_header *hdr)
2942+
void pnfs_read_resend_pnfs(struct nfs_pgio_header *hdr,
2943+
unsigned int mirror_idx)
29432944
{
29442945
struct nfs_pageio_descriptor pgio;
29452946

@@ -2950,6 +2951,7 @@ void pnfs_read_resend_pnfs(struct nfs_pgio_header *hdr)
29502951

29512952
nfs_pageio_init_read(&pgio, hdr->inode, false,
29522953
hdr->completion_ops);
2954+
pgio.pg_mirror_idx = mirror_idx;
29532955
hdr->task.tk_status = nfs_pageio_resend(&pgio, hdr);
29542956
}
29552957
}

fs/nfs/pnfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ int _pnfs_return_layout(struct inode *);
311311
int pnfs_commit_and_return_layout(struct inode *);
312312
void pnfs_ld_write_done(struct nfs_pgio_header *);
313313
void pnfs_ld_read_done(struct nfs_pgio_header *);
314-
void pnfs_read_resend_pnfs(struct nfs_pgio_header *);
314+
void pnfs_read_resend_pnfs(struct nfs_pgio_header *, unsigned int mirror_idx);
315315
struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
316316
struct nfs_open_context *ctx,
317317
loff_t pos,

0 commit comments

Comments
 (0)