Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: fix adding folio to bio

>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>

authored by

Ming Lei and committed by
Jens Axboe
26064d3e 61667cb6

+7 -4
+7 -4
block/bio.c
··· 1026 1026 void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, 1027 1027 size_t off) 1028 1028 { 1029 + unsigned long nr = off / PAGE_SIZE; 1030 + 1029 1031 WARN_ON_ONCE(len > UINT_MAX); 1030 - WARN_ON_ONCE(off > UINT_MAX); 1031 - __bio_add_page(bio, &folio->page, len, off); 1032 + __bio_add_page(bio, folio_page(folio, nr), len, off % PAGE_SIZE); 1032 1033 } 1033 1034 EXPORT_SYMBOL_GPL(bio_add_folio_nofail); 1034 1035 ··· 1050 1049 bool bio_add_folio(struct bio *bio, struct folio *folio, size_t len, 1051 1050 size_t off) 1052 1051 { 1053 - if (len > UINT_MAX || off > UINT_MAX) 1052 + unsigned long nr = off / PAGE_SIZE; 1053 + 1054 + if (len > UINT_MAX) 1054 1055 return false; 1055 - return bio_add_page(bio, &folio->page, len, off) > 0; 1056 + return bio_add_page(bio, folio_page(folio, nr), len, off % PAGE_SIZE) > 0; 1056 1057 } 1057 1058 EXPORT_SYMBOL(bio_add_folio); 1058 1059