From: Hoeun Ryu <hoeun....@lge.com> Use printk_safe_flush_on_panic() in nmi_trigger_cpumask_backtrace(). nmi_trigger_cpumask_backtrace() can be called in NMI context. For example the function is called in watchdog_overflow_callback() if the flag of hardlockup backtrace (sysctl_hardlockup_all_cpu_backtrace) is true and watchdog_overflow_callback() function is called in NMI context on some architectures. printk_safe_flush() eventually tries to lock logbuf_lock in vprintk_emit() but the logbuf_lock can be already locked in preempted contexts (task or irq in this case) or by other CPUs and it may cause deadlocks. By using printk_safe_flush_on_panic() instead of printk_safe_flush() in in nmi_trigger_cpumask_backtrace(), the backtrace triggering CPU can access the lock safely as the lock is reinitialized before calling printk_safe_flush(). The messages in logbuf can be corrupted if the NMI context preempts other contexts or ignores the lock held by other CPUs writing the buffer.
Signed-off-by: Hoeun Ryu <hoeun....@lge.com> --- lib/nmi_backtrace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c index 61a6b5a..0ace3c9 100644 --- a/lib/nmi_backtrace.c +++ b/lib/nmi_backtrace.c @@ -78,8 +78,11 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask, /* * Force flush any remote buffers that might be stuck in IRQ context * and therefore could not run their irq_work. + * Call nmi-safe version of printk_safe_flush() because this function can be + * called in NMI context like watchdog_overflow_callback() if + * sysctl_hardlockup_all_cpu_backtrace is true. */ - printk_safe_flush(); + printk_safe_flush_on_panic(); clear_bit_unlock(0, &backtrace_flag); put_cpu(); -- 2.1.4