Commit 45f29355 authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Greg Kroah-Hartman

iser-target: release stale iser connections

commit 2f1b6b7d upstream.

When receiving a new iser connect request we serialize
the pending requests by adding the newly created iser connection
to the np accept list and let the login thread process the connect
request one by one (np_accept_wait).

In case we received a disconnect request before the iser_conn
has begun processing (still linked in np_accept_list) we should
detach it from the list and clean it up and not have the login
thread process a stale connection. We do it only when the connection
state is not already terminating (initiator driven disconnect) as
this might lead us to access np_accept_mutex after the np was released
in live shutdown scenarios.
Signed-off-by: default avatarSagi Grimberg <sagig@mellanox.com>
Signed-off-by: default avatarJenny Falkovich <jennyf@mellanox.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 394adc1d
...@@ -49,6 +49,8 @@ static int ...@@ -49,6 +49,8 @@ static int
isert_rdma_accept(struct isert_conn *isert_conn); isert_rdma_accept(struct isert_conn *isert_conn);
struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
static void isert_release_work(struct work_struct *work);
static void static void
isert_qp_event_callback(struct ib_event *e, void *context) isert_qp_event_callback(struct ib_event *e, void *context)
{ {
...@@ -432,6 +434,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -432,6 +434,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
init_completion(&isert_conn->conn_wait_comp_err); init_completion(&isert_conn->conn_wait_comp_err);
kref_init(&isert_conn->conn_kref); kref_init(&isert_conn->conn_kref);
mutex_init(&isert_conn->conn_mutex); mutex_init(&isert_conn->conn_mutex);
INIT_WORK(&isert_conn->release_work, isert_release_work);
isert_conn->conn_cm_id = cma_id; isert_conn->conn_cm_id = cma_id;
isert_conn->responder_resources = event->param.conn.responder_resources; isert_conn->responder_resources = event->param.conn.responder_resources;
...@@ -674,6 +677,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, ...@@ -674,6 +677,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
{ {
struct isert_np *isert_np = cma_id->context; struct isert_np *isert_np = cma_id->context;
struct isert_conn *isert_conn; struct isert_conn *isert_conn;
bool terminating = false;
if (isert_np->np_cm_id == cma_id) if (isert_np->np_cm_id == cma_id)
return isert_np_cma_handler(cma_id->context, event); return isert_np_cma_handler(cma_id->context, event);
...@@ -681,12 +685,25 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, ...@@ -681,12 +685,25 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
isert_conn = cma_id->qp->qp_context; isert_conn = cma_id->qp->qp_context;
mutex_lock(&isert_conn->conn_mutex); mutex_lock(&isert_conn->conn_mutex);
terminating = (isert_conn->state == ISER_CONN_TERMINATING);
isert_conn_terminate(isert_conn); isert_conn_terminate(isert_conn);
mutex_unlock(&isert_conn->conn_mutex); mutex_unlock(&isert_conn->conn_mutex);
pr_info("conn %p completing conn_wait\n", isert_conn); pr_info("conn %p completing conn_wait\n", isert_conn);
complete(&isert_conn->conn_wait); complete(&isert_conn->conn_wait);
if (terminating)
goto out;
mutex_lock(&isert_np->np_accept_mutex);
if (!list_empty(&isert_conn->conn_accept_node)) {
list_del_init(&isert_conn->conn_accept_node);
isert_put_conn(isert_conn);
queue_work(isert_release_wq, &isert_conn->release_work);
}
mutex_unlock(&isert_np->np_accept_mutex);
out:
return 0; return 0;
} }
...@@ -2422,7 +2439,6 @@ static void isert_wait_conn(struct iscsi_conn *conn) ...@@ -2422,7 +2439,6 @@ static void isert_wait_conn(struct iscsi_conn *conn)
wait_for_completion(&isert_conn->conn_wait_comp_err); wait_for_completion(&isert_conn->conn_wait_comp_err);
INIT_WORK(&isert_conn->release_work, isert_release_work);
queue_work(isert_release_wq, &isert_conn->release_work); queue_work(isert_release_wq, &isert_conn->release_work);
} }
......
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