diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-06-22 22:05:39 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-06-22 22:05:39 -0400 |
commit | 23dc00de78fbfea39b61aae2d261b621fee7853d (patch) | |
tree | 047ca618c7a40ad61fe71470a889d2871a0b0c4a | |
parent | ff2ebf3f75814bc45353013782ebeb1556adfc05 (diff) |
Fix printk_ratelimited()
printk_ratelimited was behind an #ifdef CONFIG_PRINTK, which we don't
define, so it was a complete noop - oops.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | include/linux/jiffies.h | 2 | ||||
-rw-r--r-- | include/linux/printk.h | 6 | ||||
-rw-r--r-- | include/linux/spinlock.h | 5 | ||||
-rw-r--r-- | linux/ratelimit.c | 69 |
4 files changed, 77 insertions, 5 deletions
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index fe928265..c3f3e1f2 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -43,6 +43,8 @@ (time_after_eq64(a, b) && \ time_before_eq64(a, c)) +#define time_is_before_jiffies(a) time_after(jiffies, a) + #define HZ 1000 static inline u64 jiffies_to_nsecs(const unsigned long j) diff --git a/include/linux/printk.h b/include/linux/printk.h index bc1619f7..df9c1920 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -5,6 +5,7 @@ #define pr_fmt(fmt) fmt #endif +#include <linux/compiler.h> #include <stdarg.h> #include <stdio.h> @@ -169,7 +170,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...) * ratelimited messages with local ratelimit_state, * no local ratelimit_state used in the !PRINTK case */ -#ifdef CONFIG_PRINTK #define printk_ratelimited(fmt, ...) \ ({ \ static DEFINE_RATELIMIT_STATE(_rs, \ @@ -179,10 +179,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...) if (__ratelimit(&_rs)) \ printk(fmt, ##__VA_ARGS__); \ }) -#else -#define printk_ratelimited(fmt, ...) \ - no_printk(fmt, ##__VA_ARGS__) -#endif #define pr_emerg_ratelimited(fmt, ...) \ printk_ratelimited(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index bd51188d..6c4a623c 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -15,6 +15,11 @@ static inline void raw_spin_lock_init(raw_spinlock_t *lock) pthread_mutex_init(&lock->lock, NULL); } +static inline bool raw_spin_trylock(raw_spinlock_t *lock) +{ + return !pthread_mutex_trylock(&lock->lock); +} + static inline void raw_spin_lock(raw_spinlock_t *lock) { pthread_mutex_lock(&lock->lock); diff --git a/linux/ratelimit.c b/linux/ratelimit.c new file mode 100644 index 00000000..21a6d6c8 --- /dev/null +++ b/linux/ratelimit.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ratelimit.c - Do something with rate limit. + * + * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> + * + * 2008-05-01 rewrite the function and use a ratelimit_state data struct as + * parameter. Now every user can use their own standalone ratelimit_state. + */ + +#include <linux/ratelimit.h> +#include <linux/jiffies.h> +#include <linux/export.h> + +/* + * __ratelimit - rate limiting + * @rs: ratelimit_state data + * @func: name of calling function + * + * This enforces a rate limit: not more than @rs->burst callbacks + * in every @rs->interval + * + * RETURNS: + * 0 means callbacks will be suppressed. + * 1 means go ahead and do it. + */ +int ___ratelimit(struct ratelimit_state *rs, const char *func) +{ + int ret; + + if (!rs->interval) + return 1; + + /* + * If we contend on this state's lock then almost + * by definition we are too busy to print a message, + * in addition to the one that will be printed by + * the entity that is holding the lock already: + */ + if (!raw_spin_trylock(&rs->lock)) + return 0; + + if (!rs->begin) + rs->begin = jiffies; + + if (time_is_before_jiffies(rs->begin + rs->interval)) { + if (rs->missed) { + if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) { + printk(KERN_WARNING + "%s: %d callbacks suppressed\n", + func, rs->missed); + rs->missed = 0; + } + } + rs->begin = jiffies; + rs->printed = 0; + } + if (rs->burst && rs->burst > rs->printed) { + rs->printed++; + ret = 1; + } else { + rs->missed++; + ret = 0; + } + raw_spin_unlock(&rs->lock); + + return ret; +} +EXPORT_SYMBOL(___ratelimit); |