]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iser-target: release stale iser connections
authorSagi Grimberg <sagig@mellanox.com>
Thu, 4 Jun 2015 16:49:20 +0000 (19:49 +0300)
committerLuis Henriques <luis.henriques@canonical.com>
Tue, 30 Jun 2015 16:15:26 +0000 (17:15 +0100)
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>
[ luis: backported to 3.16:
  - use 'conn_accept_node' instead of 'accept_node' (field renamed by
    dac6ab305d73 "iser-target: Remove conn_ prefix from struct isert_conn members")
  - adjusted context ]
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
drivers/infiniband/ulp/isert/ib_isert.c

index 8a02eb55bc670bd7c2b2c38026e6b30680814f7b..cdd3c6a06bb95a2320f0e1efef8c388c9b169da3 100644 (file)
@@ -61,6 +61,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 inline bool
 isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
 {
@@ -624,6 +626,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        mutex_init(&isert_conn->conn_mutex);
        spin_lock_init(&isert_conn->conn_lock);
        INIT_LIST_HEAD(&isert_conn->conn_fr_pool);
+       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;
@@ -890,6 +893,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
 {
        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);
@@ -897,12 +901,25 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
        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;
 }
 
@@ -3435,7 +3452,6 @@ static void isert_wait_conn(struct iscsi_conn *conn)
 
        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);
 }