Skip to content

Commit 6001306

Browse files
jognesspmladek
authored andcommitted
printk: Avoid console_lock dance if no legacy or boot consoles
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 <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Petr Mladek <[email protected]>
1 parent 5dde3b7 commit 6001306

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

kernel/printk/printk.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,13 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
463463
/* syslog_lock protects syslog_* variables and write access to clear_seq. */
464464
static DEFINE_MUTEX(syslog_lock);
465465

466+
/*
467+
* Specifies if a legacy console is registered. If legacy consoles are
468+
* present, it is necessary to perform the console lock/unlock dance
469+
* whenever console flushing should occur.
470+
*/
471+
static bool have_legacy_console;
472+
466473
/*
467474
* Specifies if a boot console is registered. If boot consoles are present,
468475
* nbcon consoles cannot print simultaneously and must be synchronized by
@@ -471,6 +478,14 @@ static DEFINE_MUTEX(syslog_lock);
471478
*/
472479
bool have_boot_console;
473480

481+
/*
482+
* Specifies if the console lock/unlock dance is needed for console
483+
* printing. If @have_boot_console is true, the nbcon consoles will
484+
* be printed serially along with the legacy consoles because nbcon
485+
* consoles cannot print simultaneously with boot consoles.
486+
*/
487+
#define printing_via_unlock (have_legacy_console || have_boot_console)
488+
474489
#ifdef CONFIG_PRINTK
475490
DECLARE_WAIT_QUEUE_HEAD(log_wait);
476491
/* All 3 protected by @syslog_lock. */
@@ -2339,7 +2354,7 @@ asmlinkage int vprintk_emit(int facility, int level,
23392354
printed_len = vprintk_store(facility, level, dev_info, fmt, args);
23402355

23412356
/* If called from the scheduler, we can not call up(). */
2342-
if (!in_sched) {
2357+
if (!in_sched && printing_via_unlock) {
23432358
/*
23442359
* The caller may be holding system-critical or
23452360
* timing-sensitive locks. Disable preemption during
@@ -2359,7 +2374,7 @@ asmlinkage int vprintk_emit(int facility, int level,
23592374
preempt_enable();
23602375
}
23612376

2362-
if (in_sched)
2377+
if (in_sched && printing_via_unlock)
23632378
defer_console_output();
23642379
else
23652380
wake_up_klogd();
@@ -2718,7 +2733,7 @@ void resume_console(void)
27182733
*/
27192734
static int console_cpu_notify(unsigned int cpu)
27202735
{
2721-
if (!cpuhp_tasks_frozen) {
2736+
if (!cpuhp_tasks_frozen && printing_via_unlock) {
27222737
/* If trylock fails, someone else is doing the printing */
27232738
if (console_trylock())
27242739
console_unlock();
@@ -3625,6 +3640,7 @@ void register_console(struct console *newcon)
36253640
if (newcon->flags & CON_NBCON) {
36263641
nbcon_seq_force(newcon, init_seq);
36273642
} else {
3643+
have_legacy_console = true;
36283644
newcon->seq = init_seq;
36293645
}
36303646

@@ -3701,6 +3717,7 @@ EXPORT_SYMBOL(register_console);
37013717
static int unregister_console_locked(struct console *console)
37023718
{
37033719
bool use_device_lock = (console->flags & CON_NBCON) && console->write_atomic;
3720+
bool found_legacy_con = false;
37043721
bool found_boot_con = false;
37053722
unsigned long flags;
37063723
struct console *c;
@@ -3768,9 +3785,13 @@ static int unregister_console_locked(struct console *console)
37683785
for_each_console(c) {
37693786
if (c->flags & CON_BOOT)
37703787
found_boot_con = true;
3788+
if (!(c->flags & CON_NBCON))
3789+
found_legacy_con = true;
37713790
}
37723791
if (!found_boot_con)
37733792
have_boot_console = found_boot_con;
3793+
if (!found_legacy_con)
3794+
have_legacy_console = found_legacy_con;
37743795

37753796
return res;
37763797
}
@@ -3931,8 +3952,10 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
39313952
seq = prb_next_reserve_seq(prb);
39323953

39333954
/* Flush the consoles so that records up to @seq are printed. */
3934-
console_lock();
3935-
console_unlock();
3955+
if (printing_via_unlock) {
3956+
console_lock();
3957+
console_unlock();
3958+
}
39363959

39373960
for (;;) {
39383961
unsigned long begin_jiffies;
@@ -3945,6 +3968,12 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
39453968
* console->seq. Releasing console_lock flushes more
39463969
* records in case @seq is still not printed on all
39473970
* usable consoles.
3971+
*
3972+
* Holding the console_lock is not necessary if there
3973+
* are no legacy or boot consoles. However, such a
3974+
* console could register at any time. Always hold the
3975+
* console_lock as a precaution rather than
3976+
* synchronizing against register_console().
39483977
*/
39493978
console_lock();
39503979

0 commit comments

Comments
 (0)