* [PATCH printk v2 0/6] Introduce policies for unsafe flushing
@ 2026-11-11 18:19 John Ogness
2026-11-11 18:19 ` [PATCH printk v2 1/6] printk: Introduce and specify flush reasons John Ogness
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw)
To: Petr Mladek
Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao,
printk, linux-kernel, Huacai Chen, WANG Xuerui,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Ritesh Harjani (IBM),
Shrikanth Hegde, Greg Kroah-Hartman, Jason Wessel,
Daniel Thompson, Douglas Anderson, Andrew Morton,
Mukesh Kumar Chaurasiya, Feng Tang, Rio, Bradley Morgan,
Pnina Feder, Gal Pressman, Petr Pavlu, Pavel Tikhomirov,
Oleg Nesterov, Cen Zhang (Microsoft), loongarch, linuxppc-dev,
kgdb-bugreport, Randy Dunlap, Alessandro Carminati, Baoquan He,
Mike Rapoport, Pasha Tatashin, Pratyush Yadav, Dave Young, kexec,
Gustavo Luiz Duarte, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
v1 is here [0].
Until now unsafe flushing is only performed at the very end of
panic(), before entering the infinite loop. For other situations
(such as panic-kexec or panic-reboot or emergency-reboot) no
unsafe flushing is performed. The reasoning for this is because
an unsafe flush could lead to fireworks, which could prevent the
kexec or reboot from occurring.
However, some users may be willing to take on such risks in order
to see panic output. Indeed, for the netconsole (which does not
support safe atomic printing) it is a regression that such unsafe
printing does not occur. [1]
This series adds unsafe flushing policy flags per-console to
allow individual consoles to perform unsafe flushing for such
scenarios. The unsafe flushing is hard-code-enabled for the
netconsole in patch 6/6. The justification is that this is not
less safe than the legacy netconsole.
Later these policy flags could be easily exposed to userspace
via /sys/class/consoles/, once the sysfs per-console interface
is available.
Changes since v1:
- Make console.unsafe_flush_flags unsigned.
- Add missing kerneldoc description for printk_trigger_flush().
- Remove the WARN_ON_ONCE() in
nbcon_context_try_acquire_hostile() since hostile takeovers
are now possible from non-panic contexts.
- Also provide a flush reason for console_flush_on_panic().
- Add a global variable @legacy_flush_reason to track reason
for legacy flushing.
- Explicitly set PR_FLUSH_RUNTIME to 0 since it is now used to
initialize @legacy_flush_reason.
- Temporarily set @legacy_flush_reason during legacy flushing
of console_flush_on_panic() and printk_trigger_flush().
- Also set/check ctxt->allow_unsafe_takeover in
nbcon_legacy_emit_next_record() to enforce flush policies
for legacy flushing.
John Ogness
[0] https://lore.kernel.org/lkml/20261109123127.489676-1-john.ogness@linutronix.de
[1] https://lore.kernel.org/lkml/20260915100140.3631650-1-ryan.roberts@arm.com
John Ogness (6):
printk: Introduce and specify flush reasons
console: Introduce unsafe flush policy flags
printk: Evaluate flush policy in nbcon_allow_unsafe_takeover()
printk: Remove nbcon_atomic_flush_unsafe()
printk: Add panic+kexec flush point
netconsole: Always perform unsafe flushing on panic/kdb/restart
arch/loongarch/kernel/reset.c | 2 +-
arch/powerpc/kernel/traps.c | 2 +-
arch/powerpc/kernel/watchdog.c | 2 +-
drivers/net/netconsole.c | 4 +
include/linux/console.h | 39 +++++++---
include/linux/printk.h | 27 +++++--
kernel/crash_core.c | 1 +
kernel/debug/debug_core.c | 2 +-
kernel/panic.c | 8 +-
kernel/printk/internal.h | 5 +-
kernel/printk/nbcon.c | 129 ++++++++++++++++++++++-----------
kernel/printk/printk.c | 38 +++++++---
kernel/reboot.c | 2 +-
lib/nmi_backtrace.c | 2 +-
14 files changed, 181 insertions(+), 82 deletions(-)
base-commit: d01f86a7da8161aac8c6304b377cf58fb75861ca
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH printk v2 1/6] printk: Introduce and specify flush reasons 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness @ 2026-11-11 18:19 ` John Ogness 2026-11-13 15:05 ` Petr Mladek 2026-11-11 18:19 ` [PATCH printk v2 2/6] console: Introduce unsafe flush policy flags John Ogness ` (4 subsequent siblings) 5 siblings, 1 reply; 10+ messages in thread From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw) To: Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Huacai Chen, WANG Xuerui, Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP), Ritesh Harjani (IBM), Shrikanth Hegde, Greg Kroah-Hartman, Jason Wessel, Daniel Thompson, Douglas Anderson, Andrew Morton, Mukesh Kumar Chaurasiya, Feng Tang, Rio, Bradley Morgan, Pnina Feder, Gal Pressman, Petr Pavlu, Pavel Tikhomirov, Oleg Nesterov, Cen Zhang (Microsoft), loongarch, linuxppc-dev, kgdb-bugreport Prepare for per-console atomic flushing policies by introducing enum pr_flush_reason to classify various reasons for performing a printk backlog flush. The reasons are specified for printk_trigger_flush() and console_flush_on_panic(). For atomic printing from printk_trigger_flush(), propagate the reason down to __nbcon_atomic_flush_pending_con(), where the actual atomic flushing is executed. For legacy printing, use a new global variable @legacy_flush_reason to track the reason in case nbcon consoles are using legacy printing. Update all printk_trigger_flush() and console_flush_on_panic() call sites as well as any explicit lower-level atomic flush calls to specify the reason. Note that PR_FLUSH_RUNTIME is used for cases where the reason for the flush is not clearly defined. No functional change. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- arch/loongarch/kernel/reset.c | 2 +- arch/powerpc/kernel/traps.c | 2 +- arch/powerpc/kernel/watchdog.c | 2 +- include/linux/console.h | 2 +- include/linux/printk.h | 22 ++++++++++++++++++-- kernel/debug/debug_core.c | 2 +- kernel/panic.c | 6 +++--- kernel/printk/internal.h | 5 +++-- kernel/printk/nbcon.c | 28 ++++++++++++++++--------- kernel/printk/printk.c | 38 ++++++++++++++++++++++++---------- kernel/reboot.c | 2 +- lib/nmi_backtrace.c | 2 +- 12 files changed, 78 insertions(+), 35 deletions(-) diff --git a/arch/loongarch/kernel/reset.c b/arch/loongarch/kernel/reset.c index de8fa5a8a825c..3dfc4a6216cee 100644 --- a/arch/loongarch/kernel/reset.c +++ b/arch/loongarch/kernel/reset.c @@ -30,7 +30,7 @@ void machine_halt(void) clear_csr_ecfg(ECFG0_IM); pr_notice("\n\n** You can safely turn off the power now **\n\n"); - console_flush_on_panic(CONSOLE_FLUSH_PENDING); + console_flush_on_panic(CONSOLE_FLUSH_PENDING, PR_FLUSH_HANG); while (true) { __asm__ __volatile__("idle 0" : : : "memory"); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 3a8f5416e3f6e..fb7373954c9ca 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -175,7 +175,7 @@ void panic_flush_kmsg_end(void) kmsg_dump(KMSG_DUMP_PANIC); bust_spinlocks(0); debug_locks_off(); - console_flush_on_panic(CONSOLE_FLUSH_PENDING); + console_flush_on_panic(CONSOLE_FLUSH_PENDING, PR_FLUSH_RUNTIME); } static unsigned long oops_begin(struct pt_regs *regs) diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index 582ee3fd71c1b..3d4f9dcb82866 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c @@ -365,7 +365,7 @@ static void watchdog_timer_interrupt(int cpu) * * See wd_lockup_ipi. */ - printk_trigger_flush(); + printk_trigger_flush(PR_FLUSH_RUNTIME); } } diff --git a/include/linux/console.h b/include/linux/console.h index df23148987eeb..06d01f1743512 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -713,7 +713,7 @@ extern void console_lock(void); extern int console_trylock(void); extern void console_unlock(void); extern void console_unblank(void); -extern void console_flush_on_panic(enum con_flush_mode mode); +extern void console_flush_on_panic(enum con_flush_mode mode, enum pr_flush_reason reason); extern struct tty_driver *console_device(int *); extern void console_suspend(struct console *); extern void console_resume(struct console *); diff --git a/include/linux/printk.h b/include/linux/printk.h index f594c1266bfd4..711bd280d1c2f 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -145,6 +145,24 @@ void early_printk(const char *s, ...) { } struct dev_printk_info; +/** + * enum pr_flush_reason - Reason for a flush + * @PR_FLUSH_RUNTIME: A flush while the kernel is running + * @PR_FLUSH_RESTART: The kernel is ending, but another instance should + * follow (reboot, kexec) + * @PR_FLUSH_HANG: The kernel is ending and will enter an infinite loop + * @PR_FLUSH_KDB: Printing while KDB is active + * + * Flush reasons are used to determine if unsafe atomic flushing should be + * performed, based on individual console policies. + */ +enum pr_flush_reason { + PR_FLUSH_RUNTIME = 0, + PR_FLUSH_RESTART, + PR_FLUSH_HANG, + PR_FLUSH_KDB, +}; + #ifdef CONFIG_PRINTK asmlinkage __printf(4, 0) int vprintk_emit(int facility, int level, @@ -202,7 +220,7 @@ void dump_stack_print_info(const char *log_lvl); void show_regs_print_info(const char *log_lvl); extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold; extern asmlinkage void dump_stack(void) __cold; -void printk_trigger_flush(void); +void printk_trigger_flush(enum pr_flush_reason reason); void console_try_replay_all(void); void printk_legacy_allow_panic_sync(void); extern bool nbcon_device_try_acquire(struct console *con); @@ -298,7 +316,7 @@ static inline void dump_stack_lvl(const char *log_lvl) static inline void dump_stack(void) { } -static inline void printk_trigger_flush(void) +static inline void printk_trigger_flush(enum pr_flush_reason reason) { } static inline void console_try_replay_all(void) diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index b276504c1c6bd..fed8a5b38eaa1 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -999,7 +999,7 @@ void kgdb_panic(const char *msg) return; debug_locks_off(); - console_flush_on_panic(CONSOLE_FLUSH_PENDING); + console_flush_on_panic(CONSOLE_FLUSH_PENDING, PR_FLUSH_RUNTIME); if (dbg_kdb_mode) kdb_printf("PANIC: %s\n", msg); diff --git a/kernel/panic.c b/kernel/panic.c index a4dbb6b8cd2bf..32286365d4fee 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -707,11 +707,11 @@ void vpanic(const char *fmt, va_list args) * panic() is not being callled from OOPS. */ debug_locks_off(); - console_flush_on_panic(CONSOLE_FLUSH_PENDING); + console_flush_on_panic(CONSOLE_FLUSH_PENDING, PR_FLUSH_RUNTIME); if ((panic_print & SYS_INFO_PANIC_CONSOLE_REPLAY) || panic_console_replay) - console_flush_on_panic(CONSOLE_REPLAY_ALL); + console_flush_on_panic(CONSOLE_REPLAY_ALL, PR_FLUSH_RUNTIME); if (!panic_blink) panic_blink = no_blink; @@ -764,7 +764,7 @@ void vpanic(const char *fmt, va_list args) * defers printing (such as NMI) and irq_work is not available. * Explicitly flush the kernel log buffer one last time. */ - console_flush_on_panic(CONSOLE_FLUSH_PENDING); + console_flush_on_panic(CONSOLE_FLUSH_PENDING, PR_FLUSH_HANG); nbcon_atomic_flush_unsafe(); local_irq_enable(); diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index 85fbf1801cbe0..32f83658ffc5b 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -104,7 +104,7 @@ void nbcon_seq_force(struct console *con, u64 seq); bool nbcon_alloc(struct console *con); void nbcon_free(struct console *con); enum nbcon_prio nbcon_get_default_prio(void); -void nbcon_atomic_flush_pending(void); +void nbcon_atomic_flush_pending(enum pr_flush_reason reason); bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, int cookie, bool use_atomic); bool nbcon_kthread_create(struct console *con); @@ -156,7 +156,7 @@ static inline void nbcon_seq_force(struct console *con, u64 seq) { } static inline bool nbcon_alloc(struct console *con) { return false; } static inline void nbcon_free(struct console *con) { } static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; } -static inline void nbcon_atomic_flush_pending(void) { } +static inline void nbcon_atomic_flush_pending(enum pr_flush_reason reason) { } static inline bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, int cookie, bool use_atomic) { return false; } static inline void nbcon_kthread_wake(struct console *con) { } @@ -168,6 +168,7 @@ extern bool have_boot_console; extern bool have_nbcon_console; extern bool have_legacy_console; extern bool legacy_allow_panic_sync; +extern enum pr_flush_reason legacy_flush_reason; /** * struct console_flush_type - Define available console flush methods diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c index 5f8afaca88665..935fd6b86bac7 100644 --- a/kernel/printk/nbcon.c +++ b/kernel/printk/nbcon.c @@ -1542,6 +1542,7 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, * __nbcon_atomic_flush_pending_con - Flush specified nbcon console using its * write_atomic() callback * @con: The nbcon console to flush + * @reason: The reason for the flush * @stop_seq: Flush up until this record * * Return: 0 if @con was flushed up to @stop_seq Otherwise, error code on @@ -1561,7 +1562,8 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, * returned, it cannot be expected that the unfinalized record will become * available. */ -static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) +static int __nbcon_atomic_flush_pending_con(struct console *con, enum pr_flush_reason reason, + u64 stop_seq) { struct nbcon_write_context wctxt = { }; struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); @@ -1610,6 +1612,7 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) * nbcon_atomic_flush_pending_con - Flush specified nbcon console using its * write_atomic() callback * @con: The nbcon console to flush + * @reason: The reason for the flush * @stop_seq: Flush up until this record * * This will stop flushing before @stop_seq if another context has ownership. @@ -1617,13 +1620,14 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) * are added while this context was flushing and there is no other context * to handle the printing, this context must also flush those records. */ -static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) +static void nbcon_atomic_flush_pending_con(struct console *con, enum pr_flush_reason reason, + u64 stop_seq) { struct console_flush_type ft; int err; again: - err = __nbcon_atomic_flush_pending_con(con, stop_seq); + err = __nbcon_atomic_flush_pending_con(con, reason, stop_seq); /* * If there was a new owner (-EPERM, -EAGAIN), that context is @@ -1652,9 +1656,10 @@ 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 + * @reason: The reason for the flush * @stop_seq: Flush up until this record */ -static void __nbcon_atomic_flush_pending(u64 stop_seq) +static void __nbcon_atomic_flush_pending(enum pr_flush_reason reason, u64 stop_seq) { struct console *con; int cookie; @@ -1672,7 +1677,7 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq) if (nbcon_seq_read(con) >= stop_seq) continue; - nbcon_atomic_flush_pending_con(con, stop_seq); + nbcon_atomic_flush_pending_con(con, reason, stop_seq); } console_srcu_read_unlock(cookie); } @@ -1681,14 +1686,16 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq) * nbcon_atomic_flush_pending - Flush all nbcon consoles using their * write_atomic() callback * + * @reason: The reason for the flush + * * Flush the backlog up through the currently newest record. Any new * records added while flushing will not be flushed if there is another * context available to handle the flushing. This is to avoid one CPU * printing unbounded because other CPUs continue to add records. */ -void nbcon_atomic_flush_pending(void) +void nbcon_atomic_flush_pending(enum pr_flush_reason reason) { - __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb)); + __nbcon_atomic_flush_pending(reason, prb_next_reserve_seq(prb)); } /** @@ -1701,7 +1708,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(PR_FLUSH_HANG, prb_next_reserve_seq(prb)); panic_nbcon_allow_unsafe_takeover = false; } @@ -1931,7 +1938,8 @@ void nbcon_device_release(struct console *con) * using the legacy loop. */ if (ft.nbcon_atomic) { - __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb)); + __nbcon_atomic_flush_pending_con(con, PR_FLUSH_RUNTIME, + prb_next_reserve_seq(prb)); } else if (ft.legacy_direct) { if (console_trylock()) console_unlock(); @@ -2001,7 +2009,7 @@ void nbcon_kdb_release(struct nbcon_write_context *wctxt) * The console was locked only when the write_atomic() callback * was usable. */ - __nbcon_atomic_flush_pending_con(ctxt->console, prb_next_reserve_seq(prb)); + __nbcon_atomic_flush_pending_con(ctxt->console, PR_FLUSH_KDB, prb_next_reserve_seq(prb)); } /** diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 5dbcf8a9909bb..c059b40fc993c 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -464,6 +464,14 @@ bool have_boot_console; /* See printk_legacy_allow_panic_sync() for details. */ bool legacy_allow_panic_sync; +/* + * While some context is performing a backlog flush, track the reason for + * the flush in case nbcon consoles are using legacy printing. + * Synchronized by the console_lock, except in console_flush_on_panic() + * when the console_lock is ignored. + */ +enum pr_flush_reason legacy_flush_reason = PR_FLUSH_RUNTIME; + /* Avoid using irq_work when suspending. */ bool console_irqwork_blocked; @@ -2455,7 +2463,7 @@ asmlinkage int vprintk_emit(int facility, int level, printed_len = vprintk_store(facility, level, dev_info, fmt, args); if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(PR_FLUSH_RUNTIME); if (ft.nbcon_offload) nbcon_kthreads_wake(); @@ -2870,7 +2878,7 @@ static int console_cpu_notify(unsigned int cpu) if (!cpuhp_tasks_frozen) { printk_get_console_flush_type(&ft); if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(PR_FLUSH_RUNTIME); if (ft.legacy_direct) { if (console_trylock()) console_unlock(); @@ -3530,10 +3538,11 @@ static void __console_rewind_all(void) /** * console_flush_on_panic - flush console content on panic * @mode: flush all messages in buffer or just the pending ones + * @reason: The reason for the flush * * Immediately output all pending messages no matter what. */ -void console_flush_on_panic(enum con_flush_mode mode) +void console_flush_on_panic(enum con_flush_mode mode, enum pr_flush_reason reason) { struct console_flush_type ft; bool handover; @@ -3561,11 +3570,14 @@ void console_flush_on_panic(enum con_flush_mode mode) printk_get_console_flush_type(&ft); if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(PR_FLUSH_RUNTIME); /* Flush legacy consoles once allowed, even when dangerous. */ - if (legacy_allow_panic_sync) + if (legacy_allow_panic_sync) { + legacy_flush_reason = reason; console_flush_all(false, &next_seq, &handover); + legacy_flush_reason = PR_FLUSH_RUNTIME; + } } /* @@ -3775,7 +3787,7 @@ static void printk_kthreads_shutdown(void *data) * The threads may have been stopped while printing a * backlog. Flush any records left over. */ - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(PR_FLUSH_RUNTIME); } console_list_unlock(); } @@ -4537,7 +4549,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre /* Flush the consoles so that records up to @seq are printed. */ printk_get_console_flush_type(&ft); if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(PR_FLUSH_RUNTIME); if (ft.legacy_direct) { console_lock(); console_unlock(); @@ -4725,6 +4737,7 @@ void defer_console_output(void) /** * printk_trigger_flush - Attempt to flush printk buffer to consoles. + * @reason: The reason for the flush * * If possible, flush the printk buffer to all consoles in the caller's * context. If offloading is available, trigger deferred printing. @@ -4732,18 +4745,21 @@ void defer_console_output(void) * This is best effort. Depending on the system state, console states, * and caller context, no actual flushing may result from this call. */ -void printk_trigger_flush(void) +void printk_trigger_flush(enum pr_flush_reason reason) { struct console_flush_type ft; printk_get_console_flush_type(&ft); if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(reason); if (ft.nbcon_offload) nbcon_kthreads_wake(); if (ft.legacy_direct) { - if (console_trylock()) + if (console_trylock()) { + legacy_flush_reason = reason; console_unlock(); + legacy_flush_reason = PR_FLUSH_RUNTIME; + } } if (ft.legacy_offload) defer_console_output(); @@ -5090,7 +5106,7 @@ void console_try_replay_all(void) if (console_trylock()) { __console_rewind_all(); if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); + nbcon_atomic_flush_pending(PR_FLUSH_RUNTIME); if (ft.nbcon_offload) nbcon_kthreads_wake(); if (ft.legacy_offload) diff --git a/kernel/reboot.c b/kernel/reboot.c index a93c23b9e1948..f2f5dfa8e33ce 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -101,7 +101,7 @@ void emergency_restart(void) * the emergency restart. Move them to the atomic mode. */ nbcon_cpu_emergency_enter(); - printk_trigger_flush(); + printk_trigger_flush(PR_FLUSH_RESTART); machine_emergency_restart(); } diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c index f39c9eca88885..925276113d3a0 100644 --- a/lib/nmi_backtrace.c +++ b/lib/nmi_backtrace.c @@ -91,7 +91,7 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask, * Force flush any remote buffers that might be stuck in IRQ context * and therefore could not run their irq_work. */ - printk_trigger_flush(); + printk_trigger_flush(PR_FLUSH_RUNTIME); clear_bit_unlock(0, &backtrace_flag); put_cpu(); -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH printk v2 1/6] printk: Introduce and specify flush reasons 2026-11-11 18:19 ` [PATCH printk v2 1/6] printk: Introduce and specify flush reasons John Ogness @ 2026-11-13 15:05 ` Petr Mladek 0 siblings, 0 replies; 10+ messages in thread From: Petr Mladek @ 2026-11-13 15:05 UTC (permalink / raw) To: John Ogness Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Huacai Chen, WANG Xuerui, Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP), Ritesh Harjani (IBM), Shrikanth Hegde, Greg Kroah-Hartman, Jason Wessel, Daniel Thompson, Douglas Anderson, Andrew Morton, Mukesh Kumar Chaurasiya, Feng Tang, Rio, Bradley Morgan, Pnina Feder, Gal Pressman, Petr Pavlu, Pavel Tikhomirov, Oleg Nesterov, Cen Zhang (Microsoft), loongarch, linuxppc-dev, kgdb-bugreport On Wed 2026-11-11 19:25:17, John Ogness wrote: > Prepare for per-console atomic flushing policies by introducing > enum pr_flush_reason to classify various reasons for performing a > printk backlog flush. The reasons are specified for > printk_trigger_flush() and console_flush_on_panic(). > > For atomic printing from printk_trigger_flush(), propagate the > reason down to __nbcon_atomic_flush_pending_con(), where the actual > atomic flushing is executed. > > For legacy printing, use a new global variable @legacy_flush_reason > to track the reason in case nbcon consoles are using legacy > printing. > > Update all printk_trigger_flush() and console_flush_on_panic() > call sites as well as any explicit lower-level atomic flush calls > to specify the reason. > > Note that PR_FLUSH_RUNTIME is used for cases where the reason for > the flush is not clearly defined. > --- a/include/linux/printk.h > +++ b/include/linux/printk.h > @@ -145,6 +145,24 @@ void early_printk(const char *s, ...) { } > > struct dev_printk_info; > > +/** > + * enum pr_flush_reason - Reason for a flush > + * @PR_FLUSH_RUNTIME: A flush while the kernel is running > + * @PR_FLUSH_RESTART: The kernel is ending, but another instance should > + * follow (reboot, kexec) > + * @PR_FLUSH_HANG: The kernel is ending and will enter an infinite loop > + * @PR_FLUSH_KDB: Printing while KDB is active > + * > + * Flush reasons are used to determine if unsafe atomic flushing should be > + * performed, based on individual console policies. > + */ > +enum pr_flush_reason { > + PR_FLUSH_RUNTIME = 0, > + PR_FLUSH_RESTART, > + PR_FLUSH_HANG, > + PR_FLUSH_KDB, > +}; This entire patchset adds a lot of complexity just to enable all 4 new policy flags for netconsole in the last patch. There already have few dimensions which affect console flushing: + console_loglevel + nbcon_prio This patchset adds 8 new terms in pr_flush_reason and nbcon_unsafe_flush_flags just to explicitly set all flush_flags in netconsole. Let's start with pr_flush_reason. I am not sure if it is worth it: + PR_FLUSH_RUNTIME is the default + PR_FLUSH_RESTART can be detected by system_state > SYSTEM_RUNNING + PR_FLUSH_HANG has only one caller currently distinguished by the global panic_nbcon_allow_unsafe_takeover + PR_FLUSH_KDB can be detected by kdb_trap_printk and kdb_printf_cpu, see vprintk() implementation. IMHO, it makes things worse because nbcon_atomic_flush_pending() has to use PR_FLUSH_RUNTIME in vprintk_emit(). But I think that we would like to flush it the same way as an explicit flush called in the given context. Best Regards, Petr ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH printk v2 2/6] console: Introduce unsafe flush policy flags 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness 2026-11-11 18:19 ` [PATCH printk v2 1/6] printk: Introduce and specify flush reasons John Ogness @ 2026-11-11 18:19 ` John Ogness 2026-11-13 16:17 ` Petr Mladek 2026-11-11 18:19 ` [PATCH printk v2 3/6] printk: Evaluate flush policy in nbcon_allow_unsafe_takeover() John Ogness ` (3 subsequent siblings) 5 siblings, 1 reply; 10+ messages in thread From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw) To: Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Greg Kroah-Hartman Prepare for per-console atomic flushing policies by introducing a new nbcon-specific console field @unsafe_flush_flags to store the unsafe flush policies for a console. The policies are represented by bits, specified by enum nbcon_unsafe_flush_flags. Currently it is expected that any @unsafe_flush_flags bits are set prior to console registration and do not change while registered. No functional change. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- include/linux/console.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/linux/console.h b/include/linux/console.h index 06d01f1743512..beb1ee04535b7 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -194,6 +194,29 @@ enum cons_flags { CON_NBCON_ATOMIC_UNSAFE = BIT(9), }; +/** + * enum nbcon_unsafe_flush_flags - Unsafe atomic flush policy flags + * @NBCON_PANIC_FLUSH: In panic, unsafe flush before kexec or reboot. + * @NBCON_PANIC_PRINTK: In panic, unsafe flush on each printk(). + * @NBCON_NORMAL_NOTHREAD: During normal operation, when printing + * kthreads are unreliable or have been shutdown, + * unsafe flush on each printk() or on explicit + * flushing. + * @NBCON_KDB: Unsafe flush kdb output. + * + * NBCON unsafe atomic flushing always occurs at the end of panic() before + * the kernel enters an infinite loop. Users may choose to perform unsafe + * flushing in additional scenarios where the current kernel is ending in + * order to increase the chances of seeing console messages, even if it is + * not safe to do so. + */ +enum nbcon_unsafe_flush_flags { + NBCON_PANIC_FLUSH = BIT(0), + NBCON_PANIC_PRINTK = BIT(1), + NBCON_NORMAL_NOTHREAD = BIT(2), + NBCON_KDB = BIT(3), +}; + /** * struct nbcon_state - console state for nbcon consoles * @atom: Compound of the state fields for atomic operations @@ -326,6 +349,7 @@ struct nbcon_write_context { * @data: Driver private data * @node: hlist node for the console list * + * @unsafe_flush_flags: Unsafe atomic flush policy. See enum nbcon_unsafe_flush_flags * @nbcon_state: State for nbcon consoles * @nbcon_seq: Sequence number of the next record for nbcon to print * @nbcon_device_ctxt: Context available for non-printing operations @@ -461,6 +485,8 @@ struct console { */ void (*device_unlock)(struct console *con, unsigned long flags); + unsigned int unsafe_flush_flags; + atomic_t __private nbcon_state; atomic_long_t __private nbcon_seq; struct nbcon_context __private nbcon_device_ctxt; -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH printk v2 2/6] console: Introduce unsafe flush policy flags 2026-11-11 18:19 ` [PATCH printk v2 2/6] console: Introduce unsafe flush policy flags John Ogness @ 2026-11-13 16:17 ` Petr Mladek 0 siblings, 0 replies; 10+ messages in thread From: Petr Mladek @ 2026-11-13 16:17 UTC (permalink / raw) To: John Ogness Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Greg Kroah-Hartman On Wed 2026-11-11 19:25:18, John Ogness wrote: > Prepare for per-console atomic flushing policies by introducing a > new nbcon-specific console field @unsafe_flush_flags to store the > unsafe flush policies for a console. The policies are represented > by bits, specified by enum nbcon_unsafe_flush_flags. > > Currently it is expected that any @unsafe_flush_flags bits are set > prior to console registration and do not change while registered. > > No functional change. > > Signed-off-by: John Ogness <john.ogness@linutronix.de> > --- > include/linux/console.h | 26 ++++++++++++++++++++++++++ > 1 file changed, 26 insertions(+) > > diff --git a/include/linux/console.h b/include/linux/console.h > index 06d01f1743512..beb1ee04535b7 100644 > --- a/include/linux/console.h > +++ b/include/linux/console.h > @@ -194,6 +194,29 @@ enum cons_flags { > CON_NBCON_ATOMIC_UNSAFE = BIT(9), > }; > > +/** > + * enum nbcon_unsafe_flush_flags - Unsafe atomic flush policy flags > + * @NBCON_PANIC_FLUSH: In panic, unsafe flush before kexec or reboot. > + * @NBCON_PANIC_PRINTK: In panic, unsafe flush on each printk(). Do we need to distinguish between flush in printk() and an explicit flush? IMHO, there is no reason. We usually call the explicit flush because we want to trigger it. But printk(), called in the same context, should trigger/do it as well. > + * @NBCON_NORMAL_NOTHREAD: During normal operation, when printing > + * kthreads are unreliable or have been shutdown, > + * unsafe flush on each printk() or on explicit > + * flushing. Do we need to distinguish between panic and non-panic paths when the kthreads do not work? IMHO, this is more about that the system is going down and the kthreads do not work. Also what about emergency context when the system is about to continue? > + * @NBCON_KDB: Unsafe flush kdb output. OK, let's assume that we want to set a policy where we allow the unsafe takeover in the following contexts: NBCON_ALLOW_UNSAFE_NEVER NBCON_ALLOW_UNSAFE_RESTART NBCON_ALLOW_UNSAFE_EMERGENCY NBCON_ALLOW_UNSAFE_KDB , where + NEVER might actually allow it when explicitely enabled in nbcon_panic_flush_unsafe(). The word "never" just has a simple semantic in the context of the other values + RESTART would allow the unsafe takeover in printk()/flush() when the system is doing halt/reboot/crash_kexec... + EMERGENCY would allow it even in NBCON_PRIO_EMERGENCY context. + KDB would allow it in KDB context And I would get the context the following way: enum nbcon_allow_unsafe get_nbcon_allow_unsafe_request(void) { enum nbcon_prio prio; /* * The kdb check is copied from vprintk() implementation. * We should put it into a helper. */ #ifdef CONFIG_KGDB_KDB /* Allow to pass printk() to kdb but avoid a recursion. */ if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0)) return NBCON_ALLOW_UNSAFE_KDB; #endif prio = nbcon_get_default_prio(); /* FIXME: What about SYSTEM_SUSPEND? if (prio == NBCON_PRIO_PANIC || system_state > SYSTEM_RUNNING) return NBCON_ALLOW_UNSAFE_RESTART; if (prio == NBCON_PRIO_EMERGENCY) return NBCON_ALLOW_UNSAFE_EMERGENCY; return NBCON_ALLOW_UNSAFE_NEVER; } IMHO, this better fits the existing terminology and design. And it should be much easier to understand by developers and users. + * > + * NBCON unsafe atomic flushing always occurs at the end of panic() before > + * the kernel enters an infinite loop. Users may choose to perform unsafe > + * flushing in additional scenarios where the current kernel is ending in > + * order to increase the chances of seeing console messages, even if it is > + * not safe to do so. > + */ > +enum nbcon_unsafe_flush_flags { > + NBCON_PANIC_FLUSH = BIT(0), > + NBCON_PANIC_PRINTK = BIT(1), > + NBCON_NORMAL_NOTHREAD = BIT(2), > + NBCON_KDB = BIT(3), > +}; > + > /** > * struct nbcon_state - console state for nbcon consoles > * @atom: Compound of the state fields for atomic operations > @@ -326,6 +349,7 @@ struct nbcon_write_context { > * @data: Driver private data > * @node: hlist node for the console list > * > + * @unsafe_flush_flags: Unsafe atomic flush policy. See enum nbcon_unsafe_flush_flags > * @nbcon_state: State for nbcon consoles > * @nbcon_seq: Sequence number of the next record for nbcon to print > * @nbcon_device_ctxt: Context available for non-printing operations > @@ -461,6 +485,8 @@ struct console { > */ > void (*device_unlock)(struct console *con, unsigned long flags); > > + unsigned int unsafe_flush_flags; I would call it: unsigned int allow_unsafe_policy; > + > atomic_t __private nbcon_state; > atomic_long_t __private nbcon_seq; > struct nbcon_context __private nbcon_device_ctxt; And the net console would get initialized to: .allow_unsafe_policy = NBCON_ALLOW_UNSAFE_RESTART | NBCON_ALLOW_UNSAFE_KDB; And nbcon_allow_unsafe_takeover would get implemented as: static bool nbcon_allow_unsafe_takeover(struct console *con) { allow_unsafe_request = get_nbcon_allow_unsafe(); if (con->allow_unsafe_policy & get_nbcon_allow_usafe_request()) return true; return panic_nbcon_allow_unsafe_takeover; } What do you think, please? Best Regards, Petr ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH printk v2 3/6] printk: Evaluate flush policy in nbcon_allow_unsafe_takeover() 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness 2026-11-11 18:19 ` [PATCH printk v2 1/6] printk: Introduce and specify flush reasons John Ogness 2026-11-11 18:19 ` [PATCH printk v2 2/6] console: Introduce unsafe flush policy flags John Ogness @ 2026-11-11 18:19 ` John Ogness 2026-11-11 18:19 ` [PATCH printk v2 4/6] printk: Remove nbcon_atomic_flush_unsafe() John Ogness ` (2 subsequent siblings) 5 siblings, 0 replies; 10+ messages in thread From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw) To: Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Greg Kroah-Hartman Currently nbcon_allow_unsafe_takeover() is a hack, relying on the temporary setting of a global variable @panic_nbcon_allow_unsafe_takeover as a gate to determine if unsafe flushing is allowed. This hack works because unsafe flushing is only performed at the end of panic(). However, this hack is _not_ sufficient if unsafe flushing is to be allowed in other contexts. Allow unsafe flushing in other contexts by modifying nbcon_allow_unsafe_takeover() to take a console and flush reason as input and, based on the unsafe flush policies of that console, determine if unsafe flushing is allowed. This also allows the global variable @panic_nbcon_allow_unsafe_takeover to be removed. Remove the hard-coded policy for CON_NBCON_ATOMIC_UNSAFE from console_is_usable() and implement that policy logic within nbcon_allow_unsafe_takeover(). Note that this changes the flushing flow for CON_NBCON_ATOMIC_UNSAFE consoles. Rather than console_is_usable() reporting that the console is not usable, __nbcon_atomic_flush_pending_con() will report that it is unable to acquire ownership. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- include/linux/console.h | 11 +---- kernel/printk/nbcon.c | 91 +++++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/include/linux/console.h b/include/linux/console.h index beb1ee04535b7..b5024a879b96a 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -179,7 +179,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 called when allowed by + * nbcon_allow_unsafe_takeover(). */ enum cons_flags { CON_PRINTBUFFER = BIT(0), @@ -637,7 +638,6 @@ extern void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt); -extern bool nbcon_allow_unsafe_takeover(void); extern bool nbcon_kdb_try_acquire(struct console *con, struct nbcon_write_context *wctxt); extern void nbcon_kdb_release(struct nbcon_write_context *wctxt); @@ -670,13 +670,6 @@ static inline bool console_is_usable(struct console *con, short flags, bool use_ /* The write_atomic() callback is optional. */ if (!con->write_atomic) return false; - - /* - * An unsafe write_atomic() callback is only usable - * when unsafe takeovers are allowed. - */ - if ((flags & CON_NBCON_ATOMIC_UNSAFE) && !nbcon_allow_unsafe_takeover()) - return false; } /* diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c index 935fd6b86bac7..d4d2fc51f2aa7 100644 --- a/kernel/printk/nbcon.c +++ b/kernel/printk/nbcon.c @@ -557,10 +557,6 @@ static int nbcon_context_try_acquire_hostile(struct nbcon_context *ctxt, if (!ctxt->allow_unsafe_takeover) return -EPERM; - /* Ensure caller is allowed to perform unsafe hostile takeovers. */ - if (WARN_ON_ONCE(ctxt->prio != NBCON_PRIO_PANIC)) - return -EPERM; - /* * Check that try_acquire_direct() and try_acquire_handover() returned * -EBUSY in the right situation. @@ -1453,24 +1449,60 @@ enum nbcon_prio nbcon_get_default_prio(void) return NBCON_PRIO_NORMAL; } -/* - * Track if it is allowed to perform unsafe hostile takeovers of console - * ownership. When true, console drivers might perform unsafe actions while - * printing. It is externally available via nbcon_allow_unsafe_takeover(). - */ -static bool panic_nbcon_allow_unsafe_takeover; - /** * nbcon_allow_unsafe_takeover - Check if unsafe console takeovers are allowed + * for a specified console and reason * - * Return: True, when it is permitted to perform unsafe console printing + * @con: The console to check + * @reason: The reason for the unsafe takeover * - * This is also used by console_is_usable() to determine if it is allowed to - * call write_atomic() callbacks flagged as unsafe (CON_NBCON_ATOMIC_UNSAFE). + * Return: True, when @con is allowed to perform unsafe console printing */ -bool nbcon_allow_unsafe_takeover(void) +static bool nbcon_allow_unsafe_takeover(struct console *con, enum pr_flush_reason reason) { - return panic_on_this_cpu() && panic_nbcon_allow_unsafe_takeover; + int unsafe_flags = con->unsafe_flush_flags; + bool in_panic = panic_on_this_cpu(); + bool allow = false; + + switch (reason) { + case PR_FLUSH_RUNTIME: + if (in_panic) { + if (unsafe_flags & NBCON_PANIC_PRINTK) + allow = true; + + } else { + /* Only when the kthreads have been shutdown. */ + if ((unsafe_flags & NBCON_NORMAL_NOTHREAD) && + !con->kthread && + system_state > SYSTEM_RUNNING) { + allow = true; + } + } + break; + case PR_FLUSH_RESTART: + /* kexec, reboot */ + + if (in_panic) { + if (unsafe_flags & NBCON_PANIC_FLUSH) + allow = true; + + } else { + /* Printing kthreads not reliable. */ + if (unsafe_flags & NBCON_NORMAL_NOTHREAD) + allow = true; + } + break; + case PR_FLUSH_HANG: + /* Always unsafe flush before hang. */ + allow = true; + break; + case PR_FLUSH_KDB: + if (unsafe_flags & NBCON_KDB) + allow = true; + break; + } + + return allow; } /** @@ -1515,6 +1547,14 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, ctxt->prio = nbcon_get_default_prio(); if (use_atomic) { + ctxt->allow_unsafe_takeover = nbcon_allow_unsafe_takeover(con, + legacy_flush_reason); + + if ((console_srcu_read_flags(con) & CON_NBCON_ATOMIC_UNSAFE) && + !ctxt->allow_unsafe_takeover) { + return false; + } + /* * In an atomic or unknown context, use the same procedure as * in console_emit_next_record(). It allows to handover. @@ -1572,7 +1612,12 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, enum pr_flush_r ctxt->console = con; ctxt->spinwait_max_us = 2000; ctxt->prio = nbcon_get_default_prio(); - ctxt->allow_unsafe_takeover = nbcon_allow_unsafe_takeover(); + ctxt->allow_unsafe_takeover = nbcon_allow_unsafe_takeover(con, reason); + + if ((console_srcu_read_flags(con) & CON_NBCON_ATOMIC_UNSAFE) && + !ctxt->allow_unsafe_takeover) { + return -EPERM; + } while (nbcon_seq_read(con) < stop_seq) { /* @@ -1707,9 +1752,7 @@ void nbcon_atomic_flush_pending(enum pr_flush_reason reason) */ void nbcon_atomic_flush_unsafe(void) { - panic_nbcon_allow_unsafe_takeover = true; __nbcon_atomic_flush_pending(PR_FLUSH_HANG, prb_next_reserve_seq(prb)); - panic_nbcon_allow_unsafe_takeover = false; } /** @@ -1976,8 +2019,14 @@ bool nbcon_kdb_try_acquire(struct console *con, struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); memset(ctxt, 0, sizeof(*ctxt)); - ctxt->console = con; - ctxt->prio = NBCON_PRIO_EMERGENCY; + ctxt->console = con; + ctxt->prio = NBCON_PRIO_EMERGENCY; + ctxt->allow_unsafe_takeover = nbcon_allow_unsafe_takeover(con, PR_FLUSH_KDB); + + if ((console_srcu_read_flags(con) & CON_NBCON_ATOMIC_UNSAFE) && + !ctxt->allow_unsafe_takeover) { + return false; + } if (!nbcon_context_try_acquire(ctxt, false)) return false; -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH printk v2 4/6] printk: Remove nbcon_atomic_flush_unsafe() 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness ` (2 preceding siblings ...) 2026-11-11 18:19 ` [PATCH printk v2 3/6] printk: Evaluate flush policy in nbcon_allow_unsafe_takeover() John Ogness @ 2026-11-11 18:19 ` John Ogness 2026-11-11 18:19 ` [PATCH printk v2 5/6] printk: Add panic+kexec flush point John Ogness 2026-11-11 18:19 ` [PATCH printk v2 6/6] netconsole: Always perform unsafe flushing on panic/kdb/restart John Ogness 5 siblings, 0 replies; 10+ messages in thread From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw) To: Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Andrew Morton, Rio, Bradley Morgan, Randy Dunlap, Greg Kroah-Hartman, Petr Pavlu, Alessandro Carminati, Pnina Feder There is no need for the special function nbcon_atomic_flush_unsafe(), which is only called at the end of panic(). Its functionality is replaced with printk_trigger_flush(PR_FLUSH_HANG). Signed-off-by: John Ogness <john.ogness@linutronix.de> --- include/linux/printk.h | 5 ----- kernel/panic.c | 2 +- kernel/printk/nbcon.c | 12 ------------ 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 711bd280d1c2f..fd012871322c0 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -225,7 +225,6 @@ void console_try_replay_all(void); void printk_legacy_allow_panic_sync(void); extern bool nbcon_device_try_acquire(struct console *con); extern void nbcon_device_release(struct console *con); -void nbcon_atomic_flush_unsafe(void); bool pr_flush(int timeout_ms, bool reset_on_progress); #else static inline __printf(1, 0) @@ -336,10 +335,6 @@ static inline void nbcon_device_release(struct console *con) { } -static inline void nbcon_atomic_flush_unsafe(void) -{ -} - static inline bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; diff --git a/kernel/panic.c b/kernel/panic.c index 32286365d4fee..4020ad92ab141 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -765,7 +765,7 @@ void vpanic(const char *fmt, va_list args) * Explicitly flush the kernel log buffer one last time. */ console_flush_on_panic(CONSOLE_FLUSH_PENDING, PR_FLUSH_HANG); - nbcon_atomic_flush_unsafe(); + printk_trigger_flush(PR_FLUSH_HANG); local_irq_enable(); for (i = 0; ; i += PANIC_TIMER_STEP) { diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c index d4d2fc51f2aa7..972c1174619ef 100644 --- a/kernel/printk/nbcon.c +++ b/kernel/printk/nbcon.c @@ -1743,18 +1743,6 @@ void nbcon_atomic_flush_pending(enum pr_flush_reason reason) __nbcon_atomic_flush_pending(reason, prb_next_reserve_seq(prb)); } -/** - * nbcon_atomic_flush_unsafe - Flush all nbcon consoles using their - * write_atomic() callback and allowing unsafe hostile takeovers - * - * Flush the backlog up through the currently newest record. Unsafe hostile - * takeovers will be performed, if necessary. - */ -void nbcon_atomic_flush_unsafe(void) -{ - __nbcon_atomic_flush_pending(PR_FLUSH_HANG, prb_next_reserve_seq(prb)); -} - /** * nbcon_cpu_emergency_enter - Enter an emergency section where printk() * messages for that CPU are flushed directly -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH printk v2 5/6] printk: Add panic+kexec flush point 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness ` (3 preceding siblings ...) 2026-11-11 18:19 ` [PATCH printk v2 4/6] printk: Remove nbcon_atomic_flush_unsafe() John Ogness @ 2026-11-11 18:19 ` John Ogness 2026-11-12 18:20 ` sashiko-bot 2026-11-11 18:19 ` [PATCH printk v2 6/6] netconsole: Always perform unsafe flushing on panic/kdb/restart John Ogness 5 siblings, 1 reply; 10+ messages in thread From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw) To: Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Andrew Morton, Baoquan He, Mike Rapoport, Pasha Tatashin, Pratyush Yadav, Dave Young, kexec During panic, nbcon consoles transition to atomic printing. However, there are consoles that do not support safe atomic printing (CON_NBCON_ATOMIC_UNSAFE). Such consoles will only flush during panic if their unsafe flush policy allows them to do so. The unsafe flush policy NBCON_PANIC_FLUSH only allows unsafe flushing when particular flushes are explicitly invoked. Call printk_trigger_flush(PR_FLUSH_RESTART) before performing the kexec in order to give such consoles a chance to perform an unsafe flush. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- kernel/crash_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/crash_core.c b/kernel/crash_core.c index d0bd2d0cf8990..064b0af903c38 100644 --- a/kernel/crash_core.c +++ b/kernel/crash_core.c @@ -140,6 +140,7 @@ void __noclone __crash_kexec(struct pt_regs *regs) crash_setup_regs(&fixed_regs, regs); crash_save_vmcoreinfo(); + printk_trigger_flush(PR_FLUSH_RESTART); machine_crash_shutdown(&fixed_regs); crash_cma_clear_pending_dma(); machine_kexec(kexec_crash_image); -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH printk v2 5/6] printk: Add panic+kexec flush point 2026-11-11 18:19 ` [PATCH printk v2 5/6] printk: Add panic+kexec flush point John Ogness @ 2026-11-12 18:20 ` sashiko-bot 0 siblings, 0 replies; 10+ messages in thread From: sashiko-bot @ 2026-11-12 18:20 UTC (permalink / raw) To: John Ogness, Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, Andrew Morton, Baoquan He, Mike Rapoport, Pasha Tatashin, Pratyush Yadav, Dave Young, kexec Thank you for your contribution! Sashiko AI review found 1 potential issue to consider: - [Medium] crash: printk_trigger_flush() in __crash_kexec() called with wrong panic_cpu -- commit fef7b57cf45508b52c2322cc5354dee7d0cedbc1 Author: John Ogness <john.ogness@linutronix.de> printk: Add panic+kexec flush point This commit adds a call to printk_trigger_flush() in __crash_kexec() to allow consoles with the panic flush policy to flush before booting into the crash kernel. > diff --git a/kernel/crash_core.c b/kernel/crash_core.c > index d0bd2d0cf8990..064b0af903c38 100644 > --- a/kernel/crash_core.c > +++ b/kernel/crash_core.c > @@ -140,6 +140,7 @@ void __noclone __crash_kexec(struct pt_regs *regs) > > crash_setup_regs(&fixed_regs, regs); > crash_save_vmcoreinfo(); > + printk_trigger_flush(PR_FLUSH_RESTART); [Severity: Medium] Can printk_trigger_flush() be called here on CPU0 while panic_cpu still holds a non-zero CPU number or its invalid initial value? On Hyper-V root partitions, crash_nmi_callback() parks all non-zero CPUs when a panic occurs on another CPU (or when the hypervisor itself crashes with panic_cpu unset), while CPU0 disables the hypervisor and calls hv_crash_handle() -> __crash_kexec() without updating panic_cpu: arch/x86/hyperv/hv_crash.c:hv_crash_handle() { ... /* we are now fully in devirtualized normal kernel mode */ __crash_kexec(NULL); } Because panic_on_this_cpu() is false on CPU0, nbcon_get_default_prio() returns normal priority instead of panic priority. printk_trigger_flush() then skips atomic panic flushing and takes the offload path via defer_console_output() -> irq_work_queue(). When the local tick is stopped, raising the self-interrupt calls hv_send_ipi_self(), which invokes a hypercall after the hypervisor has already been disabled, faulting and aborting machine_kexec(). -- Sashiko AI review · https://sashiko.dev/#/patchset/20261111181942.593695-1-john.ogness@linutronix.de?part=5 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH printk v2 6/6] netconsole: Always perform unsafe flushing on panic/kdb/restart 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness ` (4 preceding siblings ...) 2026-11-11 18:19 ` [PATCH printk v2 5/6] printk: Add panic+kexec flush point John Ogness @ 2026-11-11 18:19 ` John Ogness 5 siblings, 0 replies; 10+ messages in thread From: John Ogness @ 2026-11-11 18:19 UTC (permalink / raw) To: Petr Mladek Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao, printk, linux-kernel, Gustavo Luiz Duarte, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev As a legacy console the netconsole would perform unsafe flushing during panic/kdb/restart. With commit 7eab73b18630 ("netconsole: convert to NBCON console infrastructure") the netconsole is now an NBCON console, however it uses the CON_NBCON_ATOMIC_UNSAFE flag and this prevents unsafe flushing except for at the very end of panic(). Enable unsafe flushing policies to allow the netconsole to perform unsafe flushing during all panic/kdb/restart variations, just as it did when it was a legacy console. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- drivers/net/netconsole.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 267254f046de9..6c1587958e915 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -2695,6 +2695,8 @@ static void free_param_target(struct netconsole_target *nt) static struct console netconsole_ext = { .name = "netcon_ext", .flags = CON_ENABLED | CON_EXTENDED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE, + .unsafe_flush_flags = NBCON_PANIC_FLUSH | NBCON_PANIC_PRINTK | NBCON_KDB | + NBCON_NORMAL_NOTHREAD, .write_thread = netconsole_write_ext, .write_atomic = netconsole_write_ext, .device_lock = netconsole_device_lock, @@ -2704,6 +2706,8 @@ static struct console netconsole_ext = { static struct console netconsole = { .name = "netcon", .flags = CON_ENABLED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE, + .unsafe_flush_flags = NBCON_PANIC_FLUSH | NBCON_PANIC_PRINTK | NBCON_KDB | + NBCON_NORMAL_NOTHREAD, .write_thread = netconsole_write_basic, .write_atomic = netconsole_write_basic, .device_lock = netconsole_device_lock, -- 2.47.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-11-13 16:17 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-11 18:19 [PATCH printk v2 0/6] Introduce policies for unsafe flushing John Ogness 2026-11-11 18:19 ` [PATCH printk v2 1/6] printk: Introduce and specify flush reasons John Ogness 2026-11-13 15:05 ` Petr Mladek 2026-11-11 18:19 ` [PATCH printk v2 2/6] console: Introduce unsafe flush policy flags John Ogness 2026-11-13 16:17 ` Petr Mladek 2026-11-11 18:19 ` [PATCH printk v2 3/6] printk: Evaluate flush policy in nbcon_allow_unsafe_takeover() John Ogness 2026-11-11 18:19 ` [PATCH printk v2 4/6] printk: Remove nbcon_atomic_flush_unsafe() John Ogness 2026-11-11 18:19 ` [PATCH printk v2 5/6] printk: Add panic+kexec flush point John Ogness 2026-11-12 18:20 ` sashiko-bot 2026-11-11 18:19 ` [PATCH printk v2 6/6] netconsole: Always perform unsafe flushing on panic/kdb/restart John Ogness
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.