mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
pNFS/flexfiles: don't reset to MDS for v4 error when previous layout forbid it
ff_layout_async_handle_error_v4() ends in -NFS4ERR_RESET_TO_MDS, which
makes ff_layout_read_release() / ff_layout_write_release() call
ff_layout_reset_read() or ff_layout_reset_write(hdr, false), and those
call pnfs_read_done_resend_to_mds() / pnfs_write_done_resend_to_mds().
Those build a page I/O descriptor with force_mds set, so the flexfiles
->pg_init() never runs and no layout is consulted anywhere on the way:
the READ or WRITE goes to the metadata server unconditionally. For a
layout carrying FF_FLAGS_NO_IO_THRU_MDS that is exactly what the server
forbade.
The fall-through into reset: is already safe, because
ff_layout_avoid_mds_available_ds() returns true for a segment with the
flag and so answers -NFS4ERR_RESET_TO_PNFS first. What is not safe is
the goto: the invalid-layout errors (NFS4ERR_PNFS_NO_LAYOUT, STALE,
BADHANDLE, ISDIR, FHEXPIRED, WRONG_TYPE) call pnfs_destroy_layout() and
jump straight to reset:, over that check. That is the case where the
file had a perfectly good layout, something forced it to be given back,
and the client answers by writing to the MDS behind the server's back.
Test at reset: itself, so it covers the goto and any future one, and ask
the inode (NFS_INO_NO_IO_THRU_MDS): the callers that jump here have just
destroyed the layout hdr, so the hdr-level flag is no longer reachable,
while the inode-level one is set for the life of the in-core inode.
-NFS4ERR_RESET_TO_PNFS is the right answer rather than an error. It is
what the fall-through already returns for the same flag, and the
resends it drives - ff_layout_resend_pnfs_read() and
ff_layout_reset_write(hdr, true) - re-enter the pgio path with force_mds
clear, so a fresh LAYOUTGET is taken, which is precisely what a
destroyed layout needs. A LAYOUTGET that fails fatally makes
pnfs_update_layout() return an error, which ->pg_init() reports; a
non-fatal refusal (NFS4ERR_LAYOUTUNAVAILABLE, NFS4ERR_TOOSMALL) returns
no segment instead, and the client keeps retrying through pNFS rather
than falling back.
ff_layout_async_handle_error_v3() needs no such change: it returns only
-NFS4ERR_RESET_TO_PNFS or -EAGAIN.
Fixes: 260074cd84 ("pNFS/flexfiles: Add support for FF_FLAGS_NO_IO_THRU_MDS")
Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
This commit is contained in:
parent
2f007ba074
commit
ec906cf7be
|
|
@ -1423,6 +1423,23 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
|
|||
if (ff_layout_avoid_mds_available_ds(lseg))
|
||||
return -NFS4ERR_RESET_TO_PNFS;
|
||||
reset:
|
||||
/*
|
||||
* FF_FLAGS_NO_IO_THRU_MDS: never resend through the MDS. The
|
||||
* caller would do so with force_mds set (ff_layout_reset_read(),
|
||||
* ff_layout_reset_write(hdr, false) -> pnfs_*_done_resend_to_mds()),
|
||||
* which builds a descriptor out of the plain MDS page ops and so
|
||||
* consults no layout at all -- this is the last point at which the
|
||||
* policy can still be applied. Retry through pNFS instead, which
|
||||
* takes a fresh LAYOUTGET; that is also the right answer for the
|
||||
* invalid-layout cases that jump here, since they have just called
|
||||
* pnfs_destroy_layout(). Having done so they can no longer ask the
|
||||
* layout hdr about the flag, hence the inode.
|
||||
*/
|
||||
if (nfs_no_io_thru_mds(inode)) {
|
||||
dprintk("%s Retry through pNFS, no MDS fallback. Error %d\n",
|
||||
__func__, task->tk_status);
|
||||
return -NFS4ERR_RESET_TO_PNFS;
|
||||
}
|
||||
dprintk("%s Retry through MDS. Error %d\n", __func__,
|
||||
task->tk_status);
|
||||
return -NFS4ERR_RESET_TO_MDS;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user