vserver 2.0 rc7
[linux-2.6.git] / drivers / char / sysrq.c
index 057eaf8..f59f7cb 100644 (file)
 #include <linux/suspend.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>         /* for fsync_bdev() */
-
+#include <linux/swap.h>
 #include <linux/spinlock.h>
+#include <linux/vt_kern.h>
+#include <linux/workqueue.h>
 
 #include <asm/ptrace.h>
 
-extern void reset_vc(unsigned int);
-
 /* Whether we react on sysrq keys or just ignore them */
 int sysrq_enabled = 1;
 
-/* Machine specific power off function */
-void (*sysrq_power_off)(void);
-
 /* Loglevel sysrq handler */
 static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
                                  struct tty_struct *tty) 
@@ -58,6 +55,7 @@ static struct sysrq_key_op sysrq_loglevel_op = {
        .handler        = sysrq_handle_loglevel,
        .help_msg       = "loglevel0-8",
        .action_msg     = "Changing Loglevel",
+       .enable_mask    = SYSRQ_ENABLE_LOG,
 };
 
 
@@ -68,12 +66,13 @@ static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
 {
        if (tty)
                do_SAK(tty);
-       reset_vc(fg_console);
+       reset_vc(vc_cons[fg_console].d);
 }
 static struct sysrq_key_op sysrq_SAK_op = {
        .handler        = sysrq_handle_SAK,
        .help_msg       = "saK",
        .action_msg     = "SAK",
+       .enable_mask    = SYSRQ_ENABLE_KEYBOARD,
 };
 #endif
 
@@ -91,6 +90,7 @@ static struct sysrq_key_op sysrq_unraw_op = {
        .handler        = sysrq_handle_unraw,
        .help_msg       = "unRaw",
        .action_msg     = "Keyboard mode set to XLATE",
+       .enable_mask    = SYSRQ_ENABLE_KEYBOARD,
 };
 #endif /* CONFIG_VT */
 
@@ -106,6 +106,7 @@ static struct sysrq_key_op sysrq_reboot_op = {
        .handler        = sysrq_handle_reboot,
        .help_msg       = "reBoot",
        .action_msg     = "Resetting",
+       .enable_mask    = SYSRQ_ENABLE_BOOT,
 };
 
 static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
@@ -118,6 +119,7 @@ static struct sysrq_key_op sysrq_sync_op = {
        .handler        = sysrq_handle_sync,
        .help_msg       = "Sync",
        .action_msg     = "Emergency Sync",
+       .enable_mask    = SYSRQ_ENABLE_SYNC,
 };
 
 static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
@@ -130,6 +132,7 @@ static struct sysrq_key_op sysrq_mountro_op = {
        .handler        = sysrq_handle_mountro,
        .help_msg       = "Unmount",
        .action_msg     = "Emergency Remount R/O",
+       .enable_mask    = SYSRQ_ENABLE_REMOUNT,
 };
 
 /* END SYNC SYSRQ HANDLERS BLOCK */
@@ -147,6 +150,7 @@ static struct sysrq_key_op sysrq_showregs_op = {
        .handler        = sysrq_handle_showregs,
        .help_msg       = "showPc",
        .action_msg     = "Show Regs",
+       .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
 
@@ -159,6 +163,7 @@ static struct sysrq_key_op sysrq_showstate_op = {
        .handler        = sysrq_handle_showstate,
        .help_msg       = "showTasks",
        .action_msg     = "Show State",
+       .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
 
@@ -171,6 +176,7 @@ static struct sysrq_key_op sysrq_showmem_op = {
        .handler        = sysrq_handle_showmem,
        .help_msg       = "showMem",
        .action_msg     = "Show Memory",
+       .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
 
 /* SHOW SYSRQ HANDLERS BLOCK */
@@ -201,6 +207,25 @@ static struct sysrq_key_op sysrq_term_op = {
        .handler        = sysrq_handle_term,
        .help_msg       = "tErm",
        .action_msg     = "Terminate All Tasks",
+       .enable_mask    = SYSRQ_ENABLE_SIGNAL,
+};
+
+static void moom_callback(void *ignored)
+{
+       out_of_memory(GFP_KERNEL);
+}
+
+static DECLARE_WORK(moom_work, moom_callback, NULL);
+
+static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
+                             struct tty_struct *tty)
+{
+       schedule_work(&moom_work);
+}
+static struct sysrq_key_op sysrq_moom_op = {
+       .handler        = sysrq_handle_moom,
+       .help_msg       = "Full",
+       .action_msg     = "Manual OOM execution",
 };
 
 static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
@@ -213,6 +238,7 @@ static struct sysrq_key_op sysrq_kill_op = {
        .handler        = sysrq_handle_kill,
        .help_msg       = "kIll",
        .action_msg     = "Kill All Tasks",
+       .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
 
 /* END SIGNAL SYSRQ HANDLERS BLOCK */
@@ -225,7 +251,8 @@ static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
 static struct sysrq_key_op sysrq_unrt_op = {
        .handler        = sysrq_handle_unrt,
        .help_msg       = "Nice",
-       .action_msg     = "Nice All RT Tasks"
+       .action_msg     = "Nice All RT Tasks",
+       .enable_mask    = SYSRQ_ENABLE_RTNICE,
 };
 
 /* Key Operations table and lock */
@@ -249,7 +276,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
 /* c */ NULL,
 /* d */        NULL,
 /* e */        &sysrq_term_op,
-/* f */        NULL,
+/* f */        &sysrq_moom_op,
 /* g */        NULL,
 /* h */        NULL,
 /* i */        &sysrq_kill_op,
@@ -321,7 +348,7 @@ void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
  * as they are inside of the lock
  */
 
-void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask)
 {
        struct sysrq_key_op *op_p;
        int orig_log_level;
@@ -335,9 +362,16 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
 
         op_p = __sysrq_get_key_op(key);
         if (op_p) {
-               printk ("%s\n", op_p->action_msg);
-               console_loglevel = orig_log_level;
-               op_p->handler(key, pt_regs, tty);
+               /* 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)) {
+                       printk ("%s\n", op_p->action_msg);
+                       console_loglevel = orig_log_level;
+                       op_p->handler(key, pt_regs, tty);
+               }
+               else
+                       printk("This sysrq operation is disabled.\n");
        } else {
                printk("HELP : ");
                /* Only print the help msg once per handler */
@@ -362,7 +396,7 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
 {
        if (!sysrq_enabled)
                return;
-       __handle_sysrq(key, pt_regs, tty);
+       __handle_sysrq(key, pt_regs, tty, 1);
 }
 
 int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,