->bi_vcnt doesn't make sense for cloned bio, which is perfectly fine passed to bio_may_need_split(). So fix bio_may_need_split() by not taking ->bi_vcnt directly, instead checking with help from bio size and bvec->len. Meantime retrieving the 1st bvec via __bvec_iter_bvec(). Fixes: abd45c159df5 ("block: handle fast path of bio splitting inline") Signed-off-by: Ming Lei --- block/blk.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/block/blk.h b/block/blk.h index e4c433f62dfc..a0b9cecba8fa 100644 --- a/block/blk.h +++ b/block/blk.h @@ -371,12 +371,19 @@ struct bio *bio_split_zone_append(struct bio *bio, static inline bool bio_may_need_split(struct bio *bio, const struct queue_limits *lim) { + const struct bio_vec *bv; + if (lim->chunk_sectors) return true; - if (bio->bi_vcnt != 1) + + if ((bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE) || + !bio->bi_io_vec) + return true; + + bv = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); + if (bio->bi_iter.bi_size > bv->bv_len) return true; - return bio->bi_io_vec->bv_len + bio->bi_io_vec->bv_offset > - lim->max_fast_segment_size; + return bv->bv_len + bv->bv_offset > lim->max_fast_segment_size; } /** -- 2.47.0