Linux NFS development
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Mike Snitzer <snitzer@hammerspace.com>, 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>,
	 Jonathan Corbet	 <corbet@lwn.net>,
	linux-mm@kvack.org, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH v7 2/5] mm: add folio_mark_dropbehind() to mark a folio dropbehind and account it
Date: Wed, 21 Oct 2026 06:52:59 -0400	[thread overview]
Message-ID: <8b666ab283f58e5913b3e4c33c52742a1153e9bd.camel@kernel.org> (raw)
In-Reply-To: <20261020220346.28020-3-snitzer@kernel.org>

On Tue, 2026-10-20 at 18:03 -0400, Mike Snitzer wrote:
> A folio allocated by an RWF_DONTCACHE write is marked dropbehind before
> it is dirtied, so folio_account_dirtied() adds it to WB_DONTCACHE_DIRTY
> and folio_clear_dirty_for_io() or folio_account_cleaned() subtracts it
> when it is cleaned.  Nothing marks a folio that already exists.  A
> caller that sets PG_dropbehind on a folio that is already dirty
> unbalances the counter: the clean subtracts what was never added, and
> once the counter goes negative, wb_stat_sum() reads it as zero and the
> DONTCACHE writeback kick stops writing anything back for every writer
> on that bdi_writeback.
> 
> Add folio_mark_dropbehind(), the inverse of the clear in
> __filemap_get_folio_mpol(): with the folio locked, mark it and, if it is
> dirty, add it to WB_DONTCACHE_DIRTY.  The folio lock orders this
> against dirtying and against folio_clear_dirty_for_io().  A concurrent
> lookup without FGP_DONTCACHE that clears the flag again subtracts what
> this added.
> 
> The name follows folio_set_dirty() and folio_mark_dirty(): the first
> only sets PG_dirty, the second also accounts the dirty folio.
> folio_set_dropbehind() likewise only sets PG_dropbehind, and
> folio_mark_dropbehind() also accounts it in WB_DONTCACHE_DIRTY.
> 
> A later commit uses it in NFSD to drop a page shared by two misaligned
> WRITEs once both have written it.
> 
> Cc: Jeff Layton <jlayton@kernel.org>
> Cc: Jens Axboe <axboe@kernel.dk>
> Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
> Cc: linux-mm@kvack.org
> Assisted-by: LLM
> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
> ---
>  include/linux/pagemap.h |  1 +
>  mm/filemap.c            | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
> index 0adfa6605653..3012bd95812a 100644
> --- a/include/linux/pagemap.h
> +++ b/include/linux/pagemap.h
> @@ -1310,6 +1310,7 @@ void end_page_writeback(struct page *page);
>  void folio_end_writeback(struct folio *folio);
>  void folio_end_writeback_no_dropbehind(struct folio *folio);
>  void folio_end_dropbehind(struct folio *folio);
> +void folio_mark_dropbehind(struct folio *folio);
>  void folio_wait_stable(struct folio *folio);
>  void __folio_mark_dirty(struct folio *folio, struct address_space *, int warn);
>  void folio_account_cleaned(struct folio *folio, struct bdi_writeback *wb);
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 00fd89cf6f55..ed7e4dbea653 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -1644,6 +1644,37 @@ void folio_end_dropbehind(struct folio *folio)
>  }
>  EXPORT_SYMBOL_GPL(folio_end_dropbehind);
>  
> +/**
> + * folio_mark_dropbehind - mark an existing folio dropbehind
> + * @folio: the folio, locked by the caller
> + *
> + * Mark @folio so that the writeback that cleans it drops it.  A folio that
> + * is already dirty is added to WB_DONTCACHE_DIRTY, as folio_account_dirtied()
> + * would have added it had it been marked when dirtied, so that the clean
> + * that subtracts it leaves the counter balanced.
> + */
> +void folio_mark_dropbehind(struct folio *folio)
> +{
> +	struct address_space *mapping = folio->mapping;
> +
> +	VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
> +
> +	if (folio_test_dropbehind(folio))
> +		return;
> +	folio_set_dropbehind(folio);
> +	if (mapping && folio_test_dirty(folio) &&
> +	    mapping_can_writeback(mapping)) {
> +		struct inode *inode = mapping->host;
> +		struct bdi_writeback *wb;
> +		struct wb_lock_cookie cookie = {};
> +
> +		wb = unlocked_inode_to_wb_begin(inode, &cookie);
> +		wb_stat_mod(wb, WB_DONTCACHE_DIRTY, folio_nr_pages(folio));
> +		unlocked_inode_to_wb_end(inode, &cookie);
> +	}
> +}
> +EXPORT_SYMBOL_GPL(folio_mark_dropbehind);
> +
>  /**
>   * folio_end_writeback_no_dropbehind - End writeback against a folio.
>   * @folio: The folio.

Chuck's sashiko had a comment on this one:

[Severity: Medium]
Could this overcount WB_DONTCACHE_DIRTY if folio_mark_dropbehind() races with
filemap_dirty_folio() in mm/page-writeback.c? The dirtying path can set
PG_dirty before folio_account_dirtied() checks PG_dropbehind, and it need not
hold the folio lock. If folio_mark_dropbehind() sets PG_dropbehind after that
dirty transition but before the accounting check, both paths increment the
counter, while folio_account_cleaned() subtracts it only once. The later NFSD
use of this helper retains the same interleaving. Could the flag update and
dirty accounting be serialized so the counter is incremented only once?
-- 
Jeff Layton <jlayton@kernel.org>

  reply	other threads:[~2026-10-21 10:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-20 22:03 [PATCH v7 0/5] mm, iomap, NFSD: stop uncached writes reading back shared pages Mike Snitzer
2026-10-20 22:03 ` [PATCH v7 1/5] mm: expose WB_DONTCACHE_DIRTY in bdi debugfs stats Mike Snitzer
2026-10-20 22:11   ` Mike Snitzer
2026-10-21 10:50   ` Jeff Layton
2026-10-20 22:03 ` [PATCH v7 2/5] mm: add folio_mark_dropbehind() to mark a folio dropbehind and account it Mike Snitzer
2026-10-21 10:52   ` Jeff Layton [this message]
2026-10-20 22:03 ` [PATCH v7 3/5] mm, iomap: keep a partly covered page until an uncached write completes it Mike Snitzer
2026-10-20 22:03 ` [PATCH v7 4/5] mm, iomap: let an uncached writer complete its shared pages itself Mike Snitzer
2026-10-21 10:54   ` Jeff Layton
2026-10-20 22:03 ` [PATCH v7 5/5] NFSD: drop a shared boundary page only once both WRITEs have written it 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=8b666ab283f58e5913b3e4c33c52742a1153e9bd.camel@kernel.org \
    --to=jlayton@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=axboe@kernel.dk \
    --cc=cel@kernel.org \
    --cc=corbet@lwn.net \
    --cc=hch@lst.de \
    --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=snitzer@hammerspace.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