* [PATCH v2] pNFS: avoid repeatedly cancelling I/O for the same lseg
@ 2026-11-05 0:01 Tim Menninger
2026-11-05 2:39 ` Trond Myklebust
0 siblings, 1 reply; 2+ messages in thread
From: Tim Menninger @ 2026-11-05 0:01 UTC (permalink / raw)
To: trondmy, anna
Cc: bcodding, Eric Badger, Jon Curley, Prabhakar Pujeri, linux-nfs,
linux-kernel, stable
Commit b739a5bd9d9f ("NFSv4/flexfiles: Cancel I/O if the layout is
recalled or revoked") added I/O cancellation when a layout segment is
invalidated while outstanding references remain.
The invalid segment stays on the layout's segment list until those
references drain. Subsequent scans can find it again and repeatedly
invoke the layout driver's cancel_io() callback. For flexfiles, this
cancels matching RPC tasks and disconnects data server RPC clients.
During RPC/RDMA data server recovery, repeated cancellation can cause a
reconnect loop that consumes essentially all client CPU and prevents
forward progress.
Record cancellation requests per mirror stripe in the flexfiles layout
segment. Each stripe is cancelled at most once, regardless of how many
times the invalid segment is encountered. A per-stripe bitmap rather
than a single per-segment bit preserves the ability to cancel I/O to a
different device after an earlier device-specific cancellation.
Cancellation is best-effort. An RPC that has already passed the
layout-validity check may not yet be visible to the cancellation
scan. Such I/O retains its lseg reference and remains subject to
the normal RPC completion and recovery paths. Suppress repeated
cancellation and disconnect requests without changing the existing
lseg lifetime and deferred layout-return accounting.
This reproduced on 6.8.0, 7.0.0, and 7.4.0-rc1. It was tested on
7.4.0-rc1 with sustained pNFS/flexfiles I/O over RPC/RDMA while
restarting the NFS service on a data server. Without it, repeated
cancellation led to a reconnect loop and no workload recovery. With it,
the client recovered after the data server returned.
Fixes: b739a5bd9d9f ("NFSv4/flexfiles: Cancel I/O if the layout is recalled or revoked")
Cc: stable@vger.kernel.org
Signed-off-by: Tim Menninger <tmenninger@everpuredata.com>
---
Changes in v2:
- Rework cancellation tracking to accommodate per-device cancellation.
- Track cancellation per stripe rather than per layout segment.
- Clarify that cancellation is best-effort.
- Document the data-server restart reproducer.
- Drop Reviewed-by tag due to substantial implementation changes.
v1: https://lore.kernel.org/all/20260916232906.4101987-1-tmenninger@everpuredata.com/
fs/nfs/flexfilelayout/flexfilelayout.c | 12 ++++++++++++
fs/nfs/flexfilelayout/flexfilelayout.h | 1 +
2 files changed, 13 insertions(+)
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 9492d6bc1d1a7..4419ded8fe586 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -11,6 +11,7 @@
#include <linux/nfs_mount.h>
#include <linux/nfs_page.h>
#include <linux/module.h>
+#include <linux/bitmap.h>
#include <linux/file.h>
#include <linux/sched/mm.h>
@@ -340,6 +341,7 @@ static void _ff_layout_free_lseg(struct nfs4_ff_layout_segment *fls)
{
if (fls) {
ff_layout_free_mirror_array(fls);
+ bitmap_free(fls->cancelled_stripes);
kfree(fls);
}
}
@@ -653,6 +655,12 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
fls->mirror_array[i]->report_interval = be32_to_cpup(p);
out_sort_mirrors:
+ fls->cancelled_stripes = bitmap_zalloc(
+ fls->mirror_array_cnt * dss_count, gfp_flags);
+ if (!fls->cancelled_stripes) {
+ rc = -ENOMEM;
+ goto out_err_free;
+ }
ff_layout_sort_mirrors(fls);
ret = &fls->generic_hdr;
dprintk("<-- %s (success)\n", __func__);
@@ -2582,6 +2590,10 @@ static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg,
if (devid && memcmp(&mirror->dss[dss_id].devid, devid,
sizeof(*devid)) != 0)
continue;
+ /* Do not cancel a stripe again while this lseg drains. */
+ if (test_and_set_bit(idx * mirror->dss_count + dss_id,
+ flseg->cancelled_stripes))
+ continue;
rcu_read_lock();
mirror_ds = rcu_dereference(mirror->dss[dss_id].mirror_ds);
if (IS_ERR_OR_NULL(mirror_ds) ||
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h
index 09c3cd6964fd6..5d5587fded76f 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.h
+++ b/fs/nfs/flexfilelayout/flexfilelayout.h
@@ -109,6 +109,7 @@ struct nfs4_ff_layout_segment {
u64 stripe_unit;
u32 flags;
u32 mirror_array_cnt;
+ unsigned long *cancelled_stripes;
struct nfs4_ff_layout_mirror *mirror_array[] __counted_by(mirror_array_cnt);
};
--
2.53.0
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH v2] pNFS: avoid repeatedly cancelling I/O for the same lseg
2026-11-05 0:01 [PATCH v2] pNFS: avoid repeatedly cancelling I/O for the same lseg Tim Menninger
@ 2026-11-05 2:39 ` Trond Myklebust
0 siblings, 0 replies; 2+ messages in thread
From: Trond Myklebust @ 2026-11-05 2:39 UTC (permalink / raw)
To: Tim Menninger, anna
Cc: bcodding, Eric Badger, Jon Curley, Prabhakar Pujeri, linux-nfs,
linux-kernel, stable
On Thu, 2026-11-05 at 00:01 +0000, Tim Menninger wrote:
> Commit b739a5bd9d9f ("NFSv4/flexfiles: Cancel I/O if the layout is
> recalled or revoked") added I/O cancellation when a layout segment is
> invalidated while outstanding references remain.
>
> The invalid segment stays on the layout's segment list until those
> references drain. Subsequent scans can find it again and repeatedly
> invoke the layout driver's cancel_io() callback. For flexfiles, this
> cancels matching RPC tasks and disconnects data server RPC clients.
> During RPC/RDMA data server recovery, repeated cancellation can cause
> a
> reconnect loop that consumes essentially all client CPU and prevents
> forward progress.
This claim isn't making sense to me.
If a layout segment is recalled or revoked, we should always be
clearing the NFS_LSEG_VALID flag bit in order to prevent it being
looked up again. New RPC calls should not be able to add that layout
segment.
So the only thing that can be found on a second run of
rpc_cancel_tasks() is a task that has been attempted cancelled
previously, but for which that cancel failed.
If you're seeing actual spinning, where the RPC call is just being
requeued by the rpc_call_done() callback, then we need to look at why
the latter is failing to handle the situation correctly.
--
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trondmy@kernel.org, trond.myklebust@hammerspace.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-05 2:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-05 0:01 [PATCH v2] pNFS: avoid repeatedly cancelling I/O for the same lseg Tim Menninger
2026-11-05 2:39 ` Trond Myklebust
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®