diff options
Diffstat (limited to 'lib/ratelimit.c')
-rw-r--r-- | lib/ratelimit.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 485e3040dcd4..26187edcc7ea 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> | 4 | * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> |
5 | * | 5 | * |
6 | * 2008-05-01 rewrite the function and use a ratelimit_state data struct as | ||
7 | * parameter. Now every user can use their own standalone ratelimit_state. | ||
8 | * | ||
6 | * This file is released under the GPLv2. | 9 | * This file is released under the GPLv2. |
7 | * | 10 | * |
8 | */ | 11 | */ |
@@ -11,41 +14,44 @@ | |||
11 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
12 | #include <linux/module.h> | 15 | #include <linux/module.h> |
13 | 16 | ||
17 | static DEFINE_SPINLOCK(ratelimit_lock); | ||
18 | |||
14 | /* | 19 | /* |
15 | * __ratelimit - rate limiting | 20 | * __ratelimit - rate limiting |
16 | * @ratelimit_jiffies: minimum time in jiffies between two callbacks | 21 | * @rs: ratelimit_state data |
17 | * @ratelimit_burst: number of callbacks we do before ratelimiting | ||
18 | * | 22 | * |
19 | * This enforces a rate limit: not more than @ratelimit_burst callbacks | 23 | * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks |
20 | * in every ratelimit_jiffies | 24 | * in every @rs->ratelimit_jiffies |
21 | */ | 25 | */ |
22 | int __ratelimit(int ratelimit_jiffies, int ratelimit_burst) | 26 | int __ratelimit(struct ratelimit_state *rs) |
23 | { | 27 | { |
24 | static DEFINE_SPINLOCK(ratelimit_lock); | ||
25 | static unsigned toks = 10 * 5 * HZ; | ||
26 | static unsigned long last_msg; | ||
27 | static int missed; | ||
28 | unsigned long flags; | 28 | unsigned long flags; |
29 | unsigned long now = jiffies; | ||
30 | 29 | ||
31 | spin_lock_irqsave(&ratelimit_lock, flags); | 30 | if (!rs->interval) |
32 | toks += now - last_msg; | ||
33 | last_msg = now; | ||
34 | if (toks > (ratelimit_burst * ratelimit_jiffies)) | ||
35 | toks = ratelimit_burst * ratelimit_jiffies; | ||
36 | if (toks >= ratelimit_jiffies) { | ||
37 | int lost = missed; | ||
38 | |||
39 | missed = 0; | ||
40 | toks -= ratelimit_jiffies; | ||
41 | spin_unlock_irqrestore(&ratelimit_lock, flags); | ||
42 | if (lost) | ||
43 | printk(KERN_WARNING "%s: %d messages suppressed\n", | ||
44 | __func__, lost); | ||
45 | return 1; | 31 | return 1; |
32 | |||
33 | spin_lock_irqsave(&ratelimit_lock, flags); | ||
34 | if (!rs->begin) | ||
35 | rs->begin = jiffies; | ||
36 | |||
37 | if (time_is_before_jiffies(rs->begin + rs->interval)) { | ||
38 | if (rs->missed) | ||
39 | printk(KERN_WARNING "%s: %d callbacks suppressed\n", | ||
40 | __func__, rs->missed); | ||
41 | rs->begin = 0; | ||
42 | rs->printed = 0; | ||
43 | rs->missed = 0; | ||
46 | } | 44 | } |
47 | missed++; | 45 | if (rs->burst && rs->burst > rs->printed) |
46 | goto print; | ||
47 | |||
48 | rs->missed++; | ||
48 | spin_unlock_irqrestore(&ratelimit_lock, flags); | 49 | spin_unlock_irqrestore(&ratelimit_lock, flags); |
49 | return 0; | 50 | return 0; |
51 | |||
52 | print: | ||
53 | rs->printed++; | ||
54 | spin_unlock_irqrestore(&ratelimit_lock, flags); | ||
55 | return 1; | ||
50 | } | 56 | } |
51 | EXPORT_SYMBOL(__ratelimit); | 57 | EXPORT_SYMBOL(__ratelimit); |