Linux filesystem development
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Joanne Koong <joannelkoong@gmail.com>
Cc: brauner@kernel.org, willy@infradead.org, wegao@suse.com,
	sashal@kernel.org, hch@infradead.org,
	linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH v1 1/1] iomap: don't mark folio uptodate if read IO has bytes pending
Date: Wed, 18 Feb 2026 18:45:34 -0800	[thread overview]
Message-ID: <20260219024534.GN6467@frogsfrogsfrogs> (raw)
In-Reply-To: <20260219003911.344478-2-joannelkoong@gmail.com>

On Wed, Feb 18, 2026 at 04:39:11PM -0800, Joanne Koong wrote:
> If a folio has ifs metadata attached to it and the folio is partially
> read in through an async IO helper with the rest of it then being read
> in through post-EOF zeroing or as inline data, and the helper
> successfully finishes the read first, then post-EOF zeroing / reading
> inline will mark the folio as uptodate in iomap_set_range_uptodate().
> 
> This is a problem because when the read completion path later calls
> iomap_read_end(), it will call folio_end_read(), which sets the uptodate
> bit using XOR semantics. Calling folio_end_read() on a folio that was
> already marked uptodate clears the uptodate bit.

Aha, I wondered if that xor thing was going to come back to bite us.

> Fix this by not marking the folio as uptodate if the read IO has bytes
> pending. The folio uptodate state will be set in the read completion
> path through iomap_end_read() -> folio_end_read().
> 
> Reported-by: Wei Gao <wegao@suse.com>
> Suggested-by: Sasha Levin <sashal@kernel.org>
> Tested-by: Wei Gao <wegao@suse.com>
> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> Fixes: b2f35ac4146d ("iomap: add caller-provided callbacks for read and readahead")

I would add:

Link: https://lore.kernel.org/linux-fsdevel/aYbmy8JdgXwsGaPP@autotest-wegao.qe.prg2.suse.org/
Cc: <stable@vger.kernel.org> # v6.19

since the recent discussion around this was sort of buried in a
different thread, and the original patch is now in a released kernel.

> ---
>  fs/iomap/buffered-io.c | 15 ++++++++++++---
>  1 file changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 58887513b894..4fc5ce963feb 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -80,18 +80,27 @@ static void iomap_set_range_uptodate(struct folio *folio, size_t off,
>  {
>  	struct iomap_folio_state *ifs = folio->private;
>  	unsigned long flags;
> -	bool uptodate = true;
> +	bool mark_uptodate = true;
>  
>  	if (folio_test_uptodate(folio))
>  		return;
>  
>  	if (ifs) {
>  		spin_lock_irqsave(&ifs->state_lock, flags);
> -		uptodate = ifs_set_range_uptodate(folio, ifs, off, len);
> +		/*
> +		 * If a read with bytes pending is in progress, we must not call
> +		 * folio_mark_uptodate(). The read completion path
> +		 * (iomap_read_end()) will call folio_end_read(), which uses XOR
> +		 * semantics to set the uptodate bit. If we set it here, the XOR
> +		 * in folio_end_read() will clear it, leaving the folio not
> +		 * uptodate.

Yeah, that makes sense.  How difficult is this to write up as an fstest?

Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

--D

> +		 */
> +		mark_uptodate = ifs_set_range_uptodate(folio, ifs, off, len) &&
> +				!ifs->read_bytes_pending;
>  		spin_unlock_irqrestore(&ifs->state_lock, flags);
>  	}
>  
> -	if (uptodate)
> +	if (mark_uptodate)
>  		folio_mark_uptodate(folio);
>  }
>  
> -- 
> 2.47.3
> 
> 

  reply	other threads:[~2026-02-19  2:45 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-19  0:39 [PATCH v1 0/1] iomap: don't mark folio uptodate if read IO has bytes pending Joanne Koong
2026-02-19  0:39 ` [PATCH v1 1/1] " Joanne Koong
2026-02-19  2:45   ` Darrick J. Wong [this message]
2026-02-19  4:23     ` Matthew Wilcox
2026-02-19  6:11       ` Darrick J. Wong
2026-02-19  6:11         ` Christoph Hellwig
2026-02-20 22:13         ` Joanne Koong
2026-02-20 23:45       ` Darrick J. Wong
2026-02-23 23:53         ` Joanne Koong
2026-02-24 15:16           ` Christoph Hellwig

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=20260219024534.GN6467@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=brauner@kernel.org \
    --cc=hch@infradead.org \
    --cc=joannelkoong@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=sashal@kernel.org \
    --cc=wegao@suse.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