Commit 5b61ff43 authored by Roi Dayan's avatar Roi Dayan Committed by Roland Dreier

IB/iser: Fix device removal flow

Change the code to destroy the "last opened" rdma_cm id after making
sure we released all other objects (QP, CQs, PD, etc) associated with
the IB device.

Since iser accesses the IB device using the rdma_cm id, we need to
free any objects that are related to the device that is associated
with the rdma_cm id prior to destroying that id.  When this isn't
done, the low level driver that created this device can be unloaded
before iser has a chance to free all the objects and a such a call may
invoke code segment which isn't valid any more and crash.

Cc: Sean Hefty <sean.hefty@intel.com
Signed-off-by: default avatarRoi Dayan <roid@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent d683b96b
...@@ -292,10 +292,10 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ...@@ -292,10 +292,10 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
} }
/** /**
* releases the FMR pool, QP and CMA ID objects, returns 0 on success, * releases the FMR pool and QP objects, returns 0 on success,
* -1 on failure * -1 on failure
*/ */
static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id) static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
{ {
int cq_index; int cq_index;
BUG_ON(ib_conn == NULL); BUG_ON(ib_conn == NULL);
...@@ -314,13 +314,9 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id) ...@@ -314,13 +314,9 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
rdma_destroy_qp(ib_conn->cma_id); rdma_destroy_qp(ib_conn->cma_id);
} }
/* if cma handler context, the caller acts s.t the cma destroy the id */
if (ib_conn->cma_id != NULL && can_destroy_id)
rdma_destroy_id(ib_conn->cma_id);
ib_conn->fmr_pool = NULL; ib_conn->fmr_pool = NULL;
ib_conn->qp = NULL; ib_conn->qp = NULL;
ib_conn->cma_id = NULL;
kfree(ib_conn->page_vec); kfree(ib_conn->page_vec);
if (ib_conn->login_buf) { if (ib_conn->login_buf) {
...@@ -415,11 +411,16 @@ static void iser_conn_release(struct iser_conn *ib_conn, int can_destroy_id) ...@@ -415,11 +411,16 @@ static void iser_conn_release(struct iser_conn *ib_conn, int can_destroy_id)
list_del(&ib_conn->conn_list); list_del(&ib_conn->conn_list);
mutex_unlock(&ig.connlist_mutex); mutex_unlock(&ig.connlist_mutex);
iser_free_rx_descriptors(ib_conn); iser_free_rx_descriptors(ib_conn);
iser_free_ib_conn_res(ib_conn, can_destroy_id); iser_free_ib_conn_res(ib_conn);
ib_conn->device = NULL; ib_conn->device = NULL;
/* on EVENT_ADDR_ERROR there's no device yet for this conn */ /* on EVENT_ADDR_ERROR there's no device yet for this conn */
if (device != NULL) if (device != NULL)
iser_device_try_release(device); iser_device_try_release(device);
/* if cma handler context, the caller actually destroy the id */
if (ib_conn->cma_id != NULL && can_destroy_id) {
rdma_destroy_id(ib_conn->cma_id);
ib_conn->cma_id = NULL;
}
iscsi_destroy_endpoint(ib_conn->ep); iscsi_destroy_endpoint(ib_conn->ep);
} }
......
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