Commit eb3fabde authored by Mike Snitzer's avatar Mike Snitzer Committed by Anna Schumaker
Browse files

pnfs/flexfiles: retry getting layout segment for reads



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: default avatarMike Snitzer <snitzer@kernel.org>
Signed-off-by: default avatarAnna Schumaker <anna.schumaker@oracle.com>
parent 0b96c75d
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -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 */
@@ -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) {
@@ -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)
	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,