Merge branch 'rework/optimizations' into for-linus

pull/1314/head
Petr Mladek 2025-08-04 14:17:17 +02:00
commit 8ac4bf010b
3 changed files with 37 additions and 11 deletions

View File

@ -64,6 +64,7 @@ struct dev_printk_info;
extern struct printk_ringbuffer *prb; extern struct printk_ringbuffer *prb;
extern bool printk_kthreads_running; extern bool printk_kthreads_running;
extern bool printk_kthreads_ready;
extern bool debug_non_panic_cpus; extern bool debug_non_panic_cpus;
__printf(4, 0) __printf(4, 0)
@ -180,6 +181,7 @@ static inline void nbcon_kthread_wake(struct console *con)
#define PRINTKRB_RECORD_MAX 0 #define PRINTKRB_RECORD_MAX 0
#define printk_kthreads_running (false) #define printk_kthreads_running (false)
#define printk_kthreads_ready (false)
/* /*
* In !PRINTK builds we still export console_sem * In !PRINTK builds we still export console_sem

View File

@ -1671,6 +1671,9 @@ bool nbcon_alloc(struct console *con)
{ {
struct nbcon_state state = { }; struct nbcon_state state = { };
/* Synchronize the kthread start. */
lockdep_assert_console_list_lock_held();
/* The write_thread() callback is mandatory. */ /* The write_thread() callback is mandatory. */
if (WARN_ON(!con->write_thread)) if (WARN_ON(!con->write_thread))
return false; return false;
@ -1701,12 +1704,15 @@ bool nbcon_alloc(struct console *con)
return false; return false;
} }
if (printk_kthreads_running) { if (printk_kthreads_ready && !have_boot_console) {
if (!nbcon_kthread_create(con)) { if (!nbcon_kthread_create(con)) {
kfree(con->pbufs); kfree(con->pbufs);
con->pbufs = NULL; con->pbufs = NULL;
return false; return false;
} }
/* Might be the first kthread. */
printk_kthreads_running = true;
} }
} }
@ -1716,14 +1722,30 @@ bool nbcon_alloc(struct console *con)
/** /**
* nbcon_free - Free and cleanup the nbcon console specific data * nbcon_free - Free and cleanup the nbcon console specific data
* @con: Console to free/cleanup nbcon data * @con: Console to free/cleanup nbcon data
*
* Important: @have_nbcon_console must be updated before calling
* this function. In particular, it can be set only when there
* is still another nbcon console registered.
*/ */
void nbcon_free(struct console *con) void nbcon_free(struct console *con)
{ {
struct nbcon_state state = { }; struct nbcon_state state = { };
if (printk_kthreads_running) /* Synchronize the kthread stop. */
lockdep_assert_console_list_lock_held();
if (printk_kthreads_running) {
nbcon_kthread_stop(con); nbcon_kthread_stop(con);
/* Might be the last nbcon console.
*
* Do not rely on printk_kthreads_check_locked(). It is not
* called in some code paths, see nbcon_free() callers.
*/
if (!have_nbcon_console)
printk_kthreads_running = false;
}
nbcon_state_set(con, &state); nbcon_state_set(con, &state);
/* Boot consoles share global printk buffers. */ /* Boot consoles share global printk buffers. */

View File

@ -3574,7 +3574,7 @@ EXPORT_SYMBOL(console_resume);
static int unregister_console_locked(struct console *console); static int unregister_console_locked(struct console *console);
/* True when system boot is far enough to create printer threads. */ /* True when system boot is far enough to create printer threads. */
static bool printk_kthreads_ready __ro_after_init; bool printk_kthreads_ready __ro_after_init;
static struct task_struct *printk_legacy_kthread; static struct task_struct *printk_legacy_kthread;
@ -3713,6 +3713,7 @@ static void printk_kthreads_check_locked(void)
if (!printk_kthreads_ready) if (!printk_kthreads_ready)
return; return;
/* Start or stop the legacy kthread when needed. */
if (have_legacy_console || have_boot_console) { if (have_legacy_console || have_boot_console) {
if (!printk_legacy_kthread && if (!printk_legacy_kthread &&
force_legacy_kthread() && force_legacy_kthread() &&
@ -4204,14 +4205,6 @@ static int unregister_console_locked(struct console *console)
*/ */
synchronize_srcu(&console_srcu); synchronize_srcu(&console_srcu);
if (console->flags & CON_NBCON)
nbcon_free(console);
console_sysfs_notify();
if (console->exit)
res = console->exit(console);
/* /*
* With this console gone, the global flags tracking registered * With this console gone, the global flags tracking registered
* console types may have changed. Update them. * console types may have changed. Update them.
@ -4232,6 +4225,15 @@ static int unregister_console_locked(struct console *console)
if (!found_nbcon_con) if (!found_nbcon_con)
have_nbcon_console = found_nbcon_con; have_nbcon_console = found_nbcon_con;
/* @have_nbcon_console must be updated before calling nbcon_free(). */
if (console->flags & CON_NBCON)
nbcon_free(console);
console_sysfs_notify();
if (console->exit)
res = console->exit(console);
/* Changed console list, may require printer threads to start/stop. */ /* Changed console list, may require printer threads to start/stop. */
printk_kthreads_check_locked(); printk_kthreads_check_locked();