| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * ratelimit.c - Do something with rate limit. | 
 | 3 |  * | 
 | 4 |  * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> | 
 | 5 |  * | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 6 |  * 2008-05-01 rewrite the function and use a ratelimit_state data struct as | 
 | 7 |  * parameter. Now every user can use their own standalone ratelimit_state. | 
 | 8 |  * | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 9 |  * This file is released under the GPLv2. | 
 | 10 |  * | 
 | 11 |  */ | 
 | 12 |  | 
 | 13 | #include <linux/kernel.h> | 
 | 14 | #include <linux/jiffies.h> | 
 | 15 | #include <linux/module.h> | 
 | 16 |  | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 17 | static DEFINE_SPINLOCK(ratelimit_lock); | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 18 |  | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 19 | /* | 
 | 20 |  * __ratelimit - rate limiting | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 21 |  * @rs: ratelimit_state data | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 22 |  * | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 23 |  * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks | 
 | 24 |  * in every @rs->ratelimit_jiffies | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 25 |  */ | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 26 | int __ratelimit(struct ratelimit_state *rs) | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 27 | { | 
| Alexey Dobriyan | 4d9c377 | 2008-07-28 15:46:21 -0700 | [diff] [blame] | 28 | 	unsigned long flags; | 
 | 29 |  | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 30 | 	if (!rs->interval) | 
 | 31 | 		return 1; | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 32 |  | 
 | 33 | 	spin_lock_irqsave(&ratelimit_lock, flags); | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 34 | 	if (!rs->begin) | 
 | 35 | 		rs->begin = jiffies; | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 36 |  | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 37 | 	if (time_is_before_jiffies(rs->begin + rs->interval)) { | 
 | 38 | 		if (rs->missed) | 
 | 39 | 			printk(KERN_WARNING "%s: %d callbacks suppressed\n", | 
 | 40 | 				__func__, rs->missed); | 
 | 41 | 		rs->begin = 0; | 
 | 42 | 		rs->printed = 0; | 
 | 43 | 		rs->missed = 0; | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 44 | 	} | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 45 | 	if (rs->burst && rs->burst > rs->printed) | 
 | 46 | 		goto print; | 
 | 47 |  | 
 | 48 | 	rs->missed++; | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 49 | 	spin_unlock_irqrestore(&ratelimit_lock, flags); | 
 | 50 | 	return 0; | 
| Dave Young | 717115e | 2008-07-25 01:45:58 -0700 | [diff] [blame] | 51 |  | 
 | 52 | print: | 
 | 53 | 	rs->printed++; | 
 | 54 | 	spin_unlock_irqrestore(&ratelimit_lock, flags); | 
 | 55 | 	return 1; | 
| Dave Young | 5f97a5a | 2008-04-29 00:59:43 -0700 | [diff] [blame] | 56 | } | 
 | 57 | EXPORT_SYMBOL(__ratelimit); |