On Mon, Nov 04, 2019 at 10:05:43AM -0800, Christoph Hellwig wrote: > diff --git a/block/blk-merge.c b/block/blk-merge.c > index 48e6725b32ee..06eb38357b41 100644 > --- a/block/blk-merge.c > +++ b/block/blk-merge.c > @@ -293,7 +293,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, > void __blk_queue_split(struct request_queue *q, struct bio **bio, > unsigned int *nr_segs) > { > - struct bio *split; > + struct bio *split = NULL; > > switch (bio_op(*bio)) { > case REQ_OP_DISCARD: > @@ -309,6 +309,19 @@ void __blk_queue_split(struct request_queue *q, struct bio **bio, > nr_segs); > break; > default: > + /* > + * All drivers must accept single-segments bios that are <= > + * PAGE_SIZE. This is a quick and dirty check that relies on > + * the fact that bi_io_vec[0] is always valid if a bio has data. > + * The check might lead to occasional false negatives when bios > + * are cloned, but compared to the performance impact of cloned > + * bios themselves the loop below doesn't matter anyway. > + */ > + if ((*bio)->bi_vcnt == 1 && > + (*bio)->bi_io_vec[0].bv_len <= PAGE_SIZE) { > + *nr_segs = 1; > + break; > + } > split = blk_bio_segment_split(q, *bio, &q->bio_split, nr_segs); > break; > } If the device advertises a chunk boundary and this small IO happens to cross it, skipping the split is going to harm performance.