Skip to content

Commit ed76c07

Browse files
marcospspmladek
authored andcommitted
printk: Introduce FORCE_CON flag
Introduce FORCE_CON flag to printk. The new flag will make it possible to create a context where printk messages will never be suppressed. This mechanism will be used in the next patch to create a force_con context on sysrq handling, removing an existing workaround on the loglevel global variable. The workaround existed to make sure that sysrq header messages were sent to all consoles, but this doesn't work with deferred messages because the loglevel might be restored to its original value before a console flushes the messages. Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com> Reviewed-by: John Ogness <john.ogness@linutronix.de> Reviewed-by: Petr Mladek <pmladek@suse.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://lore.kernel.org/r/20241105-printk-loud-con-v2-1-bd3ecdf7b0e4@suse.com Signed-off-by: Petr Mladek <pmladek@suse.com>
1 parent c903327 commit ed76c07

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

include/linux/printk.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ __printf(1, 2) __cold int _printk_deferred(const char *fmt, ...);
166166
extern void __printk_deferred_enter(void);
167167
extern void __printk_deferred_exit(void);
168168

169+
extern void printk_force_console_enter(void);
170+
extern void printk_force_console_exit(void);
171+
169172
/*
170173
* The printk_deferred_enter/exit macros are available only as a hack for
171174
* some code paths that need to defer all printk console printing. Interrupts

kernel/printk/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ int devkmsg_sysctl_set_loglvl(const struct ctl_table *table, int write,
5353

5454
/* Flags for a single printk record. */
5555
enum printk_info_flags {
56+
/* always show on console, ignore console_loglevel */
57+
LOG_FORCE_CON = 1,
5658
LOG_NEWLINE = 2, /* text ended with a newline */
5759
LOG_CONT = 8, /* text is a fragment of a continuation line */
5860
};
@@ -90,6 +92,7 @@ bool printk_percpu_data_ready(void);
9092

9193
void defer_console_output(void);
9294
bool is_printk_legacy_deferred(void);
95+
bool is_printk_force_console(void);
9396

9497
u16 printk_parse_prefix(const char *text, int *level,
9598
enum printk_info_flags *flags);

kernel/printk/printk.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,11 +1319,11 @@ static void boot_delay_msec(int level)
13191319
{
13201320
unsigned long long k;
13211321
unsigned long timeout;
1322+
bool suppress = !is_printk_force_console() &&
1323+
suppress_message_printing(level);
13221324

1323-
if ((boot_delay == 0 || system_state >= SYSTEM_RUNNING)
1324-
|| suppress_message_printing(level)) {
1325+
if ((boot_delay == 0 || system_state >= SYSTEM_RUNNING) || suppress)
13251326
return;
1326-
}
13271327

13281328
k = (unsigned long long)loops_per_msec * boot_delay;
13291329

@@ -2273,13 +2273,19 @@ int vprintk_store(int facility, int level,
22732273
if (dev_info)
22742274
flags |= LOG_NEWLINE;
22752275

2276+
if (is_printk_force_console())
2277+
flags |= LOG_FORCE_CON;
2278+
22762279
if (flags & LOG_CONT) {
22772280
prb_rec_init_wr(&r, reserve_size);
22782281
if (prb_reserve_in_last(&e, prb, &r, caller_id, PRINTKRB_RECORD_MAX)) {
22792282
text_len = printk_sprint(&r.text_buf[r.info->text_len], reserve_size,
22802283
facility, &flags, fmt, args);
22812284
r.info->text_len += text_len;
22822285

2286+
if (flags & LOG_FORCE_CON)
2287+
r.info->flags |= LOG_FORCE_CON;
2288+
22832289
if (flags & LOG_NEWLINE) {
22842290
r.info->flags |= LOG_NEWLINE;
22852291
prb_final_commit(&e);
@@ -2947,6 +2953,7 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
29472953
struct printk_info info;
29482954
struct printk_record r;
29492955
size_t len = 0;
2956+
bool force_con;
29502957

29512958
/*
29522959
* Formatting extended messages requires a separate buffer, so use the
@@ -2965,9 +2972,13 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
29652972

29662973
pmsg->seq = r.info->seq;
29672974
pmsg->dropped = r.info->seq - seq;
2975+
force_con = r.info->flags & LOG_FORCE_CON;
29682976

2969-
/* Skip record that has level above the console loglevel. */
2970-
if (may_suppress && suppress_message_printing(r.info->level))
2977+
/*
2978+
* Skip records that are not forced to be printed on consoles and that
2979+
* has level above the console loglevel.
2980+
*/
2981+
if (!force_con && may_suppress && suppress_message_printing(r.info->level))
29712982
goto out;
29722983

29732984
if (is_extended) {

kernel/printk/printk_safe.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@
1212

1313
#include "internal.h"
1414

15+
/* Context where printk messages are never suppressed */
16+
static atomic_t force_con;
17+
18+
void printk_force_console_enter(void)
19+
{
20+
atomic_inc(&force_con);
21+
}
22+
23+
void printk_force_console_exit(void)
24+
{
25+
atomic_dec(&force_con);
26+
}
27+
28+
bool is_printk_force_console(void)
29+
{
30+
return atomic_read(&force_con);
31+
}
32+
1533
static DEFINE_PER_CPU(int, printk_context);
1634

1735
/* Can be preempted by NMI. */

0 commit comments

Comments
 (0)