diff options
author | Kent Overstreet <kmo@daterainc.com> | 2014-02-10 20:45:50 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-02-11 10:40:45 -0500 |
commit | 8423ae3d7a3cfe084865262cfaeba1359d405182 (patch) | |
tree | e8e6f9c31f5622e66ff176b600cf3b3c951eb4d8 /fs | |
parent | 9d4cb8e3a5b448d802155688bf2d50ac1b9e1a51 (diff) |
block: Fix cloning of discard/write same bios
Immutable biovecs changed the way bio segments are treated in such a way that
bio_for_each_segment() cannot now do what we want for discard/write same bios,
since bi_size means something completely different for them.
Fortunately discard and write same bios never have more than a single biovec, so
bio_for_each_segment() is unnecessary and not terribly meaningful for them, but
we still have to special case them in a few places.
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bio.c | 15 |
1 files changed, 10 insertions, 5 deletions
@@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast); | |||
611 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | 611 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, |
612 | struct bio_set *bs) | 612 | struct bio_set *bs) |
613 | { | 613 | { |
614 | unsigned nr_iovecs = 0; | ||
615 | struct bvec_iter iter; | 614 | struct bvec_iter iter; |
616 | struct bio_vec bv; | 615 | struct bio_vec bv; |
617 | struct bio *bio; | 616 | struct bio *bio; |
@@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
638 | * __bio_clone_fast() anyways. | 637 | * __bio_clone_fast() anyways. |
639 | */ | 638 | */ |
640 | 639 | ||
641 | bio_for_each_segment(bv, bio_src, iter) | 640 | bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); |
642 | nr_iovecs++; | ||
643 | |||
644 | bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs); | ||
645 | if (!bio) | 641 | if (!bio) |
646 | return NULL; | 642 | return NULL; |
647 | 643 | ||
@@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
650 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; | 646 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; |
651 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; | 647 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; |
652 | 648 | ||
649 | if (bio->bi_rw & REQ_DISCARD) | ||
650 | goto integrity_clone; | ||
651 | |||
652 | if (bio->bi_rw & REQ_WRITE_SAME) { | ||
653 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; | ||
654 | goto integrity_clone; | ||
655 | } | ||
656 | |||
653 | bio_for_each_segment(bv, bio_src, iter) | 657 | bio_for_each_segment(bv, bio_src, iter) |
654 | bio->bi_io_vec[bio->bi_vcnt++] = bv; | 658 | bio->bi_io_vec[bio->bi_vcnt++] = bv; |
655 | 659 | ||
660 | integrity_clone: | ||
656 | if (bio_integrity(bio_src)) { | 661 | if (bio_integrity(bio_src)) { |
657 | int ret; | 662 | int ret; |
658 | 663 | ||