mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "tip-bot2 for John Ogness" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: John Ogness <john.ogness@linutronix.de>,
	Petr Mladek <pmladek@suse.com>,
	x86@kernel.org, linux-kernel@vger.kernel.org
Subject: [tip: sched/rt] printk: Add helper for flush type logic
Date: Mon, 09 Sep 2024 17:27:49 -0000	[thread overview]
Message-ID: <172590286986.2215.14603001390146123290.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20240820063001.36405-31-john.ogness@linutronix.de>

The following commit has been merged into the sched/rt branch of tip:

Commit-ID:     6690d6b52726bcb2b743466a1833e0b9f049b9d7
Gitweb:        https://git.kernel.org/tip/6690d6b52726bcb2b743466a1833e0b9f049b9d7
Author:        John Ogness <john.ogness@linutronix.de>
AuthorDate:    Tue, 20 Aug 2024 08:35:56 +02:06
Committer:     Petr Mladek <pmladek@suse.com>
CommitterDate: Wed, 21 Aug 2024 14:56:49 +02:00

printk: Add helper for flush type logic

There are many call sites where console flushing occur.
Depending on the system state and types of consoles, the flush
methods to use are different. A flush call site generally must
consider:

	@have_boot_console
	@have_nbcon_console
	@have_legacy_console
	@legacy_allow_panic_sync
	is_printk_preferred()

and take into account the current CPU state:

	NBCON_PRIO_NORMAL
	NBCON_PRIO_EMERGENCY
	NBCON_PRIO_PANIC

in order to decide if it should:

	flush nbcon directly via atomic_write() callback
	flush legacy directly via console_unlock
	flush legacy via offload to irq_work

All of these call sites use their own logic to make this
decision, which is complicated and error prone. Especially
later when two more flush methods will be introduced:

	flush nbcon via offload to kthread
	flush legacy via offload to kthread

Introduce a new internal struct console_flush_type that specifies
which console flushing methods should be used in the context of
the caller.

Introduce a helper function to fill out console_flush_type to
be used for flushing call sites.

Replace the logic of all flushing call sites to use the new
helper.

This change standardizes behavior, leading to both fixes and
optimizations across various call sites. For instance, in
console_cpu_notify(), the new logic ensures that nbcon consoles
are flushed when they aren’t managed by the legacy loop.
Similarly, in console_flush_on_panic(), the system no longer
needs to flush nbcon consoles if none are present.

Signed-off-by: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20240820063001.36405-31-john.ogness@linutronix.de
[pmladek@suse.com: Updated the commit message.]
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/internal.h | 73 +++++++++++++++++++++++++++++++++++++++-
 kernel/printk/nbcon.c    | 12 ++++--
 kernel/printk/printk.c   | 68 +++++++++++++++---------------------
 3 files changed, 112 insertions(+), 41 deletions(-)

diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
index 6b61350..ba2e0f1 100644
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -154,8 +154,81 @@ static inline bool console_is_usable(struct console *con, short flags) { return 
 #endif /* CONFIG_PRINTK */
 
 extern bool have_boot_console;
+extern bool have_nbcon_console;
+extern bool have_legacy_console;
 extern bool legacy_allow_panic_sync;
 
+/**
+ * struct console_flush_type - Define available console flush methods
+ * @nbcon_atomic:	Flush directly using nbcon_atomic() callback
+ * @legacy_direct:	Call the legacy loop in this context
+ * @legacy_offload:	Offload the legacy loop into IRQ
+ *
+ * Note that the legacy loop also flushes the nbcon consoles.
+ */
+struct console_flush_type {
+	bool	nbcon_atomic;
+	bool	legacy_direct;
+	bool	legacy_offload;
+};
+
+/*
+ * Identify which console flushing methods should be used in the context of
+ * the caller.
+ */
+static inline void printk_get_console_flush_type(struct console_flush_type *ft)
+{
+	memset(ft, 0, sizeof(*ft));
+
+	switch (nbcon_get_default_prio()) {
+	case NBCON_PRIO_NORMAL:
+		if (have_nbcon_console && !have_boot_console)
+			ft->nbcon_atomic = true;
+
+		/* Legacy consoles are flushed directly when possible. */
+		if (have_legacy_console || have_boot_console) {
+			if (!is_printk_legacy_deferred())
+				ft->legacy_direct = true;
+			else
+				ft->legacy_offload = true;
+		}
+		break;
+
+	case NBCON_PRIO_PANIC:
+		/*
+		 * In panic, the nbcon consoles will directly print. But
+		 * only allowed if there are no boot consoles.
+		 */
+		if (have_nbcon_console && !have_boot_console)
+			ft->nbcon_atomic = true;
+
+		if (have_legacy_console || have_boot_console) {
+			/*
+			 * This is the same decision as NBCON_PRIO_NORMAL
+			 * except that offloading never occurs in panic.
+			 *
+			 * Note that console_flush_on_panic() will flush
+			 * legacy consoles anyway, even if unsafe.
+			 */
+			if (!is_printk_legacy_deferred())
+				ft->legacy_direct = true;
+
+			/*
+			 * In panic, if nbcon atomic printing occurs,
+			 * the legacy consoles must remain silent until
+			 * explicitly allowed.
+			 */
+			if (ft->nbcon_atomic && !legacy_allow_panic_sync)
+				ft->legacy_direct = false;
+		}
+		break;
+
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+}
+
 extern struct printk_buffers printk_shared_pbufs;
 
 /**
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index afdb16c..18488d6 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -1344,6 +1344,7 @@ EXPORT_SYMBOL_GPL(nbcon_device_try_acquire);
 void nbcon_device_release(struct console *con)
 {
 	struct nbcon_context *ctxt = &ACCESS_PRIVATE(con, nbcon_device_ctxt);
+	struct console_flush_type ft;
 	int cookie;
 
 	if (!nbcon_context_exit_unsafe(ctxt))
@@ -1359,12 +1360,17 @@ void nbcon_device_release(struct console *con)
 	cookie = console_srcu_read_lock();
 	if (console_is_usable(con, console_srcu_read_flags(con)) &&
 	    prb_read_valid(prb, nbcon_seq_read(con), NULL)) {
-		if (!have_boot_console) {
+		/*
+		 * If nbcon_atomic flushing is not available, fallback to
+		 * using the legacy loop.
+		 */
+		printk_get_console_flush_type(&ft);
+		if (ft.nbcon_atomic) {
 			__nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb), false);
-		} else if (!is_printk_legacy_deferred()) {
+		} else if (ft.legacy_direct) {
 			if (console_trylock())
 				console_unlock();
-		} else {
+		} else if (ft.legacy_offload) {
 			printk_trigger_flush();
 		}
 	}
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index fc3f897..6accd17 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -468,14 +468,14 @@ static DEFINE_MUTEX(syslog_lock);
  * present, it is necessary to perform the console lock/unlock dance
  * whenever console flushing should occur.
  */
-static bool have_legacy_console;
+bool have_legacy_console;
 
 /*
  * Specifies if an nbcon console is registered. If nbcon consoles are present,
  * synchronous printing of legacy consoles will not occur during panic until
  * the backtrace has been stored to the ringbuffer.
  */
-static bool have_nbcon_console;
+bool have_nbcon_console;
 
 /*
  * Specifies if a boot console is registered. If boot consoles are present,
@@ -488,14 +488,6 @@ bool have_boot_console;
 /* See printk_legacy_allow_panic_sync() for details. */
 bool legacy_allow_panic_sync;
 
-/*
- * Specifies if the console lock/unlock dance is needed for console
- * printing. If @have_boot_console is true, the nbcon consoles will
- * be printed serially along with the legacy consoles because nbcon
- * consoles cannot print simultaneously with boot consoles.
- */
-#define printing_via_unlock (have_legacy_console || have_boot_console)
-
 #ifdef CONFIG_PRINTK
 DECLARE_WAIT_QUEUE_HEAD(log_wait);
 /* All 3 protected by @syslog_lock. */
@@ -2342,9 +2334,12 @@ out:
  */
 void printk_legacy_allow_panic_sync(void)
 {
+	struct console_flush_type ft;
+
 	legacy_allow_panic_sync = true;
 
-	if (printing_via_unlock && !is_printk_legacy_deferred()) {
+	printk_get_console_flush_type(&ft);
+	if (ft.legacy_direct) {
 		if (console_trylock())
 			console_unlock();
 	}
@@ -2354,8 +2349,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 			    const struct dev_printk_info *dev_info,
 			    const char *fmt, va_list args)
 {
-	bool do_trylock_unlock = printing_via_unlock;
-	bool defer_legacy = false;
+	struct console_flush_type ft;
 	int printed_len;
 
 	/* Suppress unimportant messages after panic happens */
@@ -2370,35 +2364,23 @@ asmlinkage int vprintk_emit(int facility, int level,
 	if (other_cpu_in_panic() && !panic_triggering_all_cpu_backtrace)
 		return 0;
 
+	printk_get_console_flush_type(&ft);
+
 	/* If called from the scheduler, we can not call up(). */
 	if (level == LOGLEVEL_SCHED) {
 		level = LOGLEVEL_DEFAULT;
-		defer_legacy = do_trylock_unlock;
-		do_trylock_unlock = false;
+		ft.legacy_offload |= ft.legacy_direct;
+		ft.legacy_direct = false;
 	}
 
 	printk_delay(level);
 
 	printed_len = vprintk_store(facility, level, dev_info, fmt, args);
 
-	if (have_nbcon_console && !have_boot_console) {
+	if (ft.nbcon_atomic)
 		nbcon_atomic_flush_pending();
 
-		/*
-		 * In panic, the legacy consoles are not allowed to print from
-		 * the printk calling context unless explicitly allowed. This
-		 * gives the safe nbcon consoles a chance to print out all the
-		 * panic messages first. This restriction only applies if
-		 * there are nbcon consoles registered and they are allowed to
-		 * flush.
-		 */
-		if (this_cpu_in_panic() && !legacy_allow_panic_sync) {
-			do_trylock_unlock = false;
-			defer_legacy = false;
-		}
-	}
-
-	if (do_trylock_unlock) {
+	if (ft.legacy_direct) {
 		/*
 		 * The caller may be holding system-critical or
 		 * timing-sensitive locks. Disable preemption during
@@ -2418,7 +2400,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 		preempt_enable();
 	}
 
-	if (defer_legacy)
+	if (ft.legacy_offload)
 		defer_console_output();
 	else
 		wake_up_klogd();
@@ -2777,10 +2759,16 @@ void resume_console(void)
  */
 static int console_cpu_notify(unsigned int cpu)
 {
-	if (!cpuhp_tasks_frozen && printing_via_unlock) {
-		/* If trylock fails, someone else is doing the printing */
-		if (console_trylock())
-			console_unlock();
+	struct console_flush_type ft;
+
+	if (!cpuhp_tasks_frozen) {
+		printk_get_console_flush_type(&ft);
+		if (ft.nbcon_atomic)
+			nbcon_atomic_flush_pending();
+		if (ft.legacy_direct) {
+			if (console_trylock())
+				console_unlock();
+		}
 	}
 	return 0;
 }
@@ -3305,6 +3293,7 @@ static void __console_rewind_all(void)
  */
 void console_flush_on_panic(enum con_flush_mode mode)
 {
+	struct console_flush_type ft;
 	bool handover;
 	u64 next_seq;
 
@@ -3328,7 +3317,8 @@ void console_flush_on_panic(enum con_flush_mode mode)
 	if (mode == CONSOLE_REPLAY_ALL)
 		__console_rewind_all();
 
-	if (!have_boot_console)
+	printk_get_console_flush_type(&ft);
+	if (ft.nbcon_atomic)
 		nbcon_atomic_flush_pending();
 
 	/* Flush legacy consoles once allowed, even when dangerous. */
@@ -3992,6 +3982,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
 {
 	unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms);
 	unsigned long remaining_jiffies = timeout_jiffies;
+	struct console_flush_type ft;
 	struct console *c;
 	u64 last_diff = 0;
 	u64 printk_seq;
@@ -4005,7 +3996,8 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
 	seq = prb_next_reserve_seq(prb);
 
 	/* Flush the consoles so that records up to @seq are printed. */
-	if (printing_via_unlock) {
+	printk_get_console_flush_type(&ft);
+	if (ft.legacy_direct) {
 		console_lock();
 		console_unlock();
 	}

  parent reply	other threads:[~2024-09-09 17:27 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-20  6:29 [PATCH printk v8 00/35] wire up write_atomic() printing John Ogness
2024-08-20  6:29 ` [PATCH printk v8 01/35] printk: Add notation to console_srcu locking John Ogness
2024-08-20 17:49   ` Paul E. McKenney
2024-09-09 17:28   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 02/35] printk: nbcon: Consolidate alloc() and init() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 03/35] printk: Properly deal with nbcon consoles on seq init John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for Petr Mladek
2024-08-20  6:29 ` [PATCH printk v8 04/35] printk: Check printk_deferred_enter()/_exit() usage John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for Sebastian Andrzej Siewior
2024-08-20  6:29 ` [PATCH printk v8 05/35] printk: nbcon: Clarify rules of the owner/waiter matching John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 06/35] printk: nbcon: Remove return value for write_atomic() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 07/35] printk: nbcon: Add detailed doc " John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 08/35] printk: nbcon: Add callbacks to synchronize with driver John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 09/35] printk: nbcon: Use driver synchronization while (un)registering John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 10/35] serial: core: Provide low-level functions to lock port John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 11/35] serial: core: Introduce wrapper to set @uart_port->cons John Ogness
2024-08-20 11:12   ` Ilpo Järvinen
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 12/35] console: Improve console_srcu_read_flags() comments John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 13/35] nbcon: Add API to acquire context for non-printing operations John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 14/35] serial: core: Acquire nbcon context in port->lock wrapper John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 15/35] printk: nbcon: Do not rely on proxy headers John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 16/35] printk: Make console_is_usable() available to nbcon.c John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 17/35] printk: Let console_is_usable() handle nbcon John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 18/35] printk: Add @flags argument for console_is_usable() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 19/35] printk: nbcon: Add helper to assign priority based on CPU state John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 20/35] printk: nbcon: Provide function to flush using write_atomic() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for Thomas Gleixner
2024-08-20  6:29 ` [PATCH printk v8 21/35] printk: Track registered boot consoles John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 22/35] printk: nbcon: Use nbcon consoles in console_flush_all() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 23/35] printk: Add is_printk_legacy_deferred() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 24/35] printk: nbcon: Flush new records on device_release() John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 25/35] printk: Flush nbcon consoles first on panic John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 26/35] printk: nbcon: Add unsafe flushing " John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 27/35] printk: Avoid console_lock dance if no legacy or boot consoles John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 28/35] printk: Track nbcon consoles John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 29/35] printk: Coordinate direct printing in panic John Ogness
2024-08-20 15:21   ` Petr Mladek
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:29 ` [PATCH printk v8 30/35] printk: Add helper for flush type logic John Ogness
2024-08-21  9:11   ` Petr Mladek
2024-08-23  5:25     ` John Ogness
2024-09-09 17:27   ` tip-bot2 for John Ogness [this message]
2024-08-20  6:29 ` [PATCH printk v8 31/35] printk: nbcon: Implement emergency sections John Ogness
2024-08-27 14:19   ` John Ogness
2024-09-04 10:34     ` Petr Mladek
2024-09-09 17:27     ` [tip: sched/rt] printk: nbcon: Use raw_cpu_ptr() instead of open coding tip-bot2 for John Ogness
2024-09-09 17:27   ` [tip: sched/rt] printk: nbcon: Implement emergency sections tip-bot2 for Thomas Gleixner
2024-08-20  6:29 ` [PATCH printk v8 32/35] panic: Mark emergency section in warn John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for Thomas Gleixner
2024-08-20  6:29 ` [PATCH printk v8 33/35] panic: Mark emergency section in oops John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:30 ` [PATCH printk v8 34/35] rcu: Mark emergency sections in rcu stalls John Ogness
2024-08-20 17:48   ` Paul E. McKenney
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-20  6:30 ` [PATCH printk v8 35/35] lockdep: Mark emergency sections in lockdep splats John Ogness
2024-09-09 17:27   ` [tip: sched/rt] " tip-bot2 for John Ogness
2024-08-21  9:21 ` [PATCH printk v8 00/35] wire up write_atomic() printing Petr Mladek
2024-08-21  9:28   ` Sebastian Andrzej Siewior
2024-08-21 14:09     ` Petr Mladek
2024-08-21 14:20       ` Sebastian Andrzej Siewior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=172590286986.2215.14603001390146123290.tip-bot2@tip-bot2 \
    --to=tip-bot2@linutronix.de \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=pmladek@suse.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®