2019-06-01 11:08:42 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2008-04-29 11:59:43 +04:00
/*
* ratelimit . c - Do something with rate limit .
*
* Isolated from kernel / printk . c by Dave Young < hidave . darkstar @ gmail . com >
*
2008-07-25 12:45:58 +04:00
* 2008 - 05 - 01 rewrite the function and use a ratelimit_state data struct as
* parameter . Now every user can use their own standalone ratelimit_state .
2008-04-29 11:59:43 +04:00
*/
2009-09-22 18:18:09 +04:00
# include <linux/ratelimit.h>
2008-04-29 11:59:43 +04:00
# include <linux/jiffies.h>
2011-11-17 06:29:17 +04:00
# include <linux/export.h>
2008-04-29 11:59:43 +04:00
/*
* __ratelimit - rate limiting
2008-07-25 12:45:58 +04:00
* @ rs : ratelimit_state data
2010-04-07 01:35:01 +04:00
* @ func : name of calling function
2008-04-29 11:59:43 +04:00
*
2010-04-07 01:35:01 +04:00
* This enforces a rate limit : not more than @ rs - > burst callbacks
* in every @ rs - > interval
*
* RETURNS :
* 0 means callbacks will be suppressed .
* 1 means go ahead and do it .
2008-04-29 11:59:43 +04:00
*/
2009-10-23 16:58:11 +04:00
int ___ratelimit ( struct ratelimit_state * rs , const char * func )
2008-04-29 11:59:43 +04:00
{
2022-08-23 20:46:48 +03:00
/* Paired with WRITE_ONCE() in .proc_handler().
* Changing two values seperately could be inconsistent
* and some message could be lost . ( See : net_ratelimit_state ) .
*/
int interval = READ_ONCE ( rs - > interval ) ;
int burst = READ_ONCE ( rs - > burst ) ;
2008-07-29 02:46:21 +04:00
unsigned long flags ;
2009-09-22 16:44:11 +04:00
int ret ;
2008-07-29 02:46:21 +04:00
2022-08-23 20:46:48 +03:00
if ( ! interval )
2008-07-25 12:45:58 +04:00
return 1 ;
2008-04-29 11:59:43 +04:00
2009-09-22 16:44:11 +04:00
/*
* If we contend on this state ' s lock then almost
* by definition we are too busy to print a message ,
* in addition to the one that will be printed by
* the entity that is holding the lock already :
*/
2009-07-25 19:50:36 +04:00
if ( ! raw_spin_trylock_irqsave ( & rs - > lock , flags ) )
2010-04-07 01:35:03 +04:00
return 0 ;
2009-09-22 16:44:11 +04:00
2008-07-25 12:45:58 +04:00
if ( ! rs - > begin )
rs - > begin = jiffies ;
2008-04-29 11:59:43 +04:00
2022-08-23 20:46:48 +03:00
if ( time_is_before_jiffies ( rs - > begin + interval ) ) {
2016-08-03 00:04:04 +03:00
if ( rs - > missed ) {
if ( ! ( rs - > flags & RATELIMIT_MSG_ON_RELEASE ) ) {
2017-10-04 02:16:45 +03:00
printk_deferred ( KERN_WARNING
" %s: %d callbacks suppressed \n " ,
func , rs - > missed ) ;
2016-08-03 00:04:04 +03:00
rs - > missed = 0 ;
}
}
2016-01-22 03:55:07 +03:00
rs - > begin = jiffies ;
2008-07-25 12:45:58 +04:00
rs - > printed = 0 ;
2008-04-29 11:59:43 +04:00
}
2022-08-23 20:46:48 +03:00
if ( burst & & burst > rs - > printed ) {
2009-09-22 16:44:11 +04:00
rs - > printed + + ;
ret = 1 ;
} else {
rs - > missed + + ;
ret = 0 ;
}
2009-07-25 19:50:36 +04:00
raw_spin_unlock_irqrestore ( & rs - > lock , flags ) ;
2008-07-25 12:45:58 +04:00
2009-09-22 16:44:11 +04:00
return ret ;
2008-04-29 11:59:43 +04:00
}
2009-10-23 16:58:11 +04:00
EXPORT_SYMBOL ( ___ratelimit ) ;