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: 5426b1711f ("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>
This commit is contained in:
Sagi Grimberg 2015-01-18 16:51:06 +02:00 committed by Roland Dreier
parent c6c95ef4ce
commit 6606e6a2ff
2 changed files with 14 additions and 15 deletions

View File

@ -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);
}

View File

@ -600,16 +600,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;
@ -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_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;
}
}
}
@ -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,
bool destroy_device)
bool destroy)
{
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,
* 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);
};