diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2015-01-18 09:51:06 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2015-02-17 15:32:46 -0500 |
commit | 6606e6a2ff2710b473838b291dc533cd8fc1471f (patch) | |
tree | 1d37d500fd385ac7c627881b9254c37c3bb0d6b2 | |
parent | c6c95ef4cec680f7a10aa425a9970744b35b6489 (diff) |
IB/iser: Fix memory regions possible leak
When teardown process starts during live IO, we need to keep the
memory regions pool (frmr/fmr) until all in-flight tasks are properly
released, since each task may return a memory region to the pool. In
order to do this, we pass a destroy flag to iser_free_ib_conn_res to
indicate we can destroy the device and the memory regions
pool. iser_conn_release will pass it as true and also DEVICE_REMOVAL
event (we need to let the device to properly remove).
Also, Since we conditionally call iser_free_rx_descriptors,
remove the extra check on iser_conn->rx_descs.
Fixes: 5426b1711fd0 ("IB/iser: Collapse cleanup and disconnect handlers")
Reported-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_initiator.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 25 |
2 files changed, 14 insertions, 15 deletions
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index bdf2b22e336b..20e859a6f1a6 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c | |||
@@ -320,9 +320,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn) | |||
320 | struct ib_conn *ib_conn = &iser_conn->ib_conn; | 320 | struct ib_conn *ib_conn = &iser_conn->ib_conn; |
321 | struct iser_device *device = ib_conn->device; | 321 | struct iser_device *device = ib_conn->device; |
322 | 322 | ||
323 | if (!iser_conn->rx_descs) | ||
324 | goto free_login_buf; | ||
325 | |||
326 | if (device->iser_free_rdma_reg_res) | 323 | if (device->iser_free_rdma_reg_res) |
327 | device->iser_free_rdma_reg_res(ib_conn); | 324 | device->iser_free_rdma_reg_res(ib_conn); |
328 | 325 | ||
@@ -334,7 +331,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn) | |||
334 | /* make sure we never redo any unmapping */ | 331 | /* make sure we never redo any unmapping */ |
335 | iser_conn->rx_descs = NULL; | 332 | iser_conn->rx_descs = NULL; |
336 | 333 | ||
337 | free_login_buf: | ||
338 | iser_free_login_buf(iser_conn); | 334 | iser_free_login_buf(iser_conn); |
339 | } | 335 | } |
340 | 336 | ||
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 695a2704bd43..f3e21abc20a6 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -600,16 +600,16 @@ void iser_release_work(struct work_struct *work) | |||
600 | /** | 600 | /** |
601 | * iser_free_ib_conn_res - release IB related resources | 601 | * iser_free_ib_conn_res - release IB related resources |
602 | * @iser_conn: iser connection struct | 602 | * @iser_conn: iser connection struct |
603 | * @destroy_device: indicator if we need to try to release | 603 | * @destroy: indicator if we need to try to release the |
604 | * the iser device (only iscsi shutdown and DEVICE_REMOVAL | 604 | * iser device and memory regoins pool (only iscsi |
605 | * will use this. | 605 | * shutdown and DEVICE_REMOVAL will use this). |
606 | * | 606 | * |
607 | * This routine is called with the iser state mutex held | 607 | * This routine is called with the iser state mutex held |
608 | * so the cm_id removal is out of here. It is Safe to | 608 | * so the cm_id removal is out of here. It is Safe to |
609 | * be invoked multiple times. | 609 | * be invoked multiple times. |
610 | */ | 610 | */ |
611 | static void iser_free_ib_conn_res(struct iser_conn *iser_conn, | 611 | static void iser_free_ib_conn_res(struct iser_conn *iser_conn, |
612 | bool destroy_device) | 612 | bool destroy) |
613 | { | 613 | { |
614 | struct ib_conn *ib_conn = &iser_conn->ib_conn; | 614 | struct ib_conn *ib_conn = &iser_conn->ib_conn; |
615 | struct iser_device *device = ib_conn->device; | 615 | struct iser_device *device = ib_conn->device; |
@@ -617,17 +617,20 @@ static void iser_free_ib_conn_res(struct iser_conn *iser_conn, | |||
617 | iser_info("freeing conn %p cma_id %p qp %p\n", | 617 | iser_info("freeing conn %p cma_id %p qp %p\n", |
618 | iser_conn, ib_conn->cma_id, ib_conn->qp); | 618 | iser_conn, ib_conn->cma_id, ib_conn->qp); |
619 | 619 | ||
620 | iser_free_rx_descriptors(iser_conn); | ||
621 | |||
622 | if (ib_conn->qp != NULL) { | 620 | if (ib_conn->qp != NULL) { |
623 | ib_conn->comp->active_qps--; | 621 | ib_conn->comp->active_qps--; |
624 | rdma_destroy_qp(ib_conn->cma_id); | 622 | rdma_destroy_qp(ib_conn->cma_id); |
625 | ib_conn->qp = NULL; | 623 | ib_conn->qp = NULL; |
626 | } | 624 | } |
627 | 625 | ||
628 | if (destroy_device && device != NULL) { | 626 | if (destroy) { |
629 | iser_device_try_release(device); | 627 | if (iser_conn->rx_descs) |
630 | ib_conn->device = NULL; | 628 | iser_free_rx_descriptors(iser_conn); |
629 | |||
630 | if (device != NULL) { | ||
631 | iser_device_try_release(device); | ||
632 | ib_conn->device = NULL; | ||
633 | } | ||
631 | } | 634 | } |
632 | } | 635 | } |
633 | 636 | ||
@@ -840,7 +843,7 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id) | |||
840 | } | 843 | } |
841 | 844 | ||
842 | static void iser_cleanup_handler(struct rdma_cm_id *cma_id, | 845 | static void iser_cleanup_handler(struct rdma_cm_id *cma_id, |
843 | bool destroy_device) | 846 | bool destroy) |
844 | { | 847 | { |
845 | struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context; | 848 | struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context; |
846 | 849 | ||
@@ -850,7 +853,7 @@ static void iser_cleanup_handler(struct rdma_cm_id *cma_id, | |||
850 | * and flush errors. | 853 | * and flush errors. |
851 | */ | 854 | */ |
852 | iser_disconnected_handler(cma_id); | 855 | iser_disconnected_handler(cma_id); |
853 | iser_free_ib_conn_res(iser_conn, destroy_device); | 856 | iser_free_ib_conn_res(iser_conn, destroy); |
854 | complete(&iser_conn->ib_completion); | 857 | complete(&iser_conn->ib_completion); |
855 | }; | 858 | }; |
856 | 859 | ||