> struct bio_vec *prev = &bio->bi_io_vec[bio->bi_vcnt - 1]; > > + /* segment size is always >= PAGE_SIZE */ I don't think that actually is true. We have various drivers with 4k segment size, for which this would not be true with a 64k page size system. > if (page == prev->bv_page && > offset == prev->bv_offset + prev->bv_len) { > if (put_same_page) > put_page(page); > + bvec_merge: > prev->bv_len += len; > bio->bi_iter.bi_size += len; Please throw in a cleanup patch that removes prev and and always uses bvec, then we can just move the done label up by two lines and handle the increment of bv_len and bi_size in a common branch. > done: > + bio->bi_phys_segments = bio->bi_vcnt; > + if (!bio_flagged(bio, BIO_SEG_VALID)) > + bio_set_flag(bio, BIO_SEG_VALID); How would BIO_SEG_VALID get set previously? And even if it did we wouldn't optimize much here, I'd just do it unconditionally. Btw, there are various comments in this function that either already were or have become out of data, like talking about REQ_PC or file system I/O - I think they could use some love.