On Mon, Feb 10, 2014 at 05:45:50PM -0800, Kent Overstreet wrote: > 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@xxxxxxxxxxxxx> Tested-by: Richard W.M. Jones <rjones@xxxxxxxxxx> I have confirmed this fixes the bug described here: https://bugzilla.redhat.com/show_bug.cgi?id=1061339 Rich. > --- > fs/bio.c | 15 ++++++++++----- > include/linux/bio.h | 11 +++++++++++ > 2 files changed, 21 insertions(+), 5 deletions(-) > > diff --git a/fs/bio.c b/fs/bio.c > index 75c49a3822..8754e7b6eb 100644 > --- a/fs/bio.c > +++ b/fs/bio.c > @@ -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; > > diff --git a/include/linux/bio.h b/include/linux/bio.h > index 70654521da..05d2a0392f 100644 > --- a/include/linux/bio.h > +++ b/include/linux/bio.h > @@ -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++; > > -- > 1.8.5.3 -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#) -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html