* [PATCH AUTOSEL 5.17 20/21] block: Do not call folio_next() on an unreferenced folio
[not found] <20220510154340.153400-1-sashal@kernel.org>
@ 2022-05-10 15:43 ` Sasha Levin
2022-05-10 17:29 ` Matthew Wilcox
0 siblings, 1 reply; 2+ messages in thread
From: Sasha Levin @ 2022-05-10 15:43 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Matthew Wilcox (Oracle), Darrick J . Wong, Brian Foster,
Sasha Levin, axboe, linux-block
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
[ Upstream commit 170f37d6aa6ad4582eefd7459015de79e244536e ]
It is unsafe to call folio_next() on a folio unless you hold a reference
on it that prevents it from being split or freed. After returning
from the iterator, iomap calls folio_end_writeback() which may drop
the last reference to the page, or allow the page to be split. If that
happens, the iterator will not advance far enough through the bio_vec,
leading to assertion failures like the BUG() in folio_end_writeback()
that checks we're not trying to end writeback on a page not currently
under writeback. Other assertion failures were also seen, but they're
all explained by this one bug.
Fix the bug by remembering where the next folio starts before returning
from the iterator. There are other ways of fixing this bug, but this
seems the simplest.
Reported-by: Darrick J. Wong <djwong@kernel.org>
Tested-by: Darrick J. Wong <djwong@kernel.org>
Reported-by: Brian Foster <bfoster@redhat.com>
Tested-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/bio.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 117d7f248ac9..2ca54c084d5a 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -272,6 +272,7 @@ struct folio_iter {
size_t offset;
size_t length;
/* private: for use by the iterator */
+ struct folio *_next;
size_t _seg_count;
int _i;
};
@@ -286,6 +287,7 @@ static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio,
PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
fi->_seg_count = bvec->bv_len;
fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
+ fi->_next = folio_next(fi->folio);
fi->_i = i;
}
@@ -293,9 +295,10 @@ static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
{
fi->_seg_count -= fi->length;
if (fi->_seg_count) {
- fi->folio = folio_next(fi->folio);
+ fi->folio = fi->_next;
fi->offset = 0;
fi->length = min(folio_size(fi->folio), fi->_seg_count);
+ fi->_next = folio_next(fi->folio);
} else if (fi->_i + 1 < bio->bi_vcnt) {
bio_first_folio(fi, bio, fi->_i + 1);
} else {
--
2.35.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH AUTOSEL 5.17 20/21] block: Do not call folio_next() on an unreferenced folio
2022-05-10 15:43 ` [PATCH AUTOSEL 5.17 20/21] block: Do not call folio_next() on an unreferenced folio Sasha Levin
@ 2022-05-10 17:29 ` Matthew Wilcox
0 siblings, 0 replies; 2+ messages in thread
From: Matthew Wilcox @ 2022-05-10 17:29 UTC (permalink / raw)
To: Sasha Levin
Cc: linux-kernel, stable, Darrick J . Wong, Brian Foster, axboe,
linux-block
On Tue, May 10, 2022 at 11:43:39AM -0400, Sasha Levin wrote:
> From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
>
> [ Upstream commit 170f37d6aa6ad4582eefd7459015de79e244536e ]
ACK the backport of this patch. The problem is latent in earlier
kernels, but there's no need to leave the trap lying around.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-05-10 17:29 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20220510154340.153400-1-sashal@kernel.org>
2022-05-10 15:43 ` [PATCH AUTOSEL 5.17 20/21] block: Do not call folio_next() on an unreferenced folio Sasha Levin
2022-05-10 17:29 ` Matthew Wilcox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox