Skip to content

Commit

Permalink
printk: Keep non-panic-CPUs out of console lock
Browse files Browse the repository at this point in the history
[ Upstream commit 51a1d25 ]

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: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20230717194607.145135-4-john.ogness@linutronix.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jogness authored and gregkh committed Sep 23, 2023
1 parent d301aa3 commit 0fb8391
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions kernel/printk/printk.c
Expand Up @@ -2585,6 +2585,25 @@ static int console_cpu_notify(unsigned int cpu)
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
*
Expand All @@ -2597,6 +2616,10 @@ void console_lock(void)
{
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();
if (console_suspended)
return;
Expand All @@ -2615,6 +2638,9 @@ EXPORT_SYMBOL(console_lock);
*/
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())
return 0;
if (console_suspended) {
Expand All @@ -2633,25 +2659,6 @@ int is_console_locked(void)
}
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
* records.
Expand Down

0 comments on commit 0fb8391

Please sign in to comment.