Messages in this thread Patch in this message | | | Subject | [PATCH] fix bio_add_page for non trivial merge_bvec_fn case | From | Dmitri Monakhov <> | Date | Sun, 08 Jun 2008 19:45:08 +0400 |
| |
We have to properly decrease all related bio's counters, especially bi_size in order to merge_bvec_fn return right result. Usually this result in false merge rejects for two absolutely valid bio_vecs. This may cause significant performance penalty for example Itanium: page_size == 16k, fs_block_size == 1k and block device is raid with small chunk_size.
Signed-off-by: Dmitri Monakhov <dmonakhov@openvz.org> --- fs/bio.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/fs/bio.c b/fs/bio.c index 7856257..d713074 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -332,14 +332,21 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page if (page == prev->bv_page && offset == prev->bv_offset + prev->bv_len) { + /* Temprory detacth last bio_vec. */ + bio->bi_size -= prev->bv_len; + bio->bi_vcnt--; + bio->bi_phys_segments--; + bio->bi_hw_segments--; + prev->bv_len += len; if (q->merge_bvec_fn && q->merge_bvec_fn(q, bio, prev) < len) { prev->bv_len -= len; - return 0; + len = 0; } - goto done; + bio->bi_size += prev->bv_len; + goto out_add_bvec; } } @@ -394,11 +401,12 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page BIOVEC_VIRT_MERGEABLE(bvec-1, bvec))) bio->bi_flags &= ~(1 << BIO_SEG_VALID); + bio->bi_size += len; +out_add_bvec: bio->bi_vcnt++; bio->bi_phys_segments++; bio->bi_hw_segments++; - done: - bio->bi_size += len; return len; } -- 1.5.4.rc4
| |