diff options
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 444b770c9595..8fe465ac008a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/ratelimit.h> | 37 | #include <linux/ratelimit.h> |
38 | #include <linux/kmsg_dump.h> | 38 | #include <linux/kmsg_dump.h> |
39 | #include <linux/syslog.h> | 39 | #include <linux/syslog.h> |
40 | #include <linux/cpu.h> | ||
41 | #include <linux/notifier.h> | ||
40 | 42 | ||
41 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
42 | 44 | ||
@@ -985,6 +987,32 @@ void resume_console(void) | |||
985 | } | 987 | } |
986 | 988 | ||
987 | /** | 989 | /** |
990 | * console_cpu_notify - print deferred console messages after CPU hotplug | ||
991 | * @self: notifier struct | ||
992 | * @action: CPU hotplug event | ||
993 | * @hcpu: unused | ||
994 | * | ||
995 | * If printk() is called from a CPU that is not online yet, the messages | ||
996 | * will be spooled but will not show up on the console. This function is | ||
997 | * called when a new CPU comes online (or fails to come up), and ensures | ||
998 | * that any such output gets printed. | ||
999 | */ | ||
1000 | static int __cpuinit console_cpu_notify(struct notifier_block *self, | ||
1001 | unsigned long action, void *hcpu) | ||
1002 | { | ||
1003 | switch (action) { | ||
1004 | case CPU_ONLINE: | ||
1005 | case CPU_DEAD: | ||
1006 | case CPU_DYING: | ||
1007 | case CPU_DOWN_FAILED: | ||
1008 | case CPU_UP_CANCELED: | ||
1009 | acquire_console_sem(); | ||
1010 | release_console_sem(); | ||
1011 | } | ||
1012 | return NOTIFY_OK; | ||
1013 | } | ||
1014 | |||
1015 | /** | ||
988 | * acquire_console_sem - lock the console system for exclusive use. | 1016 | * acquire_console_sem - lock the console system for exclusive use. |
989 | * | 1017 | * |
990 | * Acquires a semaphore which guarantees that the caller has | 1018 | * Acquires a semaphore which guarantees that the caller has |
@@ -1371,7 +1399,7 @@ int unregister_console(struct console *console) | |||
1371 | } | 1399 | } |
1372 | EXPORT_SYMBOL(unregister_console); | 1400 | EXPORT_SYMBOL(unregister_console); |
1373 | 1401 | ||
1374 | static int __init disable_boot_consoles(void) | 1402 | static int __init printk_late_init(void) |
1375 | { | 1403 | { |
1376 | struct console *con; | 1404 | struct console *con; |
1377 | 1405 | ||
@@ -1382,9 +1410,10 @@ static int __init disable_boot_consoles(void) | |||
1382 | unregister_console(con); | 1410 | unregister_console(con); |
1383 | } | 1411 | } |
1384 | } | 1412 | } |
1413 | hotcpu_notifier(console_cpu_notify, 0); | ||
1385 | return 0; | 1414 | return 0; |
1386 | } | 1415 | } |
1387 | late_initcall(disable_boot_consoles); | 1416 | late_initcall(printk_late_init); |
1388 | 1417 | ||
1389 | #if defined CONFIG_PRINTK | 1418 | #if defined CONFIG_PRINTK |
1390 | 1419 | ||
@@ -1520,9 +1549,9 @@ void kmsg_dump(enum kmsg_dump_reason reason) | |||
1520 | chars = logged_chars; | 1549 | chars = logged_chars; |
1521 | spin_unlock_irqrestore(&logbuf_lock, flags); | 1550 | spin_unlock_irqrestore(&logbuf_lock, flags); |
1522 | 1551 | ||
1523 | if (logged_chars > end) { | 1552 | if (chars > end) { |
1524 | s1 = log_buf + log_buf_len - logged_chars + end; | 1553 | s1 = log_buf + log_buf_len - chars + end; |
1525 | l1 = logged_chars - end; | 1554 | l1 = chars - end; |
1526 | 1555 | ||
1527 | s2 = log_buf; | 1556 | s2 = log_buf; |
1528 | l2 = end; | 1557 | l2 = end; |
@@ -1530,8 +1559,8 @@ void kmsg_dump(enum kmsg_dump_reason reason) | |||
1530 | s1 = ""; | 1559 | s1 = ""; |
1531 | l1 = 0; | 1560 | l1 = 0; |
1532 | 1561 | ||
1533 | s2 = log_buf + end - logged_chars; | 1562 | s2 = log_buf + end - chars; |
1534 | l2 = logged_chars; | 1563 | l2 = chars; |
1535 | } | 1564 | } |
1536 | 1565 | ||
1537 | if (!spin_trylock_irqsave(&dump_list_lock, flags)) { | 1566 | if (!spin_trylock_irqsave(&dump_list_lock, flags)) { |