Skip to content

Commit d7ff85d

Browse files
joannekoongbrauner
authored andcommitted
iomap: fix iomap_read_end() for already uptodate folios
There are some cases where when iomap_read_end() is called, the folio may already have been marked uptodate. For example, if the iomap block needed zeroing, then the folio may have been marked uptodate after the zeroing. iomap_read_end() should unlock the folio instead of calling folio_end_read(), which is how these cases were handled prior to commit f8eaf79 ("iomap: simplify ->read_folio_range() error handling for reads"). Calling folio_end_read() on an uptodate folio leads to buggy behavior where marking an already uptodate folio as uptodate will XOR it to be marked nonuptodate. Fixes: f8eaf79 ("iomap: simplify ->read_folio_range() error handling for reads") Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20251118211111.1027272-2-joannelkoong@gmail.com Tested-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reported-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 5ec58e6 commit d7ff85d

1 file changed

Lines changed: 19 additions & 18 deletions

File tree

fs/iomap/buffered-io.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -458,25 +458,26 @@ static void iomap_read_end(struct folio *folio, size_t bytes_submitted)
458458
spin_lock_irq(&ifs->state_lock);
459459
if (!ifs->read_bytes_pending) {
460460
WARN_ON_ONCE(bytes_submitted);
461-
end_read = true;
462-
} else {
463-
/*
464-
* Subtract any bytes that were initially accounted to
465-
* read_bytes_pending but skipped for IO. The +1
466-
* accounts for the bias we added in iomap_read_init().
467-
*/
468-
size_t bytes_not_submitted = folio_size(folio) + 1 -
469-
bytes_submitted;
470-
ifs->read_bytes_pending -= bytes_not_submitted;
471-
/*
472-
* If !ifs->read_bytes_pending, this means all pending
473-
* reads by the IO helper have already completed, which
474-
* means we need to end the folio read here. If
475-
* ifs->read_bytes_pending != 0, the IO helper will end
476-
* the folio read.
477-
*/
478-
end_read = !ifs->read_bytes_pending;
461+
spin_unlock_irq(&ifs->state_lock);
462+
folio_unlock(folio);
463+
return;
479464
}
465+
466+
/*
467+
* Subtract any bytes that were initially accounted to
468+
* read_bytes_pending but skipped for IO. The +1 accounts for
469+
* the bias we added in iomap_read_init().
470+
*/
471+
ifs->read_bytes_pending -=
472+
(folio_size(folio) + 1 - bytes_submitted);
473+
474+
/*
475+
* If !ifs->read_bytes_pending, this means all pending reads by
476+
* the IO helper have already completed, which means we need to
477+
* end the folio read here. If ifs->read_bytes_pending != 0,
478+
* the IO helper will end the folio read.
479+
*/
480+
end_read = !ifs->read_bytes_pending;
480481
if (end_read)
481482
uptodate = ifs_is_fully_uptodate(folio, ifs);
482483
spin_unlock_irq(&ifs->state_lock);

0 commit comments

Comments
 (0)