aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Gurtovoy <maxg@mellanox.com>2017-11-28 11:28:44 -0500
committerChristoph Hellwig <hch@lst.de>2017-11-28 11:49:22 -0500
commiteb1bd249ba016284ed762d87c1989dd822500773 (patch)
tree520a3360446477d4e142447dd8afab8a2040700c
parentf41725bbe16b0773302c0cc7dc2e89f54828712d (diff)
nvme-rdma: fix memory leak during queue allocation
In case nvme_rdma_wait_for_cm timeout expires before we get an established or rejected event (rdma_connect succeeded) from rdma_cm, we end up with leaking the ib transport resources for dedicated queue. This scenario can easily reproduced using traffic test during port toggling. Also, in order to protect from parallel ib queue destruction, that may be invoked from different context's, introduce new flag that stands for transport readiness. While we're here, protect also against a situation that we can receive rdma_cm events during ib queue destruction. Signed-off-by: Max Gurtovoy <maxg@mellanox.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/nvme/host/rdma.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 02ef0771f6b9..37af56596be6 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -77,6 +77,7 @@ struct nvme_rdma_request {
77enum nvme_rdma_queue_flags { 77enum nvme_rdma_queue_flags {
78 NVME_RDMA_Q_ALLOCATED = 0, 78 NVME_RDMA_Q_ALLOCATED = 0,
79 NVME_RDMA_Q_LIVE = 1, 79 NVME_RDMA_Q_LIVE = 1,
80 NVME_RDMA_Q_TR_READY = 2,
80}; 81};
81 82
82struct nvme_rdma_queue { 83struct nvme_rdma_queue {
@@ -390,12 +391,23 @@ out_err:
390 391
391static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue) 392static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue)
392{ 393{
393 struct nvme_rdma_device *dev = queue->device; 394 struct nvme_rdma_device *dev;
394 struct ib_device *ibdev = dev->dev; 395 struct ib_device *ibdev;
396
397 if (!test_and_clear_bit(NVME_RDMA_Q_TR_READY, &queue->flags))
398 return;
399
400 dev = queue->device;
401 ibdev = dev->dev;
395 402
396 ib_mr_pool_destroy(queue->qp, &queue->qp->rdma_mrs); 403 ib_mr_pool_destroy(queue->qp, &queue->qp->rdma_mrs);
397 404
398 rdma_destroy_qp(queue->cm_id); 405 /*
406 * The cm_id object might have been destroyed during RDMA connection
407 * establishment error flow to avoid getting other cma events, thus
408 * the destruction of the QP shouldn't use rdma_cm API.
409 */
410 ib_destroy_qp(queue->qp);
399 ib_free_cq(queue->ib_cq); 411 ib_free_cq(queue->ib_cq);
400 412
401 nvme_rdma_free_ring(ibdev, queue->rsp_ring, queue->queue_size, 413 nvme_rdma_free_ring(ibdev, queue->rsp_ring, queue->queue_size,
@@ -463,6 +475,8 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue)
463 goto out_destroy_ring; 475 goto out_destroy_ring;
464 } 476 }
465 477
478 set_bit(NVME_RDMA_Q_TR_READY, &queue->flags);
479
466 return 0; 480 return 0;
467 481
468out_destroy_ring: 482out_destroy_ring:
@@ -529,6 +543,7 @@ static int nvme_rdma_alloc_queue(struct nvme_rdma_ctrl *ctrl,
529 543
530out_destroy_cm_id: 544out_destroy_cm_id:
531 rdma_destroy_id(queue->cm_id); 545 rdma_destroy_id(queue->cm_id);
546 nvme_rdma_destroy_queue_ib(queue);
532 return ret; 547 return ret;
533} 548}
534 549