diff options
Diffstat (limited to 'drivers/md/bcache/io.c')
| -rw-r--r-- | drivers/md/bcache/io.c | 196 | 
1 files changed, 29 insertions, 167 deletions
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 9056632995b..fa028fa82df 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -11,178 +11,40 @@  #include <linux/blkdev.h> -static void bch_bi_idx_hack_endio(struct bio *bio, int error) -{ -	struct bio *p = bio->bi_private; - -	bio_endio(p, error); -	bio_put(bio); -} - -static void bch_generic_make_request_hack(struct bio *bio) -{ -	if (bio->bi_idx) { -		struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio)); - -		memcpy(clone->bi_io_vec, -		       bio_iovec(bio), -		       bio_segments(bio) * sizeof(struct bio_vec)); - -		clone->bi_sector	= bio->bi_sector; -		clone->bi_bdev		= bio->bi_bdev; -		clone->bi_rw		= bio->bi_rw; -		clone->bi_vcnt		= bio_segments(bio); -		clone->bi_size		= bio->bi_size; - -		clone->bi_private	= bio; -		clone->bi_end_io	= bch_bi_idx_hack_endio; - -		bio = clone; -	} - -	/* -	 * Hack, since drivers that clone bios clone up to bi_max_vecs, but our -	 * bios might have had more than that (before we split them per device -	 * limitations). -	 * -	 * To be taken out once immutable bvec stuff is in. -	 */ -	bio->bi_max_vecs = bio->bi_vcnt; - -	generic_make_request(bio); -} - -/** - * bch_bio_split - split a bio - * @bio:	bio to split - * @sectors:	number of sectors to split from the front of @bio - * @gfp:	gfp mask - * @bs:		bio set to allocate from - * - * Allocates and returns a new bio which represents @sectors from the start of - * @bio, and updates @bio to represent the remaining sectors. - * - * If bio_sectors(@bio) was less than or equal to @sectors, returns @bio - * unchanged. - * - * The newly allocated bio will point to @bio's bi_io_vec, if the split was on a - * bvec boundry; it is the caller's responsibility to ensure that @bio is not - * freed before the split. - */ -struct bio *bch_bio_split(struct bio *bio, int sectors, -			  gfp_t gfp, struct bio_set *bs) -{ -	unsigned idx = bio->bi_idx, vcnt = 0, nbytes = sectors << 9; -	struct bio_vec *bv; -	struct bio *ret = NULL; - -	BUG_ON(sectors <= 0); - -	if (sectors >= bio_sectors(bio)) -		return bio; - -	if (bio->bi_rw & REQ_DISCARD) { -		ret = bio_alloc_bioset(gfp, 1, bs); -		if (!ret) -			return NULL; -		idx = 0; -		goto out; -	} - -	bio_for_each_segment(bv, bio, idx) { -		vcnt = idx - bio->bi_idx; - -		if (!nbytes) { -			ret = bio_alloc_bioset(gfp, vcnt, bs); -			if (!ret) -				return NULL; - -			memcpy(ret->bi_io_vec, bio_iovec(bio), -			       sizeof(struct bio_vec) * vcnt); - -			break; -		} else if (nbytes < bv->bv_len) { -			ret = bio_alloc_bioset(gfp, ++vcnt, bs); -			if (!ret) -				return NULL; - -			memcpy(ret->bi_io_vec, bio_iovec(bio), -			       sizeof(struct bio_vec) * vcnt); - -			ret->bi_io_vec[vcnt - 1].bv_len = nbytes; -			bv->bv_offset	+= nbytes; -			bv->bv_len	-= nbytes; -			break; -		} - -		nbytes -= bv->bv_len; -	} -out: -	ret->bi_bdev	= bio->bi_bdev; -	ret->bi_sector	= bio->bi_sector; -	ret->bi_size	= sectors << 9; -	ret->bi_rw	= bio->bi_rw; -	ret->bi_vcnt	= vcnt; -	ret->bi_max_vecs = vcnt; - -	bio->bi_sector	+= sectors; -	bio->bi_size	-= sectors << 9; -	bio->bi_idx	 = idx; - -	if (bio_integrity(bio)) { -		if (bio_integrity_clone(ret, bio, gfp)) { -			bio_put(ret); -			return NULL; -		} - -		bio_integrity_trim(ret, 0, bio_sectors(ret)); -		bio_integrity_trim(bio, bio_sectors(ret), bio_sectors(bio)); -	} - -	return ret; -} -  static unsigned bch_bio_max_sectors(struct bio *bio)  { -	unsigned ret = bio_sectors(bio);  	struct request_queue *q = bdev_get_queue(bio->bi_bdev); -	unsigned max_segments = min_t(unsigned, BIO_MAX_PAGES, -				      queue_max_segments(q)); +	struct bio_vec bv; +	struct bvec_iter iter; +	unsigned ret = 0, seg = 0;  	if (bio->bi_rw & REQ_DISCARD) -		return min(ret, q->limits.max_discard_sectors); - -	if (bio_segments(bio) > max_segments || -	    q->merge_bvec_fn) { -		struct bio_vec *bv; -		int i, seg = 0; - -		ret = 0; - -		bio_for_each_segment(bv, bio, i) { -			struct bvec_merge_data bvm = { -				.bi_bdev	= bio->bi_bdev, -				.bi_sector	= bio->bi_sector, -				.bi_size	= ret << 9, -				.bi_rw		= bio->bi_rw, -			}; - -			if (seg == max_segments) -				break; +		return min(bio_sectors(bio), q->limits.max_discard_sectors); + +	bio_for_each_segment(bv, bio, iter) { +		struct bvec_merge_data bvm = { +			.bi_bdev	= bio->bi_bdev, +			.bi_sector	= bio->bi_iter.bi_sector, +			.bi_size	= ret << 9, +			.bi_rw		= bio->bi_rw, +		}; + +		if (seg == min_t(unsigned, BIO_MAX_PAGES, +				 queue_max_segments(q))) +			break; -			if (q->merge_bvec_fn && -			    q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len) -				break; +		if (q->merge_bvec_fn && +		    q->merge_bvec_fn(q, &bvm, &bv) < (int) bv.bv_len) +			break; -			seg++; -			ret += bv->bv_len >> 9; -		} +		seg++; +		ret += bv.bv_len >> 9;  	}  	ret = min(ret, queue_max_sectors(q));  	WARN_ON(!ret); -	ret = max_t(int, ret, bio_iovec(bio)->bv_len >> 9); +	ret = max_t(int, ret, bio_iovec(bio).bv_len >> 9);  	return ret;  } @@ -193,7 +55,7 @@ static void bch_bio_submit_split_done(struct closure *cl)  	s->bio->bi_end_io = s->bi_end_io;  	s->bio->bi_private = s->bi_private; -	bio_endio(s->bio, 0); +	bio_endio_nodec(s->bio, 0);  	closure_debug_destroy(&s->cl);  	mempool_free(s, s->p->bio_split_hook); @@ -232,19 +94,19 @@ void bch_generic_make_request(struct bio *bio, struct bio_split_pool *p)  	bio_get(bio);  	do { -		n = bch_bio_split(bio, bch_bio_max_sectors(bio), -				  GFP_NOIO, s->p->bio_split); +		n = bio_next_split(bio, bch_bio_max_sectors(bio), +				   GFP_NOIO, s->p->bio_split);  		n->bi_end_io	= bch_bio_submit_split_endio;  		n->bi_private	= &s->cl;  		closure_get(&s->cl); -		bch_generic_make_request_hack(n); +		generic_make_request(n);  	} while (n != bio);  	continue_at(&s->cl, bch_bio_submit_split_done, NULL);  submit: -	bch_generic_make_request_hack(bio); +	generic_make_request(bio);  }  /* Bios with headers */ @@ -272,8 +134,8 @@ void __bch_submit_bbio(struct bio *bio, struct cache_set *c)  {  	struct bbio *b = container_of(bio, struct bbio, bio); -	bio->bi_sector	= PTR_OFFSET(&b->key, 0); -	bio->bi_bdev	= PTR_CACHE(c, &b->key, 0)->bdev; +	bio->bi_iter.bi_sector	= PTR_OFFSET(&b->key, 0); +	bio->bi_bdev		= PTR_CACHE(c, &b->key, 0)->bdev;  	b->submit_time_us = local_clock_us();  	closure_bio_submit(bio, bio->bi_private, PTR_CACHE(c, &b->key, 0));  | 
