Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Mike Snitzer" <snitzer@kernel.org>,
	"Chuck Lever" <cel@kernel.org>,
	"Jeff Layton" <jlayton@kernel.org>
Cc: 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,
	"Jonathan Flynn" <jonathan.flynn@hammerspace.com>,
	"Anna Schumaker" <anna@kernel.org>
Subject: Re: [PATCH v8 7/7] NFSD: drop a shared boundary page only once both WRITEs have written it
Date: Sat, 24 Oct 2026 02:46:39 +0000	[thread overview]
Message-ID: <sashiko-outbox-183524@kernel.org> (raw)
In-Reply-To: <20261023024548.71123-8-snitzer@kernel.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] nfsd: nfsd_write_dio_seg_hold() uses PAGE_SIZE instead of min folio size
--

commit 49f26acfa03e4ed2bb366e82b2cb9296ee952e69
Author: Mike Snitzer <snitzer@kernel.org>

NFSD: drop a shared boundary page only once both WRITEs have written it

This commit issues buffered DONTCACHE segments of direct-mode WRITEs with
IOCB_DONTCACHE_DEFER so that NFSD can defer marking shared boundary pages
drop-behind until the entire WRITE and its fsync complete. Before writing a
buffered segment, NFSD checks filemap_dontcache_edge_completes() for partly
covered boundary pages and calls filemap_dontcache_edge_complete() once the
WRITE finishes.

> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index ade00dabef187..f151289345c92 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
[ ... ]
> @@ -1406,6 +1407,65 @@ nfsd_write_dio_seg_init(struct nfsd_write_dio_seg *segment,
[ ... ]
> +static void
> +nfsd_write_dio_seg_hold(struct file *file, const struct nfsd_write_dio_seg *seg,
> +			loff_t pos, size_t len, struct nfsd_write_dio_hold *hold)
> +{
> +	struct address_space *mapping = file->f_mapping;
> +
> +	hold->first = pos;
> +	hold->last = pos + len - 1;
> +	hold->complete_first = false;
> +	hold->complete_last = false;
> +	hold->written = 0;
> +	if (seg->claim && len) {
> +		bool one_page = (hold->first >> PAGE_SHIFT) ==
> +				(hold->last >> PAGE_SHIFT);
> +		bool head = hold->first & ~PAGE_MASK;
> +		bool tail = (hold->last + 1) & ~PAGE_MASK;
> +
> +		/* Only a page the segment covers partly is shared. */
> +		if (head || (one_page && tail))
> +			hold->complete_first =
> +				filemap_dontcache_edge_completes(mapping, hold->first);
> +		if (!one_page && tail)
> +			hold->complete_last =
> +				filemap_dontcache_edge_completes(mapping, hold->last);
> +	}
> +}

[Severity: Medium]
Should nfsd_write_dio_seg_hold() compute one_page, head, and tail using the
mapping's minimum folio size rather than PAGE_SHIFT and PAGE_MASK?

In nfsd_write_dio_iters_init(), misaligned direct WRITEs are split at
mapping_min_folio_nrbytes(nf->nf_file->f_mapping) boundaries:

	cut = max3(offset_align, PAGE_SIZE,
		   mapping_min_folio_nrbytes(nf->nf_file->f_mapping));

And during vfs_iocb_iter_write(), iomap_get_folio() treats a folio as a
partly covered edge unit whenever the write does not cover a full
mapping_min_folio_nrbytes() unit, setting FGP_DONTCACHE_EDGE and
FGP_DONTCACHE_DEFER so the page cache leaves the folio unmarked for the
caller to complete:

	if (iter->flags & IOMAP_DONTCACHE) {
		size_t unit = mapping_min_folio_nrbytes(iter->inode->i_mapping);
		size_t off = pos & (unit - 1);
		...
		if (off || len < unit) {
			fgp |= FGP_DONTCACHE_EDGE;
			if (iter->flags & IOMAP_DONTCACHE_DEFER)
				fgp |= FGP_DONTCACHE_DEFER;
			len = min_t(size_t, len, unit - off);
		}
	}

Likewise, filemap_dontcache_edge_completes() and
filemap_dontcache_edge_complete() check filemap_dontcache_edge_unit(), which
tests folio_nr_pages(folio) == mapping_min_folio_nrpages(mapping).

On a large-block-size filesystem where mapping_min_folio_nrbytes(mapping) is
larger than PAGE_SIZE (for example, 16 KiB blocks with 4 KiB pages), if two
neighbouring WRITEs split a 16 KiB minimum-order folio on a 4 KiB PAGE_SIZE
boundary, iomap_get_folio() defers dropbehind marking on that folio via
FGP_DONTCACHE_DEFER, but head and tail in nfsd_write_dio_seg_hold() both
evaluate to false. Wouldn't that leave the shared folio unmarked in the page
cache until reclaim, or cause a partial segment spanning multiple base pages
within the same minimum-order folio to treat hold->first and hold->last as
two separate pages?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261023024548.71123-1-snitzer@kernel.org?part=7


  reply	other threads:[~2026-10-24  2:47 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23  2:45 [PATCH v8 0/7] mm, iomap, NFSD: stop uncached writes reading back shared pages Mike Snitzer
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-24  2:46   ` sashiko-bot
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-24  2:46   ` sashiko-bot
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-24  2:46   ` sashiko-bot
2026-10-23  2:45 ` [PATCH v8 6/7] mm, iomap: let an uncached writer complete its shared pages itself Mike Snitzer
2026-10-24  2:46   ` sashiko-bot
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-24  2:46   ` sashiko-bot [this message]
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=sashiko-outbox-183524@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=anna@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=cel@kernel.org \
    --cc=corbet@lwn.net \
    --cc=hch@lst.de \
    --cc=jlayton@kernel.org \
    --cc=jonathan.flynn@hammerspace.com \
    --cc=linux-mm@kvack.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --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