aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-09-22 08:44:11 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-22 09:31:34 -0400
commit979f693def9084a452846365dfde5dcb28366333 (patch)
tree4e01718c89c770c82cb3075958a7c0d33631ccf2
parentb8c7f1dc5ca4e0d10709182233cdab932cef593d (diff)
ratelimit: Use per ratelimit context locking
I'd like to use printk_ratelimit() in atomic context, but that's not possible right now due to the spinlock usage this commit introduced more than a year ago: 717115e: printk ratelimiting rewrite As a first step push the lock into the ratelimit state structure. This allows us to deal with locking failures to be considered as an event related to that state being too busy. Also clean up the code a bit (without changing functionality): - tidy up the definitions - clean up the code flow This also shrinks the code a tiny bit: text data bss dec hex filename 264 0 4 268 10c ratelimit.o.before 255 0 0 255 ff ratelimit.o.after ( Whole-kernel data size got a bit larger, because we have two ratelimit-state data structures right now. ) Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: David S. Miller <davem@davemloft.net> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/ratelimit.h30
-rw-r--r--lib/ratelimit.c29
2 files changed, 33 insertions, 26 deletions
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
index 00044b856453..187bc16c1f15 100644
--- a/include/linux/ratelimit.h
+++ b/include/linux/ratelimit.h
@@ -1,20 +1,30 @@
1#ifndef _LINUX_RATELIMIT_H 1#ifndef _LINUX_RATELIMIT_H
2#define _LINUX_RATELIMIT_H 2#define _LINUX_RATELIMIT_H
3
3#include <linux/param.h> 4#include <linux/param.h>
5#include <linux/spinlock_types.h>
4 6
5#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) 7#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ)
6#define DEFAULT_RATELIMIT_BURST 10 8#define DEFAULT_RATELIMIT_BURST 10
7 9
8struct ratelimit_state { 10struct ratelimit_state {
9 int interval; 11 spinlock_t lock; /* protect the state */
10 int burst; 12
11 int printed; 13 int interval;
12 int missed; 14 int burst;
13 unsigned long begin; 15 int printed;
16 int missed;
17 unsigned long begin;
14}; 18};
15 19
16#define DEFINE_RATELIMIT_STATE(name, interval, burst) \ 20#define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init) \
17 struct ratelimit_state name = {interval, burst,} 21 \
22 struct ratelimit_state name = { \
23 .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
24 .interval = interval_init, \
25 .burst = burst_init, \
26 }
18 27
19extern int __ratelimit(struct ratelimit_state *rs); 28extern int __ratelimit(struct ratelimit_state *rs);
20#endif 29
30#endif /* _LINUX_RATELIMIT_H */
diff --git a/lib/ratelimit.c b/lib/ratelimit.c
index 26187edcc7ea..0e2c28e8a0ca 100644
--- a/lib/ratelimit.c
+++ b/lib/ratelimit.c
@@ -7,15 +7,12 @@
7 * parameter. Now every user can use their own standalone ratelimit_state. 7 * parameter. Now every user can use their own standalone ratelimit_state.
8 * 8 *
9 * This file is released under the GPLv2. 9 * This file is released under the GPLv2.
10 *
11 */ 10 */
12 11
13#include <linux/kernel.h> 12#include <linux/kernel.h>
14#include <linux/jiffies.h> 13#include <linux/jiffies.h>
15#include <linux/module.h> 14#include <linux/module.h>
16 15
17static DEFINE_SPINLOCK(ratelimit_lock);
18
19/* 16/*
20 * __ratelimit - rate limiting 17 * __ratelimit - rate limiting
21 * @rs: ratelimit_state data 18 * @rs: ratelimit_state data
@@ -26,11 +23,12 @@ static DEFINE_SPINLOCK(ratelimit_lock);
26int __ratelimit(struct ratelimit_state *rs) 23int __ratelimit(struct ratelimit_state *rs)
27{ 24{
28 unsigned long flags; 25 unsigned long flags;
26 int ret;
29 27
30 if (!rs->interval) 28 if (!rs->interval)
31 return 1; 29 return 1;
32 30
33 spin_lock_irqsave(&ratelimit_lock, flags); 31 spin_lock_irqsave(&rs->lock, flags);
34 if (!rs->begin) 32 if (!rs->begin)
35 rs->begin = jiffies; 33 rs->begin = jiffies;
36 34
@@ -38,20 +36,19 @@ int __ratelimit(struct ratelimit_state *rs)
38 if (rs->missed) 36 if (rs->missed)
39 printk(KERN_WARNING "%s: %d callbacks suppressed\n", 37 printk(KERN_WARNING "%s: %d callbacks suppressed\n",
40 __func__, rs->missed); 38 __func__, rs->missed);
41 rs->begin = 0; 39 rs->begin = 0;
42 rs->printed = 0; 40 rs->printed = 0;
43 rs->missed = 0; 41 rs->missed = 0;
44 } 42 }
45 if (rs->burst && rs->burst > rs->printed) 43 if (rs->burst && rs->burst > rs->printed) {
46 goto print; 44 rs->printed++;
47 45 ret = 1;
48 rs->missed++; 46 } else {
49 spin_unlock_irqrestore(&ratelimit_lock, flags); 47 rs->missed++;
50 return 0; 48 ret = 0;
49 }
50 spin_unlock_irqrestore(&rs->lock, flags);
51 51
52print: 52 return ret;
53 rs->printed++;
54 spin_unlock_irqrestore(&ratelimit_lock, flags);
55 return 1;
56} 53}
57EXPORT_SYMBOL(__ratelimit); 54EXPORT_SYMBOL(__ratelimit);