Previously, a bio_vec of bip was made of one page in the block layer, and sg_list was generated using hw information in lld. This is done in the block layer and the bio_vec has been changed to multi-page, so it is changed to configure the sg-table using the existing api, such as the sg-table setting for the bio. (e.g. multi-page map) Cc: Christoph Hellwig <hch@xxxxxx> Cc: Martin K. Petersen <martin.petersen@xxxxxxxxxx> Signed-off-by: Jinyoung Choi <j-young.choi@xxxxxxxxxxx> --- block/blk-integrity.c | 52 ----------------------------------------- block/blk-merge.c | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 52 deletions(-) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 64407b412947..c50954652177 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -55,58 +55,6 @@ int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio) } EXPORT_SYMBOL(blk_rq_count_integrity_sg); -/** - * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist - * @q: request queue - * @bio: bio with integrity metadata attached - * @sglist: target scatterlist - * - * Description: Map the integrity vectors in request into a - * scatterlist. The scatterlist must be big enough to hold all - * elements. I.e. sized using blk_rq_count_integrity_sg(). - */ -int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio, - struct scatterlist *sglist) -{ - struct bio_vec iv, ivprv = { NULL }; - struct scatterlist *sg = NULL; - unsigned int segments = 0; - struct bvec_iter iter; - int prev = 0; - - bio_for_each_integrity_vec(iv, bio, iter) { - - if (prev) { - if (!biovec_phys_mergeable(q, &ivprv, &iv)) - goto new_segment; - if (sg->length + iv.bv_len > queue_max_segment_size(q)) - goto new_segment; - - sg->length += iv.bv_len; - } else { -new_segment: - if (!sg) - sg = sglist; - else { - sg_unmark_end(sg); - sg = sg_next(sg); - } - - sg_set_page(sg, iv.bv_page, iv.bv_len, iv.bv_offset); - segments++; - } - - prev = 1; - ivprv = iv; - } - - if (sg) - sg_mark_end(sg); - - return segments; -} -EXPORT_SYMBOL(blk_rq_map_integrity_sg); - /** * blk_integrity_compare - Compare integrity profile of two disks * @gd1: Disk to compare diff --git a/block/blk-merge.c b/block/blk-merge.c index c6a0958e8df1..f17e19ff3a11 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -524,6 +524,60 @@ __blk_segment_map_sg_merge(struct request_queue *q, struct bio_vec *bvec, return true; } +#if defined(CONFIG_BLK_DEV_INTEGRITY) +/** + * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist + * @q: request queue + * @bio: bio with integrity metadata attached + * @sglist: target scatterlist + * + * Description: Map the integrity vectors in request into a scatterlist. + * The scatterlist must be big enough to hold all elements. + */ +int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio, + struct scatterlist *sglist) +{ + struct bio_vec iv, ivprv = { NULL }; + struct scatterlist *sg = NULL; + unsigned int nsegs = 0; + struct bvec_iter iter; + bool new_bio = false; + + for_each_bio(bio) { + struct bio_integrity_payload *bip = bio->bi_integrity; + + bip_for_each_mp_bvec(iv, bip, iter) { + /* + * Only try to merge bvecs from two bios given we + * have done bio internal merge when adding pages + * to bio + */ + if (new_bio && + __blk_segment_map_sg_merge(q, &iv, &ivprv, &sg)) + goto next_iv; + + if (iv.bv_offset + iv.bv_len <= PAGE_SIZE) + nsegs += __blk_bvec_map_sg(iv, sglist, &sg); + else + nsegs += blk_bvec_map_sg(q, &iv, sglist, &sg); + next_iv: + new_bio = false; + } + + if (likely(bip->bip_iter.bi_size)) { + ivprv = iv; + new_bio = true; + } + } + + if (sg) + sg_mark_end(sg); + + return nsegs; +} +EXPORT_SYMBOL(blk_rq_map_integrity_sg); +#endif /* CONFIG_BLK_DEV_INTEGRITY */ + static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, struct scatterlist *sglist, struct scatterlist **sg) -- 2.34.1