aboutsummaryrefslogtreecommitdiffstats
path: root/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch
diff options
context:
space:
mode:
Diffstat (limited to 'features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch')
-rw-r--r--features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch104
1 files changed, 104 insertions, 0 deletions
diff --git a/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch b/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch
new file mode 100644
index 00000000..63053deb
--- /dev/null
+++ b/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch
@@ -0,0 +1,104 @@
+From fbda05a6df0125f733e0e28a3e0ae60bb6765d51 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Wed, 16 Dec 2020 12:22:57 -0500
+Subject: [PATCH 2/3] clear_warn_once: bind a timer to written reset value
+
+Existing documentation has a write of "1" to clear/reset all the
+WARN_ONCE and similar to the as-booted state, so they can possibly
+be re-triggered again during debugging/testing.
+
+But having them auto-reset once a day, or once a week, might shed
+valuable information to a sysadmin on what the system is doing while
+trying to debug an issue.
+
+Here we extend the existing debugfs variable to bind a timer to the
+written value N, so that it will reset every N minutes, for N>1.
+Writing a zero will clear any previously set timer value.
+
+The pre-existing behaviour of writing N=1 will do a one-shot clear.
+
+Link: https://lore.kernel.org/r/20201126063029.2030-1-paul.gortmaker@windriver.com
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ .../admin-guide/clearing-warn-once.rst | 9 ++++++
+ kernel/panic.c | 32 +++++++++++++++++++
+ 2 files changed, 41 insertions(+)
+
+diff --git a/Documentation/admin-guide/clearing-warn-once.rst b/Documentation/admin-guide/clearing-warn-once.rst
+index 211fd926cf00..8d058bbc0859 100644
+--- a/Documentation/admin-guide/clearing-warn-once.rst
++++ b/Documentation/admin-guide/clearing-warn-once.rst
+@@ -7,3 +7,12 @@ echo 1 > /sys/kernel/debug/clear_warn_once
+
+ clears the state and allows the warnings to print once again.
+ This can be useful after test suite runs to reproduce problems.
++
++Values greater than one set a timer for a periodic state reset; e.g.
++
++echo 60 > /sys/kernel/debug/clear_warn_once
++
++will establish an hourly state reset, effectively turning WARN_ONCE
++into a long period rate-limited warning.
++
++Writing a value of zero (or one) will remove any previously set timer.
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 53088219d7df..e3a462e39062 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -636,6 +636,7 @@ EXPORT_SYMBOL(__warn_printk);
+ /* Support resetting WARN*_ONCE state */
+
+ static u64 clear_warn_once;
++static bool warn_timer_active;
+
+ static void do_clear_warn_once(void)
+ {
+@@ -643,6 +644,14 @@ static void do_clear_warn_once(void)
+ memset(__start_once, 0, __end_once - __start_once);
+ }
+
++static void timer_warn_once(struct timer_list *timer)
++{
++ do_clear_warn_once();
++ timer->expires = jiffies + clear_warn_once * HZ * 60;
++ add_timer(timer);
++}
++static DEFINE_TIMER(warn_reset_timer, timer_warn_once);
++
+ static int warn_once_get(void *data, u64 *val)
+ {
+ *val = clear_warn_once;
+@@ -653,6 +662,29 @@ static int warn_once_set(void *data, u64 val)
+ {
+ clear_warn_once = val;
+
++ if (val > 1) { /* set/reset new timer */
++ unsigned long expires = jiffies + val * HZ * 60;
++
++ if (warn_timer_active) {
++ mod_timer(&warn_reset_timer, expires);
++ } else {
++ warn_timer_active = 1;
++ warn_reset_timer.expires = expires;
++ add_timer(&warn_reset_timer);
++ }
++ return 0;
++ }
++
++ if (warn_timer_active) {
++ del_timer_sync(&warn_reset_timer);
++ warn_timer_active = 0;
++ }
++ clear_warn_once = 0;
++
++ if (val == 0) /* cleared timer, we are done */
++ return 0;
++
++ /* Getting here means val == 1 ---> so clear existing data */
+ do_clear_warn_once();
+ return 0;
+ }
+--
+2.19.1
+