6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei ming.lei@redhat.com
commit 26064d3e2b4d9a14df1072980e558c636fb023ea upstream.
4GB folio is possible on some ARCHs, such as aarch64, 16GB hugepage
is supported, then 'offset' of folio can't be held in 'unsigned int', cause warning in bio_add_folio_nofail() and IO failure.
Fix it by adjusting 'page' & trimming 'offset' so that `->bi_offset` won't be overflow, and folio can be added to bio successfully.
Fixes: ed9832bc08db ("block: introduce folio awareness and add a bigger size from folio") Cc: Kundan Kumar kundan.kumar@samsung.com Cc: Matthew Wilcox (Oracle) willy@infradead.org Cc: Christoph Hellwig hch@lst.de Cc: Luis Chamberlain mcgrof@kernel.org Cc: Gavin Shan gshan@redhat.com Signed-off-by: Ming Lei ming.lei@redhat.com Reviewed-by: Matthew Wilcox (Oracle) willy@infradead.org Link: https://lore.kernel.org/r/20250312145136.2891229-1-ming.lei@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk [ The follow-up fix fbecd731de05 ("xfs: fix zoned GC data corruption due to wrong bv_offset") addresses issues in the file fs/xfs/xfs_zone_gc.c. This file was first introduced in version v6.15-rc1. So don't backport the follow up fix to 6.12.y. ] Signed-off-by: Alva Lan alvalan9@foxmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- block/bio.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
--- a/block/bio.c +++ b/block/bio.c @@ -1156,9 +1156,10 @@ EXPORT_SYMBOL(bio_add_page); void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, size_t off) { + unsigned long nr = off / PAGE_SIZE; + WARN_ON_ONCE(len > UINT_MAX); - WARN_ON_ONCE(off > UINT_MAX); - __bio_add_page(bio, &folio->page, len, off); + __bio_add_page(bio, folio_page(folio, nr), len, off % PAGE_SIZE); } EXPORT_SYMBOL_GPL(bio_add_folio_nofail);
@@ -1179,9 +1180,11 @@ EXPORT_SYMBOL_GPL(bio_add_folio_nofail); bool bio_add_folio(struct bio *bio, struct folio *folio, size_t len, size_t off) { - if (len > UINT_MAX || off > UINT_MAX) + unsigned long nr = off / PAGE_SIZE; + + if (len > UINT_MAX) return false; - return bio_add_page(bio, &folio->page, len, off) > 0; + return bio_add_page(bio, folio_page(folio, nr), len, off % PAGE_SIZE) > 0; } EXPORT_SYMBOL(bio_add_folio);