aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/watchdog.c
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@ezchip.com>2015-06-24 19:55:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-24 20:49:40 -0400
commitfe4ba3c34352b7e8068b7f18eb233444aed17011 (patch)
treed4b34e0d809e784c59eea68cb27c16dc795e371b /kernel/watchdog.c
parentb5242e98c1cb834feb1e84026f09a4796b49eb4d (diff)
watchdog: add watchdog_cpumask sysctl to assist nohz
Change the default behavior of watchdog so it only runs on the housekeeping cores when nohz_full is enabled at build and boot time. Allow modifying the set of cores the watchdog is currently running on with a new kernel.watchdog_cpumask sysctl. In the current system, the watchdog subsystem runs a periodic timer that schedules the watchdog kthread to run. However, nohz_full cores are designed to allow userspace application code running on those cores to have 100% access to the CPU. So the watchdog system prevents the nohz_full application code from being able to run the way it wants to, thus the motivation to suppress the watchdog on nohz_full cores, which this patchset provides by default. However, if we disable the watchdog globally, then the housekeeping cores can't benefit from the watchdog functionality. So we allow disabling it only on some cores. See Documentation/lockup-watchdogs.txt for more information. [jhubbard@nvidia.com: fix a watchdog crash in some configurations] Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> Acked-by: Don Zickus <dzickus@redhat.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Ulrich Obergfell <uobergfe@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: John Hubbard <jhubbard@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/watchdog.c')
-rw-r--r--kernel/watchdog.c67
1 files changed, 62 insertions, 5 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 581a68a04c64..a6ffa43f2993 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -19,6 +19,7 @@
19#include <linux/sysctl.h> 19#include <linux/sysctl.h>
20#include <linux/smpboot.h> 20#include <linux/smpboot.h>
21#include <linux/sched/rt.h> 21#include <linux/sched/rt.h>
22#include <linux/tick.h>
22 23
23#include <asm/irq_regs.h> 24#include <asm/irq_regs.h>
24#include <linux/kvm_para.h> 25#include <linux/kvm_para.h>
@@ -58,6 +59,12 @@ int __read_mostly sysctl_softlockup_all_cpu_backtrace;
58#else 59#else
59#define sysctl_softlockup_all_cpu_backtrace 0 60#define sysctl_softlockup_all_cpu_backtrace 0
60#endif 61#endif
62static struct cpumask watchdog_cpumask __read_mostly;
63unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
64
65/* Helper for online, unparked cpus. */
66#define for_each_watchdog_cpu(cpu) \
67 for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask)
61 68
62static int __read_mostly watchdog_running; 69static int __read_mostly watchdog_running;
63static u64 __read_mostly sample_period; 70static u64 __read_mostly sample_period;
@@ -207,7 +214,7 @@ void touch_all_softlockup_watchdogs(void)
207 * do we care if a 0 races with a timestamp? 214 * do we care if a 0 races with a timestamp?
208 * all it means is the softlock check starts one cycle later 215 * all it means is the softlock check starts one cycle later
209 */ 216 */
210 for_each_online_cpu(cpu) 217 for_each_watchdog_cpu(cpu)
211 per_cpu(watchdog_touch_ts, cpu) = 0; 218 per_cpu(watchdog_touch_ts, cpu) = 0;
212} 219}
213 220
@@ -616,7 +623,7 @@ void watchdog_nmi_enable_all(void)
616 goto unlock; 623 goto unlock;
617 624
618 get_online_cpus(); 625 get_online_cpus();
619 for_each_online_cpu(cpu) 626 for_each_watchdog_cpu(cpu)
620 watchdog_nmi_enable(cpu); 627 watchdog_nmi_enable(cpu);
621 put_online_cpus(); 628 put_online_cpus();
622 629
@@ -634,7 +641,7 @@ void watchdog_nmi_disable_all(void)
634 goto unlock; 641 goto unlock;
635 642
636 get_online_cpus(); 643 get_online_cpus();
637 for_each_online_cpu(cpu) 644 for_each_watchdog_cpu(cpu)
638 watchdog_nmi_disable(cpu); 645 watchdog_nmi_disable(cpu);
639 put_online_cpus(); 646 put_online_cpus();
640 647
@@ -696,7 +703,7 @@ static void update_watchdog_all_cpus(void)
696 int cpu; 703 int cpu;
697 704
698 get_online_cpus(); 705 get_online_cpus();
699 for_each_online_cpu(cpu) 706 for_each_watchdog_cpu(cpu)
700 update_watchdog(cpu); 707 update_watchdog(cpu);
701 put_online_cpus(); 708 put_online_cpus();
702} 709}
@@ -709,8 +716,12 @@ static int watchdog_enable_all_cpus(void)
709 err = smpboot_register_percpu_thread(&watchdog_threads); 716 err = smpboot_register_percpu_thread(&watchdog_threads);
710 if (err) 717 if (err)
711 pr_err("Failed to create watchdog threads, disabled\n"); 718 pr_err("Failed to create watchdog threads, disabled\n");
712 else 719 else {
720 if (smpboot_update_cpumask_percpu_thread(
721 &watchdog_threads, &watchdog_cpumask))
722 pr_err("Failed to set cpumask for watchdog threads\n");
713 watchdog_running = 1; 723 watchdog_running = 1;
724 }
714 } else { 725 } else {
715 /* 726 /*
716 * Enable/disable the lockup detectors or 727 * Enable/disable the lockup detectors or
@@ -879,12 +890,58 @@ out:
879 mutex_unlock(&watchdog_proc_mutex); 890 mutex_unlock(&watchdog_proc_mutex);
880 return err; 891 return err;
881} 892}
893
894/*
895 * The cpumask is the mask of possible cpus that the watchdog can run
896 * on, not the mask of cpus it is actually running on. This allows the
897 * user to specify a mask that will include cpus that have not yet
898 * been brought online, if desired.
899 */
900int proc_watchdog_cpumask(struct ctl_table *table, int write,
901 void __user *buffer, size_t *lenp, loff_t *ppos)
902{
903 int err;
904
905 mutex_lock(&watchdog_proc_mutex);
906 err = proc_do_large_bitmap(table, write, buffer, lenp, ppos);
907 if (!err && write) {
908 /* Remove impossible cpus to keep sysctl output cleaner. */
909 cpumask_and(&watchdog_cpumask, &watchdog_cpumask,
910 cpu_possible_mask);
911
912 if (watchdog_running) {
913 /*
914 * Failure would be due to being unable to allocate
915 * a temporary cpumask, so we are likely not in a
916 * position to do much else to make things better.
917 */
918 if (smpboot_update_cpumask_percpu_thread(
919 &watchdog_threads, &watchdog_cpumask) != 0)
920 pr_err("cpumask update failed\n");
921 }
922 }
923 mutex_unlock(&watchdog_proc_mutex);
924 return err;
925}
926
882#endif /* CONFIG_SYSCTL */ 927#endif /* CONFIG_SYSCTL */
883 928
884void __init lockup_detector_init(void) 929void __init lockup_detector_init(void)
885{ 930{
886 set_sample_period(); 931 set_sample_period();
887 932
933#ifdef CONFIG_NO_HZ_FULL
934 if (tick_nohz_full_enabled()) {
935 if (!cpumask_empty(tick_nohz_full_mask))
936 pr_info("Disabling watchdog on nohz_full cores by default\n");
937 cpumask_andnot(&watchdog_cpumask, cpu_possible_mask,
938 tick_nohz_full_mask);
939 } else
940 cpumask_copy(&watchdog_cpumask, cpu_possible_mask);
941#else
942 cpumask_copy(&watchdog_cpumask, cpu_possible_mask);
943#endif
944
888 if (watchdog_enabled) 945 if (watchdog_enabled)
889 watchdog_enable_all_cpus(); 946 watchdog_enable_all_cpus();
890} 947}