[PATCH v2 5/7] watchdog: Fix barriers when printing backtraces from all CPUs

From: Petr Mladek
Date: Thu Dec 10 2020 - 11:02:33 EST


Any parallel softlockup reports are skipped when one CPU is already
printing backtraces from all CPUs.

The exclusive rights are synchronized using one bit in
soft_lockup_nmi_warn. There is also one memory barrier that
does not make much sense.

Use two barriers on the right location to prevent mixing two
reports.

Signed-off-by: Petr Mladek <pmladek@xxxxxxxx>
---
kernel/watchdog.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index dc8a0bf943f5..6dc1f79e36aa 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -409,12 +409,18 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
if (kvm_check_and_clear_guest_paused())
return HRTIMER_RESTART;

+ /*
+ * Prevent multiple soft-lockup reports if one cpu is already
+ * engaged in dumping all cpu back traces.
+ */
if (softlockup_all_cpu_backtrace) {
- /* Prevent multiple soft-lockup reports if one cpu is already
- * engaged in dumping cpu back traces
- */
if (test_and_set_bit(0, &soft_lockup_nmi_warn))
return HRTIMER_RESTART;
+ /*
+ * Make sure that reports are serialized. Start
+ * printing after getting the exclusive rights.
+ */
+ smp_mb__after_atomic();
}

/* Start period for the next softlockup warning. */
@@ -431,14 +437,14 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
dump_stack();

if (softlockup_all_cpu_backtrace) {
- /* Avoid generating two back traces for current
- * given that one is already made above
- */
trigger_allbutself_cpu_backtrace();
-
+ /*
+ * Make sure that everything is printed before
+ * another CPU is allowed to report lockup again.
+ */
+ smp_mb__before_atomic();
+ /* Allow a further report. */
clear_bit(0, &soft_lockup_nmi_warn);
- /* Barrier to sync with other cpus */
- smp_mb__after_atomic();
}

add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
--
2.26.2