To handle initiators dropping tcp connections while the login process is waiting on connections getting cleaned up, we need to make that login path interruptible. This patch modifies iscsit_cause_connection_reinstatement. Signed-off-by: Mike Christie <mchristi@xxxxxxxxxx> --- drivers/infiniband/ulp/isert/ib_isert.c | 12 ++++++------ drivers/target/iscsi/iscsi_target.c | 19 +++++++++++++------ drivers/target/iscsi/iscsi_target_erl0.c | 23 +++++++++++++++++------ drivers/target/iscsi/iscsi_target_erl0.h | 2 +- drivers/target/iscsi/iscsi_target_erl1.c | 2 +- drivers/target/iscsi/iscsi_target_util.c | 2 +- include/target/iscsi/iscsi_transport.h | 2 +- 7 files changed, 40 insertions(+), 22 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 314e955..c80a18c 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -725,7 +725,7 @@ break; case ISER_CONN_BOUND: case ISER_CONN_FULL_FEATURE: /* FALLTHRU */ - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0, 0); break; default: isert_warn("conn %p teminating in state %d\n", @@ -1393,7 +1393,7 @@ if (unlikely(wc->status != IB_WC_SUCCESS)) { isert_print_wc(wc, "recv"); if (wc->status != IB_WC_WR_FLUSH_ERR) - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0, 0); return; } @@ -1649,7 +1649,7 @@ if (unlikely(wc->status != IB_WC_SUCCESS)) { isert_print_wc(wc, "rdma write"); if (wc->status != IB_WC_WR_FLUSH_ERR) - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0, 0); isert_completion_put(desc, isert_cmd, device->ib_device, true); return; } @@ -1679,7 +1679,7 @@ if (unlikely(wc->status != IB_WC_SUCCESS)) { isert_print_wc(wc, "rdma read"); if (wc->status != IB_WC_WR_FLUSH_ERR) - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0, 0); isert_completion_put(desc, isert_cmd, device->ib_device, true); return; } @@ -1748,7 +1748,7 @@ if (unlikely(wc->status != IB_WC_SUCCESS)) { isert_print_wc(wc, "login send"); if (wc->status != IB_WC_WR_FLUSH_ERR) - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0, 0); } isert_unmap_tx_desc(tx_desc, ib_dev); @@ -1765,7 +1765,7 @@ if (unlikely(wc->status != IB_WC_SUCCESS)) { isert_print_wc(wc, "send"); if (wc->status != IB_WC_WR_FLUSH_ERR) - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0, 0); isert_completion_put(tx_desc, isert_cmd, ib_dev, true); return; } diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 4328036..a2e6a4f 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -4448,7 +4448,7 @@ static void iscsit_logout_post_handler_samecid( atomic_set(&conn->conn_logout_remove, 0); complete(&conn->conn_logout_comp); - iscsit_cause_connection_reinstatement(conn, sleep); + iscsit_cause_connection_reinstatement(conn, sleep, 0); iscsit_dec_conn_usage_count(conn); } @@ -4484,7 +4484,7 @@ static void iscsit_logout_post_handler_diffcid( l_conn->conn_state = TARG_CONN_STATE_IN_LOGOUT; spin_unlock_bh(&l_conn->state_lock); - iscsit_cause_connection_reinstatement(l_conn, 1); + iscsit_cause_connection_reinstatement(l_conn, 1, 0); iscsit_dec_conn_usage_count(l_conn); } @@ -4589,7 +4589,7 @@ int iscsit_free_session(struct iscsi_session *sess) iscsit_inc_conn_usage_count(conn); spin_unlock_bh(&sess->conn_lock); - iscsit_cause_connection_reinstatement(conn, 1); + iscsit_cause_connection_reinstatement(conn, 1, 0); spin_lock_bh(&sess->conn_lock); iscsit_dec_conn_usage_count(conn); @@ -4617,7 +4617,7 @@ int iscsit_stop_session( { u16 conn_count = atomic_read(&sess->nconn); struct iscsi_conn *conn, *conn_tmp = NULL; - int is_last; + int is_last, ret; spin_lock_bh(&sess->conn_lock); if (session_sleep) @@ -4638,17 +4638,24 @@ int iscsit_stop_session( iscsit_inc_conn_usage_count(conn); spin_unlock_bh(&sess->conn_lock); - iscsit_cause_connection_reinstatement(conn, 1); + ret = iscsit_cause_connection_reinstatement(conn, 1, + interruptible); spin_lock_bh(&sess->conn_lock); iscsit_dec_conn_usage_count(conn); if (is_last == 0) iscsit_dec_conn_usage_count(conn_tmp); + + if (ret) { + spin_unlock_bh(&sess->conn_lock); + return -1; + } + conn_count--; } } else { list_for_each_entry(conn, &sess->sess_conn_list, conn_list) - iscsit_cause_connection_reinstatement(conn, 0); + iscsit_cause_connection_reinstatement(conn, 0, 0); } if (session_sleep && atomic_read(&sess->nconn)) { diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index a8bcbc4..42f3610 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -867,22 +867,25 @@ void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn) complete(&conn->conn_post_wait_comp); } -void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep) +int iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep, + int interruptible) { + int ret = 0; + spin_lock_bh(&conn->state_lock); if (atomic_read(&conn->connection_exit)) { spin_unlock_bh(&conn->state_lock); - return; + return 0; } if (atomic_read(&conn->transport_failed)) { spin_unlock_bh(&conn->state_lock); - return; + return 0; } if (atomic_read(&conn->connection_reinstatement)) { spin_unlock_bh(&conn->state_lock); - return; + return 0; } if (conn->tx_thread && conn->tx_thread_active) @@ -893,14 +896,22 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep) atomic_set(&conn->connection_reinstatement, 1); if (!sleep) { spin_unlock_bh(&conn->state_lock); - return; + return 0; } atomic_set(&conn->sleep_on_conn_wait_comp, 1); spin_unlock_bh(&conn->state_lock); - wait_for_completion(&conn->conn_wait_comp); + if (interruptible) + ret = wait_for_completion_interruptible(&conn->conn_wait_comp); + else + wait_for_completion(&conn->conn_wait_comp); + complete(&conn->conn_post_wait_comp); + if (ret == -ERESTARTSYS) + return -1; + + return 0; } EXPORT_SYMBOL(iscsit_cause_connection_reinstatement); diff --git a/drivers/target/iscsi/iscsi_target_erl0.h b/drivers/target/iscsi/iscsi_target_erl0.h index 60e69e2..1c71fb0 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.h +++ b/drivers/target/iscsi/iscsi_target_erl0.h @@ -13,7 +13,7 @@ extern void iscsit_start_time2retain_handler(struct iscsi_session *); extern int iscsit_stop_time2retain_timer(struct iscsi_session *); extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *); -extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); +extern int iscsit_cause_connection_reinstatement(struct iscsi_conn *, int, int); extern void iscsit_fall_back_to_erl0(struct iscsi_session *); extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *); diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index fe9b7f1..5cbccce 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -1225,7 +1225,7 @@ static void iscsit_handle_dataout_timeout(unsigned long data) failure: spin_unlock_bh(&cmd->dataout_timeout_lock); - iscsit_cause_connection_reinstatement(conn, 0); + iscsit_cause_connection_reinstatement(conn, 0, 0); iscsit_dec_conn_usage_count(conn); } diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index f46eadf..ec11318 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -946,7 +946,7 @@ static void iscsit_handle_nopin_response_timeout(unsigned long data) } } - iscsit_cause_connection_reinstatement(conn, 0); + iscsit_cause_connection_reinstatement(conn, 0, 0); iscsit_dec_conn_usage_count(conn); } diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index ff1a4f4..b9a76ed 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -108,7 +108,7 @@ extern int iscsit_build_r2ts_for_cmd(struct iscsi_conn *, struct iscsi_cmd *, /* * From iscsi_target_erl0.c */ -extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); +extern int iscsit_cause_connection_reinstatement(struct iscsi_conn *, int, int); /* * From iscsi_target_erl1.c */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html