Skip to content

Commit 60325c2

Browse files
leitaokuba-moo
authored andcommitted
printk: Add execution context (task name/CPU) to printk_info
Extend struct printk_info to include the task name, pid, and CPU number where printk messages originate. This information is captured at vprintk_store() time and propagated through printk_message to nbcon_write_context, making it available to nbcon console drivers. This is useful for consoles like netconsole that want to include execution context in their output, allowing correlation of messages with specific tasks and CPUs regardless of where the console driver actually runs. The feature is controlled by CONFIG_PRINTK_EXECUTION_CTX, which is automatically selected by CONFIG_NETCONSOLE_DYNAMIC. When disabled, the helper functions compile to no-ops with no overhead. Suggested-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Petr Mladek <pmladek@suse.com> Reviewed-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: John Ogness <john.ogness@linutronix.de> Link: https://patch.msgid.link/20260206-nbcon-v7-1-62bda69b1b41@debian.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent ad1f18e commit 60325c2

7 files changed

Lines changed: 103 additions & 1 deletion

File tree

drivers/net/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ config NETCONSOLE_DYNAMIC
341341
bool "Dynamic reconfiguration of logging targets"
342342
depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
343343
!(NETCONSOLE=y && CONFIGFS_FS=m)
344+
select PRINTK_EXECUTION_CTX
344345
help
345346
This option enables the ability to dynamically reconfigure target
346347
parameters (interface, IP addresses, port numbers, MAC addresses)

include/linux/console.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,12 +298,20 @@ struct nbcon_context {
298298
* @outbuf: Pointer to the text buffer for output
299299
* @len: Length to write
300300
* @unsafe_takeover: If a hostile takeover in an unsafe state has occurred
301+
* @cpu: CPU on which the message was generated
302+
* @pid: PID of the task that generated the message
303+
* @comm: Name of the task that generated the message
301304
*/
302305
struct nbcon_write_context {
303306
struct nbcon_context __private ctxt;
304307
char *outbuf;
305308
unsigned int len;
306309
bool unsafe_takeover;
310+
#ifdef CONFIG_PRINTK_EXECUTION_CTX
311+
int cpu;
312+
pid_t pid;
313+
char comm[TASK_COMM_LEN];
314+
#endif
307315
};
308316

309317
/**

kernel/printk/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,20 @@ struct printk_buffers {
281281
* nothing to output and this record should be skipped.
282282
* @seq: The sequence number of the record used for @pbufs->outbuf.
283283
* @dropped: The number of dropped records from reading @seq.
284+
* @cpu: CPU on which the message was generated.
285+
* @pid: PID of the task that generated the message
286+
* @comm: Name of the task that generated the message.
284287
*/
285288
struct printk_message {
286289
struct printk_buffers *pbufs;
287290
unsigned int outbuf_len;
288291
u64 seq;
289292
unsigned long dropped;
293+
#ifdef CONFIG_PRINTK_EXECUTION_CTX
294+
int cpu;
295+
pid_t pid;
296+
char comm[TASK_COMM_LEN];
297+
#endif
290298
};
291299

292300
bool printk_get_next_message(struct printk_message *pmsg, u64 seq,

kernel/printk/nbcon.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,20 @@ void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt)
946946
}
947947
EXPORT_SYMBOL_GPL(nbcon_reacquire_nobuf);
948948

949+
#ifdef CONFIG_PRINTK_EXECUTION_CTX
950+
static void wctxt_load_execution_ctx(struct nbcon_write_context *wctxt,
951+
struct printk_message *pmsg)
952+
{
953+
wctxt->cpu = pmsg->cpu;
954+
wctxt->pid = pmsg->pid;
955+
memcpy(wctxt->comm, pmsg->comm, sizeof(wctxt->comm));
956+
static_assert(sizeof(wctxt->comm) == sizeof(pmsg->comm));
957+
}
958+
#else
959+
static void wctxt_load_execution_ctx(struct nbcon_write_context *wctxt,
960+
struct printk_message *pmsg) {}
961+
#endif
962+
949963
/**
950964
* nbcon_emit_next_record - Emit a record in the acquired context
951965
* @wctxt: The write context that will be handed to the write function
@@ -1048,6 +1062,8 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt, bool use_a
10481062
/* Initialize the write context for driver callbacks. */
10491063
nbcon_write_context_set_buf(wctxt, &pmsg.pbufs->outbuf[0], pmsg.outbuf_len);
10501064

1065+
wctxt_load_execution_ctx(wctxt, &pmsg);
1066+
10511067
if (use_atomic)
10521068
con->write_atomic(con, wctxt);
10531069
else

kernel/printk/printk.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2131,11 +2131,39 @@ static inline void printk_delay(int level)
21312131
}
21322132
}
21332133

2134+
#define CALLER_ID_MASK 0x80000000
2135+
21342136
static inline u32 printk_caller_id(void)
21352137
{
21362138
return in_task() ? task_pid_nr(current) :
2137-
0x80000000 + smp_processor_id();
2139+
CALLER_ID_MASK + smp_processor_id();
2140+
}
2141+
2142+
#ifdef CONFIG_PRINTK_EXECUTION_CTX
2143+
/* Store the opposite info than caller_id. */
2144+
static u32 printk_caller_id2(void)
2145+
{
2146+
return !in_task() ? task_pid_nr(current) :
2147+
CALLER_ID_MASK + smp_processor_id();
2148+
}
2149+
2150+
static pid_t printk_info_get_pid(const struct printk_info *info)
2151+
{
2152+
u32 caller_id = info->caller_id;
2153+
u32 caller_id2 = info->caller_id2;
2154+
2155+
return caller_id & CALLER_ID_MASK ? caller_id2 : caller_id;
2156+
}
2157+
2158+
static int printk_info_get_cpu(const struct printk_info *info)
2159+
{
2160+
u32 caller_id = info->caller_id;
2161+
u32 caller_id2 = info->caller_id2;
2162+
2163+
return ((caller_id & CALLER_ID_MASK ?
2164+
caller_id : caller_id2) & ~CALLER_ID_MASK);
21382165
}
2166+
#endif
21392167

21402168
/**
21412169
* printk_parse_prefix - Parse level and control flags.
@@ -2213,6 +2241,28 @@ static u16 printk_sprint(char *text, u16 size, int facility,
22132241
return text_len;
22142242
}
22152243

2244+
#ifdef CONFIG_PRINTK_EXECUTION_CTX
2245+
static void printk_store_execution_ctx(struct printk_info *info)
2246+
{
2247+
info->caller_id2 = printk_caller_id2();
2248+
get_task_comm(info->comm, current);
2249+
}
2250+
2251+
static void pmsg_load_execution_ctx(struct printk_message *pmsg,
2252+
const struct printk_info *info)
2253+
{
2254+
pmsg->cpu = printk_info_get_cpu(info);
2255+
pmsg->pid = printk_info_get_pid(info);
2256+
memcpy(pmsg->comm, info->comm, sizeof(pmsg->comm));
2257+
static_assert(sizeof(pmsg->comm) == sizeof(info->comm));
2258+
}
2259+
#else
2260+
static void printk_store_execution_ctx(struct printk_info *info) {}
2261+
2262+
static void pmsg_load_execution_ctx(struct printk_message *pmsg,
2263+
const struct printk_info *info) {}
2264+
#endif
2265+
22162266
__printf(4, 0)
22172267
int vprintk_store(int facility, int level,
22182268
const struct dev_printk_info *dev_info,
@@ -2320,6 +2370,7 @@ int vprintk_store(int facility, int level,
23202370
r.info->caller_id = caller_id;
23212371
if (dev_info)
23222372
memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info));
2373+
printk_store_execution_ctx(r.info);
23232374

23242375
/* A message without a trailing newline can be continued. */
23252376
if (!(flags & LOG_NEWLINE))
@@ -3002,6 +3053,7 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
30023053
pmsg->seq = r.info->seq;
30033054
pmsg->dropped = r.info->seq - seq;
30043055
force_con = r.info->flags & LOG_FORCE_CON;
3056+
pmsg_load_execution_ctx(pmsg, r.info);
30053057

30063058
/*
30073059
* Skip records that are not forced to be printed on consoles and that

kernel/printk/printk_ringbuffer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ struct printk_info {
2323
u8 flags:5; /* internal record flags */
2424
u8 level:3; /* syslog level */
2525
u32 caller_id; /* thread id or processor id */
26+
#ifdef CONFIG_PRINTK_EXECUTION_CTX
27+
u32 caller_id2; /* caller_id complement */
28+
/* name of the task that generated the message */
29+
char comm[TASK_COMM_LEN];
30+
#endif
2631

2732
struct dev_printk_info dev_info;
2833
};

lib/Kconfig.debug

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ config PRINTK_CALLER
3535
no option to enable/disable at the kernel command line parameter or
3636
sysfs interface.
3737

38+
config PRINTK_EXECUTION_CTX
39+
bool
40+
depends on PRINTK
41+
help
42+
This option extends struct printk_info to include extra execution
43+
context in printk, such as task name and CPU number from where the
44+
message originated. This is useful for correlating printk messages
45+
with specific execution contexts.
46+
47+
This is automatically enabled when a console driver that supports
48+
execution context is selected.
49+
3850
config STACKTRACE_BUILD_ID
3951
bool "Show build ID information in stacktraces"
4052
depends on PRINTK

0 commit comments

Comments
 (0)