mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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 <venkat88@linux.ibm.com>
Close: https://lore.kernel.org/linux-block/9687cf2b-1f32-44e1-b58d-2492dc6e7185@linux.ibm.com/
Repored-and-bisected-by: Christoph Hellwig <hch@infradead.org>
Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Tested-by: Christoph Hellwig <hch@infradead.org>
Fixes: ee623c892a ("block: use bvec iterator helper for bio_may_need_split()")
Cc: Nitesh Shetty <nj.shetty@samsung.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user