]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS on fatal DS connect errors
authorMike Snitzer <snitzer@kernel.org>
Thu, 4 Jun 2026 20:24:02 +0000 (16:24 -0400)
committerAnna Schumaker <anna.schumaker@hammerspace.com>
Mon, 8 Jun 2026 16:06:41 +0000 (12:06 -0400)
Commit f06bedfa62d5 ("pNFS/flexfiles: don't attempt pnfs on fatal DS
errors") teaches ff_layout_{read,write}_pagelist() to return
PNFS_NOT_ATTEMPTED when nfs4_ff_layout_prepare_ds() fails with a
nfs_error_is_fatal() errno (e.g. -ETIMEDOUT from a SOFTCONN connect
deadline, -ENOMEM, -ERESTARTSYS), so that the client gives up instead
of spinning.  pnfs_do_{read,write}() then dispatches the I/O through
pnfs_{read,write}_through_mds() → nfs_pageio_reset_{read,write}_mds().

That fallback is unconditional and silently violates FF_FLAGS_NO_IO_THRU_MDS:
when the layout segment carries the flag (typically single-mirror
appliance layouts where MDS I/O is explicitly forbidden), the
out_failed: path's \`&& !ds_fatal_error\` clause overrides the flag's
short-circuit through ff_layout_avoid_mds_available_ds() and routes
the I/O to the MDS file handle anyway.

This is reachable in practice during a data-server restart: SOFTCONN
exhaustion produces -ETIMEDOUT, which is fatal per nfs_error_is_fatal(),
which triggers PNFS_NOT_ATTEMPTED, which silently goes to MDS.

Preserve the upstream "don't spin on fatal errors" intent for layouts
that permit MDS fallback.  For layouts with FF_FLAGS_NO_IO_THRU_MDS
set, mark the layout for return and request PNFS_TRY_AGAIN instead;
if the server cannot supply a usable layout the failure now surfaces
cleanly via pnfs_update_layout(), rather than via silent MDS I/O that
contradicts the flag.

Fixes: f06bedfa62d5 ("pNFS/flexfiles: don't attempt pnfs on fatal DS errors")
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
fs/nfs/flexfilelayout/flexfilelayout.c

index 99caa8d28c259a1df8cd7bd25e7ce8f5ce770b61..0a4a06d93e6a45ae16b1d32231d795f3885b0618 100644 (file)
@@ -2204,6 +2204,14 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
 out_failed:
        if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error)
                return PNFS_TRY_AGAIN;
+       if (ff_layout_no_fallback_to_mds(lseg)) {
+               /*
+                * FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET,
+                * never fall through to MDS I/O.
+                */
+               pnfs_error_mark_layout_for_return(hdr->inode, lseg);
+               return PNFS_TRY_AGAIN;
+       }
        trace_pnfs_mds_fallback_read_pagelist(hdr->inode,
                        hdr->args.offset, hdr->args.count,
                        IOMODE_READ, NFS_I(hdr->inode)->layout, lseg);
@@ -2289,6 +2297,14 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
 out_failed:
        if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error)
                return PNFS_TRY_AGAIN;
+       if (ff_layout_no_fallback_to_mds(lseg)) {
+               /*
+                * FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET,
+                * never fall through to MDS I/O.
+                */
+               pnfs_error_mark_layout_for_return(hdr->inode, lseg);
+               return PNFS_TRY_AGAIN;
+       }
        trace_pnfs_mds_fallback_write_pagelist(hdr->inode,
                        hdr->args.offset, hdr->args.count,
                        IOMODE_RW, NFS_I(hdr->inode)->layout, lseg);