On (02/27/16 11:19), Sergey Senozhatsky wrote: [..] > > I think about a compromise. We should try to get the messages > > out only when kdump is not enabled. > > can we zap_locks() if we are on > nmi_panic()->panic()->console_flush_on_panic() path? > console_flush_on_panic() is happening after we send out smp_send_stop().
can something like this do the trick? ====8<==== >From 4186873bb4574b4bbb227e7448d56599849de0bd Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky <sergey.senozhat...@gmail.com> Subject: [PATCH] printk/nmi: restore printk_func in nmi_panic When watchdog detects a hardlockup and calls nmi_panic() `printk_func' must be restored via printk_nmi_exit() call, so panic() will be able to flush nmi buf and show backtrace and panic message. We also better explicitly ask nmi to printk_nmi_flush() in console_flush_on_panic(), because it may be too late to rely on irq work. Factor out __zap_locks(), and call it from console_flush_on_panic(). This is normally not needed, because logbuf_lock always comes with IRQ disable/enable magic, but we can panic() from nmi. Signed-off-by: Sergey Senozhatsky <sergey.senozhat...@gmail.com> --- include/linux/kernel.h | 6 ++++-- kernel/printk/printk.c | 27 ++++++++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f4fa2b2..3ee33d5 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -469,10 +469,12 @@ do { \ cpu = raw_smp_processor_id(); \ old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, cpu); \ \ - if (old_cpu == PANIC_CPU_INVALID) \ + if (old_cpu == PANIC_CPU_INVALID) { \ + printk_nmi_exit(); \ panic(fmt, ##__VA_ARGS__); \ - else if (old_cpu != cpu) \ + } else if (old_cpu != cpu) { \ nmi_panic_self_stop(regs); \ + } \ } while (0) /* diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 9917f69..0a318ed 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1462,6 +1462,15 @@ static void call_console_drivers(int level, } } +static void __zap_locks(void) +{ + debug_locks_off(); + /* If a crash is occurring, make sure we can't deadlock */ + raw_spin_lock_init(&logbuf_lock); + /* And make sure that we print immediately */ + sema_init(&console_sem, 1); +} + /* * Zap console related locks when oopsing. * To leave time for slow consoles to print a full oops, @@ -1477,11 +1486,7 @@ static void zap_locks(void) oops_timestamp = jiffies; - debug_locks_off(); - /* If a crash is occurring, make sure we can't deadlock */ - raw_spin_lock_init(&logbuf_lock); - /* And make sure that we print immediately */ - sema_init(&console_sem, 1); + __zap_locks(); } int printk_delay_msec __read_mostly; @@ -2386,15 +2391,15 @@ void console_unblank(void) */ void console_flush_on_panic(void) { - /* - * If someone else is holding the console lock, trylock will fail - * and may_schedule may be set. Ignore and proceed to unlock so - * that messages are flushed out. As this can be called from any - * context and we don't want to get preempted while flushing, - * ensure may_schedule is cleared. + __zap_locks(); + + /* As this can be called from any context and we don't want + * to get preempted while flushing, ensure may_schedule is + * cleared. */ console_trylock(); console_may_schedule = 0; + printk_nmi_flush(); console_unlock(); } -- 2.7.1