aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c89
1 files changed, 50 insertions, 39 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 267ce780abe8..abbdd9e2ac82 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -42,6 +42,7 @@
42#include <linux/notifier.h> 42#include <linux/notifier.h>
43#include <linux/rculist.h> 43#include <linux/rculist.h>
44#include <linux/poll.h> 44#include <linux/poll.h>
45#include <linux/irq_work.h>
45 46
46#include <asm/uaccess.h> 47#include <asm/uaccess.h>
47 48
@@ -62,8 +63,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
62#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ 63#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
63#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ 64#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
64 65
65DECLARE_WAIT_QUEUE_HEAD(log_wait);
66
67int console_printk[4] = { 66int console_printk[4] = {
68 DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ 67 DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
69 DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ 68 DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
@@ -87,6 +86,12 @@ static DEFINE_SEMAPHORE(console_sem);
87struct console *console_drivers; 86struct console *console_drivers;
88EXPORT_SYMBOL_GPL(console_drivers); 87EXPORT_SYMBOL_GPL(console_drivers);
89 88
89#ifdef CONFIG_LOCKDEP
90static struct lockdep_map console_lock_dep_map = {
91 .name = "console_lock"
92};
93#endif
94
90/* 95/*
91 * This is used for debugging the mess that is the VT code by 96 * This is used for debugging the mess that is the VT code by
92 * keeping track if we have the console semaphore held. It's 97 * keeping track if we have the console semaphore held. It's
@@ -217,6 +222,7 @@ struct log {
217static DEFINE_RAW_SPINLOCK(logbuf_lock); 222static DEFINE_RAW_SPINLOCK(logbuf_lock);
218 223
219#ifdef CONFIG_PRINTK 224#ifdef CONFIG_PRINTK
225DECLARE_WAIT_QUEUE_HEAD(log_wait);
220/* 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 */
221static u64 syslog_seq; 227static u64 syslog_seq;
222static u32 syslog_idx; 228static u32 syslog_idx;
@@ -1918,6 +1924,7 @@ void console_lock(void)
1918 return; 1924 return;
1919 console_locked = 1; 1925 console_locked = 1;
1920 console_may_schedule = 1; 1926 console_may_schedule = 1;
1927 mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
1921} 1928}
1922EXPORT_SYMBOL(console_lock); 1929EXPORT_SYMBOL(console_lock);
1923 1930
@@ -1939,6 +1946,7 @@ int console_trylock(void)
1939 } 1946 }
1940 console_locked = 1; 1947 console_locked = 1;
1941 console_may_schedule = 0; 1948 console_may_schedule = 0;
1949 mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_);
1942 return 1; 1950 return 1;
1943} 1951}
1944EXPORT_SYMBOL(console_trylock); 1952EXPORT_SYMBOL(console_trylock);
@@ -1948,43 +1956,6 @@ int is_console_locked(void)
1948 return console_locked; 1956 return console_locked;
1949} 1957}
1950 1958
1951/*
1952 * Delayed printk version, for scheduler-internal messages:
1953 */
1954#define PRINTK_BUF_SIZE 512
1955
1956#define PRINTK_PENDING_WAKEUP 0x01
1957#define PRINTK_PENDING_SCHED 0x02
1958
1959static DEFINE_PER_CPU(int, printk_pending);
1960static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
1961
1962void printk_tick(void)
1963{
1964 if (__this_cpu_read(printk_pending)) {
1965 int pending = __this_cpu_xchg(printk_pending, 0);
1966 if (pending & PRINTK_PENDING_SCHED) {
1967 char *buf = __get_cpu_var(printk_sched_buf);
1968 printk(KERN_WARNING "[sched_delayed] %s", buf);
1969 }
1970 if (pending & PRINTK_PENDING_WAKEUP)
1971 wake_up_interruptible(&log_wait);
1972 }
1973}
1974
1975int printk_needs_cpu(int cpu)
1976{
1977 if (cpu_is_offline(cpu))
1978 printk_tick();
1979 return __this_cpu_read(printk_pending);
1980}
1981
1982void wake_up_klogd(void)
1983{
1984 if (waitqueue_active(&log_wait))
1985 this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
1986}
1987
1988static void console_cont_flush(char *text, size_t size) 1959static void console_cont_flush(char *text, size_t size)
1989{ 1960{
1990 unsigned long flags; 1961 unsigned long flags;
@@ -2099,6 +2070,7 @@ skip:
2099 local_irq_restore(flags); 2070 local_irq_restore(flags);
2100 } 2071 }
2101 console_locked = 0; 2072 console_locked = 0;
2073 mutex_release(&console_lock_dep_map, 1, _RET_IP_);
2102 2074
2103 /* Release the exclusive_console once it is used */ 2075 /* Release the exclusive_console once it is used */
2104 if (unlikely(exclusive_console)) 2076 if (unlikely(exclusive_console))
@@ -2446,6 +2418,44 @@ static int __init printk_late_init(void)
2446late_initcall(printk_late_init); 2418late_initcall(printk_late_init);
2447 2419
2448#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
2429static DEFINE_PER_CPU(int, printk_pending);
2430static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
2431
2432static 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
2445static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
2446 .func = wake_up_klogd_work_func,
2447 .flags = IRQ_WORK_LAZY,
2448};
2449
2450void 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}
2449 2459
2450int printk_sched(const char *fmt, ...) 2460int printk_sched(const char *fmt, ...)
2451{ 2461{
@@ -2462,6 +2472,7 @@ int printk_sched(const char *fmt, ...)
2462 va_end(args); 2472 va_end(args);
2463 2473
2464 __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); 2474 __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
2475 irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
2465 local_irq_restore(flags); 2476 local_irq_restore(flags);
2466 2477
2467 return r; 2478 return r;