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
next prev parent 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