Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Mike Snitzer <snitzer@kernel.org>, Chuck Lever <cel@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>,
		linux-mm@kvack.org
Subject: Re: [PATCH v4 00/10] NFSD: keep direct-mode I/O out of the page cache
Date: Fri, 16 Oct 2026 07:18:13 -0400	[thread overview]
Message-ID: <224b94f6797ab29cde44f37b4145778829bc41c8.camel@kernel.org> (raw)
In-Reply-To: <20261015233309.42999-1-snitzer@kernel.org>

On Thu, 2026-10-15 at 19:32 -0400, Mike Snitzer wrote:
> Hi,
> 
> This series refines the heuristics NFSD_IO_DIRECT already uses, mostly
> on the WRITE path and in one corner of the READ path: the io_cache_write
> and io_cache_read modes where an aligned request goes to the filesystem
> as O_DIRECT, with DONTCACHE for the parts a misaligned WRITE cannot issue
> directly.
> 
> It does not knowingly undercut anything the existing upstream code is
> built on.  An aligned WRITE is still one O_DIRECT write and an aligned
> READ is still one O_DIRECT read.  A misaligned WRITE is still split into
> a direct middle and buffered ends, and by default those ends are still
> DONTCACHE where the filesystem supports it.  io_cache_read and
> io_cache_write mean what they did, and nothing new is asked of the
> filesystem.  What changes is where the split is cut and when it is worth
> making, which READs are worth expanding, how often a synchronous WRITE
> is persisted, and what happens to the page two misaligned WRITEs share.
> 
> 1/10 is a stable fix.  A misaligned WRITE is split into a direct middle
> and buffered ends, and the middle was cut at the filesystem's DIO offset
> alignment.  Where the page is larger than that alignment (16 and 64 KiB
> pages over 4096-byte blocks, or 4 KiB pages over 512-byte blocks) the
> middle then starts or stops inside the page a buffered end writes, its
> invalidation drops that page, and whichever of the two neighbouring
> WRITEs comes second reads it back from the device.  A misaligned end is
> now cut at a multiple of the larger of the alignment and the page size.
> An end that is already DIO-aligned gets no buffered segment and stays
> where it is, so a DIO-aligned WRITE is still issued direct on every page
> size.  Such an end can share its page with a buffered neighbour, but
> NFSD's direct WRITEs are synchronous and XFS holds its IOLOCK across
> iomap_dio_rw(), the page cache invalidation after the write included,
> so the neighbour cannot dirty that page in between and make the
> invalidation fail.
> 
> 2/10 also marks the direct middle IOCB_DONTCACHE, for when XFS
> re-issues it as buffered I/O (-ENOTBLK) because something else has
> dirtied page cache in its range, such as a local process writing the
> exported file through mmap, which XFS's IOLOCK does not keep out.
> 
> 3/10 splits a misaligned WRITE only for a direct middle of at least
> direct_misaligned_min_bytes (debugfs, default 8192), and moves the
> segment flag decisions into nfsd_write_dio_iters_init(), both from
> Christoph's suggested diff.  The threshold counts bytes: with 1/10 a
> split WRITE's middle is whole pages, and a threshold of two pages would
> demand a 32 KiB middle on 16 KiB pages and 128 KiB on 64 KiB pages.
> 
> 4/10 (Jonathan) adds direct_misaligned_dontcache (default Y), which
> selects whether the parts that are not O_DIRECT are DONTCACHE or
> cached.
> 
> 5/10 stops expanding a READ smaller than its alignment into one or two
> whole aligned device reads.  The check sits in nfsd_direct_read_ok(),
> beside the last-operation-in-COMPOUND check now in nfsd-testing.
> 
> 6/10 persists a FILE_SYNC or DATA_SYNC WRITE that is split, or issued
> buffered, once after all of its segments, instead of once per segment:
> one fsync where there were up to three.  A WRITE issued whole as
> O_DIRECT keeps IOCB_DSYNC, so iomap can still complete a DATA_SYNC
> overwrite with FUA writes.
> 
> 7/10 is an mm patch: folio_mark_dropbehind() marks an existing folio
> dropbehind and keeps WB_DONTCACHE_DIRTY balanced when the folio is
> already dirty, as folio_mark_dirty() does for PG_dirty where
> folio_set_dirty() only sets the flag.  Marking an already dirty folio
> with folio_set_dropbehind() instead drives the counter negative, and
> the DONTCACHE writeback kick then stops writing anything back for every
> writer on that bdi_writeback.
> 
> 8/10 is also mm: it reports WB_DONTCACHE_DIRTY in the bdi debugfs stats,
> as BdiDontcacheDirty and per bdi_writeback as WbDontcacheDirty, summed
> over the per-cpu batches since the flusher targets the summed value.
> The counter drives the DONTCACHE writeback kick but was not reported
> anywhere; this is how the balance 7/10 keeps was observed.  It carries
> Fixes: for the commit that added the counter.
> 
> 7/10 and 8/10 are Cc'd to linux-mm and need an mm ack.
> 
> 9/10 calls folio_mark_dropbehind() to keep the page two misaligned
> WRITEs share until both have written it, with no state in NFSD: 704
> device reads for 42895 WRITEs where there were 45144 for 45664
> (47008-byte records, 32 interleaved writers, 4 KiB pages), and on a
> four-server pNFS flexfiles rig 0.003 device reads per record instead of
> 0.014-0.015, about 2.9 GiB of page-cache growth instead of 11 GiB, and
> 2.4% to 4.9% more write throughput.
> 
> 10/10 adds tracepoints for how each direct-mode READ and WRITE was
> serviced, and why a WRITE was not issued direct.
> 
> The series applies to cel/nfsd-testing (78c334bc5ae6) and each patch
> builds with W=1 with no warnings.
> 
> Changes since v3:
> - Dropped "NFSD: Enable return of an updated stable_how to NFS
>   clients" and "NFSD: add direct-mode WRITE settings that persist each
>   WRITE" (v3 8/9 and 9/9).  The rest of the series does not depend on
>   them.
> - New 1/10, NFSD: cut a misaligned direct-mode WRITE at page
>   boundaries (Cc: stable).  v3 cut the direct middle where the DIO
>   offset alignment falls, which is a page boundary only when that
>   alignment is the page size.
> - Rebased onto the current cel/nfsd-testing.  5/10's size check moved
>   into nfsd_direct_read_ok().
> - Descriptions, comments and nfsd-io-modes.rst corrected throughout,
>   among them: 2/10 says what can still make XFS re-issue the middle
>   buffered once 1/10 keeps it off the pages the buffered ends share;
>   3/10 says why a WRITE misaligned in memory is not split; 4/10 no
>   longer misstates what the split threshold decides.
> - 3/10: the threshold is direct_misaligned_min_bytes (default 8192)
>   instead of direct_misaligned_num_pages (default 2).  On 4 KiB pages
>   the default is unchanged.  The debugfs file is renamed with its unit,
>   so a value written to the old name is not read as bytes.
> - 6/10: a WRITE issued whole as O_DIRECT keeps IOCB_DSYNC; v3 turned a
>   DATA_SYNC overwrite into a plain write plus an fsync.
> - New 7/10, mm: add folio_mark_dropbehind().  v3 marked an already
>   dirty folio dropbehind directly; the clean that follows subtracts it
>   from WB_DONTCACHE_DIRTY, which never counted it, so the counter
>   drifted negative and stopped the DONTCACHE writeback kick for the
>   whole bdi_writeback.
> - New 8/10, mm: expose WB_DONTCACHE_DIRTY in bdi debugfs stats.  Reports
>   the counter 7/10 keeps balanced; Fixes: Jeff's commit that added it.
> - 9/10: claims a page only where a buffered segment covers it partly, at
>   either end of any segment, so a multi-page start or end segment and a
>   sub-page WRITE are handled; claims for a split WRITE at any DIO offset
>   alignment, since 1/10 keeps the direct middle out of the claimed
>   pages; does not claim when the mapping's minimum folio is larger than
>   a page; allocates with __GFP_WRITE; does not mark a page a short
>   write did not reach; a FILE_SYNC or DATA_SYNC WRITE marks its shared
>   pages after its own fsync, when they are clean, so they are not
>   counted as DONTCACHE dirty and do not wake the writeback kick.  The
>   description no longer says marking must not be accounted or that the
>   kick targets marked folios.
> - 10/10: the DONTCACHE state is its own tracepoint argument instead of a
>   bit ORed into the disposition (nsegs is dropped; it follows from the
>   segment sizes); the redundant #include "vfs.h" is gone;
>   NFSD_WRITE_DIO_NO_ALIGN is renamed NFSD_WRITE_DIO_NO_ALIGNMENT to
>   match its string; mem_offset is 0 for a WRITE with no payload.
> 
> 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
> 
> Jonathan Flynn (1):
>   NFSD: add direct_misaligned_dontcache debugfs knob
> 
> Mike Snitzer (9):
>   NFSD: cut a misaligned direct-mode WRITE at page boundaries
>   NFSD: mark the direct middle of a split WRITE IOCB_DONTCACHE as well
>   NFSD: only split a direct-mode WRITE for a worthwhile direct middle
>   NFSD: do not use direct I/O for a READ smaller than its alignment
>   NFSD: persist a synchronous direct-mode WRITE once, after all of its segments
>   mm: add folio_mark_dropbehind() to mark a folio dropbehind and account it
>   mm: expose WB_DONTCACHE_DIRTY in bdi debugfs stats
>   NFSD: keep boundary page of a split direct-mode WRITE until both writers complete
>   NFSD: add tracing for how direct-mode READ and WRITE are serviced
> 
>  .../filesystems/nfs/nfsd-io-modes.rst         |  93 +++++-
>  fs/nfsd/debugfs.c                             |  25 ++
>  fs/nfsd/nfsd.h                                |   2 +
>  fs/nfsd/trace.h                               |  77 +++++
>  fs/nfsd/vfs.c                                 | 265 +++++++++++++++---
>  fs/nfsd/vfs.h                                 |   9 +
>  include/linux/pagemap.h                       |   1 +
>  mm/backing-dev.c                              |  11 +
>  mm/filemap.c                                  |  31 ++
>  9 files changed, 473 insertions(+), 41 deletions(-)
> 
> 
> base-commit: 78c334bc5ae61d23ca1cc2e43079c620f1d40866

I think this all looks good and should be good optimizations.

I take back what I said earlier about splitting the mm: patches out --
you do need the new helper for the later patches in the series. It's
fairly self-contained though so maybe it's not a big deal to carry #7
in the nfsd tree. Note that sashiko has some comments about a potential
race there too. #8 seems like it should go via mm tree though.

The other thing we should consider is whether to make the new controls
you're adding to debugfs into netlink controls instead. I see no reason
not to do that and it'll save us from having to convert them later.
-- 
Jeff Layton <jlayton@kernel.org>


  parent reply	other threads:[~2026-10-16 11:18 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 23:32 [PATCH v4 00/10] NFSD: keep direct-mode I/O out of the page cache Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 01/10] NFSD: cut a misaligned direct-mode WRITE at page boundaries Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 02/10] NFSD: mark the direct middle of a split WRITE IOCB_DONTCACHE as well Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 03/10] NFSD: only split a direct-mode WRITE for a worthwhile direct middle Mike Snitzer
2026-10-16 11:03   ` Jeff Layton
2026-10-15 23:33 ` [PATCH v4 04/10] NFSD: add direct_misaligned_dontcache debugfs knob Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 05/10] NFSD: do not use direct I/O for a READ smaller than its alignment Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 06/10] NFSD: persist a synchronous direct-mode WRITE once, after all of its segments Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 07/10] mm: add folio_mark_dropbehind() to mark a folio dropbehind and account it Mike Snitzer
2026-10-16 11:08   ` Jeff Layton
2026-10-16 11:54     ` Matthew Wilcox
2026-10-16 18:36       ` Chuck Lever
2026-10-15 23:33 ` [PATCH v4 08/10] mm: expose WB_DONTCACHE_DIRTY in bdi debugfs stats Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 09/10] NFSD: keep boundary page of a split direct-mode WRITE until both writers complete Mike Snitzer
2026-10-15 23:33 ` [PATCH v4 10/10] NFSD: add tracing for how direct-mode READ and WRITE are serviced Mike Snitzer
2026-10-16 11:18 ` Jeff Layton [this message]
2026-10-16 19:23 ` [PATCH v4 0/10] NFSD: keep direct-mode I/O out of the page cache Chuck Lever

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=224b94f6797ab29cde44f37b4145778829bc41c8.camel@kernel.org \
    --to=jlayton@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=axboe@kernel.dk \
    --cc=cel@kernel.org \
    --cc=hch@lst.de \
    --cc=linux-mm@kvack.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=snitzer@kernel.org \
    --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