Added some debug printk's for shares_write problems that Steve is seeing
[linux-2.6.git] / drivers / char / sysrq.c
1 /* -*- linux-c -*-
2  *
3  *      $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
4  *
5  *      Linux Magic System Request Key Hacks
6  *
7  *      (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
8  *      based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
9  *
10  *      (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
11  *      overhauled to use key registration
12  *      based upon discusions in irc://irc.openprojects.net/#kernelnewbies
13  */
14
15 #include <linux/config.h>
16 #include <linux/sched.h>
17 #include <linux/interrupt.h>
18 #include <linux/mm.h>
19 #include <linux/fs.h>
20 #include <linux/tty.h>
21 #include <linux/mount.h>
22 #include <linux/kdev_t.h>
23 #include <linux/major.h>
24 #include <linux/reboot.h>
25 #include <linux/sysrq.h>
26 #include <linux/kbd_kern.h>
27 #include <linux/quotaops.h>
28 #include <linux/smp_lock.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/suspend.h>
32 #include <linux/writeback.h>
33 #include <linux/buffer_head.h>          /* for fsync_bdev() */
34
35 #include <linux/spinlock.h>
36
37 #include <asm/ptrace.h>
38
39 extern void reset_vc(unsigned int);
40
41 /* Whether we react on sysrq keys or just ignore them */
42 int sysrq_enabled = 1;
43
44 /* Machine specific power off function */
45 void (*sysrq_power_off)(void);
46
47 /* Loglevel sysrq handler */
48 static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
49                                   struct tty_struct *tty) 
50 {
51         int i;
52         i = key - '0';
53         console_loglevel = 7;
54         printk("Loglevel set to %d\n", i);
55         console_loglevel = i;
56 }       
57 static struct sysrq_key_op sysrq_loglevel_op = {
58         .handler        = sysrq_handle_loglevel,
59         .help_msg       = "loglevel0-8",
60         .action_msg     = "Changing Loglevel",
61 };
62
63
64 /* SAK sysrq handler */
65 #ifdef CONFIG_VT
66 static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
67                              struct tty_struct *tty) 
68 {
69         if (tty)
70                 do_SAK(tty);
71         reset_vc(fg_console);
72 }
73 static struct sysrq_key_op sysrq_SAK_op = {
74         .handler        = sysrq_handle_SAK,
75         .help_msg       = "saK",
76         .action_msg     = "SAK",
77 };
78 #endif
79
80 #ifdef CONFIG_VT
81 /* unraw sysrq handler */
82 static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
83                                struct tty_struct *tty) 
84 {
85         struct kbd_struct *kbd = &kbd_table[fg_console];
86
87         if (kbd)
88                 kbd->kbdmode = VC_XLATE;
89 }
90 static struct sysrq_key_op sysrq_unraw_op = {
91         .handler        = sysrq_handle_unraw,
92         .help_msg       = "unRaw",
93         .action_msg     = "Keyboard mode set to XLATE",
94 };
95 #endif /* CONFIG_VT */
96
97 /* reboot sysrq handler */
98 static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
99                                 struct tty_struct *tty) 
100 {
101         machine_restart(NULL);
102 }
103
104 static struct sysrq_key_op sysrq_reboot_op = {
105         .handler        = sysrq_handle_reboot,
106         .help_msg       = "reBoot",
107         .action_msg     = "Resetting",
108 };
109
110 /* crash sysrq handler */
111 static void sysrq_handle_crash(int key, struct pt_regs *pt_regs,
112                                struct tty_struct *tty) {
113         *( (char *) 0) = 0;
114 }
115 static struct sysrq_key_op sysrq_crash_op = {
116         handler:        sysrq_handle_crash,
117         help_msg:       "Crash",
118         action_msg:     "Crashing the kernel by request",
119 };
120
121 static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
122                               struct tty_struct *tty) 
123 {
124         emergency_sync();
125 }
126
127 static struct sysrq_key_op sysrq_sync_op = {
128         .handler        = sysrq_handle_sync,
129         .help_msg       = "Sync",
130         .action_msg     = "Emergency Sync",
131 };
132
133 static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
134                                  struct tty_struct *tty) 
135 {
136         emergency_remount();
137 }
138
139 static struct sysrq_key_op sysrq_mountro_op = {
140         .handler        = sysrq_handle_mountro,
141         .help_msg       = "Unmount",
142         .action_msg     = "Emergency Remount R/O",
143 };
144
145 /* END SYNC SYSRQ HANDLERS BLOCK */
146
147
148 /* SHOW SYSRQ HANDLERS BLOCK */
149
150 static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
151                                   struct tty_struct *tty) 
152 {
153         if (pt_regs)
154                 show_regs(pt_regs);
155 }
156 static struct sysrq_key_op sysrq_showregs_op = {
157         .handler        = sysrq_handle_showregs,
158         .help_msg       = "showPc",
159         .action_msg     = "Show Regs",
160 };
161
162
163 static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
164                                    struct tty_struct *tty) 
165 {
166         show_state();
167 }
168 static struct sysrq_key_op sysrq_showstate_op = {
169         .handler        = sysrq_handle_showstate,
170         .help_msg       = "showTasks",
171         .action_msg     = "Show State",
172 };
173
174
175 static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
176                                  struct tty_struct *tty) 
177 {
178         show_mem();
179 }
180 static struct sysrq_key_op sysrq_showmem_op = {
181         .handler        = sysrq_handle_showmem,
182         .help_msg       = "showMem",
183         .action_msg     = "Show Memory",
184 };
185
186 /* SHOW SYSRQ HANDLERS BLOCK */
187
188
189 /* SIGNAL SYSRQ HANDLERS BLOCK */
190
191 /* signal sysrq helper function
192  * Sends a signal to all user processes */
193 static void send_sig_all(int sig)
194 {
195         struct task_struct *p;
196
197         for_each_process(p) {
198                 if (p->mm && p->pid != 1)
199                         /* Not swapper, init nor kernel thread */
200                         force_sig(sig, p);
201         }
202 }
203
204 static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
205                               struct tty_struct *tty) 
206 {
207         send_sig_all(SIGTERM);
208         console_loglevel = 8;
209 }
210 static struct sysrq_key_op sysrq_term_op = {
211         .handler        = sysrq_handle_term,
212         .help_msg       = "tErm",
213         .action_msg     = "Terminate All Tasks",
214 };
215
216 static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
217                               struct tty_struct *tty) 
218 {
219         send_sig_all(SIGKILL);
220         console_loglevel = 8;
221 }
222 static struct sysrq_key_op sysrq_kill_op = {
223         .handler        = sysrq_handle_kill,
224         .help_msg       = "kIll",
225         .action_msg     = "Kill All Tasks",
226 };
227
228 /* END SIGNAL SYSRQ HANDLERS BLOCK */
229
230
231 /* Key Operations table and lock */
232 static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
233 #define SYSRQ_KEY_TABLE_LENGTH 36
234 static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
235 /* 0 */ &sysrq_loglevel_op,
236 /* 1 */ &sysrq_loglevel_op,
237 /* 2 */ &sysrq_loglevel_op,
238 /* 3 */ &sysrq_loglevel_op,
239 /* 4 */ &sysrq_loglevel_op,
240 /* 5 */ &sysrq_loglevel_op,
241 /* 6 */ &sysrq_loglevel_op,
242 /* 7 */ &sysrq_loglevel_op,
243 /* 8 */ &sysrq_loglevel_op,
244 /* 9 */ &sysrq_loglevel_op,
245 /* a */ NULL, /* Don't use for system provided sysrqs,
246                  it is handled specially on the sparc
247                  and will never arrive */
248 /* b */ &sysrq_reboot_op,
249 /* c */ &sysrq_crash_op,
250 /* d */ NULL,
251 /* e */ &sysrq_term_op,
252 /* f */ NULL,
253 /* g */ NULL,
254 /* h */ NULL,
255 /* i */ &sysrq_kill_op,
256 /* j */ NULL,
257 #ifdef CONFIG_VT
258 /* k */ &sysrq_SAK_op,
259 #else
260 /* k */ NULL,
261 #endif
262 /* l */ NULL,
263 /* m */ &sysrq_showmem_op,
264 /* n */ NULL,
265 /* o */ NULL, /* This will often be registered
266                  as 'Off' at init time */
267 /* p */ &sysrq_showregs_op,
268 /* q */ NULL,
269 #ifdef CONFIG_VT
270 /* r */ &sysrq_unraw_op,
271 #else
272 /* r */ NULL,
273 #endif
274 /* s */ &sysrq_sync_op,
275 /* t */ &sysrq_showstate_op,
276 /* u */ &sysrq_mountro_op,
277 /* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
278 /* w */ NULL,
279 /* x */ NULL,
280 /* y */ NULL,
281 /* z */ NULL
282 };
283
284 /* key2index calculation, -1 on invalid index */
285 static int sysrq_key_table_key2index(int key) {
286         int retval;
287         if ((key >= '0') && (key <= '9')) {
288                 retval = key - '0';
289         } else if ((key >= 'a') && (key <= 'z')) {
290                 retval = key + 10 - 'a';
291         } else {
292                 retval = -1;
293         }
294         return retval;
295 }
296
297 /*
298  * table lock and unlocking functions, exposed to modules
299  */
300
301 void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); }
302
303 void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); }
304
305 /*
306  * get and put functions for the table, exposed to modules.
307  */
308
309 struct sysrq_key_op *__sysrq_get_key_op (int key) {
310         struct sysrq_key_op *op_p;
311         int i;
312         
313         i = sysrq_key_table_key2index(key);
314         op_p = (i == -1) ? NULL : sysrq_key_table[i];
315         return op_p;
316 }
317
318 void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
319         int i;
320
321         i = sysrq_key_table_key2index(key);
322         if (i != -1)
323                 sysrq_key_table[i] = op_p;
324 }
325
326 /*
327  * This is the non-locking version of handle_sysrq
328  * It must/can only be called by sysrq key handlers,
329  * as they are inside of the lock
330  */
331
332 void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
333 {
334         struct sysrq_key_op *op_p;
335         int orig_log_level;
336         int i, j;
337
338         __sysrq_lock_table();
339         orig_log_level = console_loglevel;
340         console_loglevel = 7;
341         printk(KERN_INFO "SysRq : ");
342
343         op_p = __sysrq_get_key_op(key);
344         if (op_p) {
345                 printk ("%s\n", op_p->action_msg);
346                 console_loglevel = orig_log_level;
347                 op_p->handler(key, pt_regs, tty);
348         } else {
349                 printk("HELP : ");
350                 /* Only print the help msg once per handler */
351                 for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 
352                 if (sysrq_key_table[i]) {
353                         for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
354                         if (j == i)
355                                 printk ("%s ", sysrq_key_table[i]->help_msg);
356                 }
357                 printk ("\n");
358                 console_loglevel = orig_log_level;
359         }
360         __sysrq_unlock_table();
361 }
362
363 /*
364  * This function is called by the keyboard handler when SysRq is pressed
365  * and any other keycode arrives.
366  */
367
368 void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
369 {
370         if (!sysrq_enabled)
371                 return;
372         __handle_sysrq(key, pt_regs, tty);
373 }
374
375 EXPORT_SYMBOL(handle_sysrq);
376 EXPORT_SYMBOL(__sysrq_lock_table);
377 EXPORT_SYMBOL(__sysrq_unlock_table);
378 EXPORT_SYMBOL(__sysrq_get_key_op);
379 EXPORT_SYMBOL(__sysrq_put_key_op);