Skip to content

Commit

Permalink
pnfs/flexfiles: retry getting layout segment for reads
Browse files Browse the repository at this point in the history
If ff_layout_pg_get_read()'s attempt to get a layout segment results
in -EAGAIN have ff_layout_pg_init_read() retry it after sleeping.

If "softerr" mount is used, use 'io_maxretrans' to limit the number of
attempts to get a layout segment.

This fixes a long-standing issue of O_DIRECT reads failing with
-EAGAIN (11) when using flexfiles Client Side Mirroring (CSM).

Cc: stable@vger.kernel.org
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
  • Loading branch information
Mike Snitzer authored and Anna Schumaker committed Jan 22, 2025
1 parent 0b96c75 commit eb3fabd
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions fs/nfs/flexfilelayout/flexfilelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,9 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
struct nfs4_pnfs_ds *ds;
u32 ds_idx;

if (NFS_SERVER(pgio->pg_inode)->flags &
(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
pgio->pg_maxretrans = io_maxretrans;
retry:
pnfs_generic_pg_check_layout(pgio, req);
/* Use full layout for now */
Expand All @@ -861,6 +864,8 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
if (!pgio->pg_lseg)
goto out_nolseg;
}
/* Reset wb_nio, since getting layout segment was successful */
req->wb_nio = 0;

ds = ff_layout_get_ds_for_read(pgio, &ds_idx);
if (!ds) {
Expand All @@ -877,14 +882,24 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;

pgio->pg_mirror_idx = ds_idx;

if (NFS_SERVER(pgio->pg_inode)->flags &
(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
pgio->pg_maxretrans = io_maxretrans;
return;
out_nolseg:
if (pgio->pg_error < 0)
return;
if (pgio->pg_error < 0) {
if (pgio->pg_error != -EAGAIN)
return;
/* Retry getting layout segment if lower layer returned -EAGAIN */
if (pgio->pg_maxretrans && req->wb_nio++ > pgio->pg_maxretrans) {
if (NFS_SERVER(pgio->pg_inode)->flags & NFS_MOUNT_SOFTERR)
pgio->pg_error = -ETIMEDOUT;
else
pgio->pg_error = -EIO;
return;
}
pgio->pg_error = 0;
/* Sleep for 1 second before retrying */
ssleep(1);
goto retry;
}
out_mds:
trace_pnfs_mds_fallback_pg_init_read(pgio->pg_inode,
0, NFS4_MAX_UINT64, IOMODE_READ,
Expand Down

0 comments on commit eb3fabd

Please sign in to comment.