From 5d6f647fc6bb57377c9f417c4752e43189f56bb1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 13 Dec 2006 00:34:36 -0800 Subject: [PATCH] [PATCH] debug: add sysrq_always_enabled boot option Most distributions enable sysrq support but set it to 0 by default. Add a sysrq_always_enabled boot option to always-enable sysrq keys. Useful for debugging - without having to modify the disribution's config files (which might not be possible if the kernel is on a live CD, etc.). Also, while at it, clean up the sysrq interfaces. [bunk@stusta.de: make sysrq_always_enabled_setup() static] Signed-off-by: Ingo Molnar Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 6 +++++ drivers/char/sysrq.c | 37 ++++++++++++++++++++++++----- drivers/char/viocons.c | 10 ++++---- include/linux/sysrq.h | 22 +++++++++++++---- kernel/sysctl.c | 3 +-- 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d8323b8893..ef69c75780 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1656,6 +1656,12 @@ and is between 256 and 4096 characters. It is defined in the file sym53c416= [HW,SCSI] See header of drivers/scsi/sym53c416.c. + sysrq_always_enabled + [KNL] + Ignore sysrq setting - this boot parameter will + neutralize any effect of /proc/sys/kernel/sysrq. + Useful for debugging. + t128= [HW,SCSI] See header of drivers/scsi/t128.c. diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 05810c8d20..13935235e0 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -41,7 +41,34 @@ #include /* Whether we react on sysrq keys or just ignore them */ -int sysrq_enabled = 1; +int __read_mostly __sysrq_enabled = 1; + +static int __read_mostly sysrq_always_enabled; + +int sysrq_on(void) +{ + return __sysrq_enabled || sysrq_always_enabled; +} + +/* + * A value of 1 means 'all', other nonzero values are an op mask: + */ +static inline int sysrq_on_mask(int mask) +{ + return sysrq_always_enabled || __sysrq_enabled == 1 || + (__sysrq_enabled & mask); +} + +static int __init sysrq_always_enabled_setup(char *str) +{ + sysrq_always_enabled = 1; + printk(KERN_INFO "debug: sysrq always enabled.\n"); + + return 1; +} + +__setup("sysrq_always_enabled", sysrq_always_enabled_setup); + static void sysrq_handle_loglevel(int key, struct tty_struct *tty) { @@ -379,8 +406,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) * Should we check for enabled operations (/proc/sysrq-trigger * should not) and is the invoked operation enabled? */ - if (!check_mask || sysrq_enabled == 1 || - (sysrq_enabled & op_p->enable_mask)) { + if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { printk("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key, tty); @@ -414,9 +440,8 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) */ void handle_sysrq(int key, struct tty_struct *tty) { - if (!sysrq_enabled) - return; - __handle_sysrq(key, tty, 1); + if (sysrq_on()) + __handle_sysrq(key, tty, 1); } EXPORT_SYMBOL(handle_sysrq); diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 6d2e314860..0e0da443cb 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -61,10 +61,7 @@ static DEFINE_SPINLOCK(consolelock); static DEFINE_SPINLOCK(consoleloglock); -#ifdef CONFIG_MAGIC_SYSRQ static int vio_sysrq_pressed; -extern int sysrq_enabled; -#endif #define VIOCHAR_NUM_BUF 16 @@ -936,8 +933,10 @@ static void vioHandleData(struct HvLpEvent *event) */ num_pushed = 0; for (index = 0; index < cevent->len; index++) { -#ifdef CONFIG_MAGIC_SYSRQ - if (sysrq_enabled) { + /* + * Will be optimized away if !CONFIG_MAGIC_SYSRQ: + */ + if (sysrq_on()) { /* 0x0f is the ascii character for ^O */ if (cevent->data[index] == '\x0f') { vio_sysrq_pressed = 1; @@ -956,7 +955,6 @@ static void vioHandleData(struct HvLpEvent *event) continue; } } -#endif /* * The sysrq sequence isn't included in this check if * sysrq is enabled and compiled into the kernel because diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 9df8833670..98a1d8cfb7 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -37,23 +37,37 @@ struct sysrq_key_op { #ifdef CONFIG_MAGIC_SYSRQ +extern int sysrq_on(void); + +/* + * Do not use this one directly: + */ +extern int __sysrq_enabled; + /* Generic SysRq interface -- you may call it from any device driver, supplying * ASCII code of the key, pointer to registers and kbd/tty structs (if they * are available -- else NULL's). */ -void handle_sysrq(int, struct tty_struct *); -void __handle_sysrq(int, struct tty_struct *, int check_mask); -int register_sysrq_key(int, struct sysrq_key_op *); -int unregister_sysrq_key(int, struct sysrq_key_op *); +void handle_sysrq(int key, struct tty_struct *tty); +void __handle_sysrq(int key, struct tty_struct *tty, int check_mask); +int register_sysrq_key(int key, struct sysrq_key_op *op); +int unregister_sysrq_key(int key, struct sysrq_key_op *op); struct sysrq_key_op *__sysrq_get_key_op(int key); #else +static inline int sysrq_on(void) +{ + return 0; +} static inline int __reterr(void) { return -EINVAL; } +static inline void handle_sysrq(int key, struct tty_struct *tty) +{ +} #define register_sysrq_key(ig,nore) __reterr() #define unregister_sysrq_key(ig,nore) __reterr() diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 130c5ec9ee..600b33358d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -65,7 +65,6 @@ extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; extern int sysctl_panic_on_oom; extern int max_threads; -extern int sysrq_enabled; extern int core_uses_pid; extern int suid_dumpable; extern char core_pattern[]; @@ -543,7 +542,7 @@ static ctl_table kern_table[] = { { .ctl_name = KERN_SYSRQ, .procname = "sysrq", - .data = &sysrq_enabled, + .data = &__sysrq_enabled, .maxlen = sizeof (int), .mode = 0644, .proc_handler = &proc_dointvec, -- 2.39.5