diff options
Diffstat (limited to 'lib/ratelimit.c')
-rw-r--r-- | lib/ratelimit.c | 55 |
1 files changed, 30 insertions, 25 deletions
diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 485e3040dcd4..35136671b215 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,43 @@ | |||
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 | static unsigned long flags; | ||
19 | |||
14 | /* | 20 | /* |
15 | * __ratelimit - rate limiting | 21 | * __ratelimit - rate limiting |
16 | * @ratelimit_jiffies: minimum time in jiffies between two callbacks | 22 | * @rs: ratelimit_state data |
17 | * @ratelimit_burst: number of callbacks we do before ratelimiting | ||
18 | * | 23 | * |
19 | * This enforces a rate limit: not more than @ratelimit_burst callbacks | 24 | * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks |
20 | * in every ratelimit_jiffies | 25 | * in every @rs->ratelimit_jiffies |
21 | */ | 26 | */ |
22 | int __ratelimit(int ratelimit_jiffies, int ratelimit_burst) | 27 | int __ratelimit(struct ratelimit_state *rs) |
23 | { | 28 | { |
24 | static DEFINE_SPINLOCK(ratelimit_lock); | 29 | if (!rs->interval) |
25 | static unsigned toks = 10 * 5 * HZ; | 30 | return 1; |
26 | static unsigned long last_msg; | ||
27 | static int missed; | ||
28 | unsigned long flags; | ||
29 | unsigned long now = jiffies; | ||
30 | 31 | ||
31 | spin_lock_irqsave(&ratelimit_lock, flags); | 32 | spin_lock_irqsave(&ratelimit_lock, flags); |
32 | toks += now - last_msg; | 33 | if (!rs->begin) |
33 | last_msg = now; | 34 | rs->begin = jiffies; |
34 | if (toks > (ratelimit_burst * ratelimit_jiffies)) | ||
35 | toks = ratelimit_burst * ratelimit_jiffies; | ||
36 | if (toks >= ratelimit_jiffies) { | ||
37 | int lost = missed; | ||
38 | 35 | ||
39 | missed = 0; | 36 | if (time_is_before_jiffies(rs->begin + rs->interval)) { |
40 | toks -= ratelimit_jiffies; | 37 | if (rs->missed) |
41 | spin_unlock_irqrestore(&ratelimit_lock, flags); | 38 | printk(KERN_WARNING "%s: %d callbacks suppressed\n", |
42 | if (lost) | 39 | __func__, rs->missed); |
43 | printk(KERN_WARNING "%s: %d messages suppressed\n", | 40 | rs->begin = 0; |
44 | __func__, lost); | 41 | rs->printed = 0; |
45 | return 1; | 42 | rs->missed = 0; |
46 | } | 43 | } |
47 | missed++; | 44 | if (rs->burst && rs->burst > rs->printed) |
45 | goto print; | ||
46 | |||
47 | rs->missed++; | ||
48 | spin_unlock_irqrestore(&ratelimit_lock, flags); | 48 | spin_unlock_irqrestore(&ratelimit_lock, flags); |
49 | return 0; | 49 | return 0; |
50 | |||
51 | print: | ||
52 | rs->printed++; | ||
53 | spin_unlock_irqrestore(&ratelimit_lock, flags); | ||
54 | return 1; | ||
50 | } | 55 | } |
51 | EXPORT_SYMBOL(__ratelimit); | 56 | EXPORT_SYMBOL(__ratelimit); |