@@ -86,8 +86,8 @@ EXPORT_SYMBOL(oops_in_progress);
86
86
static DEFINE_MUTEX (console_mutex );
87
87
88
88
/*
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 .
91
91
*/
92
92
static DEFINE_SEMAPHORE (console_sem );
93
93
HLIST_HEAD (console_list );
@@ -2640,10 +2640,10 @@ static int console_cpu_notify(unsigned int cpu)
2640
2640
}
2641
2641
2642
2642
/**
2643
- * console_lock - lock the console system for exclusive use.
2643
+ * console_lock - block the console subsystem from printing
2644
2644
*
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 .
2647
2647
*
2648
2648
* Can sleep, returns nothing.
2649
2649
*/
@@ -2660,10 +2660,10 @@ void console_lock(void)
2660
2660
EXPORT_SYMBOL (console_lock );
2661
2661
2662
2662
/**
2663
- * console_trylock - try to lock the console system for exclusive use.
2663
+ * console_trylock - try to block the console subsystem from printing
2664
2664
*
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 .
2667
2667
*
2668
2668
* returns 1 on success, and 0 on failure to acquire the lock.
2669
2669
*/
@@ -2920,10 +2920,10 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
2920
2920
}
2921
2921
2922
2922
/**
2923
- * console_unlock - unlock the console system
2923
+ * console_unlock - unblock the console subsystem from printing
2924
2924
*
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 .
2927
2927
*
2928
2928
* While the console_lock was held, console output may have been buffered
2929
2929
* by printk(). If this is the case, console_unlock(); emits
@@ -3110,9 +3110,7 @@ void console_stop(struct console *console)
3110
3110
{
3111
3111
__pr_flush (console , 1000 , true);
3112
3112
console_list_lock ();
3113
- console_lock ();
3114
3113
console_srcu_write_flags (console , console -> flags & ~CON_ENABLED );
3115
- console_unlock ();
3116
3114
console_list_unlock ();
3117
3115
3118
3116
/*
@@ -3128,9 +3126,7 @@ EXPORT_SYMBOL(console_stop);
3128
3126
void console_start (struct console * console )
3129
3127
{
3130
3128
console_list_lock ();
3131
- console_lock ();
3132
3129
console_srcu_write_flags (console , console -> flags | CON_ENABLED );
3133
- console_unlock ();
3134
3130
console_list_unlock ();
3135
3131
__pr_flush (console , 1000 , true);
3136
3132
}
@@ -3247,6 +3243,12 @@ static void console_init_seq(struct console *newcon, bool bootcon_registered)
3247
3243
* the furthest behind.
3248
3244
*/
3249
3245
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
+
3250
3252
/*
3251
3253
* Flush all consoles and set the console to start at
3252
3254
* the next unprinted sequence number.
@@ -3273,6 +3275,8 @@ static void console_init_seq(struct console *newcon, bool bootcon_registered)
3273
3275
}
3274
3276
}
3275
3277
}
3278
+
3279
+ console_unlock ();
3276
3280
}
3277
3281
}
3278
3282
}
@@ -3371,7 +3375,6 @@ void register_console(struct console *newcon)
3371
3375
}
3372
3376
3373
3377
newcon -> dropped = 0 ;
3374
- console_lock ();
3375
3378
console_init_seq (newcon , bootcon_registered );
3376
3379
3377
3380
/*
@@ -3391,7 +3394,6 @@ void register_console(struct console *newcon)
3391
3394
} else {
3392
3395
hlist_add_behind_rcu (& newcon -> node , console_list .first );
3393
3396
}
3394
- console_unlock ();
3395
3397
3396
3398
/*
3397
3399
* No need to synchronize SRCU here! The caller does not rely
@@ -3439,15 +3441,11 @@ static int unregister_console_locked(struct console *console)
3439
3441
if (res > 0 )
3440
3442
return 0 ;
3441
3443
3442
- console_lock ();
3443
-
3444
3444
/* Disable it unconditionally */
3445
3445
console_srcu_write_flags (console , console -> flags & ~CON_ENABLED );
3446
3446
3447
- if (!console_is_registered_locked (console )) {
3448
- console_unlock ();
3447
+ if (!console_is_registered_locked (console ))
3449
3448
return - ENODEV ;
3450
- }
3451
3449
3452
3450
hlist_del_init_rcu (& console -> node );
3453
3451
@@ -3463,8 +3461,6 @@ static int unregister_console_locked(struct console *console)
3463
3461
if (!hlist_empty (& console_list ) && console -> flags & CON_CONSDEV )
3464
3462
console_srcu_write_flags (console_first (), console_first ()-> flags | CON_CONSDEV );
3465
3463
3466
- console_unlock ();
3467
-
3468
3464
/*
3469
3465
* Ensure that all SRCU list walks have completed. All contexts
3470
3466
* must not be able to see this console in the list so that any
0 commit comments