[PATCH 0/3] NFS/localio: issue IO inline when not reclaiming memory
From: Mike Snitzer
Date: Mon Jul 06 2026 - 14:05:18 EST
Hi,
Every NFS LOCALIO read, write and commit is currently issued indirectly: it
is queued onto the dedicated !WQ_MEM_RECLAIM nfslocaliod_workqueue rather
than being submitted to the underlying filesystem in the calling context.
That intermediate hop was introduced by commit b9f5dd57f4a5 ("nfs/localio:
use dedicated workqueues for filesystem read and write") because:
LOCALIO submits IO directly into a stacked local filesystem (e.g. XFS)
which may in turn flush its own !WQ_MEM_RECLAIM workqueue. Doing so from a
WQ_MEM_RECLAIM worker -- most importantly writeback's wb_workfn running on
bdi_wq -- or from an explicit PF_MEMALLOC reclaim task trips
check_flush_dependency() and risks a forward-progress deadlock.
However, that hazard only exists when the submitting context is itself a
memory-reclaim context. For ordinary application/task submission -- e.g.
O_DIRECT, or an fsync-driven commit -- the workqueue hop buys nothing: it
just adds a context switch and scheduling latency per IO and throws away the
NFS client's inherent application-context parallelism.
This series makes the hop conditional. It adds a small workqueue-core
helper, current_is_workqueue_mem_reclaim(), that reports whether %current is
a WQ_MEM_RECLAIM worker using exactly the predicate check_flush_dependency()
warns on. LOCALIO uses it (together with the existing PF_MEMALLOC test) in a
new nfs_local_defer_io() helper to decide per-IO whether it must defer to
nfslocaliod_workqueue or may issue the IO inline. Reclaim contexts still
defer and are unaffected; everything else runs inline.
Patch 1 adds current_is_workqueue_mem_reclaim() and applies the gating to
the read and write paths.
Patch 2 removes never-taken FLUSH_SYNC handling from nfs_local_commit()
(every caller supplies a FLUSH_SYNC-stripped "how"), which also
drops the sole user of the ctx->done completion plumbing and the
now-unused "how" argument. No functional change.
Patch 3 extends the same gating to the commit (fsync) path. Note the
writeback-triggered commit does reach here in reclaim context --
nfs_write_inode() (the ->write_inode super_op) runs under wb_workfn
on the WQ_MEM_RECLAIM bdi_wq -- so that case correctly keeps
deferring; only app-context commits run inline.
Patch 1 touches the workqueue core (kernel/workqueue.c, include/linux/
workqueue.h), hence the Cc to Tejun Heo, Lai Jiangshan and LKML. The new
export mirrors the existing current_is_workqueue_rescuer()/current_work()
context-introspection helpers.
Additional note for reviewers:
- The inline path now stacks the NFS pgio path plus the underlying
filesystem's ->write_iter/->read_iter (and vfs_fsync_range) in task
context. The reclaim-context stack-depth concern of b9f5dd57f4a5 (2) is
avoided for the deferred paths; feedback on inline stack headroom under
deeply-stacking filesystems (XFS especially) is welcome.
All review appreciated, thanks.
Mike
Mike Snitzer (3):
NFS/localio: issue IO inline when not in a memory-reclaim context
NFS/localio: remove dead FLUSH_SYNC handling from nfs_local_commit
NFS/localio: issue commit inline when not in a memory-reclaim context
fs/nfs/internal.h | 4 +--
fs/nfs/localio.c | 56 ++++++++++++++++++++++++++++++---------
fs/nfs/write.c | 2 +-
include/linux/workqueue.h | 1 +
kernel/workqueue.c | 24 +++++++++++++++++
5 files changed, 71 insertions(+), 16 deletions(-)
--
2.44.0