diff options
Diffstat (limited to 'lib/ratelimit.c')
| -rw-r--r-- | lib/ratelimit.c | 78 |
1 files changed, 47 insertions, 31 deletions
diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 485e3040dcd..40e03ea2a96 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c @@ -3,49 +3,65 @@ * * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> * - * This file is released under the GPLv2. + * 2008-05-01 rewrite the function and use a ratelimit_state data struct as + * parameter. Now every user can use their own standalone ratelimit_state. * + * This file is released under the GPLv2. */ -#include <linux/kernel.h> +#include <linux/ratelimit.h> #include <linux/jiffies.h> -#include <linux/module.h> +#include <linux/export.h> /* * __ratelimit - rate limiting - * @ratelimit_jiffies: minimum time in jiffies between two callbacks - * @ratelimit_burst: number of callbacks we do before ratelimiting + * @rs: ratelimit_state data + * @func: name of calling function + * + * This enforces a rate limit: not more than @rs->burst callbacks + * in every @rs->interval * - * This enforces a rate limit: not more than @ratelimit_burst callbacks - * in every ratelimit_jiffies + * RETURNS: + * 0 means callbacks will be suppressed. + * 1 means go ahead and do it. */ -int __ratelimit(int ratelimit_jiffies, int ratelimit_burst) +int ___ratelimit(struct ratelimit_state *rs, const char *func) { - static DEFINE_SPINLOCK(ratelimit_lock); - static unsigned toks = 10 * 5 * HZ; - static unsigned long last_msg; - static int missed; unsigned long flags; - unsigned long now = jiffies; + int ret; - spin_lock_irqsave(&ratelimit_lock, flags); - toks += now - last_msg; - last_msg = now; - if (toks > (ratelimit_burst * ratelimit_jiffies)) - toks = ratelimit_burst * ratelimit_jiffies; - if (toks >= ratelimit_jiffies) { - int lost = missed; - - missed = 0; - toks -= ratelimit_jiffies; - spin_unlock_irqrestore(&ratelimit_lock, flags); - if (lost) - printk(KERN_WARNING "%s: %d messages suppressed\n", - __func__, lost); + if (!rs->interval) return 1; + + /* + * If we contend on this state's lock then almost + * by definition we are too busy to print a message, + * in addition to the one that will be printed by + * the entity that is holding the lock already: + */ + if (!raw_spin_trylock_irqsave(&rs->lock, flags)) + return 0; + + if (!rs->begin) + rs->begin = jiffies; + + if (time_is_before_jiffies(rs->begin + rs->interval)) { + if (rs->missed) + printk(KERN_WARNING "%s: %d callbacks suppressed\n", + func, rs->missed); + rs->begin = 0; + rs->printed = 0; + rs->missed = 0; } - missed++; - spin_unlock_irqrestore(&ratelimit_lock, flags); - return 0; + if (rs->burst && rs->burst > rs->printed) { + rs->printed++; + ret = 1; + } else { + rs->missed++; + ret = 0; + } + raw_spin_unlock_irqrestore(&rs->lock, flags); + + return ret; } -EXPORT_SYMBOL(__ratelimit); +EXPORT_SYMBOL(___ratelimit); |
