block: Introduce __blk_segment_map_sg() helper
authorAsias He <asias@redhat.com>
Thu, 2 Aug 2012 21:42:03 +0000 (23:42 +0200)
committerJens Axboe <axboe@kernel.dk>
Thu, 2 Aug 2012 21:42:03 +0000 (23:42 +0200)
Split the mapping code in blk_rq_map_sg() to a helper
__blk_segment_map_sg(), so that other mapping function, e.g.
blk_bio_map_sg(), can share the code.

Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Tejun Heo <tj@kernel.org>
Cc: Shaohua Li <shli@kernel.org>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: virtualization@lists.linux-foundation.org
Suggested-by: Jens Axboe <axboe@kernel.dk>
Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Asias He <asias@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-merge.c

index 160035f548823482968bcd58298fcf9c309e7d62..576b68e792487493fed68a440743f15551f1b782 100644 (file)
@@ -110,6 +110,49 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
        return 0;
 }
 
+static void
+__blk_segment_map_sg(struct request_queue *q, struct bio_vec *bvec,
+                    struct scatterlist *sglist, struct bio_vec **bvprv,
+                    struct scatterlist **sg, int *nsegs, int *cluster)
+{
+
+       int nbytes = bvec->bv_len;
+
+       if (*bvprv && *cluster) {
+               if ((*sg)->length + nbytes > queue_max_segment_size(q))
+                       goto new_segment;
+
+               if (!BIOVEC_PHYS_MERGEABLE(*bvprv, bvec))
+                       goto new_segment;
+               if (!BIOVEC_SEG_BOUNDARY(q, *bvprv, bvec))
+                       goto new_segment;
+
+               (*sg)->length += nbytes;
+       } else {
+new_segment:
+               if (!*sg)
+                       *sg = sglist;
+               else {
+                       /*
+                        * If the driver previously mapped a shorter
+                        * list, we could see a termination bit
+                        * prematurely unless it fully inits the sg
+                        * table on each mapping. We KNOW that there
+                        * must be more entries here or the driver
+                        * would be buggy, so force clear the
+                        * termination bit to avoid doing a full
+                        * sg_init_table() in drivers for each command.
+                        */
+                       (*sg)->page_link &= ~0x02;
+                       *sg = sg_next(*sg);
+               }
+
+               sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset);
+               (*nsegs)++;
+       }
+       *bvprv = bvec;
+}
+
 /*
  * map a request to scatterlist, return number of sg entries setup. Caller
  * must make sure sg can hold rq->nr_phys_segments entries
@@ -131,41 +174,8 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        bvprv = NULL;
        sg = NULL;
        rq_for_each_segment(bvec, rq, iter) {
-               int nbytes = bvec->bv_len;
-
-               if (bvprv && cluster) {
-                       if (sg->length + nbytes > queue_max_segment_size(q))
-                               goto new_segment;
-
-                       if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
-                               goto new_segment;
-                       if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
-                               goto new_segment;
-
-                       sg->length += nbytes;
-               } else {
-new_segment:
-                       if (!sg)
-                               sg = sglist;
-                       else {
-                               /*
-                                * If the driver previously mapped a shorter
-                                * list, we could see a termination bit
-                                * prematurely unless it fully inits the sg
-                                * table on each mapping. We KNOW that there
-                                * must be more entries here or the driver
-                                * would be buggy, so force clear the
-                                * termination bit to avoid doing a full
-                                * sg_init_table() in drivers for each command.
-                                */
-                               sg->page_link &= ~0x02;
-                               sg = sg_next(sg);
-                       }
-
-                       sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset);
-                       nsegs++;
-               }
-               bvprv = bvec;
+               __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+                                    &nsegs, &cluster);
        } /* segments in rq */