+++ /dev/null
-From 007d038bdf95ccfe2491d0078be54040d110fd06 Mon Sep 17 00:00:00 2001
-From: Nicholas Bellinger <nab@linux-iscsi.org>
-Date: Thu, 23 Jul 2015 22:30:31 +0000
-Subject: iscsi-target: Fix iser explicit logout TX kthread leak
-
-From: Nicholas Bellinger <nab@linux-iscsi.org>
-
-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 <nab@linux-iscsi.org>
- 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 <sagig@mellanox.com>
-Cc: <stable@vger.kernel.org> # v3.10+
-Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-Signed-off-by: Nicholas Bellinger <nab@daterainc.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- 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 <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)
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
+++ /dev/null
-From 007d038bdf95ccfe2491d0078be54040d110fd06 Mon Sep 17 00:00:00 2001
-From: Nicholas Bellinger <nab@linux-iscsi.org>
-Date: Thu, 23 Jul 2015 22:30:31 +0000
-Subject: iscsi-target: Fix iser explicit logout TX kthread leak
-
-From: Nicholas Bellinger <nab@linux-iscsi.org>
-
-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 <nab@linux-iscsi.org>
- 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 <sagig@mellanox.com>
-Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-Signed-off-by: Nicholas Bellinger <nab@daterainc.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- 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 | 3 +-
- drivers/target/iscsi/iscsi_target_nego.c | 34 +++++++++++++++++++++++
- 5 files changed, 67 insertions(+), 32 deletions(-)
-
---- a/drivers/target/iscsi/iscsi_target.c
-+++ b/drivers/target/iscsi/iscsi_target.c
-@@ -3937,7 +3937,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;
- }
-@@ -4023,7 +4029,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;
-@@ -4033,10 +4039,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
-@@ -604,6 +604,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
-@@ -83,6 +83,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);
-@@ -716,6 +717,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:
-@@ -726,7 +728,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)
-@@ -736,7 +738,6 @@ int iscsi_post_login_handler(
- struct se_session *se_sess = sess->se_sess;
- struct iscsi_portal_group *tpg = sess->tpg;
- struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
-- int rc;
-
- iscsit_inc_conn_usage_count(conn);
-
-@@ -777,10 +778,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
-@@ -789,15 +786,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);
-@@ -838,10 +840,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
-@@ -850,10 +848,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)
-@@ -1418,23 +1418,12 @@ static int __iscsi_target_login_thread(s
- if (ret < 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;
--
- if (ret == 1) {
- tpg_np = conn->tpg_np;
-
-- 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_np);
- }
-
---- a/drivers/target/iscsi/iscsi_target_login.h
-+++ b/drivers/target/iscsi/iscsi_target_login.h
-@@ -12,7 +12,8 @@ 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 iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
-+extern int iscsit_start_kthreads(struct iscsi_conn *);
-+extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
- extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
- bool, bool);
- extern int iscsi_target_login_thread(void *);
---- a/drivers/target/iscsi/iscsi_target_nego.c
-+++ b/drivers/target/iscsi/iscsi_target_nego.c
-@@ -17,6 +17,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>
-@@ -361,10 +362,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);
-@@ -373,6 +388,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 void iscsi_target_sk_data_ready(struct sock *sk, int count)
crypto-ixp4xx-remove-bogus-bug_on-on-scattered-dst-buffer.patch
rbd-fix-copyup-completion-race.patch
arm-omap2-hwmod-fix-_wait_target_ready-for-hwmods-without-sysc.patch
-iscsi-target-fix-iser-explicit-logout-tx-kthread-leak.patch