Merge branch 'core-printk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-printk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  ratelimit: Make suppressed output messages more useful
  printk: Remove ratelimit.h from kernel.h
  ratelimit: Fix/allow use in atomic contexts
  ratelimit: Use per ratelimit context locking
This commit is contained in:
Linus Torvalds 2009-12-05 09:50:22 -08:00
commit d0b093a8b5
8 changed files with 62 additions and 38 deletions

View file

@ -15,7 +15,6 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/typecheck.h> #include <linux/typecheck.h>
#include <linux/ratelimit.h>
#include <linux/dynamic_debug.h> #include <linux/dynamic_debug.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/bug.h> #include <asm/bug.h>
@ -241,8 +240,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
asmlinkage int printk(const char * fmt, ...) asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2))) __cold; __attribute__ ((format (printf, 1, 2))) __cold;
extern struct ratelimit_state printk_ratelimit_state; extern int __printk_ratelimit(const char *func);
extern int printk_ratelimit(void); #define printk_ratelimit() __printk_ratelimit(__func__)
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
unsigned int interval_msec); unsigned int interval_msec);

View file

@ -358,6 +358,7 @@ static const struct proto_ops name##_ops = { \
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/ratelimit.h>
extern struct ratelimit_state net_ratelimit_state; extern struct ratelimit_state net_ratelimit_state;
#endif #endif

View file

@ -1,20 +1,31 @@
#ifndef _LINUX_RATELIMIT_H #ifndef _LINUX_RATELIMIT_H
#define _LINUX_RATELIMIT_H #define _LINUX_RATELIMIT_H
#include <linux/param.h>
#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) #include <linux/param.h>
#define DEFAULT_RATELIMIT_BURST 10 #include <linux/spinlock_types.h>
#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ)
#define DEFAULT_RATELIMIT_BURST 10
struct ratelimit_state { struct ratelimit_state {
int interval; spinlock_t lock; /* protect the state */
int burst;
int printed; int interval;
int missed; int burst;
unsigned long begin; int printed;
int missed;
unsigned long begin;
}; };
#define DEFINE_RATELIMIT_STATE(name, interval, burst) \ #define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init) \
struct ratelimit_state name = {interval, burst,} \
struct ratelimit_state name = { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.interval = interval_init, \
.burst = burst_init, \
}
extern int __ratelimit(struct ratelimit_state *rs); extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
#endif #define __ratelimit(state) ___ratelimit(state, __func__)
#endif /* _LINUX_RATELIMIT_H */

View file

@ -33,6 +33,7 @@
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/ratelimit.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -1376,11 +1377,11 @@ late_initcall(disable_boot_consoles);
*/ */
DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10); DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
int printk_ratelimit(void) int __printk_ratelimit(const char *func)
{ {
return __ratelimit(&printk_ratelimit_state); return ___ratelimit(&printk_ratelimit_state, func);
} }
EXPORT_SYMBOL(printk_ratelimit); EXPORT_SYMBOL(__printk_ratelimit);
/** /**
* printk_timed_ratelimit - caller-controlled printk ratelimiting * printk_timed_ratelimit - caller-controlled printk ratelimiting

View file

@ -36,6 +36,7 @@
#include <linux/sysrq.h> #include <linux/sysrq.h>
#include <linux/highuid.h> #include <linux/highuid.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/ratelimit.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/initrd.h> #include <linux/initrd.h>
#include <linux/key.h> #include <linux/key.h>
@ -158,6 +159,8 @@ extern int no_unaligned_warning;
extern int unaligned_dump_stack; extern int unaligned_dump_stack;
#endif #endif
extern struct ratelimit_state printk_ratelimit_state;
#ifdef CONFIG_RT_MUTEXES #ifdef CONFIG_RT_MUTEXES
extern int max_lock_depth; extern int max_lock_depth;
#endif #endif

View file

@ -7,15 +7,12 @@
* parameter. Now every user can use their own standalone ratelimit_state. * parameter. Now every user can use their own standalone ratelimit_state.
* *
* This file is released under the GPLv2. * This file is released under the GPLv2.
*
*/ */
#include <linux/kernel.h> #include <linux/ratelimit.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/module.h> #include <linux/module.h>
static DEFINE_SPINLOCK(ratelimit_lock);
/* /*
* __ratelimit - rate limiting * __ratelimit - rate limiting
* @rs: ratelimit_state data * @rs: ratelimit_state data
@ -23,35 +20,43 @@ static DEFINE_SPINLOCK(ratelimit_lock);
* This enforces a rate limit: not more than @rs->ratelimit_burst callbacks * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks
* in every @rs->ratelimit_jiffies * in every @rs->ratelimit_jiffies
*/ */
int __ratelimit(struct ratelimit_state *rs) int ___ratelimit(struct ratelimit_state *rs, const char *func)
{ {
unsigned long flags; unsigned long flags;
int ret;
if (!rs->interval) if (!rs->interval)
return 1; return 1;
spin_lock_irqsave(&ratelimit_lock, flags); /*
* 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:
*/
if (!spin_trylock_irqsave(&rs->lock, flags))
return 1;
if (!rs->begin) if (!rs->begin)
rs->begin = jiffies; rs->begin = jiffies;
if (time_is_before_jiffies(rs->begin + rs->interval)) { if (time_is_before_jiffies(rs->begin + rs->interval)) {
if (rs->missed) if (rs->missed)
printk(KERN_WARNING "%s: %d callbacks suppressed\n", printk(KERN_WARNING "%s: %d callbacks suppressed\n",
__func__, rs->missed); func, rs->missed);
rs->begin = 0; rs->begin = 0;
rs->printed = 0; rs->printed = 0;
rs->missed = 0; rs->missed = 0;
} }
if (rs->burst && rs->burst > rs->printed) if (rs->burst && rs->burst > rs->printed) {
goto print; rs->printed++;
ret = 1;
} else {
rs->missed++;
ret = 0;
}
spin_unlock_irqrestore(&rs->lock, flags);
rs->missed++; return ret;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 0;
print:
rs->printed++;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 1;
} }
EXPORT_SYMBOL(__ratelimit); EXPORT_SYMBOL(___ratelimit);

View file

@ -10,7 +10,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/ratelimit.h>
#include <linux/init.h> #include <linux/init.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/sock.h> #include <net/sock.h>

View file

@ -24,6 +24,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ratelimit.h>
#include <net/sock.h> #include <net/sock.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>