提交 8423ae3d 编写于 作者: K Kent Overstreet 提交者: Jens Axboe

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: NKent Overstreet <kmo@daterainc.com>
Tested-by: NRichard W.M. Jones <rjones@redhat.com>
Signed-off-by: NJens Axboe <axboe@fb.com>
上级 9d4cb8e3
...@@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast); ...@@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast);
struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
struct bio_set *bs) struct bio_set *bs)
{ {
unsigned nr_iovecs = 0;
struct bvec_iter iter; struct bvec_iter iter;
struct bio_vec bv; struct bio_vec bv;
struct bio *bio; struct bio *bio;
...@@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, ...@@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
* __bio_clone_fast() anyways. * __bio_clone_fast() anyways.
*/ */
bio_for_each_segment(bv, bio_src, iter) bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs);
nr_iovecs++;
bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs);
if (!bio) if (!bio)
return NULL; return NULL;
...@@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, ...@@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector;
bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; bio->bi_iter.bi_size = bio_src->bi_iter.bi_size;
if (bio->bi_rw & REQ_DISCARD)
goto integrity_clone;
if (bio->bi_rw & REQ_WRITE_SAME) {
bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
goto integrity_clone;
}
bio_for_each_segment(bv, bio_src, iter) bio_for_each_segment(bv, bio_src, iter)
bio->bi_io_vec[bio->bi_vcnt++] = bv; bio->bi_io_vec[bio->bi_vcnt++] = bv;
integrity_clone:
if (bio_integrity(bio_src)) { if (bio_integrity(bio_src)) {
int ret; int ret;
......
...@@ -250,6 +250,17 @@ static inline unsigned bio_segments(struct bio *bio) ...@@ -250,6 +250,17 @@ static inline unsigned bio_segments(struct bio *bio)
struct bio_vec bv; struct bio_vec bv;
struct bvec_iter iter; struct bvec_iter iter;
/*
* We special case discard/write same, because they interpret bi_size
* differently:
*/
if (bio->bi_rw & REQ_DISCARD)
return 1;
if (bio->bi_rw & REQ_WRITE_SAME)
return 1;
bio_for_each_segment(bv, bio, iter) bio_for_each_segment(bv, bio, iter)
segs++; segs++;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册