[PATCH v4 1/2] xen/console: correct leaky-bucket rate limiter
[email protected] Wed, 29 Jul 2026 00:25:19 -0700
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
From: Denis Mukhin <[email protected]> Use existing 'ratelimit_ms' and 'ratelimit_burst' variables in do_printk_ratelimit() instead of hardcoded values 5000 and 10 respectively. Ensure rate limiter is disabled if either 'ratelimit_ms' or 'ratelimit_burst' is 0. Account for integer overflow in the rate-limiter logic. Signed-off-by: Denis Mukhin <[email protected]> --- Changes since v3: - fixed types - fixed integer division logic - I used DIM_MUL2() from xvmalloc.h I hope this is fine given another pending patch which will include xvmalloc.h for heap allocations - fixed potential problem w/ overflow of toks (introduced elapsed) - fixed potential problem with toks == 0 which is also "uninitialized" state. --- xen/drivers/char/console.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index ea4e3ff34178..76a1681670c1 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -33,6 +33,7 @@ #include <asm/setup.h> #include <xen/sections.h> #include <xen/consoled.h> +#include <xen/xvmalloc.h> #ifdef CONFIG_X86 #include <asm/guest.h> @@ -1286,21 +1287,43 @@ bool __printk_ratelimit(unsigned int ratelimit_ms, unsigned int ratelimit_burst) { static DEFINE_SPINLOCK(ratelimit_lock); - static unsigned long toks = 10 * 5 * 1000; + static unsigned long toks; static unsigned long last_msg; static unsigned int missed; + static bool initialized; + unsigned long limit; unsigned long flags; - unsigned long long now = NOW(); /* ns */ unsigned long ms; + s_time_t now; - do_div(now, 1000000); - ms = (unsigned long)now; + if ( !ratelimit_ms || !ratelimit_burst ) + return true; + + limit = DIM_MUL2(ratelimit_burst, ratelimit_ms); + + now = NOW(); /* ns */ + do_div(now, MILLISECS(1)); + ms = now; spin_lock_irqsave(&ratelimit_lock, flags); - toks += ms - last_msg; + + if ( initialized ) + { + unsigned long elapsed = ms - last_msg; + + if ( toks >= limit || elapsed >= limit - toks ) + toks = limit; + else + toks += elapsed; + } + else + { + toks = limit; + initialized = true; + } + last_msg = ms; - if ( toks > (ratelimit_burst * ratelimit_ms)) - toks = ratelimit_burst * ratelimit_ms; + if ( toks >= ratelimit_ms ) { unsigned int lost = missed; -- 2.54.0