aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-11-23 21:19:27 -0500
committerKent Overstreet <kmo@daterainc.com>2013-11-24 01:33:54 -0500
commit59d276fe02d7e887a4825ef05c80b8f8c54ba60a (patch)
treedbb8c78a922d47652c08d9f5e46d77708ac95543
parentbdb53207411ae39b8a80dda0a66d1b468cbe1380 (diff)
block: Add bio_clone_fast()
bio_clone() just got more expensive - however, most users of bio_clone() don't actually need to modify the biovec. If they aren't modifying the biovec, and they can guarantee that the original bio isn't freed before the clone (also true in most cases), we can just point the clone at the original bio's biovec. Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r--drivers/md/bcache/request.c8
-rw-r--r--fs/bio.c60
-rw-r--r--include/linux/bio.h2
3 files changed, 64 insertions, 6 deletions
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 4c0a422fd49f..63451c724781 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -613,7 +613,6 @@ struct search {
613 613
614 struct btree_op op; 614 struct btree_op op;
615 struct data_insert_op iop; 615 struct data_insert_op iop;
616 struct bio_vec bv[BIO_MAX_PAGES];
617}; 616};
618 617
619static void bch_cache_read_endio(struct bio *bio, int error) 618static void bch_cache_read_endio(struct bio *bio, int error)
@@ -761,9 +760,7 @@ static void do_bio_hook(struct search *s)
761 struct bio *bio = &s->bio.bio; 760 struct bio *bio = &s->bio.bio;
762 761
763 bio_init(bio); 762 bio_init(bio);
764 bio->bi_io_vec = s->bv; 763 __bio_clone_fast(bio, s->orig_bio);
765 bio->bi_max_vecs = BIO_MAX_PAGES;
766 __bio_clone(bio, s->orig_bio);
767 bio->bi_end_io = request_endio; 764 bio->bi_end_io = request_endio;
768 bio->bi_private = &s->cl; 765 bio->bi_private = &s->cl;
769 766
@@ -1065,8 +1062,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s)
1065 closure_bio_submit(flush, cl, s->d); 1062 closure_bio_submit(flush, cl, s->d);
1066 } 1063 }
1067 } else { 1064 } else {
1068 s->iop.bio = bio_clone_bioset(bio, GFP_NOIO, 1065 s->iop.bio = bio_clone_fast(bio, GFP_NOIO, dc->disk.bio_split);
1069 dc->disk.bio_split);
1070 1066
1071 closure_bio_submit(bio, cl, s->d); 1067 closure_bio_submit(bio, cl, s->d);
1072 } 1068 }
diff --git a/fs/bio.c b/fs/bio.c
index 1628917e262a..00dc1893c6ee 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -549,6 +549,66 @@ void __bio_clone(struct bio *bio, struct bio *bio_src)
549EXPORT_SYMBOL(__bio_clone); 549EXPORT_SYMBOL(__bio_clone);
550 550
551/** 551/**
552 * __bio_clone_fast - clone a bio that shares the original bio's biovec
553 * @bio: destination bio
554 * @bio_src: bio to clone
555 *
556 * Clone a &bio. Caller will own the returned bio, but not
557 * the actual data it points to. Reference count of returned
558 * bio will be one.
559 *
560 * Caller must ensure that @bio_src is not freed before @bio.
561 */
562void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
563{
564 BUG_ON(bio->bi_pool && BIO_POOL_IDX(bio) != BIO_POOL_NONE);
565
566 /*
567 * most users will be overriding ->bi_bdev with a new target,
568 * so we don't set nor calculate new physical/hw segment counts here
569 */
570 bio->bi_bdev = bio_src->bi_bdev;
571 bio->bi_flags |= 1 << BIO_CLONED;
572 bio->bi_rw = bio_src->bi_rw;
573 bio->bi_iter = bio_src->bi_iter;
574 bio->bi_io_vec = bio_src->bi_io_vec;
575}
576EXPORT_SYMBOL(__bio_clone_fast);
577
578/**
579 * bio_clone_fast - clone a bio that shares the original bio's biovec
580 * @bio: bio to clone
581 * @gfp_mask: allocation priority
582 * @bs: bio_set to allocate from
583 *
584 * Like __bio_clone_fast, only also allocates the returned bio
585 */
586struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs)
587{
588 struct bio *b;
589
590 b = bio_alloc_bioset(gfp_mask, 0, bs);
591 if (!b)
592 return NULL;
593
594 __bio_clone_fast(b, bio);
595
596 if (bio_integrity(bio)) {
597 int ret;
598
599 ret = bio_integrity_clone(b, bio, gfp_mask);
600
601 if (ret < 0) {
602 bio_put(b);
603 return NULL;
604 }
605 }
606
607 return b;
608}
609EXPORT_SYMBOL(bio_clone_fast);
610
611/**
552 * bio_clone_bioset - clone a bio 612 * bio_clone_bioset - clone a bio
553 * @bio_src: bio to clone 613 * @bio_src: bio to clone
554 * @gfp_mask: allocation priority 614 * @gfp_mask: allocation priority
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 1a31f9d9e057..1f83f4a3083e 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -328,6 +328,8 @@ extern mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries);
328extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); 328extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
329extern void bio_put(struct bio *); 329extern void bio_put(struct bio *);
330 330
331extern void __bio_clone_fast(struct bio *, struct bio *);
332extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *);
331extern void __bio_clone(struct bio *, struct bio *); 333extern void __bio_clone(struct bio *, struct bio *);
332extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); 334extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
333 335