Once taint flag is set it's never cleared. Following taint could be detected only via parsing kernel log messages which are different for each occasion. For repeatable taints like TAINT_MACHINE_CHECK, TAINT_BAD_PAGE, TAINT_DIE, TAINT_WARN, TAINT_LOCKUP it would be good to know count to see their rate. This patch adds sysctl with vector of counters. One for each taint flag. Counters are non-atomic in favor of simplicity. Exact count doesn't matter. Writing vector of zeroes resets counters. This is useful for detecting frequent problems with automatic monitoring. Signed-off-by: Konstantin Khlebnikov <khlebnikov@xxxxxxxxxxxxxx> --- include/linux/kernel.h | 1 + kernel/panic.c | 2 ++ kernel/sysctl.c | 9 +++++++++ 3 files changed, 12 insertions(+) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e8a6808e4f2f..900d02167bbd 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -604,6 +604,7 @@ struct taint_flag { }; extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT]; +extern int sysctl_nr_taints[TAINT_FLAGS_COUNT]; extern const char hex_asc[]; #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] diff --git a/kernel/panic.c b/kernel/panic.c index d7750a45ca8d..a3df00ebcba2 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -39,6 +39,7 @@ int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE; static unsigned long tainted_mask = IS_ENABLED(CONFIG_GCC_PLUGIN_RANDSTRUCT) ? (1 << TAINT_RANDSTRUCT) : 0; +int sysctl_nr_taints[TAINT_FLAGS_COUNT]; static int pause_on_oops; static int pause_on_oops_flag; static DEFINE_SPINLOCK(pause_on_oops_lock); @@ -434,6 +435,7 @@ void add_taint(unsigned flag, enum lockdep_ok lockdep_ok) pr_warn("Disabling lock debugging due to kernel taint\n"); set_bit(flag, &tainted_mask); + sysctl_nr_taints[flag]++; } EXPORT_SYMBOL(add_taint); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b6f2f35d0bcf..5d9727556cef 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -553,6 +553,15 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = proc_taint, }, + { + .procname = "nr_taints", + .data = &sysctl_nr_taints, + .maxlen = sizeof(sysctl_nr_taints), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ZERO, + }, { .procname = "sysctl_writes_strict", .data = &sysctl_writes_strict,