| From 2f1b6b7d9a815f341b18dfd26a363f37d4d3c96a Mon Sep 17 00:00:00 2001 |
| From: Sagi Grimberg <sagig@mellanox.com> |
| Date: Thu, 4 Jun 2015 19:49:20 +0300 |
| Subject: iser-target: release stale iser connections |
| |
| From: Sagi Grimberg <sagig@mellanox.com> |
| |
| commit 2f1b6b7d9a815f341b18dfd26a363f37d4d3c96a 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: Sagi Grimberg <sagig@mellanox.com> |
| Signed-off-by: Jenny Falkovich <jennyf@mellanox.com> |
| Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| |
| --- |
| drivers/infiniband/ulp/isert/ib_isert.c | 18 +++++++++++++++++- |
| 1 file changed, 17 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/infiniband/ulp/isert/ib_isert.c |
| +++ b/drivers/infiniband/ulp/isert/ib_isert.c |
| @@ -49,6 +49,8 @@ static int |
| isert_rdma_accept(struct isert_conn *isert_conn); |
| struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); |
| |
| +static void isert_release_work(struct work_struct *work); |
| + |
| static void |
| isert_qp_event_callback(struct ib_event *e, void *context) |
| { |
| @@ -432,6 +434,7 @@ isert_connect_request(struct rdma_cm_id |
| init_completion(&isert_conn->conn_wait_comp_err); |
| kref_init(&isert_conn->conn_kref); |
| mutex_init(&isert_conn->conn_mutex); |
| + INIT_WORK(&isert_conn->release_work, isert_release_work); |
| |
| isert_conn->conn_cm_id = cma_id; |
| isert_conn->responder_resources = event->param.conn.responder_resources; |
| @@ -674,6 +677,7 @@ isert_disconnected_handler(struct rdma_c |
| { |
| struct isert_np *isert_np = cma_id->context; |
| struct isert_conn *isert_conn; |
| + bool terminating = false; |
| |
| if (isert_np->np_cm_id == cma_id) |
| return isert_np_cma_handler(cma_id->context, event); |
| @@ -681,12 +685,25 @@ isert_disconnected_handler(struct rdma_c |
| isert_conn = cma_id->qp->qp_context; |
| |
| mutex_lock(&isert_conn->conn_mutex); |
| + terminating = (isert_conn->state == ISER_CONN_TERMINATING); |
| isert_conn_terminate(isert_conn); |
| mutex_unlock(&isert_conn->conn_mutex); |
| |
| pr_info("conn %p completing conn_wait\n", isert_conn); |
| 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; |
| } |
| |
| @@ -2422,7 +2439,6 @@ static void isert_wait_conn(struct iscsi |
| |
| 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); |
| } |
| |