Blob Blame History Raw
From 32ec0c36d7b5b4494fcedfbe4e108bd4d0ffc1dc Mon Sep 17 00:00:00 2001
From: Miroslav Benes <mbenes@suse.cz>
Date: Tue, 20 Feb 2018 14:18:00 +0100
Subject: [PATCH] livepatch: send a fake signal periodically
Patch-mainline: Not yet, work in progress
References: fate#323487

An administrator may send a fake signal to all remaining blocking tasks
of a running transition by writing to
/sys/kernel/livepatch/<patch>/signal attribute. Let's do it
automatically after 10 seconds. The timeout is chosen deliberately. It
gives the tasks enough time to transition themselves.

Theoretically, sending it once should be more than enough. Better be safe
than sorry, so send it periodically. A new workqueue job could be a
cleaner solution to achieve it, but it could also introduce deadlocks
and cause more headaches with synchronization and cancelling.

Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Miroslav Benes <mbenes@suse.cz>
---
 kernel/livepatch/transition.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c
index d6af190865d2..74fabbf3b572 100644
--- a/kernel/livepatch/transition.c
+++ b/kernel/livepatch/transition.c
@@ -29,6 +29,8 @@
 #define MAX_STACK_ENTRIES  100
 #define STACK_ERR_BUF_SIZE 128
 
+#define SIGNALS_TIMEOUT 10
+
 struct klp_patch *klp_transition_patch;
 
 static int klp_target_state = KLP_UNDEFINED;
@@ -406,6 +408,7 @@ void klp_try_complete_transition(void)
 	unsigned int cpu;
 	struct task_struct *g, *task;
 	bool complete = true;
+	static unsigned int signals_cnt = 0;
 
 	WARN_ON_ONCE(klp_target_state == KLP_UNDEFINED);
 
@@ -442,6 +445,9 @@ void klp_try_complete_transition(void)
 	put_online_cpus();
 
 	if (!complete) {
+		if (!(++signals_cnt % SIGNALS_TIMEOUT))
+			klp_send_signals();
+
 		/*
 		 * Some tasks weren't able to be switched over.  Try again
 		 * later and/or wait for other methods like kernel exit
@@ -449,10 +455,12 @@ void klp_try_complete_transition(void)
 		 */
 		schedule_delayed_work(&klp_transition_work,
 				      round_jiffies_relative(HZ));
+
 		return;
 	}
 
 	/* we're done, now cleanup the data structures */
+	signals_cnt = 0;
 	klp_complete_transition();
 }
 
-- 
2.16.1