Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only 2 : /* 3 : * ratelimit.c - Do something with rate limit. 4 : * 5 : * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> 6 : * 7 : * 2008-05-01 rewrite the function and use a ratelimit_state data struct as 8 : * parameter. Now every user can use their own standalone ratelimit_state. 9 : */ 10 : 11 : #include <linux/ratelimit.h> 12 : #include <linux/jiffies.h> 13 : #include <linux/export.h> 14 : 15 : /* 16 : * __ratelimit - rate limiting 17 : * @rs: ratelimit_state data 18 : * @func: name of calling function 19 : * 20 : * This enforces a rate limit: not more than @rs->burst callbacks 21 : * in every @rs->interval 22 : * 23 : * RETURNS: 24 : * 0 means callbacks will be suppressed. 25 : * 1 means go ahead and do it. 26 : */ 27 53 : int ___ratelimit(struct ratelimit_state *rs, const char *func) 28 : { 29 53 : unsigned long flags; 30 53 : int ret; 31 : 32 53 : if (!rs->interval) 33 : return 1; 34 : 35 : /* 36 : * If we contend on this state's lock then almost 37 : * by definition we are too busy to print a message, 38 : * in addition to the one that will be printed by 39 : * the entity that is holding the lock already: 40 : */ 41 104 : if (!raw_spin_trylock_irqsave(&rs->lock, flags)) 42 0 : return 0; 43 : 44 52 : if (!rs->begin) 45 6 : rs->begin = jiffies; 46 : 47 52 : if (time_is_before_jiffies(rs->begin + rs->interval)) { 48 0 : if (rs->missed) { 49 0 : if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) { 50 0 : printk_deferred(KERN_WARNING 51 : "%s: %d callbacks suppressed\n", 52 : func, rs->missed); 53 0 : rs->missed = 0; 54 : } 55 : } 56 0 : rs->begin = jiffies; 57 0 : rs->printed = 0; 58 : } 59 52 : if (rs->burst && rs->burst > rs->printed) { 60 15 : rs->printed++; 61 15 : ret = 1; 62 : } else { 63 37 : rs->missed++; 64 37 : ret = 0; 65 : } 66 52 : raw_spin_unlock_irqrestore(&rs->lock, flags); 67 : 68 52 : return ret; 69 : } 70 : EXPORT_SYMBOL(___ratelimit);