diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2015-01-18 16:51:06 +0200 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2015-03-23 21:02:44 -0400 |
commit | caa2a1adfedfa16ce25f4230d814f425b25b9630 (patch) | |
tree | 41216c37e7ccf131e38589b86d067ff3924514c5 /drivers/infiniband | |
parent | bbc56fba25d6a3ff29224503702614e311cc8e77 (diff) | |
download | linux-rt-caa2a1adfedfa16ce25f4230d814f425b25b9630.tar.gz |
IB/iser: Fix memory regions possible leak
commit 6606e6a2ff2710b473838b291dc533cd8fc1471f upstream.
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>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'drivers/infiniband')
-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 3821633f1065..de382af10cc8 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) struct ib_conn *ib_conn = &iser_conn->ib_conn; struct iser_device *device = ib_conn->device; - if (!iser_conn->rx_descs) - goto free_login_buf; - if (device->iser_free_rdma_reg_res) device->iser_free_rdma_reg_res(ib_conn); @@ -334,7 +331,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn) /* make sure we never redo any unmapping */ iser_conn->rx_descs = NULL; -free_login_buf: iser_free_login_buf(iser_conn); } diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 67225bb82bb5..d004d6ee2c1a 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -567,16 +567,16 @@ void iser_release_work(struct work_struct *work) /** * iser_free_ib_conn_res - release IB related resources * @iser_conn: iser connection struct - * @destroy_device: indicator if we need to try to release - * the iser device (only iscsi shutdown and DEVICE_REMOVAL - * will use this. + * @destroy: indicator if we need to try to release the + * iser device and memory regoins pool (only iscsi + * shutdown and DEVICE_REMOVAL will use this). * * This routine is called with the iser state mutex held * so the cm_id removal is out of here. It is Safe to * be invoked multiple times. */ static void iser_free_ib_conn_res(struct iser_conn *iser_conn, - bool destroy_device) + bool destroy) { struct ib_conn *ib_conn = &iser_conn->ib_conn; struct iser_device *device = ib_conn->device; @@ -584,17 +584,20 @@ static void iser_free_ib_conn_res(struct iser_conn *iser_conn, iser_info("freeing conn %p cma_id %p qp %p\n", iser_conn, ib_conn->cma_id, ib_conn->qp); - iser_free_rx_descriptors(iser_conn); - if (ib_conn->qp != NULL) { ib_conn->comp->active_qps--; rdma_destroy_qp(ib_conn->cma_id); ib_conn->qp = NULL; } - if (destroy_device && device != NULL) { - iser_device_try_release(device); - ib_conn->device = NULL; + if (destroy) { + if (iser_conn->rx_descs) + iser_free_rx_descriptors(iser_conn); + + if (device != NULL) { + iser_device_try_release(device); + ib_conn->device = NULL; + } } } @@ -803,7 +806,7 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id) } static void iser_cleanup_handler(struct rdma_cm_id *cma_id, - bool destroy_device) + bool destroy) { struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context; @@ -813,7 +816,7 @@ static void iser_cleanup_handler(struct rdma_cm_id *cma_id, * and flush errors. */ iser_disconnected_handler(cma_id); - iser_free_ib_conn_res(iser_conn, destroy_device); + iser_free_ib_conn_res(iser_conn, destroy); complete(&iser_conn->ib_completion); }; |