diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2013-03-22 18:04:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-22 19:41:20 -0400 |
| commit | dc72c32e1fd872a9a4fdfe645283c9dcd68e556d (patch) | |
| tree | 66f817ecb840f59173de2a95a9a69fb5c3a75d21 /kernel | |
| parent | fe8d52614bd419cedef85ef55850fd090373f481 (diff) | |
printk: Provide a wake_up_klogd() off-case
wake_up_klogd() is useless when CONFIG_PRINTK=n because neither printk()
nor printk_sched() are in use and there are actually no waiter on
log_wait waitqueue. It should be a stub in this case for users like
bust_spinlocks().
Otherwise this results in this warning when CONFIG_PRINTK=n and
CONFIG_IRQ_WORK=n:
kernel/built-in.o In function `wake_up_klogd':
(.text.wake_up_klogd+0xb4): undefined reference to `irq_work_queue'
To fix this, provide an off-case for wake_up_klogd() when
CONFIG_PRINTK=n.
There is much more from console_unlock() and other console related code
in printk.c that should be moved under CONFIG_PRINTK. But for now,
focus on a minimal fix as we passed the merged window already.
[akpm@linux-foundation.org: include printk.h in bust_spinlocks.c]
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Reported-by: James Hogan <james.hogan@imgtec.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/printk.c | 80 |
1 files changed, 39 insertions, 41 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 0b31715f335a..abbdd9e2ac82 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -63,8 +63,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | |||
| 63 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ | 63 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ |
| 64 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ | 64 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ |
| 65 | 65 | ||
| 66 | DECLARE_WAIT_QUEUE_HEAD(log_wait); | ||
| 67 | |||
| 68 | int console_printk[4] = { | 66 | int console_printk[4] = { |
| 69 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ | 67 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ |
| 70 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ | 68 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ |
| @@ -224,6 +222,7 @@ struct log { | |||
| 224 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | 222 | static DEFINE_RAW_SPINLOCK(logbuf_lock); |
| 225 | 223 | ||
| 226 | #ifdef CONFIG_PRINTK | 224 | #ifdef CONFIG_PRINTK |
| 225 | DECLARE_WAIT_QUEUE_HEAD(log_wait); | ||
| 227 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | 226 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
| 228 | static u64 syslog_seq; | 227 | static u64 syslog_seq; |
| 229 | static u32 syslog_idx; | 228 | static u32 syslog_idx; |
| @@ -1957,45 +1956,6 @@ int is_console_locked(void) | |||
| 1957 | return console_locked; | 1956 | return console_locked; |
| 1958 | } | 1957 | } |
| 1959 | 1958 | ||
| 1960 | /* | ||
| 1961 | * Delayed printk version, for scheduler-internal messages: | ||
| 1962 | */ | ||
| 1963 | #define PRINTK_BUF_SIZE 512 | ||
| 1964 | |||
| 1965 | #define PRINTK_PENDING_WAKEUP 0x01 | ||
| 1966 | #define PRINTK_PENDING_SCHED 0x02 | ||
| 1967 | |||
| 1968 | static DEFINE_PER_CPU(int, printk_pending); | ||
| 1969 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
| 1970 | |||
| 1971 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | ||
| 1972 | { | ||
| 1973 | int pending = __this_cpu_xchg(printk_pending, 0); | ||
| 1974 | |||
| 1975 | if (pending & PRINTK_PENDING_SCHED) { | ||
| 1976 | char *buf = __get_cpu_var(printk_sched_buf); | ||
| 1977 | printk(KERN_WARNING "[sched_delayed] %s", buf); | ||
| 1978 | } | ||
| 1979 | |||
| 1980 | if (pending & PRINTK_PENDING_WAKEUP) | ||
| 1981 | wake_up_interruptible(&log_wait); | ||
| 1982 | } | ||
| 1983 | |||
| 1984 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
| 1985 | .func = wake_up_klogd_work_func, | ||
| 1986 | .flags = IRQ_WORK_LAZY, | ||
| 1987 | }; | ||
| 1988 | |||
| 1989 | void wake_up_klogd(void) | ||
| 1990 | { | ||
| 1991 | preempt_disable(); | ||
| 1992 | if (waitqueue_active(&log_wait)) { | ||
| 1993 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | ||
| 1994 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
| 1995 | } | ||
| 1996 | preempt_enable(); | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | static void console_cont_flush(char *text, size_t size) | 1959 | static void console_cont_flush(char *text, size_t size) |
| 2000 | { | 1960 | { |
| 2001 | unsigned long flags; | 1961 | unsigned long flags; |
| @@ -2458,6 +2418,44 @@ static int __init printk_late_init(void) | |||
| 2458 | late_initcall(printk_late_init); | 2418 | late_initcall(printk_late_init); |
| 2459 | 2419 | ||
| 2460 | #if defined CONFIG_PRINTK | 2420 | #if defined CONFIG_PRINTK |
| 2421 | /* | ||
| 2422 | * Delayed printk version, for scheduler-internal messages: | ||
| 2423 | */ | ||
| 2424 | #define PRINTK_BUF_SIZE 512 | ||
| 2425 | |||
| 2426 | #define PRINTK_PENDING_WAKEUP 0x01 | ||
| 2427 | #define PRINTK_PENDING_SCHED 0x02 | ||
| 2428 | |||
| 2429 | static DEFINE_PER_CPU(int, printk_pending); | ||
| 2430 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
| 2431 | |||
| 2432 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | ||
| 2433 | { | ||
| 2434 | int pending = __this_cpu_xchg(printk_pending, 0); | ||
| 2435 | |||
| 2436 | if (pending & PRINTK_PENDING_SCHED) { | ||
| 2437 | char *buf = __get_cpu_var(printk_sched_buf); | ||
| 2438 | printk(KERN_WARNING "[sched_delayed] %s", buf); | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | if (pending & PRINTK_PENDING_WAKEUP) | ||
| 2442 | wake_up_interruptible(&log_wait); | ||
| 2443 | } | ||
| 2444 | |||
| 2445 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
| 2446 | .func = wake_up_klogd_work_func, | ||
| 2447 | .flags = IRQ_WORK_LAZY, | ||
| 2448 | }; | ||
| 2449 | |||
| 2450 | void wake_up_klogd(void) | ||
| 2451 | { | ||
| 2452 | preempt_disable(); | ||
| 2453 | if (waitqueue_active(&log_wait)) { | ||
| 2454 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | ||
| 2455 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
| 2456 | } | ||
| 2457 | preempt_enable(); | ||
| 2458 | } | ||
| 2461 | 2459 | ||
| 2462 | int printk_sched(const char *fmt, ...) | 2460 | int printk_sched(const char *fmt, ...) |
| 2463 | { | 2461 | { |
