@@ -463,6 +463,13 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
463
463
/* syslog_lock protects syslog_* variables and write access to clear_seq. */
464
464
static DEFINE_MUTEX (syslog_lock );
465
465
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
+
466
473
/*
467
474
* Specifies if a boot console is registered. If boot consoles are present,
468
475
* nbcon consoles cannot print simultaneously and must be synchronized by
@@ -471,6 +478,14 @@ static DEFINE_MUTEX(syslog_lock);
471
478
*/
472
479
bool have_boot_console ;
473
480
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
+
474
489
#ifdef CONFIG_PRINTK
475
490
DECLARE_WAIT_QUEUE_HEAD (log_wait );
476
491
/* All 3 protected by @syslog_lock. */
@@ -2339,7 +2354,7 @@ asmlinkage int vprintk_emit(int facility, int level,
2339
2354
printed_len = vprintk_store (facility , level , dev_info , fmt , args );
2340
2355
2341
2356
/* If called from the scheduler, we can not call up(). */
2342
- if (!in_sched ) {
2357
+ if (!in_sched && printing_via_unlock ) {
2343
2358
/*
2344
2359
* The caller may be holding system-critical or
2345
2360
* timing-sensitive locks. Disable preemption during
@@ -2359,7 +2374,7 @@ asmlinkage int vprintk_emit(int facility, int level,
2359
2374
preempt_enable ();
2360
2375
}
2361
2376
2362
- if (in_sched )
2377
+ if (in_sched && printing_via_unlock )
2363
2378
defer_console_output ();
2364
2379
else
2365
2380
wake_up_klogd ();
@@ -2718,7 +2733,7 @@ void resume_console(void)
2718
2733
*/
2719
2734
static int console_cpu_notify (unsigned int cpu )
2720
2735
{
2721
- if (!cpuhp_tasks_frozen ) {
2736
+ if (!cpuhp_tasks_frozen && printing_via_unlock ) {
2722
2737
/* If trylock fails, someone else is doing the printing */
2723
2738
if (console_trylock ())
2724
2739
console_unlock ();
@@ -3625,6 +3640,7 @@ void register_console(struct console *newcon)
3625
3640
if (newcon -> flags & CON_NBCON ) {
3626
3641
nbcon_seq_force (newcon , init_seq );
3627
3642
} else {
3643
+ have_legacy_console = true;
3628
3644
newcon -> seq = init_seq ;
3629
3645
}
3630
3646
@@ -3701,6 +3717,7 @@ EXPORT_SYMBOL(register_console);
3701
3717
static int unregister_console_locked (struct console * console )
3702
3718
{
3703
3719
bool use_device_lock = (console -> flags & CON_NBCON ) && console -> write_atomic ;
3720
+ bool found_legacy_con = false;
3704
3721
bool found_boot_con = false;
3705
3722
unsigned long flags ;
3706
3723
struct console * c ;
@@ -3768,9 +3785,13 @@ static int unregister_console_locked(struct console *console)
3768
3785
for_each_console (c ) {
3769
3786
if (c -> flags & CON_BOOT )
3770
3787
found_boot_con = true;
3788
+ if (!(c -> flags & CON_NBCON ))
3789
+ found_legacy_con = true;
3771
3790
}
3772
3791
if (!found_boot_con )
3773
3792
have_boot_console = found_boot_con ;
3793
+ if (!found_legacy_con )
3794
+ have_legacy_console = found_legacy_con ;
3774
3795
3775
3796
return res ;
3776
3797
}
@@ -3931,8 +3952,10 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
3931
3952
seq = prb_next_reserve_seq (prb );
3932
3953
3933
3954
/* 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
+ }
3936
3959
3937
3960
for (;;) {
3938
3961
unsigned long begin_jiffies ;
@@ -3945,6 +3968,12 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
3945
3968
* console->seq. Releasing console_lock flushes more
3946
3969
* records in case @seq is still not printed on all
3947
3970
* 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().
3948
3977
*/
3949
3978
console_lock ();
3950
3979
0 commit comments