aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/bio.c54
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/**