mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 05:06:31 +00:00
isert-scst: Fix handling of RDMA_CV_EVENT_ADDR_CHANGE
During processing RDMA_CM_EVENT_ADDR_CHANGE event rdma_bind_addr in isert_setup_id function from isert_cm_evt_listener_handler returns error -98 [EADDRINUSE]. In principle, it is logical, because at that time the socket address was still bound to the old cma_id which will be destroyed via rdma_destroy_id only after processing the RDMA_CM_EVENT_ADDR_CHANGE event. Move the creation of the cma_id in workqueue context and delete old cma_id directly, not through returning the error code to the upper level. Signed-off-by: Chesnokov Gleb <Chesnokov.G@raidix.com> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@9484 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -66,6 +66,8 @@ struct isert_portal {
|
||||
/* protected by dev_list_mutex */
|
||||
struct list_head conn_list; /* head of conns list */
|
||||
enum isert_portal_state state;
|
||||
struct work_struct work;
|
||||
struct workqueue_struct *reinit_id_wq;
|
||||
int refcnt;
|
||||
};
|
||||
|
||||
|
||||
@@ -1649,10 +1649,25 @@ static int isert_handle_failure(struct isert_conn *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void isert_portal_reinit_id_work(struct work_struct *w)
|
||||
{
|
||||
struct isert_portal *portal = container_of(w, struct isert_portal, work);
|
||||
|
||||
rdma_destroy_id(portal->cm_id);
|
||||
|
||||
portal->cm_id = isert_setup_id(portal);
|
||||
if (IS_ERR(portal->cm_id)) {
|
||||
PRINT_ERROR("Failed to create rdma id, err:%ld\n",
|
||||
PTR_ERR(portal->cm_id));
|
||||
portal->cm_id = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int isert_cm_evt_listener_handler(struct rdma_cm_id *cm_id,
|
||||
enum rdma_cm_event_type event)
|
||||
{
|
||||
struct isert_portal *portal;
|
||||
int ret = -1;
|
||||
|
||||
portal = cm_id->context;
|
||||
|
||||
@@ -1661,12 +1676,8 @@ static int isert_cm_evt_listener_handler(struct rdma_cm_id *cm_id,
|
||||
portal->cm_id = NULL;
|
||||
break;
|
||||
case RDMA_CM_EVENT_ADDR_CHANGE:
|
||||
portal->cm_id = isert_setup_id(portal);
|
||||
if (IS_ERR(portal->cm_id)) {
|
||||
PRINT_ERROR("Failed to create rdma id, err:%ld\n",
|
||||
PTR_ERR(portal->cm_id));
|
||||
portal->cm_id = NULL;
|
||||
}
|
||||
queue_work(portal->reinit_id_wq, &portal->work);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
PRINT_INFO("Listener event:%s(%d), ignored",
|
||||
@@ -1674,7 +1685,7 @@ static int isert_cm_evt_listener_handler(struct rdma_cm_id *cm_id,
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isert_cm_disconnect_handler(struct rdma_cm_id *cm_id,
|
||||
@@ -1872,6 +1883,15 @@ struct isert_portal *isert_portal_create(struct sockaddr *sa, size_t addr_len)
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
portal->reinit_id_wq = alloc_ordered_workqueue("isert_reinit_id_wq", WQ_MEM_RECLAIM);
|
||||
if (unlikely(!portal->reinit_id_wq)) {
|
||||
PRINT_ERROR("Unable to allocate reinit workqueue");
|
||||
err = -ENOMEM;
|
||||
goto free_portal;
|
||||
}
|
||||
|
||||
INIT_WORK(&portal->work, isert_portal_reinit_id_work);
|
||||
|
||||
INIT_LIST_HEAD(&portal->conn_list);
|
||||
isert_portal_list_add(portal);
|
||||
|
||||
@@ -1881,7 +1901,7 @@ struct isert_portal *isert_portal_create(struct sockaddr *sa, size_t addr_len)
|
||||
if (IS_ERR(cm_id)) {
|
||||
err = PTR_ERR(cm_id);
|
||||
PRINT_ERROR("Failed to create rdma id, err:%d", err);
|
||||
goto create_id_err;
|
||||
goto free_wq;
|
||||
}
|
||||
|
||||
portal->cm_id = cm_id;
|
||||
@@ -1890,7 +1910,9 @@ struct isert_portal *isert_portal_create(struct sockaddr *sa, size_t addr_len)
|
||||
out:
|
||||
return portal;
|
||||
|
||||
create_id_err:
|
||||
free_wq:
|
||||
destroy_workqueue(portal->reinit_id_wq);
|
||||
free_portal:
|
||||
kfree(portal);
|
||||
portal = ERR_PTR(err);
|
||||
err_alloc:
|
||||
@@ -1905,6 +1927,8 @@ static void isert_portal_free(struct isert_portal *portal)
|
||||
if (portal->refcnt > 0)
|
||||
return;
|
||||
|
||||
destroy_workqueue(portal->reinit_id_wq);
|
||||
|
||||
kfree(portal);
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user