tunnels: fix netns vs proto registration ordering
[safe/jmp/linux-2.6] / lib / ratelimit.c
index 485e304..09f5ce1 100644 (file)
@@ -3,49 +3,60 @@
  *
  * 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>
 
 /*
  * __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
  *
- * This enforces a rate limit: not more than @ratelimit_burst callbacks
- * in every ratelimit_jiffies
+ * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks
+ * in every @rs->ratelimit_jiffies
  */
-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;
+       if (!rs->interval)
+               return 1;
 
-               missed = 0;
-               toks -= ratelimit_jiffies;
-               spin_unlock_irqrestore(&ratelimit_lock, flags);
-               if (lost)
-                       printk(KERN_WARNING "%s: %d messages suppressed\n",
-                               __func__, lost);
+       /*
+        * 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 (!spin_trylock_irqsave(&rs->lock, flags))
                return 1;
+
+       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;
+       }
+       if (rs->burst && rs->burst > rs->printed) {
+               rs->printed++;
+               ret = 1;
+       } else {
+               rs->missed++;
+               ret = 0;
        }
-       missed++;
-       spin_unlock_irqrestore(&ratelimit_lock, flags);
-       return 0;
+       spin_unlock_irqrestore(&rs->lock, flags);
+
+       return ret;
 }
-EXPORT_SYMBOL(__ratelimit);
+EXPORT_SYMBOL(___ratelimit);