From: Keith Busch <kbusch@xxxxxxxxxx> Provide integrity metadata helpers equivalent to the data payload helpers for iterating a request for dma setup. Signed-off-by: Keith Busch <kbusch@xxxxxxxxxx> --- 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