Back to home page

LXR

 
 

    


0001 /*
0002  * ratelimit.c - Do something with rate limit.
0003  *
0004  * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com>
0005  *
0006  * 2008-05-01 rewrite the function and use a ratelimit_state data struct as
0007  * parameter. Now every user can use their own standalone ratelimit_state.
0008  *
0009  * This file is released under the GPLv2.
0010  */
0011 
0012 #include <linux/ratelimit.h>
0013 #include <linux/jiffies.h>
0014 #include <linux/export.h>
0015 
0016 /*
0017  * __ratelimit - rate limiting
0018  * @rs: ratelimit_state data
0019  * @func: name of calling function
0020  *
0021  * This enforces a rate limit: not more than @rs->burst callbacks
0022  * in every @rs->interval
0023  *
0024  * RETURNS:
0025  * 0 means callbacks will be suppressed.
0026  * 1 means go ahead and do it.
0027  */
0028 int ___ratelimit(struct ratelimit_state *rs, const char *func)
0029 {
0030     unsigned long flags;
0031     int ret;
0032 
0033     if (!rs->interval)
0034         return 1;
0035 
0036     /*
0037      * If we contend on this state's lock then almost
0038      * by definition we are too busy to print a message,
0039      * in addition to the one that will be printed by
0040      * the entity that is holding the lock already:
0041      */
0042     if (!raw_spin_trylock_irqsave(&rs->lock, flags))
0043         return 0;
0044 
0045     if (!rs->begin)
0046         rs->begin = jiffies;
0047 
0048     if (time_is_before_jiffies(rs->begin + rs->interval)) {
0049         if (rs->missed) {
0050             if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
0051                 pr_warn("%s: %d callbacks suppressed\n", func, rs->missed);
0052                 rs->missed = 0;
0053             }
0054         }
0055         rs->begin   = jiffies;
0056         rs->printed = 0;
0057     }
0058     if (rs->burst && rs->burst > rs->printed) {
0059         rs->printed++;
0060         ret = 1;
0061     } else {
0062         rs->missed++;
0063         ret = 0;
0064     }
0065     raw_spin_unlock_irqrestore(&rs->lock, flags);
0066 
0067     return ret;
0068 }
0069 EXPORT_SYMBOL(___ratelimit);