From: Breno Leitao <leitao@debian.org>
To: Petr Mladek <pmladek@suse.com>,
John Ogness <john.ogness@linutronix.de>,
Kiryl Shutsemau <kas@kernel.org>
Cc: linux-kernel@vger.kernel.org, printk@lists.linux.dev,
gustavold@gmail.com, samuelcrossley@gmail.com,
ryan.roberts@arm.com, brads@mainlining.org, x86@kernel.org,
Breno Leitao <leitao@debian.org>,
kernel-team@meta.com, stable@vger.kernel.org
Subject: [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic
Date: Mon, 02 Nov 2026 10:14:54 -0800 [thread overview]
Message-ID: <20261102-panic_unsafe_flush-v1-1-12d1e22fd6d8@debian.org> (raw)
In-Reply-To: <20261102-panic_unsafe_flush-v1-0-12d1e22fd6d8@debian.org>
netconsole registers with CON_NBCON_ATOMIC_UNSAFE since commit
7eab73b18630 ("netconsole: convert to NBCON console infrastructure"), so
its write_atomic() only runs from nbcon_atomic_flush_unsafe(). vpanic()
calls that right before its final busy loop, after emergency_restart()
and after __crash_kexec().
A panic that reboots (panic_timeout != 0) or boots a crash kernel
therefore never reaches the netconsole target. Before the conversion,
netconsole was a legacy console and printk() wrote each panic message to
it as it was printed.
Flush the unsafe consoles from nbcon_atomic_flush_pending() as well,
right after the safe ones, when it runs on the panic CPU with
oops_in_progress set. Every printk() on the panic CPU then reaches
netconsole again, "Rebooting in" included.
An unsafe write_atomic() that hangs now stops the panic CPU at the first
message, before the other consoles print the rest and before the reboot
or the crash kernel. Getting the messages out is worth that.
Fixes: 187de7c212e5 ("printk: nbcon: Allow unsafe write_atomic() for panic")
Reported-by: Ryan Roberts <ryan.roberts@arm.com>
Closes: https://lore.kernel.org/all/20260915100140.3631650-1-ryan.roberts@arm.com/
Suggested-by: Petr Mladek <pmladek@suse.com>
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
---
include/linux/console.h | 7 ++++---
kernel/printk/nbcon.c | 24 ++++++++++++++++++------
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/include/linux/console.h b/include/linux/console.h
index cb8be9ea4a767b..934fe72978b0e5 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -183,7 +183,8 @@ static inline void con_debug_leave(void) { }
* @CON_NBCON: Console can operate outside of the legacy style console_lock
* constraints.
* @CON_NBCON_ATOMIC_UNSAFE: The write_atomic() callback is not safe and is
- * therefore only used by nbcon_atomic_flush_unsafe().
+ * therefore only used in panic, when unsafe takeovers
+ * are allowed.
*/
enum cons_flags {
CON_PRINTBUFFER = BIT(0),
@@ -246,8 +247,8 @@ static_assert(sizeof(struct nbcon_state) <= sizeof(int));
* @NBCON_PRIO_MAX: The number of priority levels
*
* A higher priority context can takeover the console when it is
- * in the safe state. The final attempt to flush consoles in panic()
- * can be allowed to do so even in an unsafe state (Hope and pray).
+ * in the safe state. The panic CPU can be allowed to do so even in
+ * an unsafe state (Hope and pray).
*/
enum nbcon_prio {
NBCON_PRIO_NONE = 0,
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index 5f8afaca886650..19fa9f79cac3cb 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -84,8 +84,8 @@
* b) Gives up console ownership by clearing the 'prio' field.
*
* 3) Unsafe hostile takeover allows to take over the lock even when the
- * console is an unsafe state. It is used only in panic() by the final
- * attempt to flush consoles in a try and hope mode.
+ * console is an unsafe state. It is used only on the panic CPU, in a
+ * try and hope mode.
*
* Note that separate record buffers are used in panic(). As a result,
* the messages can be read and formatted without any risk even after
@@ -543,7 +543,7 @@ static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt,
* Acquire the console even in the unsafe state.
*
* It can be permitted by setting the 'allow_unsafe_takeover' field only
- * by the final attempt to flush messages in panic().
+ * on the panic CPU.
*
* Return: 0 on success. -EPERM when not allowed by the context.
*/
@@ -1653,8 +1653,9 @@ static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
* __nbcon_atomic_flush_pending - Flush all nbcon consoles using their
* write_atomic() callback
* @stop_seq: Flush up until this record
+ * @unsafe_only: Flush only the CON_NBCON_ATOMIC_UNSAFE consoles
*/
-static void __nbcon_atomic_flush_pending(u64 stop_seq)
+static void __nbcon_atomic_flush_pending(u64 stop_seq, bool unsafe_only)
{
struct console *con;
int cookie;
@@ -1666,6 +1667,9 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
if (!(flags & CON_NBCON))
continue;
+ if (unsafe_only && !(flags & CON_NBCON_ATOMIC_UNSAFE))
+ continue;
+
if (!console_is_usable(con, flags, true))
continue;
@@ -1688,7 +1692,15 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
*/
void nbcon_atomic_flush_pending(void)
{
- __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
+ u64 stop_seq = prb_next_reserve_seq(prb);
+
+ __nbcon_atomic_flush_pending(stop_seq, false);
+
+ if (panic_on_this_cpu() && oops_in_progress) {
+ panic_nbcon_allow_unsafe_takeover = true;
+ __nbcon_atomic_flush_pending(stop_seq, true);
+ panic_nbcon_allow_unsafe_takeover = false;
+ }
}
/**
@@ -1701,7 +1713,7 @@ void nbcon_atomic_flush_pending(void)
void nbcon_atomic_flush_unsafe(void)
{
panic_nbcon_allow_unsafe_takeover = true;
- __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
+ __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), false);
panic_nbcon_allow_unsafe_takeover = false;
}
--
2.53.0-Meta
next prev parent reply other threads:[~2026-11-02 18:16 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 18:14 [PATCH 0/2] panic: flush unsafe consoles before reboot and kdump Breno Leitao
2026-11-02 18:14 ` Breno Leitao [this message]
2026-11-02 18:14 ` [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown() Breno Leitao
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=20261102-panic_unsafe_flush-v1-1-12d1e22fd6d8@debian.org \
--to=leitao@debian.org \
--cc=brads@mainlining.org \
--cc=gustavold@gmail.com \
--cc=john.ogness@linutronix.de \
--cc=kas@kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pmladek@suse.com \
--cc=printk@lists.linux.dev \
--cc=ryan.roberts@arm.com \
--cc=samuelcrossley@gmail.com \
--cc=stable@vger.kernel.org \
--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®