[PATCHv2 6/7] blk-mq-dma: add support for mapping integrity metadata
Keith Busch
kbusch at meta.com
Sun Jul 20 11:40:39 PDT 2025
From: Keith Busch <kbusch at kernel.org>
Provide integrity metadata helpers equivalent to the data payload
helpers for iterating a request for dma setup.
Signed-off-by: Keith Busch <kbusch at kernel.org>
---
block/blk-mq-dma.c | 58 ++++++++++++++++++++++++++++++-----
include/linux/blk-integrity.h | 17 ++++++++++
include/linux/blk-mq-dma.h | 1 +
3 files changed, 69 insertions(+), 7 deletions(-)
diff --git a/block/blk-mq-dma.c b/block/blk-mq-dma.c
index 1e2e93c1cf5e2..a4ae043e2cd72 100644
--- a/block/blk-mq-dma.c
+++ b/block/blk-mq-dma.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2025 Christoph Hellwig
*/
+#include <linux/blk-integrity.h>
#include <linux/blk-mq-dma.h>
#include "blk.h"
@@ -10,6 +11,24 @@ struct phys_vec {
u32 len;
};
+static bool blk_dma_iter_next(struct blk_dma_iter *iter)
+{
+ if (iter->iter.bi_size)
+ return true;
+ if (!iter->bio->bi_next)
+ return false;
+
+ iter->bio = iter->bio->bi_next;
+ if (iter->integrity) {
+ iter->iter = iter->bio->bi_integrity->bip_iter;
+ iter->bvec = iter->bio->bi_integrity->bip_vec;
+ } else {
+ iter->iter = iter->bio->bi_iter;
+ iter->bvec = iter->bio->bi_io_vec;
+ }
+ return true;
+}
+
static bool blk_map_iter_next(struct request *req, struct blk_dma_iter *iter,
struct phys_vec *vec)
{
@@ -36,13 +55,8 @@ static bool blk_map_iter_next(struct request *req, struct blk_dma_iter *iter,
while (!iter->iter.bi_size || !iter->iter.bi_bvec_done) {
struct bio_vec next;
- if (!iter->iter.bi_size) {
- if (!iter->bio->bi_next)
- break;
- iter->bio = iter->bio->bi_next;
- iter->iter = iter->bio->bi_iter;
- iter->bvec = iter->bio->bi_io_vec;
- }
+ if (!blk_dma_iter_next(iter))
+ break;
next = mp_bvec_iter_bvec(iter->bvec, iter->iter);
if (bv.bv_len + next.bv_len > max_size ||
@@ -185,6 +199,7 @@ bool blk_rq_dma_map_iter_start(struct request *req, struct device *dma_dev,
struct dma_iova_state *state, struct blk_dma_iter *iter)
{
iter->iter = req->bio->bi_iter;
+ iter->integrity = false;
if (req->rq_flags & RQF_SPECIAL_PAYLOAD)
iter->bvec = &req->special_vec;
else
@@ -227,6 +242,35 @@ bool blk_rq_dma_map_iter_next(struct request *req, struct device *dma_dev,
}
EXPORT_SYMBOL_GPL(blk_rq_dma_map_iter_next);
+#ifdef CONFIG_BLK_DEV_INTEGRITY
+bool blk_rq_integrity_dma_map_iter_start(struct request *req,
+ struct device *dma_dev, struct dma_iova_state *state,
+ struct blk_dma_iter *iter)
+{
+ unsigned len = bio_integrity_bytes(&req->q->limits.integrity,
+ blk_rq_sectors(req));
+ iter->iter = req->bio->bi_integrity->bip_iter;
+ iter->bvec = req->bio->bi_integrity->bip_vec;
+ iter->integrity = true;
+ return blk_dma_map_iter_start(req, dma_dev, state, iter, len);
+}
+EXPORT_SYMBOL_GPL(blk_rq_integrity_dma_map_iter_start);
+
+bool blk_rq_integrity_dma_map_iter_next(struct request *req,
+ struct device *dma_dev, struct blk_dma_iter *iter)
+{
+ struct phys_vec vec;
+
+ if (!blk_map_iter_next(req, iter, &vec))
+ return false;
+
+ if (iter->p2pdma.map == PCI_P2PDMA_MAP_BUS_ADDR)
+ return blk_dma_map_bus(iter, &vec);
+ return blk_dma_map_direct(req, dma_dev, iter, &vec);
+}
+EXPORT_SYMBOL_GPL(blk_rq_integrity_dma_map_iter_next);
+#endif
+
static inline struct scatterlist *
blk_next_sg(struct scatterlist **sg, struct scatterlist *sglist)
{
diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h
index c7eae0bfb013f..d66ba850bb2a5 100644
--- a/include/linux/blk-integrity.h
+++ b/include/linux/blk-integrity.h
@@ -4,6 +4,7 @@
#include <linux/blk-mq.h>
#include <linux/bio-integrity.h>
+#include <linux/blk-mq-dma.h>
struct request;
@@ -29,6 +30,11 @@ int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
int blk_rq_integrity_map_user(struct request *rq, void __user *ubuf,
ssize_t bytes);
+bool blk_rq_integrity_dma_map_iter_start(struct request *req,
+ struct device *dma_dev, struct dma_iova_state *state,
+ struct blk_dma_iter *iter);
+bool blk_rq_integrity_dma_map_iter_next(struct request *req,
+ struct device *dma_dev, struct blk_dma_iter *iter);
static inline bool
blk_integrity_queue_supports_integrity(struct request_queue *q)
@@ -108,6 +114,17 @@ static inline int blk_rq_integrity_map_user(struct request *rq,
{
return -EINVAL;
}
+bool blk_rq_integrity_dma_map_iter_start(struct request *req,
+ struct device *dma_dev, struct dma_iova_state *state,
+ struct blk_dma_iter *iter)
+{
+ return false;
+}
+bool blk_rq_integrity_dma_map_iter_next(struct request *req,
+ struct device *dma_dev, struct blk_dma_iter *iter)
+{
+ return false;
+}
static inline struct blk_integrity *bdev_get_integrity(struct block_device *b)
{
return NULL;
diff --git a/include/linux/blk-mq-dma.h b/include/linux/blk-mq-dma.h
index cdbaacc3db065..8b06659bf67dd 100644
--- a/include/linux/blk-mq-dma.h
+++ b/include/linux/blk-mq-dma.h
@@ -18,6 +18,7 @@ struct blk_dma_iter {
struct bvec_iter iter;
struct bio *bio;
struct pci_p2pdma_map_state p2pdma;
+ bool integrity;
};
bool blk_rq_dma_map_iter_start(struct request *req, struct device *dma_dev,
--
2.47.1
More information about the Linux-nvme
mailing list