block: setup bi_phys_segments after splitting
authorMing Lei <ming.lei@canonical.com>
Tue, 20 Oct 2015 15:13:52 +0000 (23:13 +0800)
committerJens Axboe <axboe@fb.com>
Wed, 21 Oct 2015 21:00:50 +0000 (15:00 -0600)
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: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
block/blk-merge.c

index c4e9c37..22293fd 100644 (file)
 
 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 @@ new_segment:
                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);