mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 18:51:27 +00:00
isert-scst: Properly release resources on DEVICE_REMOVAL
When the low level driver exercises the hot unplug they would call
rdma_cm cma_remove_one which would fire DEVICE_REMOVAL event to all cma
consumers. Now, if consumer doesn't make sure they destroy all IB
objects created on that IB device instance prior to finalizing all
processing of DEVICE_REMOVAL callback, rdma_cm will let the lld to
de-register with IB core and destroy the IB device instance. And if the
consumer calls (say) ib_dereg_mr(), it will crash since that dev object
is NULL.
In the current implementation, iser-target just initiates the cleanup
and returns from DEVICE_REMOVAL callback. This deferred work creates a
race between iser-target cleaning IB objects(say MR) and lld destroying
IB device instance.
This patch includes the following fixes
-> make sure that consumer frees all IB objects associated with device
instance
-> return non-zero from the callback to destroy the rdma_cm id
Signed-off-by: Raju Rangoju <rajur@chelsio.com>
Acked-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Doug Ledford <dledford@redhat.com>
See also upstream commit 63b268d232b8 ("IB/isert: Properly release
resources on DEVICE_REMOVAL")
Signed-off-by: Chesnokov Gleb <Chesnokov.G@raidix.com>
[ bvanassche: edited patch description and moved a break statement into a code
block ]
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@9480 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -231,6 +231,9 @@ struct isert_conn {
|
||||
|
||||
struct isert_portal *portal;
|
||||
void *priv_data; /* for connection tracking */
|
||||
|
||||
wait_queue_head_t rem_wait;
|
||||
atomic_t dev_removed;
|
||||
};
|
||||
|
||||
struct isert_device {
|
||||
|
||||
@@ -1274,6 +1274,7 @@ isert_init_conn(struct isert_conn *isert_conn)
|
||||
INIT_LIST_HEAD(&isert_conn->tx_busy_list);
|
||||
spin_lock_init(&isert_conn->tx_lock);
|
||||
spin_lock_init(&isert_conn->post_recv_lock);
|
||||
init_waitqueue_head(&isert_conn->rem_wait);
|
||||
kref_init(&isert_conn->kref);
|
||||
mutex_init(&isert_conn->state_mutex);
|
||||
}
|
||||
@@ -1389,8 +1390,11 @@ static void isert_release_kref(struct kref *kref)
|
||||
|
||||
isert_free_conn_resources(isert_conn);
|
||||
|
||||
rdma_destroy_id(isert_conn->cm_id);
|
||||
isert_conn->cm_id = NULL;
|
||||
if (isert_conn->cm_id &&
|
||||
!atomic_read(&isert_conn->dev_removed)) {
|
||||
rdma_destroy_id(isert_conn->cm_id);
|
||||
isert_conn->cm_id = NULL;
|
||||
}
|
||||
|
||||
dev = isert_get_priv(&isert_conn->iscsi);
|
||||
if (dev) {
|
||||
@@ -1413,9 +1417,14 @@ static void isert_release_kref(struct kref *kref)
|
||||
isert_portal_free(isert_conn->portal);
|
||||
mutex_unlock(&dev_list_mutex);
|
||||
|
||||
isert_conn_kfree(isert_conn);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
if (atomic_read(&isert_conn->dev_removed)) {
|
||||
atomic_set(&isert_conn->dev_removed, 0);
|
||||
wake_up_interruptible(&isert_conn->rem_wait);
|
||||
} else {
|
||||
isert_conn_kfree(isert_conn);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
}
|
||||
@@ -1706,12 +1715,31 @@ static int isert_cm_evt_handler(struct rdma_cm_id *cm_id,
|
||||
|
||||
case RDMA_CM_EVENT_ADDR_CHANGE:
|
||||
case RDMA_CM_EVENT_DISCONNECTED:
|
||||
case RDMA_CM_EVENT_DEVICE_REMOVAL:
|
||||
case RDMA_CM_EVENT_TIMEWAIT_EXIT:
|
||||
isert_cm_disconnect_handler(cm_id, ev_type);
|
||||
err = isert_cm_disconnected_handler(cm_id, cm_ev);
|
||||
break;
|
||||
case RDMA_CM_EVENT_DEVICE_REMOVAL: {
|
||||
struct isert_conn *isert_conn = cm_id->qp->qp_context;
|
||||
|
||||
atomic_set(&isert_conn->dev_removed, 1);
|
||||
|
||||
isert_cm_disconnect_handler(cm_id, ev_type);
|
||||
isert_cm_disconnected_handler(cm_id, cm_ev);
|
||||
|
||||
wait_event_interruptible(isert_conn->rem_wait,
|
||||
!atomic_read(&isert_conn->dev_removed));
|
||||
|
||||
isert_conn_kfree(isert_conn);
|
||||
module_put(THIS_MODULE);
|
||||
/*
|
||||
* return non-zero from the callback to destroy
|
||||
* the rdma cm id
|
||||
*/
|
||||
err = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
case RDMA_CM_EVENT_MULTICAST_JOIN:
|
||||
case RDMA_CM_EVENT_MULTICAST_ERROR:
|
||||
PRINT_ERROR("UD-related event:%d, ignored", ev_type);
|
||||
|
||||
Reference in New Issue
Block a user