diff options
author | Ming Lei <tom.leiming@gmail.com> | 2017-02-14 10:28:59 -0500 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-02-15 14:22:05 -0500 |
commit | c18a1e09008de7d8bd82b046d38a88f4285d53f9 (patch) | |
tree | b6db3c3286d3086c587a76da819c9272dc91b19d | |
parent | 26483819f89c5cf9d27620d70c95afeeeb9bece5 (diff) |
block: introduce bio_clone_bioset_partial()
md still need bio clone(not the fast version) for behind write,
and it is more efficient to use bio_clone_bioset_partial().
The idea is simple and just copy the bvecs range specified from
parameters.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jens Axboe <axboe@fb.com>
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r-- | block/bio.c | 61 | ||||
-rw-r--r-- | include/linux/bio.h | 11 |
2 files changed, 57 insertions, 15 deletions
diff --git a/block/bio.c b/block/bio.c index 2b375020fc49..9e2b33ddca0a 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -625,21 +625,20 @@ struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs) | |||
625 | } | 625 | } |
626 | EXPORT_SYMBOL(bio_clone_fast); | 626 | EXPORT_SYMBOL(bio_clone_fast); |
627 | 627 | ||
628 | /** | 628 | static struct bio *__bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, |
629 | * bio_clone_bioset - clone a bio | 629 | struct bio_set *bs, int offset, |
630 | * @bio_src: bio to clone | 630 | int size) |
631 | * @gfp_mask: allocation priority | ||
632 | * @bs: bio_set to allocate from | ||
633 | * | ||
634 | * Clone bio. Caller will own the returned bio, but not the actual data it | ||
635 | * points to. Reference count of returned bio will be one. | ||
636 | */ | ||
637 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | ||
638 | struct bio_set *bs) | ||
639 | { | 631 | { |
640 | struct bvec_iter iter; | 632 | struct bvec_iter iter; |
641 | struct bio_vec bv; | 633 | struct bio_vec bv; |
642 | struct bio *bio; | 634 | struct bio *bio; |
635 | struct bvec_iter iter_src = bio_src->bi_iter; | ||
636 | |||
637 | /* for supporting partial clone */ | ||
638 | if (offset || size != bio_src->bi_iter.bi_size) { | ||
639 | bio_advance_iter(bio_src, &iter_src, offset); | ||
640 | iter_src.bi_size = size; | ||
641 | } | ||
643 | 642 | ||
644 | /* | 643 | /* |
645 | * Pre immutable biovecs, __bio_clone() used to just do a memcpy from | 644 | * Pre immutable biovecs, __bio_clone() used to just do a memcpy from |
@@ -663,7 +662,8 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
663 | * __bio_clone_fast() anyways. | 662 | * __bio_clone_fast() anyways. |
664 | */ | 663 | */ |
665 | 664 | ||
666 | bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); | 665 | bio = bio_alloc_bioset(gfp_mask, __bio_segments(bio_src, |
666 | &iter_src), bs); | ||
667 | if (!bio) | 667 | if (!bio) |
668 | return NULL; | 668 | return NULL; |
669 | bio->bi_bdev = bio_src->bi_bdev; | 669 | bio->bi_bdev = bio_src->bi_bdev; |
@@ -680,7 +680,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
680 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; | 680 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; |
681 | break; | 681 | break; |
682 | default: | 682 | default: |
683 | bio_for_each_segment(bv, bio_src, iter) | 683 | __bio_for_each_segment(bv, bio_src, iter, iter_src) |
684 | bio->bi_io_vec[bio->bi_vcnt++] = bv; | 684 | bio->bi_io_vec[bio->bi_vcnt++] = bv; |
685 | break; | 685 | break; |
686 | } | 686 | } |
@@ -699,9 +699,44 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
699 | 699 | ||
700 | return bio; | 700 | return bio; |
701 | } | 701 | } |
702 | |||
703 | /** | ||
704 | * bio_clone_bioset - clone a bio | ||
705 | * @bio_src: bio to clone | ||
706 | * @gfp_mask: allocation priority | ||
707 | * @bs: bio_set to allocate from | ||
708 | * | ||
709 | * Clone bio. Caller will own the returned bio, but not the actual data it | ||
710 | * points to. Reference count of returned bio will be one. | ||
711 | */ | ||
712 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | ||
713 | struct bio_set *bs) | ||
714 | { | ||
715 | return __bio_clone_bioset(bio_src, gfp_mask, bs, 0, | ||
716 | bio_src->bi_iter.bi_size); | ||
717 | } | ||
702 | EXPORT_SYMBOL(bio_clone_bioset); | 718 | EXPORT_SYMBOL(bio_clone_bioset); |
703 | 719 | ||
704 | /** | 720 | /** |
721 | * bio_clone_bioset_partial - clone a partial bio | ||
722 | * @bio_src: bio to clone | ||
723 | * @gfp_mask: allocation priority | ||
724 | * @bs: bio_set to allocate from | ||
725 | * @offset: cloned starting from the offset | ||
726 | * @size: size for the cloned bio | ||
727 | * | ||
728 | * Clone bio. Caller will own the returned bio, but not the actual data it | ||
729 | * points to. Reference count of returned bio will be one. | ||
730 | */ | ||
731 | struct bio *bio_clone_bioset_partial(struct bio *bio_src, gfp_t gfp_mask, | ||
732 | struct bio_set *bs, int offset, | ||
733 | int size) | ||
734 | { | ||
735 | return __bio_clone_bioset(bio_src, gfp_mask, bs, offset, size); | ||
736 | } | ||
737 | EXPORT_SYMBOL(bio_clone_bioset_partial); | ||
738 | |||
739 | /** | ||
705 | * bio_add_pc_page - attempt to add page to bio | 740 | * bio_add_pc_page - attempt to add page to bio |
706 | * @q: the target queue | 741 | * @q: the target queue |
707 | * @bio: destination bio | 742 | * @bio: destination bio |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 7cf8a6c70a3f..8e521194f6fc 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -183,7 +183,7 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, | |||
183 | 183 | ||
184 | #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len) | 184 | #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len) |
185 | 185 | ||
186 | static inline unsigned bio_segments(struct bio *bio) | 186 | static inline unsigned __bio_segments(struct bio *bio, struct bvec_iter *bvec) |
187 | { | 187 | { |
188 | unsigned segs = 0; | 188 | unsigned segs = 0; |
189 | struct bio_vec bv; | 189 | struct bio_vec bv; |
@@ -205,12 +205,17 @@ static inline unsigned bio_segments(struct bio *bio) | |||
205 | break; | 205 | break; |
206 | } | 206 | } |
207 | 207 | ||
208 | bio_for_each_segment(bv, bio, iter) | 208 | __bio_for_each_segment(bv, bio, iter, *bvec) |
209 | segs++; | 209 | segs++; |
210 | 210 | ||
211 | return segs; | 211 | return segs; |
212 | } | 212 | } |
213 | 213 | ||
214 | static inline unsigned bio_segments(struct bio *bio) | ||
215 | { | ||
216 | return __bio_segments(bio, &bio->bi_iter); | ||
217 | } | ||
218 | |||
214 | /* | 219 | /* |
215 | * get a reference to a bio, so it won't disappear. the intended use is | 220 | * get a reference to a bio, so it won't disappear. the intended use is |
216 | * something like: | 221 | * something like: |
@@ -384,6 +389,8 @@ extern void bio_put(struct bio *); | |||
384 | extern void __bio_clone_fast(struct bio *, struct bio *); | 389 | extern void __bio_clone_fast(struct bio *, struct bio *); |
385 | extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *); | 390 | extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *); |
386 | extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); | 391 | extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); |
392 | extern struct bio *bio_clone_bioset_partial(struct bio *, gfp_t, | ||
393 | struct bio_set *, int, int); | ||
387 | 394 | ||
388 | extern struct bio_set *fs_bio_set; | 395 | extern struct bio_set *fs_bio_set; |
389 | 396 | ||