Konstantin Demin
c3d09a3e94
imported from https://salsa.debian.org/kernel-team/linux.git commit 9d5cc9d9d6501d7f1dd7e194d4b245bd0b6c6a22 version 6.11.4-1
140 lines
4.7 KiB
Diff
140 lines
4.7 KiB
Diff
From: John Ogness <john.ogness@linutronix.de>
|
|
Date: Tue, 20 Aug 2024 08:35:53 +0206
|
|
Subject: [PATCH 27/54] printk: Avoid console_lock dance if no legacy or boot
|
|
consoles
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz
|
|
|
|
Currently the console lock is used to attempt legacy-type
|
|
printing even if there are no legacy or boot consoles registered.
|
|
If no such consoles are registered, the console lock does not
|
|
need to be taken.
|
|
|
|
Add tracking of legacy console registration and use it with
|
|
boot console tracking to avoid unnecessary code paths, i.e.
|
|
do not use the console lock if there are no boot consoles
|
|
and no legacy consoles.
|
|
|
|
Signed-off-by: John Ogness <john.ogness@linutronix.de>
|
|
Reviewed-by: Petr Mladek <pmladek@suse.com>
|
|
Link: https://lore.kernel.org/r/20240820063001.36405-28-john.ogness@linutronix.de
|
|
Signed-off-by: Petr Mladek <pmladek@suse.com>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
kernel/printk/printk.c | 39 ++++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 34 insertions(+), 5 deletions(-)
|
|
|
|
--- a/kernel/printk/printk.c
|
|
+++ b/kernel/printk/printk.c
|
|
@@ -464,6 +464,13 @@ static int console_msg_format = MSG_FORM
|
|
static DEFINE_MUTEX(syslog_lock);
|
|
|
|
/*
|
|
+ * Specifies if a legacy console is registered. If legacy consoles are
|
|
+ * present, it is necessary to perform the console lock/unlock dance
|
|
+ * whenever console flushing should occur.
|
|
+ */
|
|
+static bool have_legacy_console;
|
|
+
|
|
+/*
|
|
* Specifies if a boot console is registered. If boot consoles are present,
|
|
* nbcon consoles cannot print simultaneously and must be synchronized by
|
|
* the console lock. This is because boot consoles and nbcon consoles may
|
|
@@ -471,6 +478,14 @@ static DEFINE_MUTEX(syslog_lock);
|
|
*/
|
|
bool have_boot_console;
|
|
|
|
+/*
|
|
+ * Specifies if the console lock/unlock dance is needed for console
|
|
+ * printing. If @have_boot_console is true, the nbcon consoles will
|
|
+ * be printed serially along with the legacy consoles because nbcon
|
|
+ * consoles cannot print simultaneously with boot consoles.
|
|
+ */
|
|
+#define printing_via_unlock (have_legacy_console || have_boot_console)
|
|
+
|
|
#ifdef CONFIG_PRINTK
|
|
DECLARE_WAIT_QUEUE_HEAD(log_wait);
|
|
/* All 3 protected by @syslog_lock. */
|
|
@@ -2339,7 +2354,7 @@ asmlinkage int vprintk_emit(int facility
|
|
printed_len = vprintk_store(facility, level, dev_info, fmt, args);
|
|
|
|
/* If called from the scheduler, we can not call up(). */
|
|
- if (!in_sched) {
|
|
+ if (!in_sched && printing_via_unlock) {
|
|
/*
|
|
* The caller may be holding system-critical or
|
|
* timing-sensitive locks. Disable preemption during
|
|
@@ -2359,7 +2374,7 @@ asmlinkage int vprintk_emit(int facility
|
|
preempt_enable();
|
|
}
|
|
|
|
- if (in_sched)
|
|
+ if (in_sched && printing_via_unlock)
|
|
defer_console_output();
|
|
else
|
|
wake_up_klogd();
|
|
@@ -2719,7 +2734,7 @@ void resume_console(void)
|
|
*/
|
|
static int console_cpu_notify(unsigned int cpu)
|
|
{
|
|
- if (!cpuhp_tasks_frozen) {
|
|
+ if (!cpuhp_tasks_frozen && printing_via_unlock) {
|
|
/* If trylock fails, someone else is doing the printing */
|
|
if (console_trylock())
|
|
console_unlock();
|
|
@@ -3626,6 +3641,7 @@ void register_console(struct console *ne
|
|
if (newcon->flags & CON_NBCON) {
|
|
nbcon_seq_force(newcon, init_seq);
|
|
} else {
|
|
+ have_legacy_console = true;
|
|
newcon->seq = init_seq;
|
|
}
|
|
|
|
@@ -3702,6 +3718,7 @@ EXPORT_SYMBOL(register_console);
|
|
static int unregister_console_locked(struct console *console)
|
|
{
|
|
bool use_device_lock = (console->flags & CON_NBCON) && console->write_atomic;
|
|
+ bool found_legacy_con = false;
|
|
bool found_boot_con = false;
|
|
unsigned long flags;
|
|
struct console *c;
|
|
@@ -3769,9 +3786,13 @@ static int unregister_console_locked(str
|
|
for_each_console(c) {
|
|
if (c->flags & CON_BOOT)
|
|
found_boot_con = true;
|
|
+ if (!(c->flags & CON_NBCON))
|
|
+ found_legacy_con = true;
|
|
}
|
|
if (!found_boot_con)
|
|
have_boot_console = found_boot_con;
|
|
+ if (!found_legacy_con)
|
|
+ have_legacy_console = found_legacy_con;
|
|
|
|
return res;
|
|
}
|
|
@@ -3932,8 +3953,10 @@ static bool __pr_flush(struct console *c
|
|
seq = prb_next_reserve_seq(prb);
|
|
|
|
/* Flush the consoles so that records up to @seq are printed. */
|
|
- console_lock();
|
|
- console_unlock();
|
|
+ if (printing_via_unlock) {
|
|
+ console_lock();
|
|
+ console_unlock();
|
|
+ }
|
|
|
|
for (;;) {
|
|
unsigned long begin_jiffies;
|
|
@@ -3946,6 +3969,12 @@ static bool __pr_flush(struct console *c
|
|
* console->seq. Releasing console_lock flushes more
|
|
* records in case @seq is still not printed on all
|
|
* usable consoles.
|
|
+ *
|
|
+ * Holding the console_lock is not necessary if there
|
|
+ * are no legacy or boot consoles. However, such a
|
|
+ * console could register at any time. Always hold the
|
|
+ * console_lock as a precaution rather than
|
|
+ * synchronizing against register_console().
|
|
*/
|
|
console_lock();
|
|
|