Commit 034260d6779087431a8b2f67589c68b919299e5c

Authored by Kevin Cernekee
Committed by Ralf Baechle
1 parent d745866e4d

printk: fix delayed messages from CPU hotplug events

When a secondary CPU is being brought up, it is not uncommon for
printk() to be invoked when cpu_online(smp_processor_id()) == 0.  The
case that I witnessed personally was on MIPS:

http://lkml.org/lkml/2010/5/30/4

If (can_use_console() == 0), printk() will spool its output to log_buf
and it will be visible in "dmesg", but that output will NOT be echoed to
the console until somebody calls release_console_sem() from a CPU that
is online.  Therefore, the boot time messages from the new CPU can get
stuck in "limbo" for a long time, and might suddenly appear on the
screen when a completely unrelated event (e.g. "eth0: link is down")
occurs.

This patch modifies the console code so that any pending messages are
automatically flushed out to the console whenever a CPU hotplug
operation completes successfully or aborts.

The issue was seen on 2.6.34.

Original patch by Kevin Cernekee with cleanups by akpm and additional fixes
by Santosh Shilimkar.  This patch superseeds
https://patchwork.linux-mips.org/patch/1357/.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
To: <mingo@elte.hu>
To: <akpm@linux-foundation.org>
To: <simon.kagstrom@netinsight.net>
To: <David.Woodhouse@intel.com>
To: <lethal@linux-sh.org>
Cc: <linux-kernel@vger.kernel.org>
Cc: <linux-mips@linux-mips.org>
Reviewed-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/1534/
LKML-Reference: <ede63b5a20af951c755736f035d1e787772d7c28@localhost>
LKML-Reference: <EAF47CD23C76F840A9E7FCE10091EFAB02C5DB6D1F@dbde02.ent.ti.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 1 changed file with 31 additions and 2 deletions Side-by-side Diff

... ... @@ -37,6 +37,8 @@
37 37 #include <linux/ratelimit.h>
38 38 #include <linux/kmsg_dump.h>
39 39 #include <linux/syslog.h>
  40 +#include <linux/cpu.h>
  41 +#include <linux/notifier.h>
40 42  
41 43 #include <asm/uaccess.h>
42 44  
... ... @@ -985,6 +987,32 @@
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 1016 * acquire_console_sem - lock the console system for exclusive use.
989 1017 *
990 1018 * Acquires a semaphore which guarantees that the caller has
... ... @@ -1371,7 +1399,7 @@
1371 1399 }
1372 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 1404 struct console *con;
1377 1405  
1378 1406  
... ... @@ -1382,9 +1410,10 @@
1382 1410 unregister_console(con);
1383 1411 }
1384 1412 }
  1413 + hotcpu_notifier(console_cpu_notify, 0);
1385 1414 return 0;
1386 1415 }
1387   -late_initcall(disable_boot_consoles);
  1416 +late_initcall(printk_late_init);
1388 1417  
1389 1418 #if defined CONFIG_PRINTK
1390 1419