Skip to content

Commit b1fca27

Browse files
Andi Kleentorvalds
authored andcommitted
kernel debug: support resetting WARN*_ONCE
I like _ONCE warnings because it's guaranteed that they don't flood the log. During testing I find it useful to reset the state of the once warnings, so that I can rerun tests and see if they trigger again, or can guarantee that a test run always hits the same warnings. This patch adds a debugfs interface to reset all the _ONCE warnings so that they appear again: echo 1 > /sys/kernel/debug/clear_warn_once This is implemented by putting all the warning booleans into a special section, and clearing it. [[email protected]: coding-style fixes] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Andi Kleen <[email protected]> Tested-by: Michael Ellerman <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent fb6cc4a commit b1fca27

File tree

5 files changed

+42
-3
lines changed

5 files changed

+42
-3
lines changed

Documentation/clearing-warn-once.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
WARN_ONCE / WARN_ON_ONCE only print a warning once.
3+
4+
echo 1 > /sys/kernel/debug/clear_warn_once
5+
6+
clears the state and allows the warnings to print once again.
7+
This can be useful after test suite runs to reproduce problems.

include/asm-generic/bug.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
130130

131131
#ifndef WARN_ON_ONCE
132132
#define WARN_ON_ONCE(condition) ({ \
133-
static bool __section(.data.unlikely) __warned; \
133+
static bool __section(.data.once) __warned; \
134134
int __ret_warn_once = !!(condition); \
135135
\
136136
if (unlikely(__ret_warn_once && !__warned)) { \
@@ -142,7 +142,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
142142
#endif
143143

144144
#define WARN_ONCE(condition, format...) ({ \
145-
static bool __section(.data.unlikely) __warned; \
145+
static bool __section(.data.once) __warned; \
146146
int __ret_warn_once = !!(condition); \
147147
\
148148
if (unlikely(__ret_warn_once && !__warned)) { \
@@ -153,7 +153,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
153153
})
154154

155155
#define WARN_TAINT_ONCE(condition, taint, format...) ({ \
156-
static bool __section(.data.unlikely) __warned; \
156+
static bool __section(.data.once) __warned; \
157157
int __ret_warn_once = !!(condition); \
158158
\
159159
if (unlikely(__ret_warn_once && !__warned)) { \

include/asm-generic/sections.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern char __entry_text_start[], __entry_text_end[];
4444
extern char __start_rodata[], __end_rodata[];
4545
extern char __irqentry_text_start[], __irqentry_text_end[];
4646
extern char __softirqentry_text_start[], __softirqentry_text_end[];
47+
extern char __start_once[], __end_once[];
4748

4849
/* Start and end of .ctors section - used for constructor calls. */
4950
extern char __ctors_start[], __ctors_end[];

include/asm-generic/vmlinux.lds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@
223223
MEM_KEEP(init.data) \
224224
MEM_KEEP(exit.data) \
225225
*(.data.unlikely) \
226+
VMLINUX_SYMBOL(__start_once) = .; \
227+
*(.data.once) \
228+
VMLINUX_SYMBOL(__end_once) = .; \
226229
STRUCT_ALIGN(); \
227230
*(__tracepoints) \
228231
/* implement dynamic printk debug */ \

kernel/panic.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <linux/console.h>
2828
#include <linux/bug.h>
2929
#include <linux/ratelimit.h>
30+
#include <linux/debugfs.h>
31+
#include <asm/sections.h>
3032

3133
#define PANIC_TIMER_STEP 100
3234
#define PANIC_BLINK_SPD 18
@@ -587,6 +589,32 @@ void warn_slowpath_null(const char *file, int line)
587589
EXPORT_SYMBOL(warn_slowpath_null);
588590
#endif
589591

592+
#ifdef CONFIG_BUG
593+
594+
/* Support resetting WARN*_ONCE state */
595+
596+
static int clear_warn_once_set(void *data, u64 val)
597+
{
598+
memset(__start_once, 0, __end_once - __start_once);
599+
return 0;
600+
}
601+
602+
DEFINE_SIMPLE_ATTRIBUTE(clear_warn_once_fops,
603+
NULL,
604+
clear_warn_once_set,
605+
"%lld\n");
606+
607+
static __init int register_warn_debugfs(void)
608+
{
609+
/* Don't care about failure */
610+
debugfs_create_file("clear_warn_once", 0644, NULL,
611+
NULL, &clear_warn_once_fops);
612+
return 0;
613+
}
614+
615+
device_initcall(register_warn_debugfs);
616+
#endif
617+
590618
#ifdef CONFIG_CC_STACKPROTECTOR
591619

592620
/*

0 commit comments

Comments
 (0)