]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
watchdog: fix barriers when printing backtraces from all CPUs
authorPetr Mladek <pmladek@suse.com>
Fri, 30 Apr 2021 05:54:33 +0000 (22:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Apr 2021 18:20:36 +0000 (11:20 -0700)
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.

[pmladek@suse.com: use bit lock operations to prevent multiple soft-lockup reports]
Link: https://lkml.kernel.org/r/YFSVsLGVWMXTvlbk@alley
Link: https://lkml.kernel.org/r/20210311122130.6788-6-pmladek@suse.com
Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Laurence Oberman <loberman@redhat.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vincent Whitchurch <vincent.whitchurch@axis.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
kernel/watchdog.c

index b8d4182d14ccb47c2b3d1014b8976cb58614434d..8cf0678378d2976ddb0da2ade0bd216fc8689eac 100644 (file)
@@ -410,11 +410,12 @@ 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))
+                       if (test_and_set_bit_lock(0, &soft_lockup_nmi_warn))
                                return HRTIMER_RESTART;
                }
 
@@ -432,14 +433,8 @@ 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();
-
-                       clear_bit(0, &soft_lockup_nmi_warn);
-                       /* Barrier to sync with other cpus */
-                       smp_mb__after_atomic();
+                       clear_bit_unlock(0, &soft_lockup_nmi_warn);
                }
 
                add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);