Commit 979f693d authored by Ingo Molnar's avatar Ingo Molnar

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:

  717115e1: 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: default avatarIngo Molnar <mingo@elte.hu>
parent b8c7f1dc
#ifndef _LINUX_RATELIMIT_H #ifndef _LINUX_RATELIMIT_H
#define _LINUX_RATELIMIT_H #define _LINUX_RATELIMIT_H
#include <linux/param.h> #include <linux/param.h>
#include <linux/spinlock_types.h>
#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) #define DEFAULT_RATELIMIT_INTERVAL (5 * HZ)
#define DEFAULT_RATELIMIT_BURST 10 #define DEFAULT_RATELIMIT_BURST 10
struct ratelimit_state { struct ratelimit_state {
int interval; spinlock_t lock; /* protect the state */
int burst;
int printed; int interval;
int missed; int burst;
unsigned long begin; int printed;
int missed;
unsigned long begin;
}; };
#define DEFINE_RATELIMIT_STATE(name, interval, burst) \ #define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init) \
struct ratelimit_state name = {interval, burst,} \
struct ratelimit_state name = { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.interval = interval_init, \
.burst = burst_init, \
}
extern int __ratelimit(struct ratelimit_state *rs); extern int __ratelimit(struct ratelimit_state *rs);
#endif
#endif /* _LINUX_RATELIMIT_H */
...@@ -7,15 +7,12 @@ ...@@ -7,15 +7,12 @@
* parameter. Now every user can use their own standalone ratelimit_state. * parameter. Now every user can use their own standalone ratelimit_state.
* *
* This file is released under the GPLv2. * This file is released under the GPLv2.
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/module.h> #include <linux/module.h>
static DEFINE_SPINLOCK(ratelimit_lock);
/* /*
* __ratelimit - rate limiting * __ratelimit - rate limiting
* @rs: ratelimit_state data * @rs: ratelimit_state data
...@@ -26,11 +23,12 @@ static DEFINE_SPINLOCK(ratelimit_lock); ...@@ -26,11 +23,12 @@ static DEFINE_SPINLOCK(ratelimit_lock);
int __ratelimit(struct ratelimit_state *rs) int __ratelimit(struct ratelimit_state *rs)
{ {
unsigned long flags; unsigned long flags;
int ret;
if (!rs->interval) if (!rs->interval)
return 1; return 1;
spin_lock_irqsave(&ratelimit_lock, flags); spin_lock_irqsave(&rs->lock, flags);
if (!rs->begin) if (!rs->begin)
rs->begin = jiffies; rs->begin = jiffies;
...@@ -38,20 +36,19 @@ int __ratelimit(struct ratelimit_state *rs) ...@@ -38,20 +36,19 @@ int __ratelimit(struct ratelimit_state *rs)
if (rs->missed) if (rs->missed)
printk(KERN_WARNING "%s: %d callbacks suppressed\n", printk(KERN_WARNING "%s: %d callbacks suppressed\n",
__func__, rs->missed); __func__, rs->missed);
rs->begin = 0; rs->begin = 0;
rs->printed = 0; rs->printed = 0;
rs->missed = 0; rs->missed = 0;
} }
if (rs->burst && rs->burst > rs->printed) if (rs->burst && rs->burst > rs->printed) {
goto print; rs->printed++;
ret = 1;
rs->missed++; } else {
spin_unlock_irqrestore(&ratelimit_lock, flags); rs->missed++;
return 0; ret = 0;
}
spin_unlock_irqrestore(&rs->lock, flags);
print: return ret;
rs->printed++;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 1;
} }
EXPORT_SYMBOL(__ratelimit); EXPORT_SYMBOL(__ratelimit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment