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 <[email protected]>
---
 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

Reply via email to