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:
Bart Van Assche
2021-07-12 03:12:48 +00:00
parent 7517bd6b22
commit 6abef3d29c
2 changed files with 35 additions and 9 deletions
+2
View File
@@ -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;
};
+33 -9
View File
@@ -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);