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: Roi Dayan <roid@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
@@ -292,10 +292,10 @@ out_err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user