@@ -86,8 +86,8 @@ EXPORT_SYMBOL(oops_in_progress);
8686static DEFINE_MUTEX (console_mutex );
8787
8888/*
89- * console_sem protects console_list and console->flags updates, and also
90- * provides serialization for access to the entire console driver system .
89+ * console_sem protects updates to console->seq and console_suspended,
90+ * and also provides serialization for console printing .
9191 */
9292static DEFINE_SEMAPHORE (console_sem );
9393HLIST_HEAD (console_list );
@@ -2640,10 +2640,10 @@ static int console_cpu_notify(unsigned int cpu)
26402640}
26412641
26422642/**
2643- * console_lock - lock the console system for exclusive use.
2643+ * console_lock - block the console subsystem from printing
26442644 *
2645- * Acquires a lock which guarantees that the caller has
2646- * exclusive access to the console system and console_list .
2645+ * Acquires a lock which guarantees that no consoles will
2646+ * be in or enter their write() callback .
26472647 *
26482648 * Can sleep, returns nothing.
26492649 */
@@ -2660,10 +2660,10 @@ void console_lock(void)
26602660EXPORT_SYMBOL (console_lock );
26612661
26622662/**
2663- * console_trylock - try to lock the console system for exclusive use.
2663+ * console_trylock - try to block the console subsystem from printing
26642664 *
2665- * Try to acquire a lock which guarantees that the caller has exclusive
2666- * access to the console system and console_list .
2665+ * Try to acquire a lock which guarantees that no consoles will
2666+ * be in or enter their write() callback .
26672667 *
26682668 * returns 1 on success, and 0 on failure to acquire the lock.
26692669 */
@@ -2920,10 +2920,10 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
29202920}
29212921
29222922/**
2923- * console_unlock - unlock the console system
2923+ * console_unlock - unblock the console subsystem from printing
29242924 *
2925- * Releases the console_lock which the caller holds on the console system
2926- * and the console driver list .
2925+ * Releases the console_lock which the caller holds to block printing of
2926+ * the console subsystem .
29272927 *
29282928 * While the console_lock was held, console output may have been buffered
29292929 * by printk(). If this is the case, console_unlock(); emits
@@ -3110,9 +3110,7 @@ void console_stop(struct console *console)
31103110{
31113111 __pr_flush (console , 1000 , true);
31123112 console_list_lock ();
3113- console_lock ();
31143113 console_srcu_write_flags (console , console -> flags & ~CON_ENABLED );
3115- console_unlock ();
31163114 console_list_unlock ();
31173115
31183116 /*
@@ -3128,9 +3126,7 @@ EXPORT_SYMBOL(console_stop);
31283126void console_start (struct console * console )
31293127{
31303128 console_list_lock ();
3131- console_lock ();
31323129 console_srcu_write_flags (console , console -> flags | CON_ENABLED );
3133- console_unlock ();
31343130 console_list_unlock ();
31353131 __pr_flush (console , 1000 , true);
31363132}
@@ -3247,6 +3243,12 @@ static void console_init_seq(struct console *newcon, bool bootcon_registered)
32473243 * the furthest behind.
32483244 */
32493245 if (bootcon_registered && !keep_bootcon ) {
3246+ /*
3247+ * Hold the console_lock to stop console printing and
3248+ * guarantee safe access to console->seq.
3249+ */
3250+ console_lock ();
3251+
32503252 /*
32513253 * Flush all consoles and set the console to start at
32523254 * the next unprinted sequence number.
@@ -3273,6 +3275,8 @@ static void console_init_seq(struct console *newcon, bool bootcon_registered)
32733275 }
32743276 }
32753277 }
3278+
3279+ console_unlock ();
32763280 }
32773281 }
32783282}
@@ -3371,7 +3375,6 @@ void register_console(struct console *newcon)
33713375 }
33723376
33733377 newcon -> dropped = 0 ;
3374- console_lock ();
33753378 console_init_seq (newcon , bootcon_registered );
33763379
33773380 /*
@@ -3391,7 +3394,6 @@ void register_console(struct console *newcon)
33913394 } else {
33923395 hlist_add_behind_rcu (& newcon -> node , console_list .first );
33933396 }
3394- console_unlock ();
33953397
33963398 /*
33973399 * No need to synchronize SRCU here! The caller does not rely
@@ -3439,15 +3441,11 @@ static int unregister_console_locked(struct console *console)
34393441 if (res > 0 )
34403442 return 0 ;
34413443
3442- console_lock ();
3443-
34443444 /* Disable it unconditionally */
34453445 console_srcu_write_flags (console , console -> flags & ~CON_ENABLED );
34463446
3447- if (!console_is_registered_locked (console )) {
3448- console_unlock ();
3447+ if (!console_is_registered_locked (console ))
34493448 return - ENODEV ;
3450- }
34513449
34523450 hlist_del_init_rcu (& console -> node );
34533451
@@ -3463,8 +3461,6 @@ static int unregister_console_locked(struct console *console)
34633461 if (!hlist_empty (& console_list ) && console -> flags & CON_CONSDEV )
34643462 console_srcu_write_flags (console_first (), console_first ()-> flags | CON_CONSDEV );
34653463
3466- console_unlock ();
3467-
34683464 /*
34693465 * Ensure that all SRCU list walks have completed. All contexts
34703466 * must not be able to see this console in the list so that any
0 commit comments