LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH printk 0/6] Introduce policies for unsafe flushing
@ 2026-11-09 12:31 John Ogness
  2026-11-09 12:31 ` [PATCH printk 1/6] printk: Introduce and specify flush reasons John Ogness
  0 siblings, 1 reply; 3+ messages in thread
From: John Ogness @ 2026-11-09 12:31 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao,
	printk, linux-kernel, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP),
	Ritesh Harjani (IBM), Shrikanth Hegde, Andrew Morton, Feng Tang,
	Jinjie Ruan, Mukesh Kumar Chaurasiya, Oleg Nesterov,
	Pavel Tikhomirov, Bradley Morgan, Christian Brauner (Amutable),
	Cen Zhang (Microsoft), Petr Pavlu, linuxppc-dev,
	Greg Kroah-Hartman, Rio, Aaron Tomlin, Bradley Morgan,
	Andy Shevchenko, Alessandro Carminati, Randy Dunlap, Pnina Feder,
	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

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. [0] 

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.

John Ogness

[0] 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/powerpc/kernel/watchdog.c |   2 +-
 drivers/net/netconsole.c       |   4 ++
 include/linux/console.h        |  37 ++++++++---
 include/linux/printk.h         |  27 ++++++--
 kernel/crash_core.c            |   1 +
 kernel/panic.c                 |   2 +-
 kernel/printk/internal.h       |   4 +-
 kernel/printk/nbcon.c          | 117 ++++++++++++++++++++++-----------
 kernel/printk/printk.c         |  16 ++---
 kernel/reboot.c                |   2 +-
 lib/nmi_backtrace.c            |   2 +-
 11 files changed, 146 insertions(+), 68 deletions(-)


base-commit: d01f86a7da8161aac8c6304b377cf58fb75861ca
-- 
2.47.3



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH printk 1/6] printk: Introduce and specify flush reasons
  2026-11-09 12:31 [PATCH printk 0/6] Introduce policies for unsafe flushing John Ogness
@ 2026-11-09 12:31 ` John Ogness
  2026-11-09 16:37   ` kernel test robot
  0 siblings, 1 reply; 3+ messages in thread
From: John Ogness @ 2026-11-09 12:31 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Sergey Senozhatsky, Steven Rostedt, Ryan Roberts, Breno Leitao,
	printk, linux-kernel, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP),
	Ritesh Harjani (IBM), Shrikanth Hegde, Andrew Morton, Feng Tang,
	Jinjie Ruan, Mukesh Kumar Chaurasiya, Oleg Nesterov,
	Pavel Tikhomirov, Bradley Morgan, Christian Brauner (Amutable),
	Cen Zhang (Microsoft), Petr Pavlu, linuxppc-dev

Prepare for per-console atomic flushing policies by introducing
enum pr_flush_reason to classify various reasons for performing a
printk backlog flush using printk_trigger_flush().

Propagate the reason down to __nbcon_atomic_flush_pending_con(),
where the actually atomic flushing is executed.

Update all printk_trigger_flush() call sites as well as an
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/powerpc/kernel/watchdog.c |  2 +-
 include/linux/printk.h         | 22 ++++++++++++++++++++--
 kernel/printk/internal.h       |  4 ++--
 kernel/printk/nbcon.c          | 28 ++++++++++++++++++----------
 kernel/printk/printk.c         | 16 ++++++++--------
 kernel/reboot.c                |  2 +-
 lib/nmi_backtrace.c            |  2 +-
 7 files changed, 51 insertions(+), 25 deletions(-)

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/printk.h b/include/linux/printk.h
index f594c1266bfd4..c669497bd3378 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,
+	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/printk/internal.h b/kernel/printk/internal.h
index 85fbf1801cbe0..7f1f4677609da 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) { }
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..ab9f2d6a6526a 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2455,7 +2455,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 +2870,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();
@@ -3561,7 +3561,7 @@ 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)
@@ -3775,7 +3775,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 +4537,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();
@@ -4732,13 +4732,13 @@ 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) {
@@ -5090,7 +5090,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] 3+ messages in thread

* Re: [PATCH printk 1/6] printk: Introduce and specify flush reasons
  2026-11-09 12:31 ` [PATCH printk 1/6] printk: Introduce and specify flush reasons John Ogness
@ 2026-11-09 16:37   ` kernel test robot
  0 siblings, 0 replies; 3+ messages in thread
From: kernel test robot @ 2026-11-09 16:37 UTC (permalink / raw)
  To: John Ogness, Petr Mladek
  Cc: oe-kbuild-all, Sergey Senozhatsky, Steven Rostedt, Ryan Roberts,
	Breno Leitao, printk, linux-kernel, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
	Ritesh Harjani (IBM), Shrikanth Hegde, Andrew Morton,
	Linux Memory Management List, Feng Tang, Jinjie Ruan,
	Mukesh Kumar Chaurasiya, Oleg Nesterov, Pavel Tikhomirov,
	Bradley Morgan, Christian Brauner (Amutable),
	Cen Zhang (Microsoft), Petr Pavlu, linuxppc-dev

Hi John,

kernel test robot noticed the following build warnings:

[auto build test WARNING on d01f86a7da8161aac8c6304b377cf58fb75861ca]

url:    https://github.com/intel-lab-lkp/linux/commits/John-Ogness/printk-Introduce-and-specify-flush-reasons/20261109-133718
base:   d01f86a7da8161aac8c6304b377cf58fb75861ca
patch link:    https://lore.kernel.org/r/20261109123127.489676-2-john.ogness%40linutronix.de
patch subject: [PATCH printk 1/6] printk: Introduce and specify flush reasons
config: openrisc-defconfig (https://download.01.org/0day-ci/archive/20261110/202611100015.e1CNRy54-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261110/202611100015.e1CNRy54-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611100015.e1CNRy54-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: kernel/printk/printk.c:4735 function parameter 'reason' not described in 'printk_trigger_flush'
>> Warning: kernel/printk/printk.c:4735 function parameter 'reason' not described in 'printk_trigger_flush'

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-09 16:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-09 12:31 [PATCH printk 0/6] Introduce policies for unsafe flushing John Ogness
2026-11-09 12:31 ` [PATCH printk 1/6] printk: Introduce and specify flush reasons John Ogness
2026-11-09 16:37   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox