[PATCH -next] kernel/watchdog_hld.c: Complete the flush of the hard deadlock log messages to the serial port

From: Xu Qiang
Date: Mon Nov 02 2020 - 01:38:34 EST


when hardlockup_all_cpu_backtrace is on, and there are
a large number of cores in the system, it takes
a long time to output the hard deadlock logs of all cores
to the serial port. When the console_flush_on_panic function
in panic is executed, console_locked is still held.
As a result, garbled characters are displayed in the serial port log.

To solve this problem, wait for a maximum of 10s for the serial port
to be released before entering the panic mode.

Signed-off-by: Xu Qiang <xuqiang36@xxxxxxxxxx>
---
kernel/watchdog_hld.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
index a546bc54f6ff..d3410b9fd3c3 100644
--- a/kernel/watchdog_hld.c
+++ b/kernel/watchdog_hld.c
@@ -13,8 +13,10 @@
#define pr_fmt(fmt) "NMI watchdog: " fmt

#include <linux/nmi.h>
+#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/module.h>
+#include <linux/console.h>
#include <linux/sched/debug.h>

#include <asm/irq_regs.h>
@@ -129,6 +131,7 @@ static void watchdog_overflow_callback(struct perf_event *event,
* then this is a good indication the cpu is stuck
*/
if (is_hardlockup()) {
+ int i;
int this_cpu = smp_processor_id();

/* only print hardlockups once */
@@ -151,9 +154,15 @@ static void watchdog_overflow_callback(struct perf_event *event,
if (sysctl_hardlockup_all_cpu_backtrace &&
!test_and_set_bit(0, &hardlockup_allcpu_dumped))
trigger_allbutself_cpu_backtrace();
-
- if (hardlockup_panic)
+ if (hardlockup_panic) {
+ /* Wait for all CPUs to complete wake_up_klogd_work_func */
+ for (i = 0; i < 10 * 1000; i++) {
+ if (console_trylock())
+ break;
+ mdelay(1);
+ }
nmi_panic(regs, "Hard LOCKUP");
+ }
atomic_inc(&hardlockup_detected);

__this_cpu_write(hard_watchdog_warn, true);
--
2.25.0