From c798bfadf60d852a97bda34e3f5792c7899ea175 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Aug 2015 17:49:17 -0700 Subject: [PATCH] 3.10-stable patches added patches: iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch --- ...iser-explicit-logout-tx-kthread-leak.patch | 284 ++++++++++++++++++ queue-3.10/series | 1 + 2 files changed, 285 insertions(+) create mode 100644 queue-3.10/iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch diff --git a/queue-3.10/iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch b/queue-3.10/iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch new file mode 100644 index 00000000000..bc4db6faabd --- /dev/null +++ b/queue-3.10/iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch @@ -0,0 +1,284 @@ +From 007d038bdf95ccfe2491d0078be54040d110fd06 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Thu, 23 Jul 2015 22:30:31 +0000 +Subject: iscsi-target: Fix iser explicit logout TX kthread leak + +From: Nicholas Bellinger + +commit 007d038bdf95ccfe2491d0078be54040d110fd06 upstream. + +This patch fixes a regression introduced with the following commit +in v4.0-rc1 code, where an explicit iser-target logout would result +in ->tx_thread_active being incorrectly cleared by the logout post +handler, and subsequent TX kthread leak: + + commit 88dcd2dab5c23b1c9cfc396246d8f476c872f0ca + Author: Nicholas Bellinger + Date: Thu Feb 26 22:19:15 2015 -0800 + + iscsi-target: Convert iscsi_thread_set usage to kthread.h + +To address this bug, change iscsit_logout_post_handler_closesession() +and iscsit_logout_post_handler_samecid() to only cmpxchg() on +->tx_thread_active for traditional iscsi/tcp connections. + +This is required because iscsi/tcp connections are invoking logout +post handler logic directly from TX kthread context, while iser +connections are invoking logout post handler logic from a seperate +workqueue context. + +Cc: Sagi Grimberg +Cc: # v3.10+ +Signed-off-by: Nicholas Bellinger +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/iscsi/iscsi_target.c | 18 ++++++++++-- + drivers/target/iscsi/iscsi_target_core.h | 1 + drivers/target/iscsi/iscsi_target_login.c | 43 +++++++++++------------------- + drivers/target/iscsi/iscsi_target_login.h | 1 + drivers/target/iscsi/iscsi_target_nego.c | 34 +++++++++++++++++++++++ + 5 files changed, 66 insertions(+), 31 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -3874,7 +3874,13 @@ get_immediate: + } + + transport_err: +- iscsit_take_action_for_connection_exit(conn); ++ /* ++ * Avoid the normal connection failure code-path if this connection ++ * is still within LOGIN mode, and iscsi_np process context is ++ * responsible for cleaning up the early connection failure. ++ */ ++ if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) ++ iscsit_take_action_for_connection_exit(conn); + out: + return 0; + } +@@ -3956,7 +3962,7 @@ reject: + + int iscsi_target_rx_thread(void *arg) + { +- int ret; ++ int ret, rc; + u8 buffer[ISCSI_HDR_LEN], opcode; + u32 checksum = 0, digest = 0; + struct iscsi_conn *conn = arg; +@@ -3966,10 +3972,16 @@ int iscsi_target_rx_thread(void *arg) + * connection recovery / failure event can be triggered externally. + */ + allow_signal(SIGINT); ++ /* ++ * Wait for iscsi_post_login_handler() to complete before allowing ++ * incoming iscsi/tcp socket I/O, and/or failing the connection. ++ */ ++ rc = wait_for_completion_interruptible(&conn->rx_login_comp); ++ if (rc < 0) ++ return 0; + + if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { + struct completion comp; +- int rc; + + init_completion(&comp); + rc = wait_for_completion_interruptible(&comp); +--- a/drivers/target/iscsi/iscsi_target_core.h ++++ b/drivers/target/iscsi/iscsi_target_core.h +@@ -589,6 +589,7 @@ struct iscsi_conn { + int bitmap_id; + int rx_thread_active; + struct task_struct *rx_thread; ++ struct completion rx_login_comp; + int tx_thread_active; + struct task_struct *tx_thread; + /* list_head for session connection list */ +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -84,6 +84,7 @@ static struct iscsi_login *iscsi_login_i + init_completion(&conn->conn_logout_comp); + init_completion(&conn->rx_half_close_comp); + init_completion(&conn->tx_half_close_comp); ++ init_completion(&conn->rx_login_comp); + spin_lock_init(&conn->cmd_lock); + spin_lock_init(&conn->conn_usage_lock); + spin_lock_init(&conn->immed_queue_lock); +@@ -718,6 +719,7 @@ int iscsit_start_kthreads(struct iscsi_c + + return 0; + out_tx: ++ send_sig(SIGINT, conn->tx_thread, 1); + kthread_stop(conn->tx_thread); + conn->tx_thread_active = false; + out_bitmap: +@@ -728,7 +730,7 @@ out_bitmap: + return ret; + } + +-int iscsi_post_login_handler( ++void iscsi_post_login_handler( + struct iscsi_np *np, + struct iscsi_conn *conn, + u8 zero_tsih) +@@ -738,7 +740,6 @@ int iscsi_post_login_handler( + struct se_session *se_sess = sess->se_sess; + struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess); + struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; +- int rc; + + iscsit_inc_conn_usage_count(conn); + +@@ -779,10 +780,6 @@ int iscsi_post_login_handler( + sess->sess_ops->InitiatorName); + spin_unlock_bh(&sess->conn_lock); + +- rc = iscsit_start_kthreads(conn); +- if (rc) +- return rc; +- + iscsi_post_login_start_timers(conn); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads +@@ -791,15 +788,20 @@ int iscsi_post_login_handler( + iscsit_thread_get_cpumask(conn); + conn->conn_rx_reset_cpumask = 1; + conn->conn_tx_reset_cpumask = 1; +- ++ /* ++ * Wakeup the sleeping iscsi_target_rx_thread() now that ++ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. ++ */ ++ complete(&conn->rx_login_comp); + iscsit_dec_conn_usage_count(conn); ++ + if (stop_timer) { + spin_lock_bh(&se_tpg->session_lock); + iscsit_stop_time2retain_timer(sess); + spin_unlock_bh(&se_tpg->session_lock); + } + iscsit_dec_session_usage_count(sess); +- return 0; ++ return; + } + + iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1); +@@ -840,10 +842,6 @@ int iscsi_post_login_handler( + " iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt); + spin_unlock_bh(&se_tpg->session_lock); + +- rc = iscsit_start_kthreads(conn); +- if (rc) +- return rc; +- + iscsi_post_login_start_timers(conn); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads +@@ -852,10 +850,12 @@ int iscsi_post_login_handler( + iscsit_thread_get_cpumask(conn); + conn->conn_rx_reset_cpumask = 1; + conn->conn_tx_reset_cpumask = 1; +- ++ /* ++ * Wakeup the sleeping iscsi_target_rx_thread() now that ++ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. ++ */ ++ complete(&conn->rx_login_comp); + iscsit_dec_conn_usage_count(conn); +- +- return 0; + } + + static void iscsi_handle_login_thread_timeout(unsigned long data) +@@ -1331,20 +1331,9 @@ static int __iscsi_target_login_thread(s + if (iscsi_target_start_negotiation(login, conn) < 0) + goto new_sess_out; + +- if (!conn->sess) { +- pr_err("struct iscsi_conn session pointer is NULL!\n"); +- goto new_sess_out; +- } +- + iscsi_stop_login_thread_timer(np); + +- if (signal_pending(current)) +- goto new_sess_out; +- +- ret = iscsi_post_login_handler(np, conn, zero_tsih); +- +- if (ret < 0) +- goto new_sess_out; ++ iscsi_post_login_handler(np, conn, zero_tsih); + + iscsit_deaccess_np(np, tpg); + tpg = NULL; +--- a/drivers/target/iscsi/iscsi_target_login.h ++++ b/drivers/target/iscsi/iscsi_target_login.h +@@ -12,6 +12,7 @@ extern int iscsit_accept_np(struct iscsi + extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); + extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); + extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); ++extern int iscsit_start_kthreads(struct iscsi_conn *); + extern int iscsi_target_login_thread(void *); + extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *); + +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -19,6 +19,7 @@ + ******************************************************************************/ + + #include ++#include + #include + #include + #include +@@ -352,10 +353,24 @@ static int iscsi_target_do_tx_login_io(s + ntohl(login_rsp->statsn), login->rsp_length); + + padding = ((-login->rsp_length) & 3); ++ /* ++ * Before sending the last login response containing the transition ++ * bit for full-feature-phase, go ahead and start up TX/RX threads ++ * now to avoid potential resource allocation failures after the ++ * final login response has been sent. ++ */ ++ if (login->login_complete) { ++ int rc = iscsit_start_kthreads(conn); ++ if (rc) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ++ ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ return -1; ++ } ++ } + + if (conn->conn_transport->iscsit_put_login_tx(conn, login, + login->rsp_length + padding) < 0) +- return -1; ++ goto err; + + login->rsp_length = 0; + mutex_lock(&sess->cmdsn_mutex); +@@ -364,6 +379,23 @@ static int iscsi_target_do_tx_login_io(s + mutex_unlock(&sess->cmdsn_mutex); + + return 0; ++ ++err: ++ if (login->login_complete) { ++ if (conn->rx_thread && conn->rx_thread_active) { ++ send_sig(SIGINT, conn->rx_thread, 1); ++ kthread_stop(conn->rx_thread); ++ } ++ if (conn->tx_thread && conn->tx_thread_active) { ++ send_sig(SIGINT, conn->tx_thread, 1); ++ kthread_stop(conn->tx_thread); ++ } ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ } ++ return -1; + } + + static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login) diff --git a/queue-3.10/series b/queue-3.10/series index 7f6cbe067d8..cea9d6a0a68 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -18,3 +18,4 @@ x86-xen-probe-target-addresses-in-set_aliased_prot-before-the-hypercall.patch xen-gntdevt-fix-race-condition-in-gntdev_release.patch crypto-ixp4xx-remove-bogus-bug_on-on-scattered-dst-buffer.patch rbd-fix-copyup-completion-race.patch +iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch -- 2.47.2