Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
[linux-2.6-block.git] / block / blk-merge.c
index 17713d7d98d588f73fc94ff8a886e90a47b93212..57f7990b342dd1957077ae48baf71283663c0e73 100644 (file)
@@ -105,7 +105,7 @@ static struct bio *blk_bio_discard_split(struct request_queue *q,
 static struct bio *blk_bio_write_zeroes_split(struct request_queue *q,
                struct bio *bio, struct bio_set *bs, unsigned *nsegs)
 {
-       *nsegs = 1;
+       *nsegs = 0;
 
        if (!q->limits.max_write_zeroes_sectors)
                return NULL;
@@ -202,8 +202,6 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
        struct bio_vec bv, bvprv, *bvprvp = NULL;
        struct bvec_iter iter;
        unsigned nsegs = 0, sectors = 0;
-       bool do_split = true;
-       struct bio *new = NULL;
        const unsigned max_sectors = get_max_io_size(q, bio);
        const unsigned max_segs = queue_max_segments(q);
 
@@ -245,45 +243,36 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
                }
        }
 
-       do_split = false;
+       *segs = nsegs;
+       return NULL;
 split:
        *segs = nsegs;
-
-       if (do_split) {
-               new = bio_split(bio, sectors, GFP_NOIO, bs);
-               if (new)
-                       bio = new;
-       }
-
-       return do_split ? new : NULL;
+       return bio_split(bio, sectors, GFP_NOIO, bs);
 }
 
-void blk_queue_split(struct request_queue *q, struct bio **bio)
+void __blk_queue_split(struct request_queue *q, struct bio **bio,
+               unsigned int *nr_segs)
 {
-       struct bio *split, *res;
-       unsigned nsegs;
+       struct bio *split;
 
        switch (bio_op(*bio)) {
        case REQ_OP_DISCARD:
        case REQ_OP_SECURE_ERASE:
-               split = blk_bio_discard_split(q, *bio, &q->bio_split, &nsegs);
+               split = blk_bio_discard_split(q, *bio, &q->bio_split, nr_segs);
                break;
        case REQ_OP_WRITE_ZEROES:
-               split = blk_bio_write_zeroes_split(q, *bio, &q->bio_split, &nsegs);
+               split = blk_bio_write_zeroes_split(q, *bio, &q->bio_split,
+                               nr_segs);
                break;
        case REQ_OP_WRITE_SAME:
-               split = blk_bio_write_same_split(q, *bio, &q->bio_split, &nsegs);
+               split = blk_bio_write_same_split(q, *bio, &q->bio_split,
+                               nr_segs);
                break;
        default:
-               split = blk_bio_segment_split(q, *bio, &q->bio_split, &nsegs);
+               split = blk_bio_segment_split(q, *bio, &q->bio_split, nr_segs);
                break;
        }
 
-       /* 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) {
                /* there isn't chance to merge the splitted bio */
                split->bi_opf |= REQ_NOMERGE;
@@ -304,19 +293,25 @@ void blk_queue_split(struct request_queue *q, struct bio **bio)
                *bio = split;
        }
 }
+
+void blk_queue_split(struct request_queue *q, struct bio **bio)
+{
+       unsigned int nr_segs;
+
+       __blk_queue_split(q, bio, &nr_segs);
+}
 EXPORT_SYMBOL(blk_queue_split);
 
-static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
-                                            struct bio *bio)
+unsigned int blk_recalc_rq_segments(struct request *rq)
 {
        unsigned int nr_phys_segs = 0;
-       struct bvec_iter iter;
+       struct req_iterator iter;
        struct bio_vec bv;
 
-       if (!bio)
+       if (!rq->bio)
                return 0;
 
-       switch (bio_op(bio)) {
+       switch (bio_op(rq->bio)) {
        case REQ_OP_DISCARD:
        case REQ_OP_SECURE_ERASE:
        case REQ_OP_WRITE_ZEROES:
@@ -325,30 +320,11 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
                return 1;
        }
 
-       for_each_bio(bio) {
-               bio_for_each_bvec(bv, bio, iter)
-                       bvec_split_segs(q, &bv, &nr_phys_segs, NULL, UINT_MAX);
-       }
-
+       rq_for_each_bvec(bv, rq, iter)
+               bvec_split_segs(rq->q, &bv, &nr_phys_segs, NULL, UINT_MAX);
        return nr_phys_segs;
 }
 
-void blk_recalc_rq_segments(struct request *rq)
-{
-       rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio);
-}
-
-void blk_recount_segments(struct request_queue *q, struct bio *bio)
-{
-       struct bio *nxt = bio->bi_next;
-
-       bio->bi_next = NULL;
-       bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio);
-       bio->bi_next = nxt;
-
-       bio_set_flag(bio, BIO_SEG_VALID);
-}
-
 static inline struct scatterlist *blk_next_sg(struct scatterlist **sg,
                struct scatterlist *sglist)
 {
@@ -519,16 +495,13 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
 }
 EXPORT_SYMBOL(blk_rq_map_sg);
 
-static inline int ll_new_hw_segment(struct request_queue *q,
-                                   struct request *req,
-                                   struct bio *bio)
+static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
+               unsigned int nr_phys_segs)
 {
-       int nr_phys_segs = bio_phys_segments(q, bio);
-
-       if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q))
+       if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(req->q))
                goto no_merge;
 
-       if (blk_integrity_merge_bio(q, req, bio) == false)
+       if (blk_integrity_merge_bio(req->q, req, bio) == false)
                goto no_merge;
 
        /*
@@ -539,12 +512,11 @@ static inline int ll_new_hw_segment(struct request_queue *q,
        return 1;
 
 no_merge:
-       req_set_nomerge(q, req);
+       req_set_nomerge(req->q, req);
        return 0;
 }
 
-int ll_back_merge_fn(struct request_queue *q, struct request *req,
-                    struct bio *bio)
+int ll_back_merge_fn(struct request *req, struct bio *bio, unsigned int nr_segs)
 {
        if (req_gap_back_merge(req, bio))
                return 0;
@@ -553,21 +525,15 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
                return 0;
        if (blk_rq_sectors(req) + bio_sectors(bio) >
            blk_rq_get_max_sectors(req, blk_rq_pos(req))) {
-               req_set_nomerge(q, req);
+               req_set_nomerge(req->q, req);
                return 0;
        }
-       if (!bio_flagged(req->biotail, BIO_SEG_VALID))
-               blk_recount_segments(q, req->biotail);
-       if (!bio_flagged(bio, BIO_SEG_VALID))
-               blk_recount_segments(q, bio);
 
-       return ll_new_hw_segment(q, req, bio);
+       return ll_new_hw_segment(req, bio, nr_segs);
 }
 
-int ll_front_merge_fn(struct request_queue *q, struct request *req,
-                     struct bio *bio)
+int ll_front_merge_fn(struct request *req, struct bio *bio, unsigned int nr_segs)
 {
-
        if (req_gap_front_merge(req, bio))
                return 0;
        if (blk_integrity_rq(req) &&
@@ -575,15 +541,11 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req,
                return 0;
        if (blk_rq_sectors(req) + bio_sectors(bio) >
            blk_rq_get_max_sectors(req, bio->bi_iter.bi_sector)) {
-               req_set_nomerge(q, req);
+               req_set_nomerge(req->q, req);
                return 0;
        }
-       if (!bio_flagged(bio, BIO_SEG_VALID))
-               blk_recount_segments(q, bio);
-       if (!bio_flagged(req->bio, BIO_SEG_VALID))
-               blk_recount_segments(q, req->bio);
 
-       return ll_new_hw_segment(q, req, bio);
+       return ll_new_hw_segment(req, bio, nr_segs);
 }
 
 static bool req_attempt_discard_merge(struct request_queue *q, struct request *req,