55716d26439f5 (Thomas Gleixner 2019-06-01 10:08:42 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 2) /*
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 3) * ratelimit.c - Do something with rate limit.
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 4) *
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 5) * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com>
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 6) *
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 7) * 2008-05-01 rewrite the function and use a ratelimit_state data struct as
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 8) * parameter. Now every user can use their own standalone ratelimit_state.
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 9) */
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 10)
3fff4c42bd0a8 (Ingo Molnar 2009-09-22 16:18:09 +0200 11) #include <linux/ratelimit.h>
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 12) #include <linux/jiffies.h>
8bc3bcc93a2b4 (Paul Gortmaker 2011-11-16 21:29:17 -0500 13) #include <linux/export.h>
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 14)
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 15) /*
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 16) * __ratelimit - rate limiting
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 17) * @rs: ratelimit_state data
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 18) * @func: name of calling function
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 19) *
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 20) * This enforces a rate limit: not more than @rs->burst callbacks
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 21) * in every @rs->interval
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 22) *
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 23) * RETURNS:
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 24) * 0 means callbacks will be suppressed.
2a7268abc48c8 (Yong Zhang 2010-04-06 14:35:01 -0700 25) * 1 means go ahead and do it.
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 26) */
5c828713358cb (Christian Borntraeger 2009-10-23 14:58:11 +0200 27) int ___ratelimit(struct ratelimit_state *rs, const char *func)
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 28) {
4d9c377c81d37 (Alexey Dobriyan 2008-07-28 15:46:21 -0700 29) unsigned long flags;
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 30) int ret;
4d9c377c81d37 (Alexey Dobriyan 2008-07-28 15:46:21 -0700 31)
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 32) if (!rs->interval)
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 33) return 1;
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 34)
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 35) /*
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 36) * If we contend on this state's lock then almost
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 37) * by definition we are too busy to print a message,
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 38) * in addition to the one that will be printed by
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 39) * the entity that is holding the lock already:
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 40) */
07354eb1a74d1 (Thomas Gleixner 2009-07-25 17:50:36 +0200 41) if (!raw_spin_trylock_irqsave(&rs->lock, flags))
57119c34e53bb (Yong Zhang 2010-04-06 14:35:03 -0700 42) return 0;
edaac8e316750 (Ingo Molnar 2009-09-22 14:44:11 +0200 43)
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 44) if (!rs->begin)
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 45) rs->begin = jiffies;
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 46)
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 47) if (time_is_before_jiffies(rs->begin + rs->interval)) {
6b1d174b0c27b (Borislav Petkov 2016-08-02 14:04:04 -0700 48) if (rs->missed) {
6b1d174b0c27b (Borislav Petkov 2016-08-02 14:04:04 -0700 49) if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
656d61ce96662 (Sergey Senozhatsky 2017-10-03 16:16:45 -0700 50) printk_deferred(KERN_WARNING
656d61ce96662 (Sergey Senozhatsky 2017-10-03 16:16:45 -0700 51) "%s: %d callbacks suppressed\n",
656d61ce96662 (Sergey Senozhatsky 2017-10-03 16:16:45 -0700 52) func, rs->missed);
6b1d174b0c27b (Borislav Petkov 2016-08-02 14:04:04 -0700 53) rs->missed = 0;
6b1d174b0c27b (Borislav Petkov 2016-08-02 14:04:04 -0700 54) }
6b1d174b0c27b (Borislav Petkov 2016-08-02 14:04:04 -0700 55) }
c2594bc37f446 (Jaewon Kim 2016-01-21 16:55:07 -0800 56) rs->begin = jiffies;
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 57) rs->printed = 0;
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 58) }
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 59) if (rs->burst && rs->burst > rs->printed) {
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 60) rs->printed++;
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 61) ret = 1;
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 62) } else {
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 63) rs->missed++;
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 64) ret = 0;
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 65) }
07354eb1a74d1 (Thomas Gleixner 2009-07-25 17:50:36 +0200 66) raw_spin_unlock_irqrestore(&rs->lock, flags);
717115e1a5856 (Dave Young 2008-07-25 01:45:58 -0700 67)
979f693def908 (Ingo Molnar 2009-09-22 14:44:11 +0200 68) return ret;
5f97a5a8799b8 (Dave Young 2008-04-29 00:59:43 -0700 69) }
5c828713358cb (Christian Borntraeger 2009-10-23 14:58:11 +0200 70) EXPORT_SYMBOL(___ratelimit);