Skip to content

Commit c18a1e0

Browse files
ming1shligit
authored andcommitted
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>
1 parent 2648381 commit c18a1e0

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

block/bio.c

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -625,21 +625,20 @@ struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs)
625625
}
626626
EXPORT_SYMBOL(bio_clone_fast);
627627

628-
/**
629-
* bio_clone_bioset - clone a bio
630-
* @bio_src: bio to clone
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)
628+
static struct bio *__bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
629+
struct bio_set *bs, int offset,
630+
int size)
639631
{
640632
struct bvec_iter iter;
641633
struct bio_vec bv;
642634
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+
}
643642

644643
/*
645644
* 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,
663662
* __bio_clone_fast() anyways.
664663
*/
665664

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);
667667
if (!bio)
668668
return NULL;
669669
bio->bi_bdev = bio_src->bi_bdev;
@@ -680,7 +680,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
680680
bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
681681
break;
682682
default:
683-
bio_for_each_segment(bv, bio_src, iter)
683+
__bio_for_each_segment(bv, bio_src, iter, iter_src)
684684
bio->bi_io_vec[bio->bi_vcnt++] = bv;
685685
break;
686686
}
@@ -699,8 +699,43 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
699699

700700
return bio;
701701
}
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+
}
702718
EXPORT_SYMBOL(bio_clone_bioset);
703719

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+
704739
/**
705740
* bio_add_pc_page - attempt to add page to bio
706741
* @q: the target queue

include/linux/bio.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
183183

184184
#define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
185185

186-
static inline unsigned bio_segments(struct bio *bio)
186+
static inline unsigned __bio_segments(struct bio *bio, struct bvec_iter *bvec)
187187
{
188188
unsigned segs = 0;
189189
struct bio_vec bv;
@@ -205,12 +205,17 @@ static inline unsigned bio_segments(struct bio *bio)
205205
break;
206206
}
207207

208-
bio_for_each_segment(bv, bio, iter)
208+
__bio_for_each_segment(bv, bio, iter, *bvec)
209209
segs++;
210210

211211
return segs;
212212
}
213213

214+
static inline unsigned bio_segments(struct bio *bio)
215+
{
216+
return __bio_segments(bio, &bio->bi_iter);
217+
}
218+
214219
/*
215220
* get a reference to a bio, so it won't disappear. the intended use is
216221
* something like:
@@ -384,6 +389,8 @@ extern void bio_put(struct bio *);
384389
extern void __bio_clone_fast(struct bio *, struct bio *);
385390
extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *);
386391
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);
387394

388395
extern struct bio_set *fs_bio_set;
389396

0 commit comments

Comments
 (0)