aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/panic.c
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2015-11-06 19:32:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 20:50:42 -0500
commit08d78658f393fefaa2e6507ea052c6f8ef4002a2 (patch)
treed013128ecf2efb6f4d2701f92745cab54f7511ab /kernel/panic.c
parent7f8306429c4c75f9e2bf39fcfe990b0af2f7292d (diff)
panic: release stale console lock to always get the logbuf printed out
In some cases we may end up killing the CPU holding the console lock while still having valuable data in logbuf. E.g. I'm observing the following: - A crash is happening on one CPU and console_unlock() is being called on some other. - console_unlock() tries to print out the buffer before releasing the lock and on slow console it takes time. - in the meanwhile crashing CPU does lots of printk()-s with valuable data (which go to the logbuf) and sends IPIs to all other CPUs. - console_unlock() finishes printing previous chunk and enables interrupts before trying to print out the rest, the CPU catches the IPI and never releases console lock. This is not the only possible case: in VT/fb subsystems we have many other console_lock()/console_unlock() users. Non-masked interrupts (or receiving NMI in case of extreme slowness) will have the same result. Getting the whole console buffer printed out on crash should be top priority. [akpm@linux-foundation.org: tweak comment text] Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Cc: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Baoquan He <bhe@redhat.com> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Xie XiuQi <xiexiuqi@huawei.com> Cc: Seth Jennings <sjenning@redhat.com> Cc: "K. Y. Srinivasan" <kys@microsoft.com> Cc: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index 04e91ff7560b..4579dbb7ed87 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -23,6 +23,7 @@
23#include <linux/sysrq.h> 23#include <linux/sysrq.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/nmi.h> 25#include <linux/nmi.h>
26#include <linux/console.h>
26 27
27#define PANIC_TIMER_STEP 100 28#define PANIC_TIMER_STEP 100
28#define PANIC_BLINK_SPD 18 29#define PANIC_BLINK_SPD 18
@@ -147,6 +148,15 @@ void panic(const char *fmt, ...)
147 148
148 bust_spinlocks(0); 149 bust_spinlocks(0);
149 150
151 /*
152 * We may have ended up stopping the CPU holding the lock (in
153 * smp_send_stop()) while still having some valuable data in the console
154 * buffer. Try to acquire the lock then release it regardless of the
155 * result. The release will also print the buffers out.
156 */
157 console_trylock();
158 console_unlock();
159
150 if (!panic_blink) 160 if (!panic_blink)
151 panic_blink = no_blink; 161 panic_blink = no_blink;
152 162