]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
blk-integrity: use iterator for mapping sg
authorKeith Busch <kbusch@kernel.org>
Wed, 13 Aug 2025 15:31:51 +0000 (08:31 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 25 Aug 2025 13:44:39 +0000 (07:44 -0600)
Modify blk_rq_map_integrity_sg to use the blk-mq mapping iterator. This
produces more efficient code and converges the integrity mapping
implementations to reduce future maintenance burdens.

The function implementation moves from blk-integrity.c to blk-mq-dma.c
in order to use the types and functions private to that file.

Signed-off-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20250813153153.3260897-8-kbusch@meta.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-integrity.c
block/blk-mq-dma.c

index 056b8948369d55b135e52a0391043c1e47459de7..dd97b27366e0e94c44d089e491166c079902d2a6 100644 (file)
@@ -122,64 +122,6 @@ out:
                                   NULL);
 }
 
-/**
- * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
- * @rq:                request to map
- * @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() or
- * rq->nr_integrity_segments.
- */
-int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
-{
-       struct bio_vec iv, ivprv = { NULL };
-       struct request_queue *q = rq->q;
-       struct scatterlist *sg = NULL;
-       struct bio *bio = rq->bio;
-       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);
-
-       /*
-        * Something must have been wrong if the figured number of segment
-        * is bigger than number of req's physical integrity segments
-        */
-       BUG_ON(segments > rq->nr_integrity_segments);
-       BUG_ON(segments > queue_max_integrity_segments(q));
-       return segments;
-}
-EXPORT_SYMBOL(blk_rq_map_integrity_sg);
-
 int blk_rq_integrity_map_user(struct request *rq, void __user *ubuf,
                              ssize_t bytes)
 {
index 60a244a129c3c503ffd593351088d2bb7c3354d6..660b5e200ccf6932fd169ccdbf88ae12c14932ba 100644 (file)
@@ -379,4 +379,49 @@ bool blk_rq_integrity_dma_map_iter_next(struct request *req,
        return blk_dma_map_direct(req, dma_dev, iter, &vec);
 }
 EXPORT_SYMBOL_GPL(blk_rq_integrity_dma_map_iter_next);
+
+/**
+ * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
+ * @rq:                request to map
+ * @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() or
+ * rq->nr_integrity_segments.
+ */
+int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
+{
+       struct request_queue *q = rq->q;
+       struct scatterlist *sg = NULL;
+       struct bio *bio = rq->bio;
+       unsigned int segments = 0;
+       struct phys_vec vec;
+
+       struct blk_map_iter iter = {
+               .bio = bio,
+               .iter = bio_integrity(bio)->bip_iter,
+               .bvecs = bio_integrity(bio)->bip_vec,
+               .is_integrity = true,
+       };
+
+       while (blk_map_iter_next(rq, &iter, &vec)) {
+               sg = blk_next_sg(&sg, sglist);
+               sg_set_page(sg, phys_to_page(vec.paddr), vec.len,
+                               offset_in_page(vec.paddr));
+               segments++;
+       }
+
+       if (sg)
+               sg_mark_end(sg);
+
+       /*
+        * Something must have been wrong if the figured number of segment
+        * is bigger than number of req's physical integrity segments
+        */
+       BUG_ON(segments > rq->nr_integrity_segments);
+       BUG_ON(segments > queue_max_integrity_segments(q));
+       return segments;
+}
+EXPORT_SYMBOL(blk_rq_map_integrity_sg);
 #endif