diff options
-rw-r--r-- | block/bio.c | 52 |
1 files changed, 23 insertions, 29 deletions
diff --git a/block/bio.c b/block/bio.c index fb12df9af0fc..0ec61c9e536c 100644 --- a/block/bio.c +++ b/block/bio.c @@ -744,7 +744,6 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page } } - bio->bi_iter.bi_size += len; goto done; } @@ -761,32 +760,29 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page return 0; /* - * setup the new entry, we might clear it again later if we - * cannot add the page - */ - bvec = &bio->bi_io_vec[bio->bi_vcnt]; - bvec->bv_page = page; - bvec->bv_len = len; - bvec->bv_offset = offset; - bio->bi_vcnt++; - bio->bi_phys_segments++; - bio->bi_iter.bi_size += len; - - /* - * Perform a recount if the number of segments is greater - * than queue_max_segments(q). + * we might lose a segment or two here, but rather that than + * make this too complex. */ - while (bio->bi_phys_segments > queue_max_segments(q)) { + while (bio->bi_phys_segments >= queue_max_segments(q)) { if (retried_segments) - goto failed; + return 0; retried_segments = 1; blk_recount_segments(q, bio); } /* + * setup the new entry, we might clear it again later if we + * cannot add the page + */ + bvec = &bio->bi_io_vec[bio->bi_vcnt]; + bvec->bv_page = page; + bvec->bv_len = len; + bvec->bv_offset = offset; + + /* * if queue has other restrictions (eg varying max sector size * depending on offset), it can specify a merge_bvec_fn in the * queue to get further control @@ -803,25 +799,23 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page * merge_bvec_fn() returns number of bytes it can accept * at this offset */ - if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len) - goto failed; + if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len) { + bvec->bv_page = NULL; + bvec->bv_len = 0; + bvec->bv_offset = 0; + return 0; + } } /* If we may be able to merge these biovecs, force a recount */ - if (bio->bi_vcnt > 1 && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec))) + if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec))) bio->bi_flags &= ~(1 << BIO_SEG_VALID); + bio->bi_vcnt++; + bio->bi_phys_segments++; done: + bio->bi_iter.bi_size += len; return len; - - failed: - bvec->bv_page = NULL; - bvec->bv_len = 0; - bvec->bv_offset = 0; - bio->bi_vcnt--; - bio->bi_iter.bi_size -= len; - blk_recount_segments(q, bio); - return 0; } /** |