All of 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: 15+ 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-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]

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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.