From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933044AbbA2Ka4 (ORCPT ); Thu, 29 Jan 2015 05:30:56 -0500 Received: from ip4-83-240-67-251.cust.nbox.cz ([83.240.67.251]:44737 "EHLO ip4-83-240-18-248.cust.nbox.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755867AbbA2JAb (ORCPT ); Thu, 29 Jan 2015 04:00:31 -0500 From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Sagi Grimberg , Nicholas Bellinger , Jiri Slaby Subject: [PATCH 3.12 132/176] iser-target: Fix flush + disconnect completion handling Date: Wed, 28 Jan 2015 15:29:22 +0100 Message-Id: <3ad6cac25c7e7c48d279c5e5af06fdc62e762896.1422455352.git.jslaby@suse.cz> X-Mailer: git-send-email 2.2.2 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sagi Grimberg 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit 128e9cc84566a84146baea2335b3824288eed817 upstream. ISER_CONN_UP state is not sufficient to know if we should wait for completion of flush errors and disconnected_handler event. Instead, split it to 2 states: - ISER_CONN_UP: Got to CM connected phase, This state indicates that we need to wait for a CM disconnect event before going to teardown. - ISER_CONN_FULL_FEATURE: Got to full feature phase after we posted login response, This state indicates that we posted recv buffers and we need to wait for flush completions before going to teardown. Also avoid deffering disconnected handler to a work, and handle it within disconnected handler. More work here is needed to handle DEVICE_REMOVAL event correctly (cleanup all resources). Squashed: iser-target: Don't deffer disconnected handler to a work Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger Signed-off-by: Jiri Slaby --- drivers/infiniband/ulp/isert/ib_isert.c | 50 +++++++++++++++++++-------------- drivers/infiniband/ulp/isert/ib_isert.h | 2 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index c0a5b4a85424..e387b738ad6b 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -654,6 +654,9 @@ isert_connected_handler(struct rdma_cm_id *cma_id) { struct isert_conn *isert_conn = cma_id->context; + pr_info("conn %p\n", isert_conn); + + isert_conn->state = ISER_CONN_UP; kref_get(&isert_conn->conn_kref); } @@ -680,8 +683,9 @@ isert_put_conn(struct isert_conn *isert_conn) * @isert_conn: isert connection struct * * Notes: - * In case the connection state is UP, move state + * In case the connection state is FULL_FEATURE, move state * to TEMINATING and start teardown sequence (rdma_disconnect). + * In case the connection state is UP, complete flush as well. * * This routine must be called with conn_mutex held. Thus it is * safe to call multiple times. @@ -691,32 +695,31 @@ isert_conn_terminate(struct isert_conn *isert_conn) { int err; - if (isert_conn->state == ISER_CONN_UP) { - isert_conn->state = ISER_CONN_TERMINATING; + switch (isert_conn->state) { + case ISER_CONN_TERMINATING: + break; + case ISER_CONN_UP: + /* + * No flush completions will occur as we didn't + * get to ISER_CONN_FULL_FEATURE yet, complete + * to allow teardown progress. + */ + complete(&isert_conn->conn_wait_comp_err); + case ISER_CONN_FULL_FEATURE: /* FALLTHRU */ pr_info("Terminating conn %p state %d\n", isert_conn, isert_conn->state); + isert_conn->state = ISER_CONN_TERMINATING; err = rdma_disconnect(isert_conn->conn_cm_id); if (err) pr_warn("Failed rdma_disconnect isert_conn %p\n", isert_conn); + break; + default: + pr_warn("conn %p teminating in state %d\n", + isert_conn, isert_conn->state); } } -static void -isert_disconnect_work(struct work_struct *work) -{ - struct isert_conn *isert_conn = container_of(work, - struct isert_conn, conn_logout_work); - - pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - mutex_lock(&isert_conn->conn_mutex); - 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); -} - static int isert_disconnected_handler(struct rdma_cm_id *cma_id) { @@ -731,8 +734,12 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id) isert_conn = (struct isert_conn *)cma_id->context; - INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); - schedule_work(&isert_conn->conn_logout_work); + mutex_lock(&isert_conn->conn_mutex); + 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); return 0; } @@ -984,7 +991,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, if (ret) return ret; - isert_conn->state = ISER_CONN_UP; + /* Now we are in FULL_FEATURE phase */ + isert_conn->state = ISER_CONN_FULL_FEATURE; goto post_send; } diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index f0ed44c89b71..7dc90b5ac4ae 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -23,6 +23,7 @@ enum iser_ib_op_code { enum iser_conn_state { ISER_CONN_INIT, ISER_CONN_UP, + ISER_CONN_FULL_FEATURE, ISER_CONN_TERMINATING, ISER_CONN_DOWN, }; @@ -112,7 +113,6 @@ struct isert_conn { struct ib_mr *conn_mr; struct ib_qp *conn_qp; struct isert_device *conn_device; - struct work_struct conn_logout_work; struct mutex conn_mutex; struct completion conn_wait; struct completion conn_wait_comp_err; -- 2.2.2