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 e54198657b65625085834847ab6271087323ffea 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).
Unified · Split
| @@ -4074,6 +4074,17 @@ reject: · 4073 unmodified lines | |||
| 4074 | return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); | 4074 | return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
| 4075 | } | 4075 | } |
| 4076 | 4076 | ||
| 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 | |||
| 4077 | int iscsi_target_rx_thread(void *arg) | 4088 | int iscsi_target_rx_thread(void *arg) |
| 4078 | { | 4089 | { |
| 4079 | int ret, rc; | 4090 | int ret, rc; |
| @@ -4091,7 +4102,7 @@ int iscsi_target_rx_thread(void *arg) · 11 unmodified lines | |||
| 4091 | * incoming iscsi/tcp socket I/O, and/or failing the connection. | 4102 | * incoming iscsi/tcp socket I/O, and/or failing the connection. |
| 4092 | */ | 4103 | */ |
| 4093 | rc = wait_for_completion_interruptible(&conn->rx_login_comp); | 4104 | rc = wait_for_completion_interruptible(&conn->rx_login_comp); |
| 4094 | if (rc < 0) | 4105 | if (rc < 0 || iscsi_target_check_conn_state(conn)) |
| 4095 | return 0; | 4106 | return 0; |
| 4096 | 4107 | ||
| 4097 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { | 4108 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { |
| @@ -388,6 +388,7 @@ err: · 387 unmodified lines | |||
| 388 | if (login->login_complete) { | 388 | if (login->login_complete) { |
| 389 | if (conn->rx_thread && conn->rx_thread_active) { | 389 | if (conn->rx_thread && conn->rx_thread_active) { |
| 390 | send_sig(SIGINT, conn->rx_thread, 1); | 390 | send_sig(SIGINT, conn->rx_thread, 1); |
| 391 | complete(&conn->rx_login_comp); | ||
| 391 | kthread_stop(conn->rx_thread); | 392 | kthread_stop(conn->rx_thread); |
| 392 | } | 393 | } |
| 393 | if (conn->tx_thread && conn->tx_thread_active) { | 394 | if (conn->tx_thread && conn->tx_thread_active) { |