Target/iser: Fix hangs in connection teardown
authorSagi Grimberg <sagig@mellanox.com>
Mon, 19 May 2014 14:44:23 +0000 (17:44 +0300)
committerNicholas Bellinger <nab@linux-iscsi.org>
Mon, 19 May 2014 21:38:49 +0000 (14:38 -0700)
In ungraceful teardowns isert close flows seem racy such that
isert_wait_conn hangs as RDMA_CM_EVENT_DISCONNECTED never
gets invoked (no one called rdma_disconnect).

Both graceful and ungraceful teardowns will have rx flush errors
(isert posts a batch once connection is established). Once all
flush errors are consumed we invoke isert_wait_conn and it will
be responsible for calling rdma_disconnect. This way it can be
sure that rdma_disconnect was called and it won't wait forever.

This patch also removes the logout_posted indicator. either the
logout completion was consumed and no problem decrementing the
post_send_buf_count, or it was consumed as a flush error. no point
of keeping it for isert_wait_conn as there is no danger that
isert_conn will be accidentally removed while it is running.

(Drop unnecessary sleep_on_conn_wait_comp check in
 isert_cq_rx_comp_err - nab)

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Cc: stable@vger.kernel.org # 3.10+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h

index 7676bcb7105aac073202cc29e3231bea26dbc23d..ef73a38bcb6b169cafed11f75248e697bcbc7c98 100644 (file)
@@ -787,14 +787,10 @@ isert_disconnect_work(struct work_struct *work)
                isert_put_conn(isert_conn);
                return;
        }
-       if (!isert_conn->logout_posted) {
-               pr_debug("Calling rdma_disconnect for !logout_posted from"
-                        " isert_disconnect_work\n");
-               rdma_disconnect(isert_conn->conn_cm_id);
-               mutex_unlock(&isert_conn->conn_mutex);
-               iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
-               goto wake_up;
-       }
+
+       /* Send DREQ/DREP towards our initiator */
+       rdma_disconnect(isert_conn->conn_cm_id);
+
        mutex_unlock(&isert_conn->conn_mutex);
 
 wake_up:
@@ -1822,11 +1818,8 @@ isert_do_control_comp(struct work_struct *work)
                break;
        case ISTATE_SEND_LOGOUTRSP:
                pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n");
-               /*
-                * Call atomic_dec(&isert_conn->post_send_buf_count)
-                * from isert_wait_conn()
-                */
-               isert_conn->logout_posted = true;
+
+               atomic_dec(&isert_conn->post_send_buf_count);
                iscsit_logout_post_handler(cmd, cmd->conn);
                break;
        case ISTATE_SEND_TEXTRSP:
@@ -2032,6 +2025,8 @@ isert_cq_rx_comp_err(struct isert_conn *isert_conn)
        isert_conn->state = ISER_CONN_DOWN;
        mutex_unlock(&isert_conn->conn_mutex);
 
+       iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+
        complete(&isert_conn->conn_wait_comp_err);
 }
 
@@ -3211,15 +3206,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
        struct isert_conn *isert_conn = conn->context;
 
        pr_debug("isert_wait_conn: Starting \n");
-       /*
-        * Decrement post_send_buf_count for special case when called
-        * from isert_do_control_comp() -> iscsit_logout_post_handler()
-        */
-       mutex_lock(&isert_conn->conn_mutex);
-       if (isert_conn->logout_posted)
-               atomic_dec(&isert_conn->post_send_buf_count);
 
-       if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) {
+       mutex_lock(&isert_conn->conn_mutex);
+       if (isert_conn->conn_cm_id) {
                pr_debug("Calling rdma_disconnect from isert_wait_conn\n");
                rdma_disconnect(isert_conn->conn_cm_id);
        }
index da6612e6800004b0984880d54ef57bcaab1b0be1..a2e926452f76750d4b45050a6d0112f078a46880 100644 (file)
@@ -116,7 +116,6 @@ struct isert_device;
 
 struct isert_conn {
        enum iser_conn_state    state;
-       bool                    logout_posted;
        int                     post_recv_buf_count;
        atomic_t                post_send_buf_count;
        u32                     responder_resources;