From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756311AbcHBUki (ORCPT ); Tue, 2 Aug 2016 16:40:38 -0400 Received: from mga09.intel.com ([134.134.136.24]:11690 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753369AbcHBUkO (ORCPT ); Tue, 2 Aug 2016 16:40:14 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,462,1464678000"; d="scan'208";a="858501707" From: Andi Kleen To: akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org, Andi Kleen Subject: [PATCH] Support resetting WARN*_ONCE Date: Tue, 2 Aug 2016 13:40:05 -0700 Message-Id: <1470170405-21530-1-git-send-email-andi@firstfloor.org> X-Mailer: git-send-email 2.5.5 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andi Kleen WARN*_ONCE warnings only appear once. 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 flags into a special section, and clearing it. Signed-off-by: Andi Kleen --- include/asm-generic/bug.h | 6 +++--- include/asm-generic/sections.h | 1 + include/asm-generic/vmlinux.lds.h | 3 +++ kernel/panic.c | 24 ++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 6f96247226a4..4dae133b51c9 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -113,7 +113,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint, }) #define WARN_ON_ONCE(condition) ({ \ - static bool __section(.data.unlikely) __warned; \ + static bool __section(.data.once) __warned; \ int __ret_warn_once = !!(condition); \ \ if (unlikely(__ret_warn_once && !__warned)) { \ @@ -124,7 +124,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint, }) #define WARN_ONCE(condition, format...) ({ \ - static bool __section(.data.unlikely) __warned; \ + static bool __section(.data.once) __warned; \ int __ret_warn_once = !!(condition); \ \ if (unlikely(__ret_warn_once && !__warned)) { \ @@ -135,7 +135,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint, }) #define WARN_TAINT_ONCE(condition, taint, format...) ({ \ - static bool __section(.data.unlikely) __warned; \ + static bool __section(.data.once) __warned; \ int __ret_warn_once = !!(condition); \ \ if (unlikely(__ret_warn_once && !__warned)) { \ diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index af0254c09424..0e9826a4acab 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -36,6 +36,7 @@ extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[]; extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __entry_text_start[], __entry_text_end[]; extern char __start_rodata[], __end_rodata[]; +extern char __start_once[], __end_once[]; /* Start and end of .ctors section - used for constructor calls. */ extern char __ctors_start[], __ctors_end[]; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 6a67ab94b553..4b8d43b7c07f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -204,6 +204,9 @@ MEM_KEEP(init.data) \ MEM_KEEP(exit.data) \ *(.data.unlikely) \ + VMLINUX_SYMBOL(__start_once) = .; \ + *(.data.once) \ + VMLINUX_SYMBOL(__end_once) = .; \ STRUCT_ALIGN(); \ *(__tracepoints) \ /* implement dynamic printk debug */ \ diff --git a/kernel/panic.c b/kernel/panic.c index 8aa74497cc5a..4f52356f1562 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -25,6 +25,7 @@ #include #include #include +#include #define PANIC_TIMER_STEP 100 #define PANIC_BLINK_SPD 18 @@ -553,6 +554,29 @@ void warn_slowpath_null(const char *file, int line) EXPORT_SYMBOL(warn_slowpath_null); #endif +/* Support resetting WARN*_ONCE state */ + +static int clear_warn_once_set(void *data, u64 val) +{ + memset(__start_once, 0, __end_once - __start_once); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(clear_warn_once_fops, + NULL, + clear_warn_once_set, + "%lld\n"); + +static __init int register_warn_debugfs(void) +{ + /* Don't care about failure */ + debugfs_create_file("clear_warn_once", 0644, NULL, + NULL, &clear_warn_once_fops); + return 0; +} + +__initcall(register_warn_debugfs); + #ifdef CONFIG_CC_STACKPROTECTOR /* -- 2.5.5