Commit 11a61205 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] generalise net_ratelimit (printk_ratelimit)

From: Anton Blanchard <anton@samba.org>

Generate a global printk rate-limiting function, printk_ratelimit().

Also, use it in the page allocator warning code.  Also add a dump_stack to
that code.

Later, we need to switch net_ratelimit() over to use printk_ratelimit().
parent 2b45d70f
...@@ -251,6 +251,25 @@ the different loglevels. ...@@ -251,6 +251,25 @@ the different loglevels.
============================================================== ==============================================================
printk_ratelimit:
Some warning messages are rate limited. printk_ratelimit specifies
the minimum length of time between these messages, by default we
allow one every 5 seconds.
A value of 0 will disable rate limiting.
==============================================================
printk_ratelimit_burst:
While long term we enforce one message per printk_ratelimit
seconds, we do allow a burst of messages to pass through.
printk_ratelimit_burst specifies the number of messages we can
send before ratelimiting kicks in.
==============================================================
reboot-cmd: (Sparc only) reboot-cmd: (Sparc only)
??? This seems to be a way to give an argument to the Sparc ??? This seems to be a way to give an argument to the Sparc
......
...@@ -89,6 +89,8 @@ asmlinkage int printk(const char * fmt, ...) ...@@ -89,6 +89,8 @@ asmlinkage int printk(const char * fmt, ...)
unsigned long int_sqrt(unsigned long); unsigned long int_sqrt(unsigned long);
extern int printk_ratelimit(void);
static inline void console_silent(void) static inline void console_silent(void)
{ {
console_loglevel = 0; console_loglevel = 0;
......
...@@ -127,6 +127,8 @@ enum ...@@ -127,6 +127,8 @@ enum
KERN_PANIC_ON_OOPS=57, /* int: whether we will panic on an oops */ KERN_PANIC_ON_OOPS=57, /* int: whether we will panic on an oops */
KERN_HPPA_PWRSW=58, /* int: hppa soft-power enable */ KERN_HPPA_PWRSW=58, /* int: hppa soft-power enable */
KERN_HPPA_UNALIGNED=59, /* int: hppa unaligned-trap enable */ KERN_HPPA_UNALIGNED=59, /* int: hppa unaligned-trap enable */
KERN_PRINTK_RATELIMIT=60, /* int: tune printk ratelimiting */
KERN_PRINTK_RATELIMIT_BURST=61, /* int: tune printk ratelimiting */
}; };
......
...@@ -763,3 +763,45 @@ void tty_write_message(struct tty_struct *tty, char *msg) ...@@ -763,3 +763,45 @@ void tty_write_message(struct tty_struct *tty, char *msg)
tty->driver->write(tty, 0, msg, strlen(msg)); tty->driver->write(tty, 0, msg, strlen(msg));
return; return;
} }
/* minimum time in jiffies between messages */
int printk_ratelimit_jiffies = 5*HZ;
/* number of messages we send before ratelimiting */
int printk_ratelimit_burst = 10;
/*
* printk rate limiting, lifted from the networking subsystem.
*
* This enforces a rate limit: not more than one kernel message
* every printk_ratelimit_jiffies to make a denial-of-service
* attack impossible.
*/
int printk_ratelimit(void)
{
static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
static unsigned long toks = 10*5*HZ;
static unsigned long last_msg;
static int missed;
unsigned long flags;
unsigned long now = jiffies;
spin_lock_irqsave(&ratelimit_lock, flags);
toks += now - last_msg;
last_msg = now;
if (toks > (printk_ratelimit_burst * printk_ratelimit_jiffies))
toks = printk_ratelimit_burst * printk_ratelimit_jiffies;
if (toks >= printk_ratelimit_jiffies) {
int lost = missed;
missed = 0;
toks -= printk_ratelimit_jiffies;
spin_unlock_irqrestore(&ratelimit_lock, flags);
if (lost)
printk(KERN_WARNING "printk: %d messages suppressed.\n", lost);
return 1;
}
missed++;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 0;
}
EXPORT_SYMBOL(printk_ratelimit);
...@@ -60,6 +60,8 @@ extern int cad_pid; ...@@ -60,6 +60,8 @@ extern int cad_pid;
extern int pid_max; extern int pid_max;
extern int sysctl_lower_zone_protection; extern int sysctl_lower_zone_protection;
extern int min_free_kbytes; extern int min_free_kbytes;
extern int printk_ratelimit_jiffies;
extern int printk_ratelimit_burst;
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535; static int maxolduid = 65535;
...@@ -579,6 +581,22 @@ static ctl_table kern_table[] = { ...@@ -579,6 +581,22 @@ static ctl_table kern_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = &proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{
.ctl_name = KERN_PRINTK_RATELIMIT,
.procname = "printk_ratelimit",
.data = &printk_ratelimit_jiffies,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = KERN_PRINTK_RATELIMIT_BURST,
.procname = "printk_ratelimit_burst",
.data = &printk_ratelimit_burst,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{ .ctl_name = 0 } { .ctl_name = 0 }
}; };
......
...@@ -669,10 +669,11 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, ...@@ -669,10 +669,11 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
} }
nopage: nopage:
if (!(gfp_mask & __GFP_NOWARN)) { if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit()) {
printk("%s: page allocation failure." printk(KERN_WARNING "%s: page allocation failure."
" order:%d, mode:0x%x\n", " order:%d, mode:0x%x\n",
p->comm, order, gfp_mask); p->comm, order, gfp_mask);
dump_stack();
} }
return NULL; return NULL;
got_pg: got_pg:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment