diff options
Diffstat (limited to 'drivers/target/iscsi/iscsi_target.c')
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 4e68b62193ed..cd77a064c772 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -3998,7 +3998,13 @@ get_immediate: | |||
3998 | } | 3998 | } |
3999 | 3999 | ||
4000 | transport_err: | 4000 | transport_err: |
4001 | iscsit_take_action_for_connection_exit(conn); | 4001 | /* |
4002 | * Avoid the normal connection failure code-path if this connection | ||
4003 | * is still within LOGIN mode, and iscsi_np process context is | ||
4004 | * responsible for cleaning up the early connection failure. | ||
4005 | */ | ||
4006 | if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) | ||
4007 | iscsit_take_action_for_connection_exit(conn); | ||
4002 | out: | 4008 | out: |
4003 | return 0; | 4009 | return 0; |
4004 | } | 4010 | } |
@@ -4082,7 +4088,7 @@ reject: | |||
4082 | 4088 | ||
4083 | int iscsi_target_rx_thread(void *arg) | 4089 | int iscsi_target_rx_thread(void *arg) |
4084 | { | 4090 | { |
4085 | int ret; | 4091 | int ret, rc; |
4086 | u8 buffer[ISCSI_HDR_LEN], opcode; | 4092 | u8 buffer[ISCSI_HDR_LEN], opcode; |
4087 | u32 checksum = 0, digest = 0; | 4093 | u32 checksum = 0, digest = 0; |
4088 | struct iscsi_conn *conn = arg; | 4094 | struct iscsi_conn *conn = arg; |
@@ -4092,10 +4098,16 @@ int iscsi_target_rx_thread(void *arg) | |||
4092 | * connection recovery / failure event can be triggered externally. | 4098 | * connection recovery / failure event can be triggered externally. |
4093 | */ | 4099 | */ |
4094 | allow_signal(SIGINT); | 4100 | allow_signal(SIGINT); |
4101 | /* | ||
4102 | * Wait for iscsi_post_login_handler() to complete before allowing | ||
4103 | * incoming iscsi/tcp socket I/O, and/or failing the connection. | ||
4104 | */ | ||
4105 | rc = wait_for_completion_interruptible(&conn->rx_login_comp); | ||
4106 | if (rc < 0) | ||
4107 | return 0; | ||
4095 | 4108 | ||
4096 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { | 4109 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { |
4097 | struct completion comp; | 4110 | struct completion comp; |
4098 | int rc; | ||
4099 | 4111 | ||
4100 | init_completion(&comp); | 4112 | init_completion(&comp); |
4101 | rc = wait_for_completion_interruptible(&comp); | 4113 | rc = wait_for_completion_interruptible(&comp); |
@@ -4532,7 +4544,18 @@ static void iscsit_logout_post_handler_closesession( | |||
4532 | struct iscsi_conn *conn) | 4544 | struct iscsi_conn *conn) |
4533 | { | 4545 | { |
4534 | struct iscsi_session *sess = conn->sess; | 4546 | struct iscsi_session *sess = conn->sess; |
4535 | int sleep = cmpxchg(&conn->tx_thread_active, true, false); | 4547 | int sleep = 1; |
4548 | /* | ||
4549 | * Traditional iscsi/tcp will invoke this logic from TX thread | ||
4550 | * context during session logout, so clear tx_thread_active and | ||
4551 | * sleep if iscsit_close_connection() has not already occured. | ||
4552 | * | ||
4553 | * Since iser-target invokes this logic from it's own workqueue, | ||
4554 | * always sleep waiting for RX/TX thread shutdown to complete | ||
4555 | * within iscsit_close_connection(). | ||
4556 | */ | ||
4557 | if (conn->conn_transport->transport_type == ISCSI_TCP) | ||
4558 | sleep = cmpxchg(&conn->tx_thread_active, true, false); | ||
4536 | 4559 | ||
4537 | atomic_set(&conn->conn_logout_remove, 0); | 4560 | atomic_set(&conn->conn_logout_remove, 0); |
4538 | complete(&conn->conn_logout_comp); | 4561 | complete(&conn->conn_logout_comp); |
@@ -4546,7 +4569,10 @@ static void iscsit_logout_post_handler_closesession( | |||
4546 | static void iscsit_logout_post_handler_samecid( | 4569 | static void iscsit_logout_post_handler_samecid( |
4547 | struct iscsi_conn *conn) | 4570 | struct iscsi_conn *conn) |
4548 | { | 4571 | { |
4549 | int sleep = cmpxchg(&conn->tx_thread_active, true, false); | 4572 | int sleep = 1; |
4573 | |||
4574 | if (conn->conn_transport->transport_type == ISCSI_TCP) | ||
4575 | sleep = cmpxchg(&conn->tx_thread_active, true, false); | ||
4550 | 4576 | ||
4551 | atomic_set(&conn->conn_logout_remove, 0); | 4577 | atomic_set(&conn->conn_logout_remove, 0); |
4552 | complete(&conn->conn_logout_comp); | 4578 | complete(&conn->conn_logout_comp); |
@@ -4765,6 +4791,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) | |||
4765 | struct iscsi_session *sess; | 4791 | struct iscsi_session *sess; |
4766 | struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; | 4792 | struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; |
4767 | struct se_session *se_sess, *se_sess_tmp; | 4793 | struct se_session *se_sess, *se_sess_tmp; |
4794 | LIST_HEAD(free_list); | ||
4768 | int session_count = 0; | 4795 | int session_count = 0; |
4769 | 4796 | ||
4770 | spin_lock_bh(&se_tpg->session_lock); | 4797 | spin_lock_bh(&se_tpg->session_lock); |
@@ -4786,14 +4813,17 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) | |||
4786 | } | 4813 | } |
4787 | atomic_set(&sess->session_reinstatement, 1); | 4814 | atomic_set(&sess->session_reinstatement, 1); |
4788 | spin_unlock(&sess->conn_lock); | 4815 | spin_unlock(&sess->conn_lock); |
4789 | spin_unlock_bh(&se_tpg->session_lock); | ||
4790 | 4816 | ||
4791 | iscsit_free_session(sess); | 4817 | list_move_tail(&se_sess->sess_list, &free_list); |
4792 | spin_lock_bh(&se_tpg->session_lock); | 4818 | } |
4819 | spin_unlock_bh(&se_tpg->session_lock); | ||
4820 | |||
4821 | list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) { | ||
4822 | sess = (struct iscsi_session *)se_sess->fabric_sess_ptr; | ||
4793 | 4823 | ||
4824 | iscsit_free_session(sess); | ||
4794 | session_count++; | 4825 | session_count++; |
4795 | } | 4826 | } |
4796 | spin_unlock_bh(&se_tpg->session_lock); | ||
4797 | 4827 | ||
4798 | pr_debug("Released %d iSCSI Session(s) from Target Portal" | 4828 | pr_debug("Released %d iSCSI Session(s) from Target Portal" |
4799 | " Group: %hu\n", session_count, tpg->tpgt); | 4829 | " Group: %hu\n", session_count, tpg->tpgt); |