]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
717115e1 DY |
2 | #ifndef _LINUX_RATELIMIT_H |
3 | #define _LINUX_RATELIMIT_H | |
979f693d | 4 | |
717115e1 | 5 | #include <linux/param.h> |
6b1d174b | 6 | #include <linux/sched.h> |
f40c396a | 7 | #include <linux/spinlock.h> |
717115e1 | 8 | |
979f693d IM |
9 | #define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) |
10 | #define DEFAULT_RATELIMIT_BURST 10 | |
717115e1 | 11 | |
6b1d174b BP |
12 | /* issue num suppressed message on exit */ |
13 | #define RATELIMIT_MSG_ON_RELEASE BIT(0) | |
14 | ||
717115e1 | 15 | struct ratelimit_state { |
07354eb1 | 16 | raw_spinlock_t lock; /* protect the state */ |
979f693d IM |
17 | |
18 | int interval; | |
19 | int burst; | |
20 | int printed; | |
21 | int missed; | |
22 | unsigned long begin; | |
6b1d174b | 23 | unsigned long flags; |
717115e1 DY |
24 | }; |
25 | ||
89e3f909 | 26 | #define RATELIMIT_STATE_INIT(name, interval_init, burst_init) { \ |
07354eb1 | 27 | .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ |
979f693d IM |
28 | .interval = interval_init, \ |
29 | .burst = burst_init, \ | |
30 | } | |
717115e1 | 31 | |
89e3f909 DM |
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 | ||
f40c396a OH |
40 | static inline void ratelimit_state_init(struct ratelimit_state *rs, |
41 | int interval, int burst) | |
42 | { | |
6b1d174b BP |
43 | memset(rs, 0, sizeof(*rs)); |
44 | ||
07354eb1 | 45 | raw_spin_lock_init(&rs->lock); |
6b1d174b BP |
46 | rs->interval = interval; |
47 | rs->burst = burst; | |
48 | } | |
49 | ||
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 | ||
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 | |
69 | ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags) | |
70 | { | |
71 | rs->flags = flags; | |
f40c396a OH |
72 | } |
73 | ||
f5d87d85 NK |
74 | extern struct ratelimit_state printk_ratelimit_state; |
75 | ||
5c828713 CB |
76 | extern int ___ratelimit(struct ratelimit_state *rs, const char *func); |
77 | #define __ratelimit(state) ___ratelimit(state, __func__) | |
979f693d | 78 | |
86e4ca66 DM |
79 | #ifdef CONFIG_PRINTK |
80 | ||
1b011e2f JS |
81 | #define WARN_ON_RATELIMIT(condition, state) ({ \ |
82 | bool __rtn_cond = !!(condition); \ | |
83 | WARN_ON(__rtn_cond && __ratelimit(state)); \ | |
84 | __rtn_cond; \ | |
85 | }) | |
86e4ca66 | 86 | |
2351a6c6 | 87 | #define WARN_RATELIMIT(condition, format, ...) \ |
86e4ca66 DM |
88 | ({ \ |
89 | static DEFINE_RATELIMIT_STATE(_rs, \ | |
90 | DEFAULT_RATELIMIT_INTERVAL, \ | |
91 | DEFAULT_RATELIMIT_BURST); \ | |
2351a6c6 MT |
92 | int rtn = !!(condition); \ |
93 | \ | |
94 | if (unlikely(rtn && __ratelimit(&_rs))) \ | |
95 | WARN(rtn, format, ##__VA_ARGS__); \ | |
96 | \ | |
97 | rtn; \ | |
86e4ca66 DM |
98 | }) |
99 | ||
100 | #else | |
101 | ||
102 | #define WARN_ON_RATELIMIT(condition, state) \ | |
103 | WARN_ON(condition) | |
104 | ||
2351a6c6 | 105 | #define WARN_RATELIMIT(condition, format, ...) \ |
86e4ca66 | 106 | ({ \ |
2351a6c6 | 107 | int rtn = WARN(condition, format, ##__VA_ARGS__); \ |
86e4ca66 DM |
108 | rtn; \ |
109 | }) | |
110 | ||
111 | #endif | |
112 | ||
979f693d | 113 | #endif /* _LINUX_RATELIMIT_H */ |