15f97a5a8SDave Young /* 25f97a5a8SDave Young * ratelimit.c - Do something with rate limit. 35f97a5a8SDave Young * 45f97a5a8SDave Young * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> 55f97a5a8SDave Young * 6717115e1SDave Young * 2008-05-01 rewrite the function and use a ratelimit_state data struct as 7717115e1SDave Young * parameter. Now every user can use their own standalone ratelimit_state. 8717115e1SDave Young * 95f97a5a8SDave Young * This file is released under the GPLv2. 105f97a5a8SDave Young */ 115f97a5a8SDave Young 123fff4c42SIngo Molnar #include <linux/ratelimit.h> 135f97a5a8SDave Young #include <linux/jiffies.h> 14*8bc3bcc9SPaul Gortmaker #include <linux/export.h> 155f97a5a8SDave Young 165f97a5a8SDave Young /* 175f97a5a8SDave Young * __ratelimit - rate limiting 18717115e1SDave Young * @rs: ratelimit_state data 192a7268abSYong Zhang * @func: name of calling function 205f97a5a8SDave Young * 212a7268abSYong Zhang * This enforces a rate limit: not more than @rs->burst callbacks 222a7268abSYong Zhang * in every @rs->interval 232a7268abSYong Zhang * 242a7268abSYong Zhang * RETURNS: 252a7268abSYong Zhang * 0 means callbacks will be suppressed. 262a7268abSYong Zhang * 1 means go ahead and do it. 275f97a5a8SDave Young */ 285c828713SChristian Borntraeger int ___ratelimit(struct ratelimit_state *rs, const char *func) 295f97a5a8SDave Young { 304d9c377cSAlexey Dobriyan unsigned long flags; 31979f693dSIngo Molnar int ret; 324d9c377cSAlexey Dobriyan 33717115e1SDave Young if (!rs->interval) 34717115e1SDave Young return 1; 355f97a5a8SDave Young 36edaac8e3SIngo Molnar /* 37edaac8e3SIngo Molnar * If we contend on this state's lock then almost 38edaac8e3SIngo Molnar * by definition we are too busy to print a message, 39edaac8e3SIngo Molnar * in addition to the one that will be printed by 40edaac8e3SIngo Molnar * the entity that is holding the lock already: 41edaac8e3SIngo Molnar */ 4207354eb1SThomas Gleixner if (!raw_spin_trylock_irqsave(&rs->lock, flags)) 4357119c34SYong Zhang return 0; 44edaac8e3SIngo Molnar 45717115e1SDave Young if (!rs->begin) 46717115e1SDave Young rs->begin = jiffies; 475f97a5a8SDave Young 48717115e1SDave Young if (time_is_before_jiffies(rs->begin + rs->interval)) { 49717115e1SDave Young if (rs->missed) 50717115e1SDave Young printk(KERN_WARNING "%s: %d callbacks suppressed\n", 515c828713SChristian Borntraeger func, rs->missed); 52717115e1SDave Young rs->begin = 0; 53717115e1SDave Young rs->printed = 0; 54717115e1SDave Young rs->missed = 0; 555f97a5a8SDave Young } 56979f693dSIngo Molnar if (rs->burst && rs->burst > rs->printed) { 57717115e1SDave Young rs->printed++; 58979f693dSIngo Molnar ret = 1; 59979f693dSIngo Molnar } else { 60979f693dSIngo Molnar rs->missed++; 61979f693dSIngo Molnar ret = 0; 62979f693dSIngo Molnar } 6307354eb1SThomas Gleixner raw_spin_unlock_irqrestore(&rs->lock, flags); 64979f693dSIngo Molnar 65979f693dSIngo Molnar return ret; 665f97a5a8SDave Young } 675c828713SChristian Borntraeger EXPORT_SYMBOL(___ratelimit); 68