Message ID | 20200804162402.2087-3-andrzej.p@collabora.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add configurable handler to execute a compound action | expand |
On 04. 08. 20, 18:24, Andrzej Pietrasiewicz wrote: > Userland might want to execute e.g. 'w' (show blocked tasks), followed > by 's' (sync), followed by 1000 ms delay and then followed by 'c' (crash) > upon a single magic SysRq. Or one might want to execute the famous "Raising > Elephants Is So Utterly Boring" action. This patch adds a configurable > handler, triggered with 'C', for this exact purpose. The user specifies the > composition of the compound action using syntax similar to getopt, where > each letter corresponds to an individual action and a colon followed by a > number corresponds to a delay of that many milliseconds, e.g.: > > ws:1000c > > or > > r:100eis:1000ub I think I miss what's that good for, given I can do it one-by-one without setting such strings anywhere (I usually want to do different things on different kinds of crashes)? > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com> > --- > Documentation/admin-guide/sysrq.rst | 9 ++++ > drivers/tty/sysrq.c | 81 ++++++++++++++++++++++++++++- > include/linux/sysrq.h | 1 + > 3 files changed, 90 insertions(+), 1 deletion(-) > > diff --git a/Documentation/admin-guide/sysrq.rst b/Documentation/admin-guide/sysrq.rst > index 67dfa4c29093..80bdd8bf9636 100644 > --- a/Documentation/admin-guide/sysrq.rst > +++ b/Documentation/admin-guide/sysrq.rst > @@ -32,6 +32,7 @@ to 1. Here is the list of possible values in /proc/sys/kernel/sysrq: > 64 = 0x40 - enable signalling of processes (term, kill, oom-kill) > 128 = 0x80 - allow reboot/poweroff > 256 = 0x100 - allow nicing of all RT tasks > + 512 = 0x200 - allow compound action > > You can set the value in the file by the following command:: > > @@ -148,6 +149,14 @@ Command Function > > ``z`` Dump the ftrace buffer > > +``C`` Execute a predefined, compound action. The action is defined with > + sysrq.sysrq_compound_action module parameter, whose value contains known > + command keys (except ``C`` to prevent recursion). The command keys can > + be optionally followed by a colon and a number of milliseconds to wait > + after executing the last action. For example: > + > + sysrq.sysrq_compound_action=r:100eis:1000ub > + > ``0``-``9`` Sets the console log level, controlling which kernel messages > will be printed to your console. (``0``, for example would make > it so that only emergency messages like PANICs or OOPSes would > diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c > index 52e344bfe8c0..ffcda1316675 100644 > --- a/drivers/tty/sysrq.c > +++ b/drivers/tty/sysrq.c > @@ -19,6 +19,7 @@ > #include <linux/sched/rt.h> > #include <linux/sched/debug.h> > #include <linux/sched/task.h> > +#include <linux/delay.h> > #include <linux/interrupt.h> > #include <linux/mm.h> > #include <linux/fs.h> > @@ -439,6 +440,15 @@ static const struct sysrq_key_op sysrq_unrt_op = { > .enable_mask = SYSRQ_ENABLE_RTNICE, > }; > > +static void sysrq_action_compound(int key); > + > +static struct sysrq_key_op sysrq_action_compound_op = { > + .handler = sysrq_action_compound, > + .help_msg = "execute-compound-action(C)", > + .action_msg = "Execute compound action", > + .enable_mask = SYSRQ_ENABLE_COMPOUND, > +}; > + > /* Key Operations table and lock */ > static DEFINE_SPINLOCK(sysrq_key_table_lock); > > @@ -501,7 +511,7 @@ static const struct sysrq_key_op *sysrq_key_table[62] = { > &sysrq_ftrace_dump_op, /* z */ > NULL, /* A */ > NULL, /* B */ > - NULL, /* C */ > + &sysrq_action_compound_op, /* C */ > NULL, /* D */ > NULL, /* E */ > NULL, /* F */ > @@ -634,6 +644,7 @@ EXPORT_SYMBOL(handle_sysrq); > > #ifdef CONFIG_INPUT > static int sysrq_reset_downtime_ms; > +static char *sysrq_compound_action; > > /* Simple translation table for the SysRq keys */ > static const unsigned char sysrq_xlate[KEY_CNT] = > @@ -787,6 +798,61 @@ static void sysrq_of_get_keyreset_config(void) > { > } > #endif > +#define SYSRQ_COMPOUND_ACTION_VALIDATE 0 > +#define SYSRQ_COMPOUND_ACTION_RUN 1 > + > +static int sysrq_process_compound_action(int pass) > +{ > + const char *action = sysrq_compound_action; > + const struct sysrq_key_op *op_p; > + int ret, delay; > + > + while (*action) { > + op_p = __sysrq_get_key_op(*action); > + if (!op_p) > + return -EINVAL; > + > + /* Don't allow calling ourselves recursively */ > + if (op_p == &sysrq_action_compound_op) > + return -EINVAL; > + > + if (pass == SYSRQ_COMPOUND_ACTION_RUN) > + __handle_sysrq(*action, false); > + > + if (*++action == ':') { > + ret = sscanf(action++, ":%d", &delay); You likely want %u and unsigned int. No negative delays. > + if (ret < 1) /* we want at least ":[0-9]" => 1 item */ > + return -EINVAL; > + > + while (*action >= '0' && *action <= '9') > + ++action; > + if (pass == SYSRQ_COMPOUND_ACTION_RUN) > + mdelay(delay); > + } > + } > + > + return 0; > +} > + > +static void sysrq_action_compound(int key) > +{ > + if (!sysrq_compound_action) { > + pr_err("Unconfigured compound action for %s", > + sysrq_action_compound_op.help_msg); Missing \n. > + return; > + } > + > + if (sysrq_process_compound_action(SYSRQ_COMPOUND_ACTION_VALIDATE)) { > + pr_err("Incorrect compound action %s for %s", The same. > + sysrq_compound_action, > + sysrq_action_compound_op.help_msg); > + > + return; > + } > + > + sysrq_process_compound_action(SYSRQ_COMPOUND_ACTION_RUN); > +} > > static void sysrq_reinject_alt_sysrq(struct work_struct *work) > { > @@ -1079,8 +1145,21 @@ module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq, > > module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644); > > +module_param(sysrq_compound_action, charp, 0644); > +MODULE_PARM_DESC(sysrq_compound_action, > + "Compound sysrq action to be executed on Alt-Shift-SysRq-C\n" > + "The compound action definition consists of known SysRq action letters except 'C',\n" > + "each letter can be optionally followed by a colon and a number of milliseconds to wait\n" > + "after executing the last action.\n" > + "Example:\n" > + "To unRaw, wait 100ms, tErminate, kIll, Sync, wait 1000ms, Unmount, Boot\n" > + "sysrq.sysrq_compound_action=r:100eis:1000ub"); This looks bad in the output, use at least one \t at the start of a new line inside the string.
Hi Jiri, W dniu 12.08.2020 o 13:45, Jiri Slaby pisze: > On 04. 08. 20, 18:24, Andrzej Pietrasiewicz wrote: >> Userland might want to execute e.g. 'w' (show blocked tasks), followed >> by 's' (sync), followed by 1000 ms delay and then followed by 'c' (crash) >> upon a single magic SysRq. Or one might want to execute the famous "Raising >> Elephants Is So Utterly Boring" action. This patch adds a configurable >> handler, triggered with 'C', for this exact purpose. The user specifies the >> composition of the compound action using syntax similar to getopt, where >> each letter corresponds to an individual action and a colon followed by a >> number corresponds to a delay of that many milliseconds, e.g.: >> >> ws:1000c >> >> or >> >> r:100eis:1000ub > > I think I miss what's that good for, given I can do it one-by-one > without setting such strings anywhere (I usually want to do different > things on different kinds of crashes)? > The "REISUB" action is a common way of handling a bad situation, though, so having a shortcut for a common way is helpful, yet we are not forcing this particular action to happen when the 'C' sysrq is invoked and offer configurability instead. I addressed the comments you had with regard to the code in a v2 series. Regards, Andrzej
Hi Andrzej, I love your patch! Yet something to improve: [auto build test ERROR on bcf876870b95592b52519ed4aafcf9d95999bc9c] url: https://github.com/0day-ci/linux/commits/Andrzej-Pietrasiewicz/Add-configurable-handler-to-execute-a-compound-action/20210929-183114 base: bcf876870b95592b52519ed4aafcf9d95999bc9c config: um-x86_64_defconfig (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/c2e145de22842a121477d2c3dbe2bca210434138 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Andrzej-Pietrasiewicz/Add-configurable-handler-to-execute-a-compound-action/20210929-183114 git checkout c2e145de22842a121477d2c3dbe2bca210434138 # save the attached .config to linux build tree mkdir build_dir make W=1 O=build_dir ARCH=um SUBARCH=x86_64 SHELL=/bin/bash drivers/tty/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): cc1: warning: arch/um/include/uapi: No such file or directory [-Wmissing-include-dirs] >> drivers/tty/sysrq.c:1159:1: error: expected identifier or '(' before '{' token 1159 | { | ^ drivers/tty/sysrq.c: In function 'sysrq_action_compound': >> drivers/tty/sysrq.c:1164:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 1164 | { | ^ drivers/tty/sysrq.c:1168:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 1168 | { | ^ drivers/tty/sysrq.c:1174:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 1174 | { | ^ In file included from include/linux/linkage.h:7, from include/linux/kernel.h:8, from include/linux/list.h:9, from include/linux/rculist.h:10, from include/linux/sched/signal.h:5, from drivers/tty/sysrq.c:18: >> drivers/tty/sysrq.c:1188:19: error: storage class specified for parameter 'sysrq_toggle_support' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~~~~ include/linux/export.h:98:21: note: in definition of macro '___EXPORT_SYMBOL' 98 | extern typeof(sym) sym; \ | ^~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:99:20: error: storage class specified for parameter '__kstrtab_sysrq_toggle_support' 99 | extern const char __kstrtab_##sym[]; \ | ^~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:100:20: error: storage class specified for parameter '__kstrtabns_sysrq_toggle_support' 100 | extern const char __kstrtabns_##sym[]; \ | ^~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:101:24: error: expected declaration specifiers before ';' token 101 | __CRC_SYMBOL(sym, sec); \ | ^ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:102:2: error: expected declaration specifiers before 'asm' 102 | asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ | ^~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ include/linux/export.h:67:36: error: storage class specified for parameter '__ksymtab_sysrq_toggle_support' 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:67:22: error: parameter '__ksymtab_sysrq_toggle_support' is initialized 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:67:36: error: section attribute not allowed for '__ksymtab_sysrq_toggle_support' 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:67:22: warning: 'used' attribute ignored [-Wattributes] 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ >> include/linux/export.h:67:36: error: alignment may not be specified for '__ksymtab_sysrq_toggle_support' 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:159:33: note: in expansion of macro '_EXPORT_SYMBOL' 159 | #define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1188:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL' 1188 | EXPORT_SYMBOL_GPL(sysrq_toggle_support); | ^~~~~~~~~~~~~~~~~ drivers/tty/sysrq.c:1192:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 1192 | { | ^ drivers/tty/sysrq.c:1215:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 1215 | { | ^ In file included from include/linux/linkage.h:7, from include/linux/kernel.h:8, from include/linux/list.h:9, from include/linux/rculist.h:10, from include/linux/sched/signal.h:5, from drivers/tty/sysrq.c:18: >> drivers/tty/sysrq.c:1218:15: error: storage class specified for parameter 'register_sysrq_key' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~~~~~~ include/linux/export.h:98:21: note: in definition of macro '___EXPORT_SYMBOL' 98 | extern typeof(sym) sym; \ | ^~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:99:20: error: storage class specified for parameter '__kstrtab_register_sysrq_key' 99 | extern const char __kstrtab_##sym[]; \ | ^~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:100:20: error: storage class specified for parameter '__kstrtabns_register_sysrq_key' 100 | extern const char __kstrtabns_##sym[]; \ | ^~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:101:24: error: expected declaration specifiers before ';' token 101 | __CRC_SYMBOL(sym, sec); \ | ^ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:102:2: error: expected declaration specifiers before 'asm' 102 | asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ | ^~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ include/linux/export.h:67:36: error: storage class specified for parameter '__ksymtab_register_sysrq_key' 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:67:22: error: parameter '__ksymtab_register_sysrq_key' is initialized 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:67:36: error: section attribute not allowed for '__ksymtab_register_sysrq_key' 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:67:22: warning: 'used' attribute ignored [-Wattributes] 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ >> include/linux/export.h:67:36: error: alignment may not be specified for '__ksymtab_register_sysrq_key' 67 | static const struct kernel_symbol __ksymtab_##sym \ | ^~~~~~~~~~ include/linux/export.h:108:2: note: in expansion of macro '__KSYMTAB_ENTRY' 108 | __KSYMTAB_ENTRY(sym, sec) | ^~~~~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1218:1: note: in expansion of macro 'EXPORT_SYMBOL' 1218 | EXPORT_SYMBOL(register_sysrq_key); | ^~~~~~~~~~~~~ drivers/tty/sysrq.c:1221:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token 1221 | { | ^ In file included from include/linux/linkage.h:7, from include/linux/kernel.h:8, from include/linux/list.h:9, from include/linux/rculist.h:10, from include/linux/sched/signal.h:5, from drivers/tty/sysrq.c:18: drivers/tty/sysrq.c:1224:15: error: storage class specified for parameter 'unregister_sysrq_key' 1224 | EXPORT_SYMBOL(unregister_sysrq_key); | ^~~~~~~~~~~~~~~~~~~~ include/linux/export.h:98:21: note: in definition of macro '___EXPORT_SYMBOL' 98 | extern typeof(sym) sym; \ | ^~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1224:1: note: in expansion of macro 'EXPORT_SYMBOL' 1224 | EXPORT_SYMBOL(unregister_sysrq_key); | ^~~~~~~~~~~~~ include/linux/export.h:99:20: error: storage class specified for parameter '__kstrtab_unregister_sysrq_key' 99 | extern const char __kstrtab_##sym[]; \ | ^~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1224:1: note: in expansion of macro 'EXPORT_SYMBOL' 1224 | EXPORT_SYMBOL(unregister_sysrq_key); | ^~~~~~~~~~~~~ include/linux/export.h:100:20: error: storage class specified for parameter '__kstrtabns_unregister_sysrq_key' 100 | extern const char __kstrtabns_##sym[]; \ | ^~~~~~~~~~~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1224:1: note: in expansion of macro 'EXPORT_SYMBOL' 1224 | EXPORT_SYMBOL(unregister_sysrq_key); | ^~~~~~~~~~~~~ include/linux/export.h:101:24: error: expected declaration specifiers before ';' token 101 | __CRC_SYMBOL(sym, sec); \ | ^ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1224:1: note: in expansion of macro 'EXPORT_SYMBOL' 1224 | EXPORT_SYMBOL(unregister_sysrq_key); | ^~~~~~~~~~~~~ include/linux/export.h:102:2: error: expected declaration specifiers before 'asm' 102 | asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ | ^~~ include/linux/export.h:147:39: note: in expansion of macro '___EXPORT_SYMBOL' 147 | #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) | ^~~~~~~~~~~~~~~~ include/linux/export.h:155:34: note: in expansion of macro '__EXPORT_SYMBOL' 155 | #define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "") | ^~~~~~~~~~~~~~~ include/linux/export.h:158:29: note: in expansion of macro '_EXPORT_SYMBOL' 158 | #define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "") | ^~~~~~~~~~~~~~ drivers/tty/sysrq.c:1224:1: note: in expansion of macro 'EXPORT_SYMBOL' 1224 | EXPORT_SYMBOL(unregister_sysrq_key); vim +1159 drivers/tty/sysrq.c 1158 > 1159 { 1160 } 1161 > 1162 static void sysrq_action_compound(int key) 1163 static inline void sysrq_register_handler(void) > 1164 { 1165 } 1166 1167 static inline void sysrq_unregister_handler(void) 1168 { 1169 } 1170 1171 #endif /* CONFIG_INPUT */ 1172 1173 int sysrq_toggle_support(int enable_mask) 1174 { 1175 bool was_enabled = sysrq_on(); 1176 1177 sysrq_enabled = enable_mask; 1178 1179 if (was_enabled != sysrq_on()) { 1180 if (sysrq_on()) 1181 sysrq_register_handler(); 1182 else 1183 sysrq_unregister_handler(); 1184 } 1185 1186 return 0; 1187 } > 1188 EXPORT_SYMBOL_GPL(sysrq_toggle_support); 1189 1190 static int __sysrq_swap_key_ops(int key, const struct sysrq_key_op *insert_op_p, 1191 const struct sysrq_key_op *remove_op_p) 1192 { 1193 int retval; 1194 1195 spin_lock(&sysrq_key_table_lock); 1196 if (__sysrq_get_key_op(key) == remove_op_p) { 1197 __sysrq_put_key_op(key, insert_op_p); 1198 retval = 0; 1199 } else { 1200 retval = -1; 1201 } 1202 spin_unlock(&sysrq_key_table_lock); 1203 1204 /* 1205 * A concurrent __handle_sysrq either got the old op or the new op. 1206 * Wait for it to go away before returning, so the code for an old 1207 * op is not freed (eg. on module unload) while it is in use. 1208 */ 1209 synchronize_rcu(); 1210 1211 return retval; 1212 } 1213 1214 int register_sysrq_key(int key, const struct sysrq_key_op *op_p) 1215 { 1216 return __sysrq_swap_key_ops(key, op_p, NULL); 1217 } > 1218 EXPORT_SYMBOL(register_sysrq_key); 1219 1220 int unregister_sysrq_key(int key, const struct sysrq_key_op *op_p) 1221 { 1222 return __sysrq_swap_key_ops(key, NULL, op_p); 1223 } > 1224 EXPORT_SYMBOL(unregister_sysrq_key); 1225 1226 #ifdef CONFIG_PROC_FS 1227 /* 1228 * writing 'C' to /proc/sysrq-trigger is like sysrq-C 1229 */ 1230 static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, 1231 size_t count, loff_t *ppos) 1232 { 1233 if (count) { 1234 char c; 1235 1236 if (get_user(c, buf)) 1237 return -EFAULT; 1238 __handle_sysrq(c, false); 1239 } 1240 1241 return count; 1242 } 1243 > 1244 static const struct proc_ops sysrq_trigger_proc_ops = { > 1245 .proc_write = write_sysrq_trigger, 1246 .proc_lseek = noop_llseek, 1247 }; 1248 1249 static void sysrq_init_procfs(void) 1250 { 1251 if (!proc_create("sysrq-trigger", S_IWUSR, NULL, 1252 &sysrq_trigger_proc_ops)) 1253 pr_err("Failed to register proc interface\n"); 1254 } 1255 1256 #else 1257 1258 static inline void sysrq_init_procfs(void) 1259 { 1260 } 1261 1262 #endif /* CONFIG_PROC_FS */ 1263 1264 static int __init sysrq_init(void) 1265 { 1266 sysrq_init_procfs(); 1267 1268 if (sysrq_on()) 1269 sysrq_register_handler(); 1270 1271 return 0; 1272 } > 1273 device_initcall(sysrq_init); --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/Documentation/admin-guide/sysrq.rst b/Documentation/admin-guide/sysrq.rst index 67dfa4c29093..80bdd8bf9636 100644 --- a/Documentation/admin-guide/sysrq.rst +++ b/Documentation/admin-guide/sysrq.rst @@ -32,6 +32,7 @@ to 1. Here is the list of possible values in /proc/sys/kernel/sysrq: 64 = 0x40 - enable signalling of processes (term, kill, oom-kill) 128 = 0x80 - allow reboot/poweroff 256 = 0x100 - allow nicing of all RT tasks + 512 = 0x200 - allow compound action You can set the value in the file by the following command:: @@ -148,6 +149,14 @@ Command Function ``z`` Dump the ftrace buffer +``C`` Execute a predefined, compound action. The action is defined with + sysrq.sysrq_compound_action module parameter, whose value contains known + command keys (except ``C`` to prevent recursion). The command keys can + be optionally followed by a colon and a number of milliseconds to wait + after executing the last action. For example: + + sysrq.sysrq_compound_action=r:100eis:1000ub + ``0``-``9`` Sets the console log level, controlling which kernel messages will be printed to your console. (``0``, for example would make it so that only emergency messages like PANICs or OOPSes would diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 52e344bfe8c0..ffcda1316675 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -19,6 +19,7 @@ #include <linux/sched/rt.h> #include <linux/sched/debug.h> #include <linux/sched/task.h> +#include <linux/delay.h> #include <linux/interrupt.h> #include <linux/mm.h> #include <linux/fs.h> @@ -439,6 +440,15 @@ static const struct sysrq_key_op sysrq_unrt_op = { .enable_mask = SYSRQ_ENABLE_RTNICE, }; +static void sysrq_action_compound(int key); + +static struct sysrq_key_op sysrq_action_compound_op = { + .handler = sysrq_action_compound, + .help_msg = "execute-compound-action(C)", + .action_msg = "Execute compound action", + .enable_mask = SYSRQ_ENABLE_COMPOUND, +}; + /* Key Operations table and lock */ static DEFINE_SPINLOCK(sysrq_key_table_lock); @@ -501,7 +511,7 @@ static const struct sysrq_key_op *sysrq_key_table[62] = { &sysrq_ftrace_dump_op, /* z */ NULL, /* A */ NULL, /* B */ - NULL, /* C */ + &sysrq_action_compound_op, /* C */ NULL, /* D */ NULL, /* E */ NULL, /* F */ @@ -634,6 +644,7 @@ EXPORT_SYMBOL(handle_sysrq); #ifdef CONFIG_INPUT static int sysrq_reset_downtime_ms; +static char *sysrq_compound_action; /* Simple translation table for the SysRq keys */ static const unsigned char sysrq_xlate[KEY_CNT] = @@ -787,6 +798,61 @@ static void sysrq_of_get_keyreset_config(void) { } #endif +#define SYSRQ_COMPOUND_ACTION_VALIDATE 0 +#define SYSRQ_COMPOUND_ACTION_RUN 1 + +static int sysrq_process_compound_action(int pass) +{ + const char *action = sysrq_compound_action; + const struct sysrq_key_op *op_p; + int ret, delay; + + while (*action) { + op_p = __sysrq_get_key_op(*action); + if (!op_p) + return -EINVAL; + + /* Don't allow calling ourselves recursively */ + if (op_p == &sysrq_action_compound_op) + return -EINVAL; + + if (pass == SYSRQ_COMPOUND_ACTION_RUN) + __handle_sysrq(*action, false); + + if (*++action == ':') { + ret = sscanf(action++, ":%d", &delay); + if (ret < 1) /* we want at least ":[0-9]" => 1 item */ + return -EINVAL; + + while (*action >= '0' && *action <= '9') + ++action; + if (pass == SYSRQ_COMPOUND_ACTION_RUN) + mdelay(delay); + } + } + + return 0; +} + +static void sysrq_action_compound(int key) +{ + if (!sysrq_compound_action) { + pr_err("Unconfigured compound action for %s", + sysrq_action_compound_op.help_msg); + + return; + } + + if (sysrq_process_compound_action(SYSRQ_COMPOUND_ACTION_VALIDATE)) { + pr_err("Incorrect compound action %s for %s", + sysrq_compound_action, + sysrq_action_compound_op.help_msg); + + return; + } + + sysrq_process_compound_action(SYSRQ_COMPOUND_ACTION_RUN); +} static void sysrq_reinject_alt_sysrq(struct work_struct *work) { @@ -1079,8 +1145,21 @@ module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq, module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644); +module_param(sysrq_compound_action, charp, 0644); +MODULE_PARM_DESC(sysrq_compound_action, + "Compound sysrq action to be executed on Alt-Shift-SysRq-C\n" + "The compound action definition consists of known SysRq action letters except 'C',\n" + "each letter can be optionally followed by a colon and a number of milliseconds to wait\n" + "after executing the last action.\n" + "Example:\n" + "To unRaw, wait 100ms, tErminate, kIll, Sync, wait 1000ms, Unmount, Boot\n" + "sysrq.sysrq_compound_action=r:100eis:1000ub"); #else +{ +} + +static void sysrq_action_compound(int key) static inline void sysrq_register_handler(void) { } diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 3a582ec7a2f1..6df4442f12a9 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -28,6 +28,7 @@ #define SYSRQ_ENABLE_SIGNAL 0x0040 #define SYSRQ_ENABLE_BOOT 0x0080 #define SYSRQ_ENABLE_RTNICE 0x0100 +#define SYSRQ_ENABLE_COMPOUND 0x0200 struct sysrq_key_op { void (* const handler)(int);
Userland might want to execute e.g. 'w' (show blocked tasks), followed by 's' (sync), followed by 1000 ms delay and then followed by 'c' (crash) upon a single magic SysRq. Or one might want to execute the famous "Raising Elephants Is So Utterly Boring" action. This patch adds a configurable handler, triggered with 'C', for this exact purpose. The user specifies the composition of the compound action using syntax similar to getopt, where each letter corresponds to an individual action and a colon followed by a number corresponds to a delay of that many milliseconds, e.g.: ws:1000c or r:100eis:1000ub Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com> --- Documentation/admin-guide/sysrq.rst | 9 ++++ drivers/tty/sysrq.c | 81 ++++++++++++++++++++++++++++- include/linux/sysrq.h | 1 + 3 files changed, 90 insertions(+), 1 deletion(-)