nvme fixes for Linux 7.1

- Fix memory leak for peer-to-peer addresses
  - Fix dma map leaks on resource errors
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE3Fbyvv+648XNRdHTPe3zGtjzRgkFAmoPHMwACgkQPe3zGtjz
 RgmG7hAAl7k8gw6sUW0ouwdhYSdTpW6iEqXm2DZ3Nyb3gikYzbgnkznChgcNMdxG
 pFSkeO0BHFq7ARj8nqGNKP19cprx5u4EQhiI24swS5WpqpUtIfvdMbrYU4bzR13Q
 yOueovuTFnRmTaw8YGYbjRUgoqoDTDwP6gZhFEHpZvbtgz5fRDymIoaMmC6uI0jM
 vpGAO8mTDZPkJvizn3mtvif5wiWvSC5BCxElH8ouJwSYaIVRlCwZk2hf4Rqu7FUe
 N0ZoS9XUfAYBWaHesXrRD5t9o9pLAmCDDAfujlP8NKtvothXH3NN+NwFJgxsE88e
 jx7RIiKLUmJsYMlOrAc/d6UZBZJa9vmNNbuZDdeRSGQFZcbrMrawdOHEppSRJBty
 HWA6JhqMiltqTp8VGQG+ooqAUkkyop2Ral4ztO+448o9SlKp6tJZSl5z63sPnDsv
 CRg6A58uQKvWhPXaqxuJGCh35Sb7Y4GpH/O8GWY/4adC6o/9joT9bz4/s4VzBLrU
 BOG9Y1gRsitKGJ118Cf8wf09AU//1UazhEMLILgvWd7TsApjfqxY5omgAP98ucyz
 aRDHRj2417r91/0quhCBcUhTH5/qKI4vw+xzEixk3kyxtc4WFhx6puyywc+ykMf6
 aYTqPGhtXpb+f+Ze1dFxdGCvF1epUnO58mOFah6GtuVMK3vHIGY=
 =Rf9Q
 -----END PGP SIGNATURE-----

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
commit 94449463d2

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 @@ 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;