Commit 94449463 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'nvme-7.1-2026-05-21' of git://git.infradead.org/nvme into block-7.1

Pull NVMe fixes from Keith:

"- Fix memory leak for peer-to-peer addresses
 - Fix dma map leaks on resource errors"

* tag 'nvme-7.1-2026-05-21' of git://git.infradead.org/nvme:
  nvme-pci: fix dma mapping leak on data setup error
  nvme-pci: fix dma_vecs leak on p2p memory
parents 431e4004 1bf86336
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -966,7 +966,8 @@ static bool nvme_pci_prp_save_mapping(struct request *req,
{
	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);

	if (dma_use_iova(&iod->dma_state) || !dma_need_unmap(dma_dev))
	if (dma_use_iova(&iod->dma_state) || !dma_need_unmap(dma_dev) ||
	    (iod->flags & IOD_DATA_P2P))
		return true;

	if (!iod->nr_dma_vecs) {
@@ -996,6 +997,23 @@ static bool nvme_pci_prp_iter_next(struct request *req, struct device *dma_dev,
	return nvme_pci_prp_save_mapping(req, dma_dev, iter);
}

static void nvme_unmap_iter(struct request *req, struct blk_dma_iter *iter,
			    struct dma_iova_state *state)
{
	struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
	struct device *dev = nvmeq->dev->dev;

	if (!blk_rq_dma_unmap(req, dev, state, iter->len, iter->p2pdma.map)) {
		unsigned int attrs = 0;

		if (iter->p2pdma.map == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE)
			attrs |= DMA_ATTR_MMIO;

		dma_unmap_phys(dev, iter->addr, iter->len, rq_dma_dir(req),
			       attrs);
	}
}

static blk_status_t nvme_pci_setup_data_prp(struct request *req,
		struct blk_dma_iter *iter)
{
@@ -1006,8 +1024,10 @@ static blk_status_t nvme_pci_setup_data_prp(struct request *req,
	unsigned int prp_len, i;
	__le64 *prp_list;

	if (!nvme_pci_prp_save_mapping(req, nvmeq->dev->dev, iter))
	if (!nvme_pci_prp_save_mapping(req, nvmeq->dev->dev, iter)) {
		nvme_unmap_iter(req, iter, &iod->dma_state);
		return iter->status;
	}

	/*
	 * PRP1 always points to the start of the DMA transfers.
@@ -1112,6 +1132,7 @@ static blk_status_t nvme_pci_setup_data_prp(struct request *req,
	dev_err_once(nvmeq->dev->dev,
		"Incorrectly formed request for payload:%d nents:%d\n",
		blk_rq_payload_bytes(req), blk_rq_nr_phys_segments(req));
	nvme_unmap_data(req);
	return BLK_STS_IOERR;
}

@@ -1155,8 +1176,11 @@ static blk_status_t nvme_pci_setup_data_sgl(struct request *req,

	sg_list = dma_pool_alloc(nvme_dma_pool(nvmeq, iod), GFP_ATOMIC,
			&sgl_dma);
	if (!sg_list)
	if (!sg_list) {
		nvme_unmap_iter(req, iter, &iod->dma_state);
		return BLK_STS_RESOURCE;
	}

	iod->descriptors[iod->nr_descriptors++] = sg_list;

	do {
@@ -1313,8 +1337,10 @@ static blk_status_t nvme_pci_setup_meta_iter(struct request *req)

	sg_list = dma_pool_alloc(nvmeq->descriptor_pools.small, GFP_ATOMIC,
			&sgl_dma);
	if (!sg_list)
	if (!sg_list) {
		nvme_unmap_iter(req, &iter, &iod->meta_dma_state);
		return BLK_STS_RESOURCE;
	}

	iod->meta_descriptor = sg_list;
	iod->meta_dma = sgl_dma;