[PATCH] nvme-pci: always use blk_map_iter for metadata

Christoph Hellwig hch at lst.de
Tue Oct 21 00:19:35 PDT 2025


On Mon, Oct 20, 2025 at 11:24:44AM -0700, Keith Busch wrote:
> From: Keith Busch <kbusch at kernel.org>
> 
> The dma_map_bvec helper doesn't work for p2p data. Rather than special
> case it, just use the same mapping logic so that the driver doesn't need
> to consider memory types.

We already consider the memory types for the data path, so treating the
metadasta path where p2p is even more unlikely sounds like the wrong
tradeoff.  If we have a single segment we just need a single
is_pci_p2pdma_page check to skip direct mapping path.  Something like
this untested patch:

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index c916176bd9f0..c8cfcc64d5ca 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1042,7 +1042,7 @@ static blk_status_t nvme_map_data(struct request *req)
 	return nvme_pci_setup_data_prp(req, &iter);
 }
 
-static blk_status_t nvme_pci_setup_meta_sgls(struct request *req)
+static blk_status_t nvme_pci_setup_meta_iter(struct request *req)
 {
 	struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
 	unsigned int entries = req->nr_integrity_segments;
@@ -1073,7 +1073,9 @@ static blk_status_t nvme_pci_setup_meta_sgls(struct request *req)
 	 * mechanism to catch any misunderstandings between the application and
 	 * device.
 	 */
-	if (entries == 1 && !(nvme_req(req)->flags & NVME_REQ_USERCMD)) {
+	if (entries == 1 &&
+	    !(nvme_req(req)->flags & NVME_REQ_USERCMD) &&
+	    nvme_ctrl_meta_sgl_supported(&dev->ctrl)) {
 		iod->cmd.common.metadata = cpu_to_le64(iter.addr);
 		iod->meta_total_len = iter.len;
 		iod->meta_dma = iter.addr;
@@ -1125,10 +1127,12 @@ static blk_status_t nvme_pci_setup_meta_mptr(struct request *req)
 static blk_status_t nvme_map_metadata(struct request *req)
 {
 	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+	struct bio_vec bv = req_bvec(req);
 
-	if ((iod->cmd.common.flags & NVME_CMD_SGL_METABUF) &&
-	    nvme_pci_metadata_use_sgls(req))
-		return nvme_pci_setup_meta_sgls(req);
+	if (((iod->cmd.common.flags & NVME_CMD_SGL_METABUF) &&
+	     nvme_pci_metadata_use_sgls(req)) ||
+	    is_pci_p2pdma_page(bv.bv_page))
+		return nvme_pci_setup_meta_iter(req);
 	return nvme_pci_setup_meta_mptr(req);
 }
 



More information about the Linux-nvme mailing list