aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/watchdog.c
diff options
context:
space:
mode:
authorUlrich Obergfell <uobergfe@redhat.com>2015-09-04 18:45:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-04 19:54:41 -0400
commit8c073d27d7ad293bf734cc8475689413afadab81 (patch)
tree335ed5a8c2b0e82cf6d3554d31cafc6dc4f77e48 /kernel/watchdog.c
parent81a4beef91ba4a9e8ad6054ca9933dff7e25ff28 (diff)
watchdog: introduce watchdog_suspend() and watchdog_resume()
This interface can be utilized to deactivate the hard and soft lockup detector temporarily. Callers are expected to minimize the duration of deactivation. Multiple deactivations are allowed to occur in parallel but should be rare in practice. [akpm@linux-foundation.org: remove unneeded static initialization] Signed-off-by: Ulrich Obergfell <uobergfe@redhat.com> Reviewed-by: Aaron Tomlin <atomlin@redhat.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Don Zickus <dzickus@redhat.com> Cc: Ulrich Obergfell <uobergfe@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: Stephane Eranian <eranian@google.com> Cc: Chris Metcalf <cmetcalf@ezchip.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Ingo Molnar <mingo@redhat.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.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 6c489e49c610..e6eb5b697212 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -67,6 +67,7 @@ unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
67#define for_each_watchdog_cpu(cpu) \ 67#define for_each_watchdog_cpu(cpu) \
68 for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask) 68 for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask)
69 69
70static int __read_mostly watchdog_suspended;
70static int __read_mostly watchdog_running; 71static int __read_mostly watchdog_running;
71static u64 __read_mostly sample_period; 72static u64 __read_mostly sample_period;
72 73
@@ -700,6 +701,50 @@ static void watchdog_unpark_threads(void)
700 put_online_cpus(); 701 put_online_cpus();
701} 702}
702 703
704/*
705 * Suspend the hard and soft lockup detector by parking the watchdog threads.
706 */
707int watchdog_suspend(void)
708{
709 int ret = 0;
710
711 mutex_lock(&watchdog_proc_mutex);
712 /*
713 * Multiple suspend requests can be active in parallel (counted by
714 * the 'watchdog_suspended' variable). If the watchdog threads are
715 * running, the first caller takes care that they will be parked.
716 * The state of 'watchdog_running' cannot change while a suspend
717 * request is active (see related changes in 'proc' handlers).
718 */
719 if (watchdog_running && !watchdog_suspended)
720 ret = watchdog_park_threads();
721
722 if (ret == 0)
723 watchdog_suspended++;
724
725 mutex_unlock(&watchdog_proc_mutex);
726
727 return ret;
728}
729
730/*
731 * Resume the hard and soft lockup detector by unparking the watchdog threads.
732 */
733void watchdog_resume(void)
734{
735 mutex_lock(&watchdog_proc_mutex);
736
737 watchdog_suspended--;
738 /*
739 * The watchdog threads are unparked if they were previously running
740 * and if there is no more active suspend request.
741 */
742 if (watchdog_running && !watchdog_suspended)
743 watchdog_unpark_threads();
744
745 mutex_unlock(&watchdog_proc_mutex);
746}
747
703static void restart_watchdog_hrtimer(void *info) 748static void restart_watchdog_hrtimer(void *info)
704{ 749{
705 struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer); 750 struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer);
@@ -818,6 +863,12 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
818 863
819 mutex_lock(&watchdog_proc_mutex); 864 mutex_lock(&watchdog_proc_mutex);
820 865
866 if (watchdog_suspended) {
867 /* no parameter changes allowed while watchdog is suspended */
868 err = -EAGAIN;
869 goto out;
870 }
871
821 /* 872 /*
822 * If the parameter is being read return the state of the corresponding 873 * If the parameter is being read return the state of the corresponding
823 * bit(s) in 'watchdog_enabled', else update 'watchdog_enabled' and the 874 * bit(s) in 'watchdog_enabled', else update 'watchdog_enabled' and the
@@ -903,6 +954,12 @@ int proc_watchdog_thresh(struct ctl_table *table, int write,
903 954
904 mutex_lock(&watchdog_proc_mutex); 955 mutex_lock(&watchdog_proc_mutex);
905 956
957 if (watchdog_suspended) {
958 /* no parameter changes allowed while watchdog is suspended */
959 err = -EAGAIN;
960 goto out;
961 }
962
906 old = ACCESS_ONCE(watchdog_thresh); 963 old = ACCESS_ONCE(watchdog_thresh);
907 err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 964 err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
908 965
@@ -934,6 +991,13 @@ int proc_watchdog_cpumask(struct ctl_table *table, int write,
934 int err; 991 int err;
935 992
936 mutex_lock(&watchdog_proc_mutex); 993 mutex_lock(&watchdog_proc_mutex);
994
995 if (watchdog_suspended) {
996 /* no parameter changes allowed while watchdog is suspended */
997 err = -EAGAIN;
998 goto out;
999 }
1000
937 err = proc_do_large_bitmap(table, write, buffer, lenp, ppos); 1001 err = proc_do_large_bitmap(table, write, buffer, lenp, ppos);
938 if (!err && write) { 1002 if (!err && write) {
939 /* Remove impossible cpus to keep sysctl output cleaner. */ 1003 /* Remove impossible cpus to keep sysctl output cleaner. */
@@ -951,6 +1015,7 @@ int proc_watchdog_cpumask(struct ctl_table *table, int write,
951 pr_err("cpumask update failed\n"); 1015 pr_err("cpumask update failed\n");
952 } 1016 }
953 } 1017 }
1018out:
954 mutex_unlock(&watchdog_proc_mutex); 1019 mutex_unlock(&watchdog_proc_mutex);
955 return err; 1020 return err;
956} 1021}