Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdced438 authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

block: setup bi_phys_segments after splitting



The number of bio->bi_phys_segments is always obtained
during bio splitting, so it is natural to setup it
just after bio splitting, then we can avoid to compute
nr_segment again during merge.

Reviewed-by: default avatarJeff Moyer <jmoyer@redhat.com>
Signed-off-by: default avatarMing Lei <ming.lei@canonical.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 0809e3ac
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -11,13 +11,16 @@

static struct bio *blk_bio_discard_split(struct request_queue *q,
					 struct bio *bio,
					 struct bio_set *bs)
					 struct bio_set *bs,
					 unsigned *nsegs)
{
	unsigned int max_discard_sectors, granularity;
	int alignment;
	sector_t tmp;
	unsigned split_sectors;

	*nsegs = 1;

	/* Zero-sector (unknown) and one-sector granularities are the same.  */
	granularity = max(q->limits.discard_granularity >> 9, 1U);

@@ -51,8 +54,11 @@ static struct bio *blk_bio_discard_split(struct request_queue *q,

static struct bio *blk_bio_write_same_split(struct request_queue *q,
					    struct bio *bio,
					    struct bio_set *bs)
					    struct bio_set *bs,
					    unsigned *nsegs)
{
	*nsegs = 1;

	if (!q->limits.max_write_same_sectors)
		return NULL;

@@ -64,7 +70,8 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,

static struct bio *blk_bio_segment_split(struct request_queue *q,
					 struct bio *bio,
					 struct bio_set *bs)
					 struct bio_set *bs,
					 unsigned *segs)
{
	struct bio_vec bv, bvprv, *bvprvp = NULL;
	struct bvec_iter iter;
@@ -106,22 +113,30 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
		sectors += bv.bv_len >> 9;
	}

	*segs = nsegs;
	return NULL;
split:
	*segs = nsegs;
	return bio_split(bio, sectors, GFP_NOIO, bs);
}

void blk_queue_split(struct request_queue *q, struct bio **bio,
		     struct bio_set *bs)
{
	struct bio *split;
	struct bio *split, *res;
	unsigned nsegs;

	if ((*bio)->bi_rw & REQ_DISCARD)
		split = blk_bio_discard_split(q, *bio, bs);
		split = blk_bio_discard_split(q, *bio, bs, &nsegs);
	else if ((*bio)->bi_rw & REQ_WRITE_SAME)
		split = blk_bio_write_same_split(q, *bio, bs);
		split = blk_bio_write_same_split(q, *bio, bs, &nsegs);
	else
		split = blk_bio_segment_split(q, *bio, q->bio_split);
		split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs);

	/* physical segments can be figured out during splitting */
	res = split ? split : *bio;
	res->bi_phys_segments = nsegs;
	bio_set_flag(res, BIO_SEG_VALID);

	if (split) {
		bio_chain(split, *bio);