Commit e31d6883 authored by Thomas Gleixner's avatar Thomas Gleixner

watchdog/core, powerpc: Lock cpus across reconfiguration

Instead of dropping the cpu hotplug lock after stopping NMI watchdog and
threads and reaquiring for restart, the code and the protection rules
become more obvious when holding cpu hotplug lock across the full
reconfiguration.
Suggested-by: default avatarLinus Torvalds <torvalds@linuxfoundation.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: linuxppc-dev@lists.ozlabs.org
Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1710022105570.2114@nanos
parent 6b9dc480
...@@ -359,21 +359,17 @@ void watchdog_nmi_stop(void) ...@@ -359,21 +359,17 @@ void watchdog_nmi_stop(void)
{ {
int cpu; int cpu;
cpus_read_lock();
for_each_cpu(cpu, &wd_cpus_enabled) for_each_cpu(cpu, &wd_cpus_enabled)
stop_wd_on_cpu(cpu); stop_wd_on_cpu(cpu);
cpus_read_unlock();
} }
void watchdog_nmi_start(void) void watchdog_nmi_start(void)
{ {
int cpu; int cpu;
cpus_read_lock();
watchdog_calc_timeouts(); watchdog_calc_timeouts();
for_each_cpu_and(cpu, cpu_online_mask, &watchdog_cpumask) for_each_cpu_and(cpu, cpu_online_mask, &watchdog_cpumask)
start_wd_on_cpu(cpu); start_wd_on_cpu(cpu);
cpus_read_unlock();
} }
/* /*
......
...@@ -351,7 +351,7 @@ void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread ...@@ -351,7 +351,7 @@ void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread
static struct cpumask tmp; static struct cpumask tmp;
unsigned int cpu; unsigned int cpu;
get_online_cpus(); lockdep_assert_cpus_held();
mutex_lock(&smpboot_threads_lock); mutex_lock(&smpboot_threads_lock);
/* Park threads that were exclusively enabled on the old mask. */ /* Park threads that were exclusively enabled on the old mask. */
...@@ -367,7 +367,6 @@ void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread ...@@ -367,7 +367,6 @@ void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread
cpumask_copy(old, new); cpumask_copy(old, new);
mutex_unlock(&smpboot_threads_lock); mutex_unlock(&smpboot_threads_lock);
put_online_cpus();
} }
static DEFINE_PER_CPU(atomic_t, cpu_hotplug_state) = ATOMIC_INIT(CPU_POST_DEAD); static DEFINE_PER_CPU(atomic_t, cpu_hotplug_state) = ATOMIC_INIT(CPU_POST_DEAD);
......
...@@ -535,7 +535,6 @@ static void softlockup_update_smpboot_threads(void) ...@@ -535,7 +535,6 @@ static void softlockup_update_smpboot_threads(void)
smpboot_update_cpumask_percpu_thread(&watchdog_threads, smpboot_update_cpumask_percpu_thread(&watchdog_threads,
&watchdog_allowed_mask); &watchdog_allowed_mask);
__lockup_detector_cleanup();
} }
/* Temporarily park all watchdog threads */ /* Temporarily park all watchdog threads */
...@@ -554,6 +553,7 @@ static void softlockup_unpark_threads(void) ...@@ -554,6 +553,7 @@ static void softlockup_unpark_threads(void)
static void softlockup_reconfigure_threads(void) static void softlockup_reconfigure_threads(void)
{ {
cpus_read_lock();
watchdog_nmi_stop(); watchdog_nmi_stop();
softlockup_park_all_threads(); softlockup_park_all_threads();
set_sample_period(); set_sample_period();
...@@ -561,6 +561,12 @@ static void softlockup_reconfigure_threads(void) ...@@ -561,6 +561,12 @@ static void softlockup_reconfigure_threads(void)
if (watchdog_enabled && watchdog_thresh) if (watchdog_enabled && watchdog_thresh)
softlockup_unpark_threads(); softlockup_unpark_threads();
watchdog_nmi_start(); watchdog_nmi_start();
cpus_read_unlock();
/*
* Must be called outside the cpus locked section to prevent
* recursive locking in the perf code.
*/
__lockup_detector_cleanup();
} }
/* /*
...@@ -605,9 +611,11 @@ static inline void watchdog_disable_all_cpus(void) { } ...@@ -605,9 +611,11 @@ static inline void watchdog_disable_all_cpus(void) { }
static inline void softlockup_init_threads(void) { } static inline void softlockup_init_threads(void) { }
static void softlockup_reconfigure_threads(void) static void softlockup_reconfigure_threads(void)
{ {
cpus_read_lock();
watchdog_nmi_stop(); watchdog_nmi_stop();
lockup_detector_update_enable(); lockup_detector_update_enable();
watchdog_nmi_start(); watchdog_nmi_start();
cpus_read_unlock();
} }
#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */ #endif /* !CONFIG_SOFTLOCKUP_DETECTOR */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment