ib_dma_map_sg() returns 0 on a P2P mapping failure, losing the DMA layer's -EREMOTEIO, so nvme-rdma reports a path error. Default multipath requeues the I/O forever, and without multipath it burns nvme_max_retries requeues, then completes as retryable BLK_STS_TRANSPORT. Map the data and metadata scatterlists with ib_dma_map_sgtable_attrs() and return BLK_STS_TARGET for -EREMOTEIO, matching nvme-pci (commit 91fb2b6052f7 ("nvme-pci: convert to using dma_map_sgtable()")). Scatterlists stay: ib_map_mr_sg() consumes them, so blk_rq_dma_map does not apply. Start the request only after mapping succeeds so multipath accounting is never taken for an unmapped request, and ratelimit the map-failure message. Fixes: 23528aa3320a ("nvme: enable PCI P2PDMA support for RDMA transport") Cc: stable@vger.kernel.org # v7.1 Assisted-by: Claude:claude-fable-5 Signed-off-by: Mykola Marzhan --- drivers/nvme/host/rdma.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 6909e3542794..f8edb23552ad 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -1469,6 +1469,7 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq, int *count, int *pi_count) { struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); + struct sg_table sgt; int ret; req->data_sgl.sg_table.sgl = (struct scatterlist *)(req + 1); @@ -1480,12 +1481,14 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq, req->data_sgl.nents = blk_rq_map_sg(rq, req->data_sgl.sg_table.sgl); - *count = ib_dma_map_sg(ibdev, req->data_sgl.sg_table.sgl, - req->data_sgl.nents, rq_dma_dir(rq)); - if (unlikely(*count <= 0)) { - ret = -EIO; + sgt = (struct sg_table) { + .sgl = req->data_sgl.sg_table.sgl, + .orig_nents = req->data_sgl.nents, + }; + ret = ib_dma_map_sgtable_attrs(ibdev, &sgt, rq_dma_dir(rq), 0); + if (unlikely(ret)) goto out_free_table; - } + *count = sgt.nents; if (blk_integrity_rq(rq)) { req->metadata_sgl->sg_table.sgl = @@ -1501,14 +1504,14 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq, req->metadata_sgl->nents = blk_rq_map_integrity_sg(rq, req->metadata_sgl->sg_table.sgl); - *pi_count = ib_dma_map_sg(ibdev, - req->metadata_sgl->sg_table.sgl, - req->metadata_sgl->nents, - rq_dma_dir(rq)); - if (unlikely(*pi_count <= 0)) { - ret = -EIO; + sgt = (struct sg_table) { + .sgl = req->metadata_sgl->sg_table.sgl, + .orig_nents = req->metadata_sgl->nents, + }; + ret = ib_dma_map_sgtable_attrs(ibdev, &sgt, rq_dma_dir(rq), 0); + if (unlikely(ret)) goto out_free_pi_table; - } + *pi_count = sgt.nents; } return 0; @@ -2026,8 +2029,6 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, if (ret) goto unmap_qe; - nvme_start_request(rq); - if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) && queue->pi_support && (c->common.opcode == nvme_cmd_write || @@ -2039,11 +2040,13 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, err = nvme_rdma_map_data(queue, rq, c); if (unlikely(err < 0)) { - dev_err(queue->ctrl->ctrl.device, - "Failed to map data (%d)\n", err); + dev_err_ratelimited(queue->ctrl->ctrl.device, + "Failed to map data (%d)\n", err); goto err; } + nvme_start_request(rq); + sqe->cqe.done = nvme_rdma_send_done; ib_dma_sync_single_for_device(dev, sqe->dma, @@ -2063,6 +2066,9 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, ret = nvme_host_path_error(rq); else if (err == -ENOMEM || err == -EAGAIN) ret = BLK_STS_RESOURCE; + /* Peer memory unreachable from this device: don't retry. */ + else if (err == -EREMOTEIO) + ret = BLK_STS_TARGET; else ret = BLK_STS_IOERR; nvme_cleanup_cmd(rq); -- 2.52.0