@@ -463,6 +463,13 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
463463/* syslog_lock protects syslog_* variables and write access to clear_seq. */
464464static 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 */
472479bool 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
475490DECLARE_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 */
27192734static 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);
37013717static 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