Linux Kernel Log Rate Limiting: printk_ratelimited() & pr_warn_ratelimited()

Rate-Limited printk in Linux Kernel | Free Linux Kernel Programming Course | EmbeddedPathashala

EmbeddedPathashalaLinux Kernel Programming › Rate-Limited printk
Rate-Limited printk in Linux Kernel
How to prevent kernel log flooding using printk_ratelimited and pr_<foo>_ratelimited macros — Linux 6.x Edition
⏱ 15 min read
🆓 Free Course
🐧 Linux 6.x
Series: PREV_LEC NEXT_LEC

Rate-Limited printk: Preventing Kernel Log Flooding in Linux 6.x

Topics Covered in This Tutorial
printk_ratelimited kernel log rate limiting pr_warn_ratelimited kernel log flooding free linux kernel course linux device driver logging kernel module debugging printk_ratelimit_burst

1. The Problem: Kernel Log Flooding

Every Linux kernel driver developer eventually faces a situation where a piece of code that runs very frequently — like an interrupt handler, a timer callback, or a hot path inside a driver — also needs to emit a log message when something goes wrong.

The challenge is: if that code path fires hundreds or thousands of times per second, a regular printk() call on each execution will fill the kernel ring buffer extremely fast. Important messages from other subsystems get pushed out, the system becomes sluggish because logging I/O competes with real work, and diagnosing the actual problem becomes harder, not easier.

⚠ Real-World Problem Think about a hardware interrupt that fires at several kilohertz when a cable is disconnected. A printk() on every interrupt event would generate thousands of log lines per second — crippling the system and making the log useless.

The Linux kernel solves this with rate-limited logging. Rate limiting means: allow a certain number of log messages through within a defined time window, and silently suppress the rest. When suppression ends, the kernel emits a single summary line telling you how many messages were dropped — so you never lose visibility into the scale of the problem.

2. What Is Rate Limiting in Kernel Logging?

Rate limiting in kernel logging is a built-in mechanism that controls how many identical or repetitive log messages can appear in the kernel ring buffer within a given time interval. It is not about filtering messages by content — it is purely about frequency control.

The two parameters that govern this behavior are:

  • Time interval — the window in seconds during which the burst count is measured
  • Burst count — the maximum number of messages allowed to pass through during the time interval before rate limiting activates

Once the burst count is exhausted within the time window, subsequent messages are silently counted but not printed. When the window expires and messages start flowing again, the kernel first prints a line like:

[timestamp] my_driver: 4820 callbacks suppressed

This tells you the exact number of messages that were held back, which is extremely useful during debugging.

ℹ Key Concept Rate limiting does not mean the event did not happen. It only means the kernel chose not to log every single occurrence. The suppressed count line ensures you always know the scale of repetition.

3. How Rate Limiting Works Internally

The rate-limiting logic in the Linux kernel lives in lib/ratelimit.c. The core function is ___ratelimit(), which maintains a struct ratelimit_state per call site. This structure keeps track of:

  • When the current time window started
  • How many messages have been printed in this window
  • How many messages have been suppressed in this window

Each time a rate-limited printk is called, the kernel checks:

  1. Has the current time window expired? If yes, reset the counter and start fresh.
  2. Is the current count within the allowed burst? If yes, print the message and increment the counter.
  3. Is the burst exceeded? If yes, suppress the message, increment the suppressed counter, and continue.

When a new window starts after suppression, the kernel first emits the suppressed count, then allows the next burst.

✅ Linux 6.x Note In Linux 6.x, the ratelimit state is initialized with DEFINE_RATELIMIT_STATE() and the underlying token bucket algorithm has been stable since Linux 3.x. The printk_ratelimited() macro uses a statically allocated ratelimit state local to each call site, so different call sites in your driver have independent rate limits.

4. Controlling Rate Limits via sysctl

The kernel exposes the global default rate-limit parameters through the sysctl interface under /proc/sys/kernel/. You can read and modify them at runtime without rebooting.

Reading the current values

# Read both parameters at once
cat /proc/sys/kernel/printk_ratelimit
cat /proc/sys/kernel/printk_ratelimit_burst

On a typical Linux 6.x system the defaults are:

  • printk_ratelimit = 5 (seconds — the time window)
  • printk_ratelimit_burst = 10 (messages allowed per window)

Modifying them temporarily (until reboot)

# Allow 20 messages every 10 seconds
echo 10 > /proc/sys/kernel/printk_ratelimit
echo 20 > /proc/sys/kernel/printk_ratelimit_burst

Making changes permanent via sysctl.conf

# Add to /etc/sysctl.conf or /etc/sysctl.d/99-custom.conf
kernel.printk_ratelimit = 10
kernel.printk_ratelimit_burst = 20

# Apply immediately
sudo sysctl -p
⚠ Important These global sysctl values apply to printk_ratelimited(). However, drivers that define their own DEFINE_RATELIMIT_STATE() with explicit interval and burst values are not affected by the sysctl knobs — they use whatever values the driver hardcodes.

5. Using printk_ratelimited in Your Driver

Using rate-limited printk in a kernel module or device driver is straightforward. The API is a drop-in replacement for regular printk(). It takes the same arguments: a log level constant followed by a format string and optional arguments.

Basic syntax

printk_ratelimited(KERN_WARNING "mydriver: something went wrong: %d\n", error_code);

Complete minimal kernel module example

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/timer.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("EmbeddedPathashala");
MODULE_DESCRIPTION("Rate-limited printk demo — Linux 6.x");

static struct timer_list demo_timer;
static unsigned long fire_count = 0;

/* Timer callback — fires every 100ms */
static void timer_handler(struct timer_list *t)
{
    fire_count++;

    /*
     * This runs 10 times per second.
     * With rate limiting: only ~10 messages pass through
     * every 5 seconds. The rest are suppressed.
     */
    printk_ratelimited(KERN_WARNING
        "mymodule: timer fired (count=%lu)\n", fire_count);

    /* Re-arm the timer */
    mod_timer(&demo_timer, jiffies + msecs_to_jiffies(100));
}

static int __init demo_init(void)
{
    pr_info("mymodule: loaded\n");
    timer_setup(&demo_timer, timer_handler, 0);
    mod_timer(&demo_timer, jiffies + msecs_to_jiffies(100));
    return 0;
}

static void __exit demo_exit(void)
{
    del_timer_sync(&demo_timer);
    pr_info("mymodule: removed (total fires=%lu)\n", fire_count);
}

module_init(demo_init);
module_exit(demo_exit);

When you load this module and watch the kernel log with dmesg -w, you will see roughly 10 lines per 5-second window, followed by a suppressed-count line, rather than a flood of 50 lines every 5 seconds.

✅ Tip Always use printk_ratelimited() (with the d at the end). The older printk_ratelimit() (without the d) is deprecated and should not be used in new kernel code.

6. The pr_<foo>_ratelimited Macro Family

Just as the kernel provides the convenient pr_info(), pr_warn(), pr_err() shorthand macros for regular printk at specific log levels, it also provides rate-limited equivalents for every log level. These are cleaner, shorter, and the recommended way to do rate-limited logging in modern kernel code.

The complete list

pr_emerg_ratelimited(fmt, ...)   /* KERN_EMERG  — system unusable */
pr_alert_ratelimited(fmt, ...)   /* KERN_ALERT  — action must be taken immediately */
pr_crit_ratelimited(fmt, ...)    /* KERN_CRIT   — critical condition */
pr_err_ratelimited(fmt, ...)     /* KERN_ERR    — error condition */
pr_warn_ratelimited(fmt, ...)    /* KERN_WARNING — warning condition */
pr_notice_ratelimited(fmt, ...) /* KERN_NOTICE — normal but significant */
pr_info_ratelimited(fmt, ...)   /* KERN_INFO   — informational */

Notice there is no pr_debug_ratelimited() — debug messages are typically already conditional on CONFIG_DYNAMIC_DEBUG or similar mechanisms and don’t need rate limiting in the same way.

Example usage in a real driver scenario

#include <linux/module.h>
#include <linux/kernel.h>

/*
 * This simulates an interrupt handler in a network driver.
 * Network interrupts can fire thousands of times per second
 * under heavy load, so rate-limited logging is essential.
 */
static irqreturn_t mynic_interrupt(int irq, void *dev_id)
{
    u32 status = read_hw_status(dev_id);

    if (status & ERR_FIFO_OVERFLOW) {
        /*
         * FIFO overflow can happen in bursts.
         * Rate-limit prevents log flooding during
         * a network storm or sustained hardware error.
         */
        pr_warn_ratelimited("mynic: FIFO overflow detected (status=0x%08x)\n",
                            status);
        clear_fifo(dev_id);
    }

    if (status & ERR_LINK_DOWN) {
        /* Link events are rare — regular printk is fine here */
        pr_err("mynic: link down on port %d\n", get_port(dev_id));
    }

    return IRQ_HANDLED;
}

In the example above, a FIFO overflow can happen repeatedly in rapid succession. Using pr_warn_ratelimited() ensures the log stays readable without losing the information that overflows are occurring. A link-down event, being rare, does not need rate limiting.

7. When Should You Use Rate-Limited Logging?

Knowing when to reach for rate-limited printk versus regular printk is an important skill for kernel driver development. Here is a practical guide:

Rate-Limited vs Regular printk — Decision Guide
Code Location Call Frequency Recommended API Reason
Interrupt handler Very high (kHz) pr_warn_ratelimited() Prevents log flood
Timer callback High (10s-100s Hz) printk_ratelimited() Avoids buffer saturation
Hot path (network RX/TX) Very high pr_err_ratelimited() Error visibility without flooding
Module init / probe Once pr_info() / pr_err() No repetition risk
Error recovery path Low (rare errors) pr_err() Each occurrence matters
Hardware watchdog / retries Bursty pr_warn_ratelimited() Capture burst without overrun

8. How the Rate Limiter Decides — Flow Diagram

Every call to printk_ratelimited() goes through a decision path inside ___ratelimit(). The diagram below shows that path using inline HTML:

printk_ratelimited() Internal Decision Flow
printk_ratelimited() called
⏱ Has time window
expired?
YES
Reset window & counter
Print suppressed count
✅ Print message
NO
Count < burst
limit?
YES
✅ Print
message
NO
🚫 Suppress
+ count++
Rate Limiter State Variables
Variable Where Set Default (Linux 6.x) Effect
interval sysctl or DEFINE_RATELIMIT_STATE 5 seconds Time window duration
burst sysctl or DEFINE_RATELIMIT_STATE 10 messages Max messages per window
printed Auto-tracked per call site Resets each window Count of messages printed this window
missed Auto-tracked per call site Resets after reporting Count shown in “N callbacks suppressed” line

📌 Key Takeaways

  • Use printk_ratelimited() whenever a code path can fire at high frequency
  • The default is 10 messages per 5-second window, adjustable via /proc/sys/kernel/printk_ratelimit*
  • Suppressed messages are counted and reported — you never silently lose information about event frequency
  • The pr_<foo>_ratelimited() macros are the modern, preferred way to do rate-limited logging
  • Never use the deprecated printk_ratelimit() without the d in new code
  • Different call sites maintain independent rate-limit state — one noisy path does not suppress others

🎯 Interview Q&A — Rate-Limited printk

Q1. What is the purpose of rate-limited printk in Linux kernel drivers?
Rate-limited printk prevents the kernel log buffer from being flooded by repetitive messages from high-frequency code paths such as interrupt handlers or timer callbacks. It allows a limited number of messages through per time window and silently counts the rest, reporting the suppressed count when the window expires.
Q2. What is the default rate-limit window and burst count on Linux 6.x?
By default, the window is 5 seconds and the burst count is 10 messages. These are controlled by /proc/sys/kernel/printk_ratelimit and /proc/sys/kernel/printk_ratelimit_burst respectively.
Q3. What is the difference between printk_ratelimited() and printk_ratelimit()?
printk_ratelimited() (with d) is the current API — it is a complete macro that wraps printk() with a per-call-site rate limit state. printk_ratelimit() (without d) is an older, deprecated function that returned a boolean to let the caller decide whether to print. The newer form is cleaner, safer, and is what you should use in all new kernel code.
Q4. How does the kernel let you know how many messages were suppressed?
When the rate-limit window resets and logging resumes, the kernel automatically prints a line in the format N callbacks suppressed before the next actual message, where N is the count of suppressed messages. This is handled internally by ___ratelimit() in lib/ratelimit.c.
Q5. Does changing sysctl printk_ratelimit affect all rate-limited printks in the kernel?
It affects printk_ratelimited() calls that use the global default ratelimit state. Subsystems or drivers that initialize their own DEFINE_RATELIMIT_STATE() with explicit interval and burst values are not affected by the sysctl settings — they use their own independently tuned parameters.
Q6. Can you name all the pr_<foo>_ratelimited macros available in Linux 6.x?
pr_emerg_ratelimited(), pr_alert_ratelimited(), pr_crit_ratelimited(), pr_err_ratelimited(), pr_warn_ratelimited(), pr_notice_ratelimited(), and pr_info_ratelimited(). There is no debug-level variant as debug messages are handled through separate mechanisms like CONFIG_DYNAMIC_DEBUG.
Q7. In which kernel source file is the actual rate-limiting logic implemented?
The core rate-limiting logic is in lib/ratelimit.c, specifically in the ___ratelimit() function. The struct ratelimit_state that tracks per-call-site state is defined in include/linux/ratelimit.h.
🚀 Free Linux Kernel Programming Course

Explore the complete free kernel programming series on EmbeddedPathashala — from writing your first module to building production-quality device drivers.

View Full Course Index Device Driver Series

Leave a Reply

Your email address will not be published. Required fields are marked *