Skip to content

Commit d747755

Browse files
Feng Tangakpm00
authored andcommitted
panic: add 'panic_sys_info' sysctl to take human readable string parameter
Bitmap definition for 'panic_print' is hard to remember and decode. Add 'panic_sys_info='sysctl to take human readable string like "tasks,mem,timers,locks,ftrace,..." and translate it into bitmap. The detailed mapping is: SYS_INFO_TASKS "tasks" SYS_INFO_MEM "mem" SYS_INFO_TIMERS "timers" SYS_INFO_LOCKS "locks" SYS_INFO_FTRACE "ftrace" SYS_INFO_ALL_CPU_BT "all_bt" SYS_INFO_BLOCKED_TASKS "blocked_tasks" [[email protected]: add __maybe_unused to sys_info_avail] Link: https://lkml.kernel.org/r/20250708-fix-clang-sys_info_avail-warning-v1-1-60d239eacd64@kernel.org Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Feng Tang <[email protected]> Suggested-by: Petr Mladek <[email protected]> Cc: John Ogness <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Lance Yang <[email protected]> Cc: "Paul E . McKenney" <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Nathan Chancellor <[email protected]> Cc: Andy Shevchenko <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent b76e89e commit d747755

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

Documentation/admin-guide/sysctl/kernel.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,24 @@ So for example to print tasks and memory info on panic, user can::
899899
echo 3 > /proc/sys/kernel/panic_print
900900

901901

902+
panic_sys_info
903+
==============
904+
905+
A comma separated list of extra information to be dumped on panic,
906+
for example, "tasks,mem,timers,...". It is a human readable alternative
907+
to 'panic_print'. Possible values are:
908+
909+
============= ===================================================
910+
tasks print all tasks info
911+
mem print system memory info
912+
timer print timers info
913+
lock print locks info if CONFIG_LOCKDEP is on
914+
ftrace print ftrace buffer
915+
all_bt print all CPUs backtrace (if available in the arch)
916+
blocked_tasks print only tasks in uninterruptible (blocked) state
917+
============= ===================================================
918+
919+
902920
panic_on_rcu_stall
903921
==================
904922

include/linux/sys_info.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef _LINUX_SYS_INFO_H
33
#define _LINUX_SYS_INFO_H
44

5+
#include <linux/sysctl.h>
6+
57
/*
68
* SYS_INFO_PANIC_CONSOLE_REPLAY is for panic case only, as it needs special
79
* handling which only fits panic case.
@@ -16,5 +18,11 @@
1618
#define SYS_INFO_BLOCKED_TASKS 0x00000080
1719

1820
void sys_info(unsigned long si_mask);
21+
unsigned long sys_info_parse_param(char *str);
1922

23+
#ifdef CONFIG_SYSCTL
24+
int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write,
25+
void *buffer, size_t *lenp,
26+
loff_t *ppos);
27+
#endif
2028
#endif /* _LINUX_SYS_INFO_H */

kernel/panic.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ static const struct ctl_table kern_panic_table[] = {
126126
.mode = 0644,
127127
.proc_handler = proc_douintvec,
128128
},
129+
{
130+
.procname = "panic_sys_info",
131+
.data = &panic_print,
132+
.maxlen = sizeof(panic_print),
133+
.mode = 0644,
134+
.proc_handler = sysctl_sys_info_handler,
135+
},
129136
};
130137

131138
static __init int kernel_panic_sysctls_init(void)

lib/sys_info.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,100 @@
33
#include <linux/console.h>
44
#include <linux/kernel.h>
55
#include <linux/ftrace.h>
6+
#include <linux/sysctl.h>
67
#include <linux/nmi.h>
78

89
#include <linux/sys_info.h>
910

11+
struct sys_info_name {
12+
unsigned long bit;
13+
const char *name;
14+
};
15+
16+
/*
17+
* When 'si_names' gets updated, please make sure the 'sys_info_avail'
18+
* below is updated accordingly.
19+
*/
20+
static const struct sys_info_name si_names[] = {
21+
{ SYS_INFO_TASKS, "tasks" },
22+
{ SYS_INFO_MEM, "mem" },
23+
{ SYS_INFO_TIMERS, "timers" },
24+
{ SYS_INFO_LOCKS, "locks" },
25+
{ SYS_INFO_FTRACE, "ftrace" },
26+
{ SYS_INFO_ALL_CPU_BT, "all_bt" },
27+
{ SYS_INFO_BLOCKED_TASKS, "blocked_tasks" },
28+
};
29+
30+
/* Expecting string like "xxx_sys_info=tasks,mem,timers,locks,ftrace,..." */
31+
unsigned long sys_info_parse_param(char *str)
32+
{
33+
unsigned long si_bits = 0;
34+
char *s, *name;
35+
int i;
36+
37+
s = str;
38+
while ((name = strsep(&s, ",")) && *name) {
39+
for (i = 0; i < ARRAY_SIZE(si_names); i++) {
40+
if (!strcmp(name, si_names[i].name)) {
41+
si_bits |= si_names[i].bit;
42+
break;
43+
}
44+
}
45+
}
46+
47+
return si_bits;
48+
}
49+
50+
#ifdef CONFIG_SYSCTL
51+
52+
static const char sys_info_avail[] __maybe_unused = "tasks,mem,timers,locks,ftrace,all_bt,blocked_tasks";
53+
54+
int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write,
55+
void *buffer, size_t *lenp,
56+
loff_t *ppos)
57+
{
58+
char names[sizeof(sys_info_avail) + 1];
59+
struct ctl_table table;
60+
unsigned long *si_bits_global;
61+
62+
si_bits_global = ro_table->data;
63+
64+
if (write) {
65+
unsigned long si_bits;
66+
int ret;
67+
68+
table = *ro_table;
69+
table.data = names;
70+
table.maxlen = sizeof(names);
71+
ret = proc_dostring(&table, write, buffer, lenp, ppos);
72+
if (ret)
73+
return ret;
74+
75+
si_bits = sys_info_parse_param(names);
76+
/* The access to the global value is not synchronized. */
77+
WRITE_ONCE(*si_bits_global, si_bits);
78+
return 0;
79+
} else {
80+
/* for 'read' operation */
81+
char *delim = "";
82+
int i, len = 0;
83+
84+
for (i = 0; i < ARRAY_SIZE(si_names); i++) {
85+
if (*si_bits_global & si_names[i].bit) {
86+
len += scnprintf(names + len, sizeof(names) - len,
87+
"%s%s", delim, si_names[i].name);
88+
delim = ",";
89+
}
90+
}
91+
92+
table = *ro_table;
93+
table.data = names;
94+
table.maxlen = sizeof(names);
95+
return proc_dostring(&table, write, buffer, lenp, ppos);
96+
}
97+
}
98+
#endif
99+
10100
void sys_info(unsigned long si_mask)
11101
{
12102
if (si_mask & SYS_INFO_TASKS)

0 commit comments

Comments
 (0)