All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kara <jack@suse.cz>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
	pmladek@suse.cz, Frederic Weisbecker <fweisbec@gmail.com>,
	Steven Rostedt <rostedt@goodmis.org>, Jan Kara <jack@suse.cz>
Subject: [PATCH 7/8] kernel: Avoid softlockups in stop_machine() during heavy printing
Date: Tue, 25 Mar 2014 18:55:00 +0100	[thread overview]
Message-ID: <1395770101-24534-8-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <1395770101-24534-1-git-send-email-jack@suse.cz>

When there are lots of messages accumulated in printk buffer, printing
them (especially over serial console) can take a long time (tens of
seconds). stop_machine() will effectively make all cpus spin in
multi_cpu_stop() waiting for the CPU doing printing to print all the
messages which triggers NMI softlockup watchdog and RCU stall detector
which add even more to the messages to print. Since machine doesn't do
anything (except serving interrupts) during this time, also network
connections are dropped and other disturbances may happen.

Paper over the problem by waiting for printk buffer to be empty before
starting to stop CPUs. In theory a burst of new messages can be appended
to the printk buffer before CPUs enter multi_cpu_stop() so this isn't a 100%
solution but it works OK in practice and I'm not aware of a reasonably
simple better solution.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 include/linux/console.h |  1 +
 kernel/printk/printk.c  | 22 ++++++++++++++++++++++
 kernel/stop_machine.c   |  9 +++++++++
 3 files changed, 32 insertions(+)

diff --git a/include/linux/console.h b/include/linux/console.h
index 7571a16bd653..c61c169f85b3 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -150,6 +150,7 @@ extern int console_trylock(void);
 extern void console_unlock(void);
 extern void console_conditional_schedule(void);
 extern void console_unblank(void);
+extern void console_flush(void);
 extern struct tty_driver *console_device(int *);
 extern void console_stop(struct console *);
 extern void console_start(struct console *);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 8d981b2b5bb1..1c0577383af5 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2306,6 +2306,28 @@ struct tty_driver *console_device(int *index)
 }
 
 /*
+ * Wait until all messages accumulated in the printk buffer are printed to
+ * console. Note that as soon as this function returns, new messages may be
+ * added to the printk buffer by other CPUs.
+ */
+void console_flush(void)
+{
+	bool retry;
+	unsigned long flags;
+
+	while (1) {
+		raw_spin_lock_irqsave(&logbuf_lock, flags);
+		retry = console_seq != log_next_seq;
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		if (!retry || console_suspended)
+			break;
+		/* Cycle console_sem to wait for outstanding printing */
+		console_lock();
+		console_unlock();
+	}
+}
+
+/*
  * Prevent further output on the passed console device so that (for example)
  * serial drivers can disable console output before suspending a port, and can
  * re-enable output afterwards.
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 84571e09c907..14ac740e0c7f 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -21,6 +21,7 @@
 #include <linux/smpboot.h>
 #include <linux/atomic.h>
 #include <linux/lglock.h>
+#include <linux/console.h>
 
 /*
  * Structure to determine completion condition and record errors.  May
@@ -574,6 +575,14 @@ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
 		return ret;
 	}
 
+	/*
+	 * If there are lots of outstanding messages, printing them can take a
+	 * long time and all cpus would be spinning waiting for the printing to
+	 * finish thus triggering NMI watchdog, RCU lockups etc. Wait for the
+	 * printing here to avoid these.
+	 */
+	console_flush();
+
 	/* Set the initial state and stop all online cpus. */
 	set_state(&msdata, MULTI_STOP_PREPARE);
 	return stop_cpus(cpu_online_mask, multi_cpu_stop, &msdata);
-- 
1.8.1.4


  parent reply	other threads:[~2014-03-25 17:57 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-25 17:54 [PATCH 0/8 v4] printk: Cleanups and softlockup avoidance Jan Kara
2014-03-25 17:54 ` [PATCH 1/8] printk: Remove outdated comment Jan Kara
2014-03-25 17:54 ` [PATCH 2/8] printk: Release lockbuf_lock before calling console_trylock_for_printk() Jan Kara
2014-04-23 20:56   ` Andrew Morton
2014-04-24 10:18     ` Jan Kara
2014-03-25 17:54 ` [PATCH 3/8] printk: Enable interrupts " Jan Kara
2014-03-25 17:54 ` [PATCH 4/8] printk: Remove separate printk_sched buffers and use printk buf instead Jan Kara
2014-05-05 18:37   ` Steven Rostedt
2014-03-25 17:54 ` [PATCH 5/8] printk: Hand over printing to console if printing too long Jan Kara
2014-03-25 17:54 ` [PATCH 6/8] printk: Start printing handover kthreads on demand Jan Kara
2014-03-26 17:16   ` One Thousand Gnomes
2014-03-26 19:06     ` Jan Kara
2014-03-25 17:55 ` Jan Kara [this message]
2014-03-25 17:55 ` [PATCH 8/8] printk: Add config option for disabling printk offloading Jan Kara
2014-03-26 17:23   ` One Thousand Gnomes
2014-03-26 19:28     ` Jan Kara
2014-04-18 18:54       ` Andrew Morton
2014-04-22 10:22         ` One Thousand Gnomes
2014-04-23 11:08           ` Jan Kara
2014-04-23 12:35             ` One Thousand Gnomes
2014-04-23 14:29               ` Jan Kara
2014-04-23 18:17             ` Andrew Morton
2014-04-23 21:16               ` One Thousand Gnomes
2014-04-23 21:41                 ` Jiri Kosina
2014-04-24 14:00                   ` One Thousand Gnomes
2014-05-15 21:28               ` Jan Kara
2014-04-23  9:30         ` Jan Kara
2014-04-08 14:27 ` [PATCH 0/8 v4] printk: Cleanups and softlockup avoidance Jan Kara
2014-04-08 19:02   ` Andrew Morton
  -- strict thread matches above, loose matches on Subject: below --
2014-03-14 16:21 [PATCH 0/8 v3] " Jan Kara
2014-03-14 16:21 ` [PATCH 7/8] kernel: Avoid softlockups in stop_machine() during heavy printing Jan Kara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1395770101-24534-8-git-send-email-jack@suse.cz \
    --to=jack@suse.cz \
    --cc=akpm@linux-foundation.org \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pmladek@suse.cz \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.