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.
Unified · Split
| @@ -325,10 +325,31 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page · 324 unmodified lines | ||
| 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 | /* |
| @@ -382,6 +403,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page · 47 unmodified lines | ||
| 382 | 403 | bio->bi_vcnt++; |
| 383 | 404 | bio->bi_phys_segments++; |
| 384 | 405 | bio->bi_hw_segments++; |
| 406 | + done: | |
| 385 | 407 | bio->bi_size += len; |
| 386 | 408 | return len; |
| 387 | 409 | } |