From: Mike Snitzer <snitzer@kernel.org>
To: Chuck Lever <cel@kernel.org>, Jeff Layton <jlayton@kernel.org>
Cc: linux-nfs@vger.kernel.org, NeilBrown <neil@brown.name>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
Christoph Hellwig <hch@lst.de>, Jens Axboe <axboe@kernel.dk>,
Matthew Wilcox <willy@infradead.org>,
Jonathan Corbet <corbet@lwn.net>,
linux-mm@kvack.org, linux-fsdevel@vger.kernel.org
Subject: [PATCH v8 0/7] mm, iomap, NFSD: stop uncached writes reading back shared pages
Date: Thu, 22 Oct 2026 22:45:41 -0400 [thread overview]
Message-ID: <20261023024548.71123-1-snitzer@kernel.org> (raw)
Hi,
Please consider this v8 for the v7.5 development cycle, so that it can
go upstream in the v7.5 merge window.
An uncached (RWF_DONTCACHE) buffered write drops each page it writes
once that page is written back. A page the write covers only partly is
shared with the neighbouring write, and once the first of the two has
been written back the second has to read it back from disk before it
can write its part. 32 threads writing interleaved records to one file
on XFS (emulated 4Kn NVMe, 4 KiB pages), before and after 5/7:
record pwritev2() flags 4 KiB device MiB/s
bytes reads per write
before after before after
47008 RWF_DONTCACHE 0.97 0.0005 831 2281
47008 RWF_DONTCACHE|RWF_DSYNC 0.99 0.0005 601 1227
6000 RWF_DONTCACHE 0.97 0.0001 121 488
6000 RWF_DONTCACHE|RWF_DSYNC 0.99 0.0002 90 206
What is left after is metadata: 49152-byte records, which cover only
whole pages, read 0.0005 per write either way. The test program and
script that produced this table, and how to run them, are in:
https://lore.kernel.org/linux-nfs/atqJBS8MlYfeUU-t@kernel.org/
5/7 has the page cache keep such a page for the write that completes
it. 6/7 lets a writer that syncs its own write, as NFSD does for a
stable WRITE, complete those pages itself once the sync is done. 7/7
is the NFSD change that uses it. 3/7 reports the DONTCACHE dirty count
in the bdi debugfs stats, and 4/7 adds folio_mark_dropbehind(), which
5/7 and 6/7 use.
1/7 and 2/7 are fixes the review of v7 turned up in code that is
already queued or upstream, and each stands on its own:
- 1/7 fixes 80728157d1bd ("NFSD: cut a misaligned direct-mode WRITE at
page boundaries") in cel/nfsd-testing: where the mapping's smallest
folio is a block larger than a page, NFSD cut a WRITE's misaligned
ends inside a block, so the direct middle and a buffered end shared
it. Chuck, maybe best to fold into 80728157d1bd ?
- 2/7 fixes 88d6f128d06d ("mm: track DONTCACHE dirty pages per
bdi_writeback"), in v7.3: a cached lookup that clears the dropbehind
flag could take a folio off WB_DONTCACHE_DIRTY that was never counted
there, or leave one counted with nothing to uncount it. It applies
to v7.3 as it is, if the mm side would rather take it alone.
The prerequisite NFSD changes are staged in cel/nfsd-testing; this
series applies on top of it at 6d13b7f74eec ("NFSD: Map every NFS_ACLv2
reply status into aclstat2"), and each patch builds with W=1 with no
warnings.
2/7 to 6/7 are mm, with small iomap changes in 5/7 and 6/7, and are
Cc'd to linux-mm and linux-fsdevel. If the mm and iomap maintainers
are agreeable, their acks would let Chuck take the series through the
nfsd tree. But whatever approach the maintainers prefer for this kind
of cross-subsystem merge is obviously fine.
Changes since v7, from Jeff's review and the sashiko findings he
relayed:
- 1/7 and 2/7 are new (above).
- 3/7 (v7 1/5): a comment dropped; Jeff's Reviewed-by.
- 4/7 (v7 2/5): folio_mark_dropbehind() counted a folio as DONTCACHE
dirty when it found PG_dirty set, but PG_dirty is set before
folio_account_dirtied() counts the folio, without the folio lock, so
a folio marked in between was counted twice. It now sets the flag
and tests the dirty tag, which is set in the same i_pages section that
counts the folio, under the i_pages lock.
- 5/7 (v7 3/5): the edge is the smallest folio the mapping allows, a
page or a block where blocks are larger, both in iomap's test and in
what is marked: a larger folio found there, left by readahead or
another buffered write, is no longer marked whole.
- 6/7 (v7 4/5): an edge already clean is dropped before the folio lock
is released, not after with a trylock that could miss it; and only
an edge-sized folio, as in 5/7.
- 7/7 (v7 5/5): unchanged.
Tested on XFS on an emulated 4Kn NVMe, 4 KiB pages, 32 threads of
interleaved 47008-byte records (12288 bytes where noted), 4 KiB device
reads per write, v7 against v8:
v7 v8
RWF_DONTCACHE over large folios
readahead left 0.94 0.0026
RWF_DONTCACHE, 16 KiB blocks 1.62 0.0014
12288-byte records 2.89 0.0004
NFS WRITEs through NFSD DIRECT,
16 KiB blocks 3.46 0.0016
(v7 in 128 MiB runs, v8 in 1 GiB runs; on 16 KiB blocks one block read
back per write is 4.0 here.) In every run of v8, BdiDontcacheDirty
(3/7) was back at 0 after the final sync, including runs mixing
uncached writes, cached writes and mmap stores on one file, and every
record verified.
v7: https://lore.kernel.org/linux-nfs/20261020220346.28020-1-snitzer@kernel.org/
v6: https://lore.kernel.org/linux-nfs/atbfEbgMU6UGkn2X@kernel.org/
v5: https://lore.kernel.org/linux-nfs/20261019150725.1507-1-snitzer@kernel.org/
v4: https://lore.kernel.org/linux-nfs/20261015233309.42999-1-snitzer@kernel.org/
v3: https://lore.kernel.org/linux-nfs/20261001045502.48381-1-snitzer@kernel.org/
v2: https://lore.kernel.org/linux-nfs/20260929231329.22018-1-snitzer@kernel.org/
v1: https://lore.kernel.org/linux-nfs/20260929173423.16149-1-snitzer@kernel.org/
Thanks,
Mike
Mike Snitzer (7):
NFSD: cut a misaligned direct-mode WRITE at the mapping's smallest folio
mm: take a folio off WB_DONTCACHE_DIRTY only if it was counted there
mm: expose WB_DONTCACHE_DIRTY in bdi debugfs stats
mm: add folio_mark_dropbehind() to mark a folio dropbehind and account it
mm, iomap: keep a partly covered page until an uncached write completes it
mm, iomap: let an uncached writer complete its shared pages itself
NFSD: drop a shared boundary page only once both WRITEs have written it
.../filesystems/nfs/nfsd-io-modes.rst | 17 ++
fs/iomap/buffered-io.c | 20 +-
fs/iomap/trace.h | 3 +-
fs/nfsd/vfs.c | 113 ++++++++--
include/linux/fs.h | 8 +-
include/linux/iomap.h | 1 +
include/linux/pagemap.h | 12 ++
mm/backing-dev.c | 6 +
mm/filemap.c | 193 ++++++++++++++++--
9 files changed, 338 insertions(+), 35 deletions(-)
base-commit: 6d13b7f74eec16e08d5e7f772ee119432a14ef2c
--
2.52.0
next reply other threads:[~2026-10-23 2:45 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 2:45 Mike Snitzer [this message]
2026-10-23 2:45 ` [PATCH v8 1/7] NFSD: cut a misaligned direct-mode WRITE at the mapping's smallest folio Mike Snitzer
2026-10-23 17:45 ` Chuck Lever
2026-10-24 1:11 ` Mike Snitzer
2026-10-23 2:45 ` [PATCH v8 2/7] mm: take a folio off WB_DONTCACHE_DIRTY only if it was counted there Mike Snitzer
2026-10-23 2:45 ` [PATCH v8 3/7] mm: expose WB_DONTCACHE_DIRTY in bdi debugfs stats Mike Snitzer
2026-10-23 2:45 ` [PATCH v8 4/7] mm: add folio_mark_dropbehind() to mark a folio dropbehind and account it Mike Snitzer
2026-10-23 2:45 ` [PATCH v8 5/7] mm, iomap: keep a partly covered page until an uncached write completes it Mike Snitzer
2026-10-23 2:45 ` [PATCH v8 6/7] mm, iomap: let an uncached writer complete its shared pages itself Mike Snitzer
2026-10-23 2:45 ` [PATCH v8 7/7] NFSD: drop a shared boundary page only once both WRITEs have written it Mike Snitzer
2026-10-23 10:57 ` [PATCH v8 0/7] mm, iomap, NFSD: stop uncached writes reading back shared pages Jeff Layton
2026-10-23 14:12 ` Mike Snitzer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261023024548.71123-1-snitzer@kernel.org \
--to=snitzer@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=axboe@kernel.dk \
--cc=cel@kernel.org \
--cc=corbet@lwn.net \
--cc=hch@lst.de \
--cc=jlayton@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox