Skip to contentSkip to conversation

Patch "iscsi-target: Fix iser explicit logout TX kthread leak" has been added to the 3.10-stable tree

PATCH [email protected] 1 participant 1 message Aug 14, 2015

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

iscsi-target: Fix iser explicit logout TX kthread leak

to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch
and it can be found in the queue-3.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 007d038bdf95ccfe2491d0078be54040d110fd06 Mon Sep 17 00:00:00 2001

From: Nicholas Bellinger <[email protected]>
Date: Thu, 23 Jul 2015 22:30:31 +0000
Subject: iscsi-target: Fix iser explicit logout TX kthread leak

From: Nicholas Bellinger <[email protected]>

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 <[email protected]>
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.

---
 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(-)
drivers/target/iscsi/iscsi_target.c +15 -3
@@ -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);
drivers/target/iscsi/iscsi_target_core.h +1 -0
@@ -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 */
drivers/target/iscsi/iscsi_target_login.c +16 -27

107 lines not on this page · raw message

drivers/target/iscsi/iscsi_target_login.h +1 -0
@@ -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 *);
 
drivers/target/iscsi/iscsi_target_nego.c +33 -1
@@ -19,6 +19,7 @@
  ******************************************************************************/
 
 #include <linux/ctype.h>
+#include <linux/kthread.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
@@ -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)

Patches currently in stable-queue which might be from [email protected] are

queue-3.10/iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch