* [PATCH v2 0/1] iomap: don't mark folio uptodate if read IO has bytes pending
@ 2026-03-03 23:34 Joanne Koong
2026-03-03 23:34 ` [PATCH v2 1/1] " Joanne Koong
2026-03-04 13:19 ` [PATCH v2 0/1] " Christian Brauner
0 siblings, 2 replies; 3+ messages in thread
From: Joanne Koong @ 2026-03-03 23:34 UTC (permalink / raw)
To: brauner; +Cc: djwong, hch, willy, wegao, sashal, stable, linux-fsdevel
This is a fix for this scenario:
->read_folio() gets called on a folio size that is 16k while the file is 4k:
a) ifs->read_bytes_pending gets initialized to 16k
b) ->read_folio_range() is called for the 4k read
c) the 4k read succeeds, ifs->read_bytes_pending is now 12k and the
0 to 4k range is marked uptodate
d) the post-eof blocks are zeroed and marked uptodate in the call to
iomap_set_range_uptodate()
e) iomap_set_range_uptodate() sees all the ranges are marked
uptodate and it marks the folio uptodate
f) iomap_read_end() gets called to subtract the 12k from
ifs->read_bytes_pending. it too sees all the ranges are marked
uptodate and marks the folio uptodate using XOR
g) the XOR call clears the uptodate flag on the folio
The same situation can occur if the last range read for the folio is done as
an inline read and all the previous ranges have already completed by the time
the inline read completes.
For more context, the full discussion can be found in [1]. There was a
discussion about alternative approaches in that thread, but they had more
complications.
There is another discussion in v1 [2] about consolidating the read paths.
Until that is resolved, this patch fixes the issue.
Thanks,
Joanne
[1] https://lore.kernel.org/linux-fsdevel/CAJnrk1Z9za5w4FoJqTGx50zR2haHHaoot1KJViQyEHJQq4=34w@mail.gmail.com/#t
[2] https://lore.kernel.org/linux-fsdevel/20260219003911.344478-1-joannelkoong@gmail.com/T/#u
Changelog
---------
v1: https://lore.kernel.org/linux-fsdevel/20260219003911.344478-1-joannelkoong@gmail.com/T/#u
Changes made to v1:
* Add Darrick's reviewed-by, cc stable@, add link to discussion to commit
message (Darrick)
Joanne Koong (1):
iomap: don't mark folio uptodate if read IO has bytes pending
fs/iomap/buffered-io.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/1] iomap: don't mark folio uptodate if read IO has bytes pending
2026-03-03 23:34 [PATCH v2 0/1] iomap: don't mark folio uptodate if read IO has bytes pending Joanne Koong
@ 2026-03-03 23:34 ` Joanne Koong
2026-03-04 13:19 ` [PATCH v2 0/1] " Christian Brauner
1 sibling, 0 replies; 3+ messages in thread
From: Joanne Koong @ 2026-03-03 23:34 UTC (permalink / raw)
To: brauner; +Cc: djwong, hch, willy, wegao, sashal, stable, linux-fsdevel
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.
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>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Cc: <stable@vger.kernel.org> # v6.19
Link: https://lore.kernel.org/linux-fsdevel/aYbmy8JdgXwsGaPP@autotest-wegao.qe.prg2.suse.org/
Fixes: b2f35ac4146d ("iomap: add caller-provided callbacks for read and readahead")
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
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 bc82083e420a..00f0efaf12b2 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.
+ */
+ 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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 0/1] iomap: don't mark folio uptodate if read IO has bytes pending
2026-03-03 23:34 [PATCH v2 0/1] iomap: don't mark folio uptodate if read IO has bytes pending Joanne Koong
2026-03-03 23:34 ` [PATCH v2 1/1] " Joanne Koong
@ 2026-03-04 13:19 ` Christian Brauner
1 sibling, 0 replies; 3+ messages in thread
From: Christian Brauner @ 2026-03-04 13:19 UTC (permalink / raw)
To: Joanne Koong
Cc: Christian Brauner, djwong, hch, willy, wegao, sashal, stable,
linux-fsdevel
On Tue, 03 Mar 2026 15:34:19 -0800, Joanne Koong wrote:
> This is a fix for this scenario:
>
> ->read_folio() gets called on a folio size that is 16k while the file is 4k:
> a) ifs->read_bytes_pending gets initialized to 16k
> b) ->read_folio_range() is called for the 4k read
> c) the 4k read succeeds, ifs->read_bytes_pending is now 12k and the
> 0 to 4k range is marked uptodate
> d) the post-eof blocks are zeroed and marked uptodate in the call to
> iomap_set_range_uptodate()
> e) iomap_set_range_uptodate() sees all the ranges are marked
> uptodate and it marks the folio uptodate
> f) iomap_read_end() gets called to subtract the 12k from
> ifs->read_bytes_pending. it too sees all the ranges are marked
> uptodate and marks the folio uptodate using XOR
> g) the XOR call clears the uptodate flag on the folio
>
> [...]
Applied to the vfs.fixes branch of the vfs/vfs.git tree.
Patches in the vfs.fixes branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.fixes
[1/1] iomap: don't mark folio uptodate if read IO has bytes pending
https://git.kernel.org/vfs/vfs/c/debc1a492b26
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-03-04 13:19 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-03 23:34 [PATCH v2 0/1] iomap: don't mark folio uptodate if read IO has bytes pending Joanne Koong
2026-03-03 23:34 ` [PATCH v2 1/1] " Joanne Koong
2026-03-04 13:19 ` [PATCH v2 0/1] " Christian Brauner
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.