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