mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
ed76c07c68
Introduce FORCE_CON flag to printk. The new flag will make it possible to create a context where printk messages will never be suppressed. This mechanism will be used in the next patch to create a force_con context on sysrq handling, removing an existing workaround on the loglevel global variable. The workaround existed to make sure that sysrq header messages were sent to all consoles, but this doesn't work with deferred messages because the loglevel might be restored to its original value before a console flushes the messages. Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com> Reviewed-by: John Ogness <john.ogness@linutronix.de> Reviewed-by: Petr Mladek <pmladek@suse.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://lore.kernel.org/r/20241105-printk-loud-con-v2-1-bd3ecdf7b0e4@suse.com Signed-off-by: Petr Mladek <pmladek@suse.com>
89 lines
1.7 KiB
C
89 lines
1.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* printk_safe.c - Safe printk for printk-deadlock-prone contexts
|
|
*/
|
|
|
|
#include <linux/preempt.h>
|
|
#include <linux/kdb.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/kprobes.h>
|
|
|
|
#include "internal.h"
|
|
|
|
/* Context where printk messages are never suppressed */
|
|
static atomic_t force_con;
|
|
|
|
void printk_force_console_enter(void)
|
|
{
|
|
atomic_inc(&force_con);
|
|
}
|
|
|
|
void printk_force_console_exit(void)
|
|
{
|
|
atomic_dec(&force_con);
|
|
}
|
|
|
|
bool is_printk_force_console(void)
|
|
{
|
|
return atomic_read(&force_con);
|
|
}
|
|
|
|
static DEFINE_PER_CPU(int, printk_context);
|
|
|
|
/* Can be preempted by NMI. */
|
|
void __printk_safe_enter(void)
|
|
{
|
|
this_cpu_inc(printk_context);
|
|
}
|
|
|
|
/* Can be preempted by NMI. */
|
|
void __printk_safe_exit(void)
|
|
{
|
|
this_cpu_dec(printk_context);
|
|
}
|
|
|
|
void __printk_deferred_enter(void)
|
|
{
|
|
cant_migrate();
|
|
__printk_safe_enter();
|
|
}
|
|
|
|
void __printk_deferred_exit(void)
|
|
{
|
|
cant_migrate();
|
|
__printk_safe_exit();
|
|
}
|
|
|
|
bool is_printk_legacy_deferred(void)
|
|
{
|
|
/*
|
|
* The per-CPU variable @printk_context can be read safely in any
|
|
* context. CPU migration is always disabled when set.
|
|
*/
|
|
return (force_legacy_kthread() ||
|
|
this_cpu_read(printk_context) ||
|
|
in_nmi());
|
|
}
|
|
|
|
asmlinkage int vprintk(const char *fmt, va_list args)
|
|
{
|
|
#ifdef CONFIG_KGDB_KDB
|
|
/* Allow to pass printk() to kdb but avoid a recursion. */
|
|
if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0))
|
|
return vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args);
|
|
#endif
|
|
|
|
/*
|
|
* Use the main logbuf even in NMI. But avoid calling console
|
|
* drivers that might have their own locks.
|
|
*/
|
|
if (is_printk_legacy_deferred())
|
|
return vprintk_deferred(fmt, args);
|
|
|
|
/* No obstacles. */
|
|
return vprintk_default(fmt, args);
|
|
}
|
|
EXPORT_SYMBOL(vprintk);
|