diff options
Diffstat (limited to 'include/linux/ratelimit.h')
| -rw-r--r-- | include/linux/ratelimit.h | 93 |
1 files changed, 62 insertions, 31 deletions
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h index 0a260d8a18bf..7aaad158ee37 100644 --- a/include/linux/ratelimit.h +++ b/include/linux/ratelimit.h @@ -1,50 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_RATELIMIT_H #define _LINUX_RATELIMIT_H -#include <linux/param.h> +#include <linux/ratelimit_types.h> +#include <linux/sched.h> #include <linux/spinlock.h> -#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) -#define DEFAULT_RATELIMIT_BURST 10 +static inline void ratelimit_state_init(struct ratelimit_state *rs, + int interval, int burst) +{ + memset(rs, 0, sizeof(*rs)); -struct ratelimit_state { - raw_spinlock_t lock; /* protect the state */ + raw_spin_lock_init(&rs->lock); + rs->interval = interval; + rs->burst = burst; +} - int interval; - int burst; - int printed; - int missed; - unsigned long begin; -}; +static inline void ratelimit_default_init(struct ratelimit_state *rs) +{ + return ratelimit_state_init(rs, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); +} -#define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init) \ - \ - struct ratelimit_state name = { \ - .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ - .interval = interval_init, \ - .burst = burst_init, \ - } +static inline void ratelimit_state_inc_miss(struct ratelimit_state *rs) +{ + atomic_inc(&rs->missed); +} -static inline void ratelimit_state_init(struct ratelimit_state *rs, - int interval, int burst) +static inline int ratelimit_state_get_miss(struct ratelimit_state *rs) { - raw_spin_lock_init(&rs->lock); - rs->interval = interval; - rs->burst = burst; - rs->printed = 0; - rs->missed = 0; - rs->begin = 0; + return atomic_read(&rs->missed); } -extern struct ratelimit_state printk_ratelimit_state; +static inline int ratelimit_state_reset_miss(struct ratelimit_state *rs) +{ + return atomic_xchg_relaxed(&rs->missed, 0); +} -extern int ___ratelimit(struct ratelimit_state *rs, const char *func); -#define __ratelimit(state) ___ratelimit(state, __func__) +static inline void ratelimit_state_reset_interval(struct ratelimit_state *rs, int interval_init) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&rs->lock, flags); + rs->interval = interval_init; + rs->flags &= ~RATELIMIT_INITIALIZED; + atomic_set(&rs->rs_n_left, rs->burst); + ratelimit_state_reset_miss(rs); + raw_spin_unlock_irqrestore(&rs->lock, flags); +} + +static inline void ratelimit_state_exit(struct ratelimit_state *rs) +{ + int m; + + if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) + return; + + m = ratelimit_state_reset_miss(rs); + if (m) + pr_warn("%s: %d output lines suppressed due to ratelimiting\n", current->comm, m); +} + +static inline void +ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags) +{ + rs->flags = flags; +} + +extern struct ratelimit_state printk_ratelimit_state; #ifdef CONFIG_PRINTK -#define WARN_ON_RATELIMIT(condition, state) \ - WARN_ON((condition) && __ratelimit(state)) +#define WARN_ON_RATELIMIT(condition, state) ({ \ + bool __rtn_cond = !!(condition); \ + WARN_ON(__rtn_cond && __ratelimit(state)); \ + __rtn_cond; \ +}) #define WARN_RATELIMIT(condition, format, ...) \ ({ \ |
