aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-09-12 15:37:10 -0400
committerIngo Molnar <mingo@kernel.org>2017-09-14 05:41:06 -0400
commit2eb2527f847d1bd8d8fb9db1e8139db5d6eddb36 (patch)
treebad2df55355015f32828b2c56d414830c0321663
parent0d85923c7a81719567311ba0eae8ecb2efd4c8a0 (diff)
watchdog/core: Create new thread handling infrastructure
The lockup detector reconfiguration tears down all watchdog threads when the watchdog is disabled and sets them up again when its enabled. That's a pointless exercise. The watchdog threads are not consuming an insane amount of resources, so it's enough to set them up at init time and keep them in parked position when the watchdog is disabled and unpark them when it is reenabled. The smpboot thread infrastructure takes care of keeping the force parked threads in place even across cpu hotplug. Another horrible mechanism are the open coded park/unpark loops which are used for reconfiguration of the watchdog. The smpboot infrastructure allows exactly the same via smpboot_update_cpumask_thread_percpu(), which is cpu hotplug safe. Using that instead of the open coded loops allows to get rid of the hotplug locking mess in the watchdog code. Implement a clean infrastructure which allows to replace the open coded nonsense. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Don Zickus <dzickus@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Chris Metcalf <cmetcalf@mellanox.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sebastian Siewior <bigeasy@linutronix.de> Cc: Ulrich Obergfell <uobergfe@redhat.com> Link: http://lkml.kernel.org/r/20170912194147.377182587@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/watchdog.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 8935a3a4c2fb..b35518375fb7 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -139,6 +139,9 @@ unsigned int __read_mostly softlockup_panic =
139 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE; 139 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
140int __read_mostly soft_watchdog_enabled; 140int __read_mostly soft_watchdog_enabled;
141 141
142struct cpumask watchdog_allowed_mask __read_mostly;
143static bool softlockup_threads_initialized __read_mostly;
144
142static u64 __read_mostly sample_period; 145static u64 __read_mostly sample_period;
143 146
144static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); 147static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
@@ -584,12 +587,84 @@ static void watchdog_disable_all_cpus(void)
584 } 587 }
585} 588}
586 589
590static void softlockup_update_smpboot_threads(void)
591{
592 lockdep_assert_held(&watchdog_mutex);
593
594 if (!softlockup_threads_initialized)
595 return;
596
597 smpboot_update_cpumask_percpu_thread(&watchdog_threads,
598 &watchdog_allowed_mask);
599 __lockup_detector_cleanup();
600}
601
602/* Temporarily park all watchdog threads */
603static void softlockup_park_all_threads(void)
604{
605 cpumask_clear(&watchdog_allowed_mask);
606 softlockup_update_smpboot_threads();
607}
608
609/*
610 * Park threads which are not longer enabled and unpark threads which have
611 * been newly enabled.
612 */
613static void softlockup_update_threads(void)
614{
615 cpumask_copy(&watchdog_allowed_mask, &watchdog_cpumask);
616 softlockup_update_smpboot_threads();
617}
618
619static void softlockup_reconfigure_threads(bool enabled)
620{
621 softlockup_park_all_threads();
622 set_sample_period();
623 if (enabled)
624 softlockup_update_threads();
625}
626
627/*
628 * Create the watchdog thread infrastructure.
629 *
630 * The threads are not unparked as watchdog_allowed_mask is empty. When
631 * the threads are sucessfully initialized, take the proper locks and
632 * unpark the threads in the watchdog_cpumask if the watchdog is enabled.
633 */
634static __init void softlockup_init_threads(void)
635{
636 int ret;
637
638 /*
639 * If sysctl is off and watchdog got disabled on the command line,
640 * nothing to do here.
641 */
642 if (!IS_ENABLED(CONFIG_SYSCTL) &&
643 !(watchdog_enabled && watchdog_thresh))
644 return;
645
646 ret = smpboot_register_percpu_thread_cpumask(&watchdog_threads,
647 &watchdog_allowed_mask);
648 if (ret) {
649 pr_err("Failed to initialize soft lockup detector threads\n");
650 return;
651 }
652
653 mutex_lock(&watchdog_mutex);
654 softlockup_threads_initialized = true;
655 softlockup_reconfigure_threads(watchdog_enabled && watchdog_thresh);
656 mutex_unlock(&watchdog_mutex);
657}
658
587#else /* CONFIG_SOFTLOCKUP_DETECTOR */ 659#else /* CONFIG_SOFTLOCKUP_DETECTOR */
588static inline int watchdog_park_threads(void) { return 0; } 660static inline int watchdog_park_threads(void) { return 0; }
589static inline void watchdog_unpark_threads(void) { } 661static inline void watchdog_unpark_threads(void) { }
590static inline int watchdog_enable_all_cpus(void) { return 0; } 662static inline int watchdog_enable_all_cpus(void) { return 0; }
591static inline void watchdog_disable_all_cpus(void) { } 663static inline void watchdog_disable_all_cpus(void) { }
592static inline void set_sample_period(void) { } 664static inline void set_sample_period(void) { }
665static inline void softlockup_init_threads(void) { }
666static inline void softlockup_update_threads(void) { }
667static inline void softlockup_reconfigure_threads(bool enabled) { }
593#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */ 668#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */
594 669
595static void __lockup_detector_cleanup(void) 670static void __lockup_detector_cleanup(void)