Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8423ae3d authored by Kent Overstreet's avatar Kent Overstreet Committed by Jens Axboe
Browse files

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: default avatarKent Overstreet <kmo@daterainc.com>
Tested-by: default avatarRichard W.M. Jones <rjones@redhat.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 9d4cb8e3
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast);
struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
			     struct bio_set *bs)
{
	unsigned nr_iovecs = 0;
	struct bvec_iter iter;
	struct bio_vec bv;
	struct bio *bio;
@@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
	 *    __bio_clone_fast() anyways.
	 */

	bio_for_each_segment(bv, bio_src, iter)
		nr_iovecs++;

	bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs);
	bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs);
	if (!bio)
		return NULL;

@@ -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_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->bi_io_vec[bio->bi_vcnt++] = bv;

integrity_clone:
	if (bio_integrity(bio_src)) {
		int ret;

+11 −0
Original line number Diff line number Diff line
@@ -250,6 +250,17 @@ static inline unsigned bio_segments(struct bio *bio)
	struct bio_vec bv;
	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)
		segs++;