Commit 51a1d258 authored by John Ogness's avatar John Ogness Committed by Petr Mladek

printk: Keep non-panic-CPUs out of console lock

When in a panic situation, non-panic CPUs should avoid holding the
console lock so as not to contend with the panic CPU. This is already
implemented with abandon_console_lock_in_panic(), which is checked
after each printed line. However, non-panic CPUs should also avoid
trying to acquire the console lock during a panic.

Modify console_trylock() to fail and console_lock() to block() when
called from a non-panic CPU during a panic.
Signed-off-by: default avatarJohn Ogness <john.ogness@linutronix.de>
Reviewed-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20230717194607.145135-4-john.ogness@linutronix.de
parent 7b23a66d
...@@ -2583,6 +2583,25 @@ static int console_cpu_notify(unsigned int cpu) ...@@ -2583,6 +2583,25 @@ static int console_cpu_notify(unsigned int cpu)
return 0; return 0;
} }
/*
* Return true when this CPU should unlock console_sem without pushing all
* messages to the console. This reduces the chance that the console is
* locked when the panic CPU tries to use it.
*/
static bool abandon_console_lock_in_panic(void)
{
if (!panic_in_progress())
return false;
/*
* We can use raw_smp_processor_id() here because it is impossible for
* the task to be migrated to the panic_cpu, or away from it. If
* panic_cpu has already been set, and we're not currently executing on
* that CPU, then we never will be.
*/
return atomic_read(&panic_cpu) != raw_smp_processor_id();
}
/** /**
* console_lock - block the console subsystem from printing * console_lock - block the console subsystem from printing
* *
...@@ -2595,6 +2614,10 @@ void console_lock(void) ...@@ -2595,6 +2614,10 @@ void console_lock(void)
{ {
might_sleep(); might_sleep();
/* On panic, the console_lock must be left to the panic cpu. */
while (abandon_console_lock_in_panic())
msleep(1000);
down_console_sem(); down_console_sem();
if (console_suspended) if (console_suspended)
return; return;
...@@ -2613,6 +2636,9 @@ EXPORT_SYMBOL(console_lock); ...@@ -2613,6 +2636,9 @@ EXPORT_SYMBOL(console_lock);
*/ */
int console_trylock(void) int console_trylock(void)
{ {
/* On panic, the console_lock must be left to the panic cpu. */
if (abandon_console_lock_in_panic())
return 0;
if (down_trylock_console_sem()) if (down_trylock_console_sem())
return 0; return 0;
if (console_suspended) { if (console_suspended) {
...@@ -2631,25 +2657,6 @@ int is_console_locked(void) ...@@ -2631,25 +2657,6 @@ int is_console_locked(void)
} }
EXPORT_SYMBOL(is_console_locked); EXPORT_SYMBOL(is_console_locked);
/*
* Return true when this CPU should unlock console_sem without pushing all
* messages to the console. This reduces the chance that the console is
* locked when the panic CPU tries to use it.
*/
static bool abandon_console_lock_in_panic(void)
{
if (!panic_in_progress())
return false;
/*
* We can use raw_smp_processor_id() here because it is impossible for
* the task to be migrated to the panic_cpu, or away from it. If
* panic_cpu has already been set, and we're not currently executing on
* that CPU, then we never will be.
*/
return atomic_read(&panic_cpu) != raw_smp_processor_id();
}
/* /*
* Check if the given console is currently capable and allowed to print * Check if the given console is currently capable and allowed to print
* records. * records.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment