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

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
Loading
Loading
Loading
Loading
+26 −19
Original line number Diff line number Diff line
@@ -2583,6 +2583,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
 *
@@ -2595,6 +2614,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;
@@ -2613,6 +2636,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) {
@@ -2631,25 +2657,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.