Commit 6606e6a2 authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Roland Dreier

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: 5426b171 ("IB/iser: Collapse cleanup and disconnect handlers")
Reported-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarSagi Grimberg <sagig@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent c6c95ef4
...@@ -320,9 +320,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn) ...@@ -320,9 +320,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn)
struct ib_conn *ib_conn = &iser_conn->ib_conn; struct ib_conn *ib_conn = &iser_conn->ib_conn;
struct iser_device *device = ib_conn->device; struct iser_device *device = ib_conn->device;
if (!iser_conn->rx_descs)
goto free_login_buf;
if (device->iser_free_rdma_reg_res) if (device->iser_free_rdma_reg_res)
device->iser_free_rdma_reg_res(ib_conn); device->iser_free_rdma_reg_res(ib_conn);
...@@ -334,7 +331,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn) ...@@ -334,7 +331,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn)
/* make sure we never redo any unmapping */ /* make sure we never redo any unmapping */
iser_conn->rx_descs = NULL; iser_conn->rx_descs = NULL;
free_login_buf:
iser_free_login_buf(iser_conn); iser_free_login_buf(iser_conn);
} }
......
...@@ -600,16 +600,16 @@ void iser_release_work(struct work_struct *work) ...@@ -600,16 +600,16 @@ void iser_release_work(struct work_struct *work)
/** /**
* iser_free_ib_conn_res - release IB related resources * iser_free_ib_conn_res - release IB related resources
* @iser_conn: iser connection struct * @iser_conn: iser connection struct
* @destroy_device: indicator if we need to try to release * @destroy: indicator if we need to try to release the
* the iser device (only iscsi shutdown and DEVICE_REMOVAL * iser device and memory regoins pool (only iscsi
* will use this. * shutdown and DEVICE_REMOVAL will use this).
* *
* This routine is called with the iser state mutex held * This routine is called with the iser state mutex held
* so the cm_id removal is out of here. It is Safe to * so the cm_id removal is out of here. It is Safe to
* be invoked multiple times. * be invoked multiple times.
*/ */
static void iser_free_ib_conn_res(struct iser_conn *iser_conn, 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 ib_conn *ib_conn = &iser_conn->ib_conn;
struct iser_device *device = ib_conn->device; struct iser_device *device = ib_conn->device;
...@@ -617,17 +617,20 @@ static void iser_free_ib_conn_res(struct iser_conn *iser_conn, ...@@ -617,17 +617,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_info("freeing conn %p cma_id %p qp %p\n",
iser_conn, ib_conn->cma_id, ib_conn->qp); iser_conn, ib_conn->cma_id, ib_conn->qp);
iser_free_rx_descriptors(iser_conn);
if (ib_conn->qp != NULL) { if (ib_conn->qp != NULL) {
ib_conn->comp->active_qps--; ib_conn->comp->active_qps--;
rdma_destroy_qp(ib_conn->cma_id); rdma_destroy_qp(ib_conn->cma_id);
ib_conn->qp = NULL; ib_conn->qp = NULL;
} }
if (destroy_device && device != NULL) { if (destroy) {
iser_device_try_release(device); if (iser_conn->rx_descs)
ib_conn->device = NULL; iser_free_rx_descriptors(iser_conn);
if (device != NULL) {
iser_device_try_release(device);
ib_conn->device = NULL;
}
} }
} }
...@@ -840,7 +843,7 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id) ...@@ -840,7 +843,7 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
} }
static void iser_cleanup_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; struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context;
...@@ -850,7 +853,7 @@ static void iser_cleanup_handler(struct rdma_cm_id *cma_id, ...@@ -850,7 +853,7 @@ static void iser_cleanup_handler(struct rdma_cm_id *cma_id,
* and flush errors. * and flush errors.
*/ */
iser_disconnected_handler(cma_id); 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); complete(&iser_conn->ib_completion);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment