diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 884db3ddf5771..e6515791e6e3c 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1140,6 +1140,7 @@ static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np) timer_setup(&conn->nopin_response_timer, iscsit_handle_nopin_response_timeout, 0); timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0); + timer_setup(&conn->login_timer, iscsit_login_timeout, 0); if (iscsit_conn_set_transport(conn, np->np_transport) < 0) goto free_conn; diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index c3069aaaf33da..acfc0fc29fd59 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -479,12 +479,18 @@ static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *); static bool __iscsi_target_sk_check_close(struct sock *sk) { - if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { - pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE," - "returning FALSE\n"); + switch (sk->sk_state) { + case TCP_FIN_WAIT1: + case TCP_FIN_WAIT2: + case TCP_CLOSE_WAIT: + case TCP_LAST_ACK: + case TCP_CLOSE: + pr_debug("__iscsi_target_sk_check_close: socket closing," + "returning TRUE\n"); return true; + default: + return false; } - return false; } static bool iscsi_target_sk_check_close(struct iscsi_conn *conn) @@ -542,25 +548,6 @@ static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login iscsi_target_login_sess_out(conn, zero_tsih, true); } -struct conn_timeout { - struct timer_list timer; - struct iscsi_conn *conn; -}; - -static void iscsi_target_login_timeout(struct timer_list *t) -{ - struct conn_timeout *timeout = from_timer(timeout, t, timer); - struct iscsi_conn *conn = timeout->conn; - - pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); - - if (conn->login_kworker) { - pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n", - conn->login_kworker->comm, conn->login_kworker->pid); - send_sig(SIGINT, conn->login_kworker, 1); - } -} - static void iscsi_target_do_login_rx(struct work_struct *work) { struct iscsi_conn *conn = container_of(work, @@ -569,7 +556,6 @@ static void iscsi_target_do_login_rx(struct work_struct *work) struct iscsi_np *np = login->np; struct iscsi_portal_group *tpg = conn->tpg; struct iscsi_tpg_np *tpg_np = conn->tpg_np; - struct conn_timeout timeout; int rc, zero_tsih = login->zero_tsih; bool state; @@ -607,14 +593,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work) conn->login_kworker = current; allow_signal(SIGINT); - timeout.conn = conn; - timer_setup_on_stack(&timeout.timer, iscsi_target_login_timeout, 0); - mod_timer(&timeout.timer, jiffies + TA_LOGIN_TIMEOUT * HZ); - pr_debug("Starting login timer for %s/%d\n", current->comm, current->pid); - rc = conn->conn_transport->iscsit_get_login_rx(conn, login); - del_timer_sync(&timeout.timer); - destroy_timer_on_stack(&timeout.timer); flush_signals(current); conn->login_kworker = NULL; @@ -631,6 +610,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work) if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE)) goto err; } else if (rc == 1) { + iscsit_stop_login_timer(conn); iscsi_target_nego_release(conn); iscsi_post_login_handler(np, conn, zero_tsih); iscsit_deaccess_np(np, tpg, tpg_np); @@ -639,6 +619,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work) err: iscsi_target_restore_sock_callbacks(conn); + iscsit_stop_login_timer(conn); iscsi_target_login_drop(conn, login); iscsit_deaccess_np(np, tpg, tpg_np); } @@ -1283,6 +1264,9 @@ int iscsi_target_start_negotiation( set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); write_unlock_bh(&sk->sk_callback_lock); } + + iscsit_start_login_timer(conn); + /* * If iscsi_target_do_login returns zero to signal more PDU * exchanges are required to complete the login, go ahead and @@ -1301,8 +1285,10 @@ int iscsi_target_start_negotiation( iscsi_target_restore_sock_callbacks(conn); iscsi_remove_failed_auth_entry(conn); } - if (ret != 0) + if (ret != 0) { + iscsit_stop_login_timer(conn); iscsi_target_nego_release(conn); + } return ret; } diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 89183b3b178ff..bb623a068fd22 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -1056,6 +1056,34 @@ void iscsit_stop_nopin_timer(struct iscsi_conn *conn) spin_unlock_bh(&conn->nopin_timer_lock); } +void iscsit_login_timeout(struct timer_list *t) +{ + struct iscsi_conn *conn = from_timer(conn, t, login_timer); + + pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); + + if (conn->login_kworker) { + pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n", + conn->login_kworker->comm, conn->login_kworker->pid); + send_sig(SIGINT, conn->login_kworker, 1); + } else { + pr_debug("Shutting down the socket.\n"); + kernel_sock_shutdown(conn->sock, SHUT_RDWR); + } +} + +void iscsit_start_login_timer(struct iscsi_conn *conn) +{ + pr_debug("Login timer started\n"); + mod_timer(&conn->login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ); +} + +void iscsit_stop_login_timer(struct iscsi_conn *conn) +{ + pr_debug("Login timer stopped\n"); + del_timer_sync(&conn->login_timer); +} + int iscsit_send_tx_data( struct iscsi_cmd *cmd, struct iscsi_conn *conn, diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 68e84803b0a1a..0b7a2a66ef7ae 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -56,6 +56,9 @@ extern void iscsit_handle_nopin_timeout(struct timer_list *t); extern void __iscsit_start_nopin_timer(struct iscsi_conn *); extern void iscsit_start_nopin_timer(struct iscsi_conn *); extern void iscsit_stop_nopin_timer(struct iscsi_conn *); +extern void iscsit_login_timeout(struct timer_list *t); +extern void iscsit_start_login_timer(struct iscsi_conn *); +extern void iscsit_stop_login_timer(struct iscsi_conn *); extern int iscsit_send_tx_data(struct iscsi_cmd *, struct iscsi_conn *, int); extern int iscsit_fe_sendpage_sg(struct iscsi_cmd *, struct iscsi_conn *); extern int iscsit_tx_login_rsp(struct iscsi_conn *, u8, u8); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index b3441f2e7c7a5..7dba3fb1eef45 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -577,6 +577,7 @@ struct iscsi_conn { struct timer_list nopin_timer; struct timer_list nopin_response_timer; struct timer_list transport_timer; + struct timer_list login_timer; struct task_struct *login_kworker; /* Spinlock used for add/deleting cmd's from conn_cmd_list */ spinlock_t cmd_lock;