Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[BLOCK] bio: check for same page merge possibilities in __bio_add_page()

For filesystems with a blocksize < page size, we can merge same page
calls into the bio_vec at the end of the bio. This saves segments
on systems with a page size > the "normal" 4kb fs block size.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@suse.de>

+24 -2
+24 -2
fs/bio.c
··· 325 325 if (unlikely(bio_flagged(bio, BIO_CLONED))) 326 326 return 0; 327 327 328 - if (bio->bi_vcnt >= bio->bi_max_vecs) 328 + if (((bio->bi_size + len) >> 9) > max_sectors) 329 329 return 0; 330 330 331 - if (((bio->bi_size + len) >> 9) > max_sectors) 331 + /* 332 + * For filesystems with a blocksize smaller than the pagesize 333 + * we will often be called with the same page as last time and 334 + * a consecutive offset. Optimize this special case. 335 + */ 336 + if (bio->bi_vcnt > 0) { 337 + struct bio_vec *prev = &bio->bi_io_vec[bio->bi_vcnt - 1]; 338 + 339 + if (page == prev->bv_page && 340 + offset == prev->bv_offset + prev->bv_len) { 341 + prev->bv_len += len; 342 + if (q->merge_bvec_fn && 343 + q->merge_bvec_fn(q, bio, prev) < len) { 344 + prev->bv_len -= len; 345 + return 0; 346 + } 347 + 348 + goto done; 349 + } 350 + } 351 + 352 + if (bio->bi_vcnt >= bio->bi_max_vecs) 332 353 return 0; 333 354 334 355 /* ··· 403 382 bio->bi_vcnt++; 404 383 bio->bi_phys_segments++; 405 384 bio->bi_hw_segments++; 385 + done: 406 386 bio->bi_size += len; 407 387 return len; 408 388 }