From f7ba87dfa8e42642d43faf29a71cee338086218b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 10 Jan 2026 21:42:36 +0800 Subject: [PATCH] block: account for bi_bvec_done in bio_may_need_split() When checking if a bio fits in a single segment, bio_may_need_split() compares bi_size against the current bvec's bv_len. However, for partially consumed bvecs (bi_bvec_done > 0), such as in cloned or split bios, the remaining bytes in the current bvec is actually (bv_len - bi_bvec_done), not bv_len. This could cause bio_may_need_split() to incorrectly return false, leading to nr_phys_segments being set to 1 when the bio actually spans multiple segments. This triggers the WARN_ON in __blk_rq_map_sg() when the actual mapped segments exceed the expected count. Fix by subtracting bi_bvec_done from bv_len in the comparison. Reported-by: Venkat Rao Bagalkote Close: https://lore.kernel.org/linux-block/9687cf2b-1f32-44e1-b58d-2492dc6e7185@linux.ibm.com/ Repored-and-bisected-by: Christoph Hellwig Tested-by: Venkat Rao Bagalkote Tested-by: Christoph Hellwig Fixes: ee623c892aa5 ("block: use bvec iterator helper for bio_may_need_split()") Cc: Nitesh Shetty Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- block/blk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk.h b/block/blk.h index 98f4dfd4ec758..980eef1f56903 100644 --- a/block/blk.h +++ b/block/blk.h @@ -380,7 +380,7 @@ static inline bool bio_may_need_split(struct bio *bio, return true; bv = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); - if (bio->bi_iter.bi_size > bv->bv_len) + if (bio->bi_iter.bi_size > bv->bv_len - bio->bi_iter.bi_bvec_done) return true; return bv->bv_len + bv->bv_offset > lim->max_fast_segment_size; } -- 2.47.3