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
This commit is contained in:
Jens Axboe
2026-05-21 09:12:40 -06:00
+30 -4
View File
@@ -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 @@ bad_sgl:
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;