[printk,v2,15/26] printk: Track registered boot consoles

Message ID 20240218185726.1994771-16-john.ogness@linutronix.de
State New
Headers
Series wire up write_atomic() printing |

Commit Message

John Ogness Feb. 18, 2024, 6:57 p.m. UTC
  Unfortunately it is not known if a boot console and a regular
(legacy or nbcon) console use the same hardware. For this reason
they must not be allowed to print simultaneously.

For legacy consoles this is not an issue because they are
already synchronized with the boot consoles using the console
lock. However nbcon consoles can be triggered separately.

Add a global flag @have_boot_console to identify if any boot
consoles are registered. This will be used in follow-up commits
to ensure that boot consoles and nbcon consoles cannot print
simultaneously.

Signed-off-by: John Ogness <john.ogness@linutronix.de>
---
 kernel/printk/printk.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
  

Comments

Petr Mladek Feb. 23, 2024, 3:57 p.m. UTC | #1
On Sun 2024-02-18 20:03:15, John Ogness wrote:
> Unfortunately it is not known if a boot console and a regular
> (legacy or nbcon) console use the same hardware. For this reason
> they must not be allowed to print simultaneously.
> 
> For legacy consoles this is not an issue because they are
> already synchronized with the boot consoles using the console
> lock. However nbcon consoles can be triggered separately.
> 
> Add a global flag @have_boot_console to identify if any boot
> consoles are registered. This will be used in follow-up commits
> to ensure that boot consoles and nbcon consoles cannot print
> simultaneously.
> 
> Signed-off-by: John Ogness <john.ogness@linutronix.de>

Reviewed-by: Petr Mladek <pmladek@suse.com>

Just a nit below.

> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -3598,6 +3611,17 @@ static int unregister_console_locked(struct console *console)
>  	if (console->exit)
>  		res = console->exit(console);
>  
> +	/*
> +	 * With this console gone, the global flags tracking registered
> +	 * console types may have changed. Update them.
> +	 */
> +	for_each_console(c) {
> +		if (c->flags & CON_BOOT)
> +			found_boot_con = true;
> +	}
> +	if (!found_boot_con)
> +		have_boot_console = false;

I would use:

	have_boot_console = found_boot_console;

But I do not have strong opinion. Maybe, you wanted to make
it obvious that the function only clears the flag.

Best Regards,
Petr
  

Patch

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ea170ade4d42..1b14159990ba 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -463,6 +463,14 @@  static int console_msg_format = MSG_FORMAT_DEFAULT;
 /* syslog_lock protects syslog_* variables and write access to clear_seq. */
 static DEFINE_MUTEX(syslog_lock);
 
+/*
+ * Specifies if a boot console is registered. If boot consoles are present,
+ * nbcon consoles cannot print simultaneously and must be synchronized by
+ * the console lock. This is because boot consoles and nbcon consoles may
+ * have mapped the same hardware.
+ */
+bool have_boot_console;
+
 #ifdef CONFIG_PRINTK
 DECLARE_WAIT_QUEUE_HEAD(log_wait);
 /* All 3 protected by @syslog_lock. */
@@ -3499,6 +3507,9 @@  void register_console(struct console *newcon)
 	if (newcon->flags & CON_NBCON)
 		nbcon_init(newcon);
 
+	if (newcon->flags & CON_BOOT)
+		have_boot_console = true;
+
 	/*
 	 * Put this console in the list - keep the
 	 * preferred driver at the head of the list.
@@ -3551,6 +3562,8 @@  EXPORT_SYMBOL(register_console);
 /* Must be called under console_list_lock(). */
 static int unregister_console_locked(struct console *console)
 {
+	bool found_boot_con = false;
+	struct console *c;
 	int res;
 
 	lockdep_assert_console_list_lock_held();
@@ -3598,6 +3611,17 @@  static int unregister_console_locked(struct console *console)
 	if (console->exit)
 		res = console->exit(console);
 
+	/*
+	 * With this console gone, the global flags tracking registered
+	 * console types may have changed. Update them.
+	 */
+	for_each_console(c) {
+		if (c->flags & CON_BOOT)
+			found_boot_con = true;
+	}
+	if (!found_boot_con)
+		have_boot_console = false;
+
 	return res;
 }