Skip to content

Commit ca82c2b

Browse files
author
Nicholas Bellinger
committed
iscsi-target: Fix rx_login_comp hang after login failure
This patch addresses a case where iscsi_target_do_tx_login_io() fails sending the last login response PDU, after the RX/TX threads have already been started. The case centers around iscsi_target_rx_thread() not invoking allow_signal(SIGINT) before the send_sig(SIGINT, ...) occurs from the failure path, resulting in RX thread hanging indefinately on iscsi_conn->rx_login_comp. Note this bug is a regression introduced by: commit e541986 Author: Nicholas Bellinger <nab@linux-iscsi.org> Date: Wed Jul 22 23:14:19 2015 -0700 iscsi-target: Fix iscsit_start_kthreads failure OOPs To address this bug, complete ->rx_login_complete for good measure in the failure path, and immediately return from RX thread context if connection state did not actually reach full feature phase (TARG_CONN_STATE_LOGGED_IN). Cc: Sagi Grimberg <sagig@mellanox.com> Cc: <stable@vger.kernel.org> # v3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
1 parent 82a819e commit ca82c2b

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

drivers/target/iscsi/iscsi_target.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4074,6 +4074,17 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
40744074
return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
40754075
}
40764076

4077+
static bool iscsi_target_check_conn_state(struct iscsi_conn *conn)
4078+
{
4079+
bool ret;
4080+
4081+
spin_lock_bh(&conn->state_lock);
4082+
ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
4083+
spin_unlock_bh(&conn->state_lock);
4084+
4085+
return ret;
4086+
}
4087+
40774088
int iscsi_target_rx_thread(void *arg)
40784089
{
40794090
int ret, rc;
@@ -4091,7 +4102,7 @@ int iscsi_target_rx_thread(void *arg)
40914102
* incoming iscsi/tcp socket I/O, and/or failing the connection.
40924103
*/
40934104
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4094-
if (rc < 0)
4105+
if (rc < 0 || iscsi_target_check_conn_state(conn))
40954106
return 0;
40964107

40974108
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {

drivers/target/iscsi/iscsi_target_nego.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
388388
if (login->login_complete) {
389389
if (conn->rx_thread && conn->rx_thread_active) {
390390
send_sig(SIGINT, conn->rx_thread, 1);
391+
complete(&conn->rx_login_comp);
391392
kthread_stop(conn->rx_thread);
392393
}
393394
if (conn->tx_thread && conn->tx_thread_active) {

0 commit comments

Comments
 (0)