include/linux/printk.h | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 696a56be7d3e..ae98c388a377 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -316,31 +316,23 @@ extern asmlinkage void dump_stack(void) __cold; /* * Print a one-time message (analogous to WARN_ONCE() et al): + * + * "once" here is a misnomer. It's shorthand for "at most once a minute". */ - #ifdef CONFIG_PRINTK -#define printk_once(fmt, ...) \ -({ \ - static bool __print_once __read_mostly; \ - bool __ret_print_once = !__print_once; \ - \ - if (!__print_once) { \ - __print_once = true; \ - printk(fmt, ##__VA_ARGS__); \ - } \ - unlikely(__ret_print_once); \ -}) -#define printk_deferred_once(fmt, ...) \ -({ \ - static bool __print_once __read_mostly; \ - bool __ret_print_once = !__print_once; \ - \ - if (!__print_once) { \ - __print_once = true; \ - printk_deferred(fmt, ##__VA_ARGS__); \ - } \ - unlikely(__ret_print_once); \ -}) + +#define do_just_once(stmt) ({ \ + static DEFINE_RATELIMIT_STATE(_rs, HZ*60, 1); \ + bool __do_it = __ratelimit(&_rs); \ + if (unlikely(__do_it)) \ + stmt; \ + unlikely(__do_it); }) + +#define printk_once(fmt, ...) \ + do_just_once(printk(fmt, ##__VA_ARGS__)) +#define printk_deferred_once(fmt, ...) \ + do_just_once(printk_deferred(fmt, ##__VA_ARGS__)) + #else #define printk_once(fmt, ...) \ no_printk(fmt, ##__VA_ARGS__)