xref: /linux/include/linux/ratelimit.h (revision 97851c601636a0e40f8237b83a6b70fc5e231e0c)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_RATELIMIT_H
3 #define _LINUX_RATELIMIT_H
4 
5 #include <linux/ratelimit_types.h>
6 #include <linux/sched.h>
7 #include <linux/spinlock.h>
8 
ratelimit_state_init(struct ratelimit_state * rs,int interval,int burst)9 static inline void ratelimit_state_init(struct ratelimit_state *rs,
10 					int interval, int burst)
11 {
12 	memset(rs, 0, sizeof(*rs));
13 
14 	raw_spin_lock_init(&rs->lock);
15 	rs->interval	= interval;
16 	rs->burst	= burst;
17 }
18 
ratelimit_default_init(struct ratelimit_state * rs)19 static inline void ratelimit_default_init(struct ratelimit_state *rs)
20 {
21 	return ratelimit_state_init(rs, DEFAULT_RATELIMIT_INTERVAL,
22 					DEFAULT_RATELIMIT_BURST);
23 }
24 
ratelimit_state_inc_miss(struct ratelimit_state * rs)25 static inline void ratelimit_state_inc_miss(struct ratelimit_state *rs)
26 {
27 	atomic_inc(&rs->missed);
28 }
29 
ratelimit_state_get_miss(struct ratelimit_state * rs)30 static inline int ratelimit_state_get_miss(struct ratelimit_state *rs)
31 {
32 	return atomic_read(&rs->missed);
33 }
34 
ratelimit_state_reset_miss(struct ratelimit_state * rs)35 static inline int ratelimit_state_reset_miss(struct ratelimit_state *rs)
36 {
37 	return atomic_xchg_relaxed(&rs->missed, 0);
38 }
39 
ratelimit_state_reset_interval(struct ratelimit_state * rs,int interval_init)40 static inline void ratelimit_state_reset_interval(struct ratelimit_state *rs, int interval_init)
41 {
42 	unsigned long flags;
43 
44 	raw_spin_lock_irqsave(&rs->lock, flags);
45 	rs->interval = interval_init;
46 	rs->flags &= ~RATELIMIT_INITIALIZED;
47 	atomic_set(&rs->rs_n_left, rs->burst);
48 	ratelimit_state_reset_miss(rs);
49 	raw_spin_unlock_irqrestore(&rs->lock, flags);
50 }
51 
ratelimit_state_exit(struct ratelimit_state * rs)52 static inline void ratelimit_state_exit(struct ratelimit_state *rs)
53 {
54 	int m;
55 
56 	if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE))
57 		return;
58 
59 	m = ratelimit_state_reset_miss(rs);
60 	if (m)
61 		pr_warn("%s: %d output lines suppressed due to ratelimiting\n", current->comm, m);
62 }
63 
64 static inline void
ratelimit_set_flags(struct ratelimit_state * rs,unsigned long flags)65 ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags)
66 {
67 	rs->flags = flags;
68 }
69 
70 extern struct ratelimit_state printk_ratelimit_state;
71 
72 #ifdef CONFIG_PRINTK
73 
74 #define WARN_ON_RATELIMIT(condition, state)	({		\
75 	bool __rtn_cond = !!(condition);			\
76 	WARN_ON(__rtn_cond && __ratelimit(state));		\
77 	__rtn_cond;						\
78 })
79 
80 #define WARN_RATELIMIT(condition, format, ...)			\
81 ({								\
82 	static DEFINE_RATELIMIT_STATE(_rs,			\
83 				      DEFAULT_RATELIMIT_INTERVAL,	\
84 				      DEFAULT_RATELIMIT_BURST);	\
85 	int rtn = !!(condition);				\
86 								\
87 	if (unlikely(rtn && __ratelimit(&_rs)))			\
88 		WARN(rtn, format, ##__VA_ARGS__);		\
89 								\
90 	rtn;							\
91 })
92 
93 #else
94 
95 #define WARN_ON_RATELIMIT(condition, state)			\
96 	WARN_ON(condition)
97 
98 #define WARN_RATELIMIT(condition, format, ...)			\
99 ({								\
100 	int rtn = WARN(condition, format, ##__VA_ARGS__);	\
101 	rtn;							\
102 })
103 
104 #endif
105 
106 #endif /* _LINUX_RATELIMIT_H */
107