diff options
-rw-r--r-- | block/bio.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/block/bio.c b/block/bio.c index 3d4a072375ef..471d7382c7d1 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -748,6 +748,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
748 | } | 748 | } |
749 | } | 749 | } |
750 | 750 | ||
751 | bio->bi_iter.bi_size += len; | ||
751 | goto done; | 752 | goto done; |
752 | } | 753 | } |
753 | 754 | ||
@@ -764,29 +765,32 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
764 | return 0; | 765 | return 0; |
765 | 766 | ||
766 | /* | 767 | /* |
767 | * we might lose a segment or two here, but rather that than | 768 | * setup the new entry, we might clear it again later if we |
768 | * make this too complex. | 769 | * cannot add the page |
770 | */ | ||
771 | bvec = &bio->bi_io_vec[bio->bi_vcnt]; | ||
772 | bvec->bv_page = page; | ||
773 | bvec->bv_len = len; | ||
774 | bvec->bv_offset = offset; | ||
775 | bio->bi_vcnt++; | ||
776 | bio->bi_phys_segments++; | ||
777 | bio->bi_iter.bi_size += len; | ||
778 | |||
779 | /* | ||
780 | * Perform a recount if the number of segments is greater | ||
781 | * than queue_max_segments(q). | ||
769 | */ | 782 | */ |
770 | 783 | ||
771 | while (bio->bi_phys_segments >= queue_max_segments(q)) { | 784 | while (bio->bi_phys_segments > queue_max_segments(q)) { |
772 | 785 | ||
773 | if (retried_segments) | 786 | if (retried_segments) |
774 | return 0; | 787 | goto failed; |
775 | 788 | ||
776 | retried_segments = 1; | 789 | retried_segments = 1; |
777 | blk_recount_segments(q, bio); | 790 | blk_recount_segments(q, bio); |
778 | } | 791 | } |
779 | 792 | ||
780 | /* | 793 | /* |
781 | * setup the new entry, we might clear it again later if we | ||
782 | * cannot add the page | ||
783 | */ | ||
784 | bvec = &bio->bi_io_vec[bio->bi_vcnt]; | ||
785 | bvec->bv_page = page; | ||
786 | bvec->bv_len = len; | ||
787 | bvec->bv_offset = offset; | ||
788 | |||
789 | /* | ||
790 | * if queue has other restrictions (eg varying max sector size | 794 | * if queue has other restrictions (eg varying max sector size |
791 | * depending on offset), it can specify a merge_bvec_fn in the | 795 | * depending on offset), it can specify a merge_bvec_fn in the |
792 | * queue to get further control | 796 | * queue to get further control |
@@ -795,7 +799,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
795 | struct bvec_merge_data bvm = { | 799 | struct bvec_merge_data bvm = { |
796 | .bi_bdev = bio->bi_bdev, | 800 | .bi_bdev = bio->bi_bdev, |
797 | .bi_sector = bio->bi_iter.bi_sector, | 801 | .bi_sector = bio->bi_iter.bi_sector, |
798 | .bi_size = bio->bi_iter.bi_size, | 802 | .bi_size = bio->bi_iter.bi_size - len, |
799 | .bi_rw = bio->bi_rw, | 803 | .bi_rw = bio->bi_rw, |
800 | }; | 804 | }; |
801 | 805 | ||
@@ -803,23 +807,25 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
803 | * merge_bvec_fn() returns number of bytes it can accept | 807 | * merge_bvec_fn() returns number of bytes it can accept |
804 | * at this offset | 808 | * at this offset |
805 | */ | 809 | */ |
806 | if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len) { | 810 | if (q->merge_bvec_fn(q, &bvm, bvec) < bvec->bv_len) |
807 | bvec->bv_page = NULL; | 811 | goto failed; |
808 | bvec->bv_len = 0; | ||
809 | bvec->bv_offset = 0; | ||
810 | return 0; | ||
811 | } | ||
812 | } | 812 | } |
813 | 813 | ||
814 | /* If we may be able to merge these biovecs, force a recount */ | 814 | /* If we may be able to merge these biovecs, force a recount */ |
815 | if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec))) | 815 | if (bio->bi_vcnt > 1 && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec))) |
816 | bio->bi_flags &= ~(1 << BIO_SEG_VALID); | 816 | bio->bi_flags &= ~(1 << BIO_SEG_VALID); |
817 | 817 | ||
818 | bio->bi_vcnt++; | ||
819 | bio->bi_phys_segments++; | ||
820 | done: | 818 | done: |
821 | bio->bi_iter.bi_size += len; | ||
822 | return len; | 819 | return len; |
820 | |||
821 | failed: | ||
822 | bvec->bv_page = NULL; | ||
823 | bvec->bv_len = 0; | ||
824 | bvec->bv_offset = 0; | ||
825 | bio->bi_vcnt--; | ||
826 | bio->bi_iter.bi_size -= len; | ||
827 | blk_recount_segments(q, bio); | ||
828 | return 0; | ||
823 | } | 829 | } |
824 | 830 | ||
825 | /** | 831 | /** |