block: Introduce __blk_segment_map_sg() helper
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>
This commit is contained in:
parent
53362a05ae
commit
963ab9e5da
|
@ -110,6 +110,49 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
|
||||||
return 0;
|
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
|
* map a request to scatterlist, return number of sg entries setup. Caller
|
||||||
* must make sure sg can hold rq->nr_phys_segments entries
|
* 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;
|
bvprv = NULL;
|
||||||
sg = NULL;
|
sg = NULL;
|
||||||
rq_for_each_segment(bvec, rq, iter) {
|
rq_for_each_segment(bvec, rq, iter) {
|
||||||
int nbytes = bvec->bv_len;
|
__blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
|
||||||
|
&nsegs, &cluster);
|
||||||
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;
|
|
||||||
} /* segments in rq */
|
} /* segments in rq */
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue