* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / char / sysrq.c
blob85e436565cba4912e0c172a507ae8f783fef0005
1 /* -*- linux-c -*-
3 * $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
5 * Linux Magic System Request Key Hacks
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 */
11 #include <linux/config.h>
12 #include <linux/sched.h>
13 #include <linux/interrupt.h>
14 #include <linux/mm.h>
15 #include <linux/fs.h>
16 #include <linux/mount.h>
17 #include <linux/kdev_t.h>
18 #include <linux/major.h>
19 #include <linux/reboot.h>
20 #include <linux/sysrq.h>
21 #include <linux/kbd_kern.h>
22 #include <linux/quotaops.h>
23 #include <linux/smp_lock.h>
25 #include <asm/ptrace.h>
27 #ifdef CONFIG_APM
28 #include <linux/apm_bios.h>
29 #endif
31 extern void wakeup_bdflush(int);
32 extern void reset_vc(unsigned int);
33 extern int console_loglevel;
34 extern struct vfsmount *vfsmntlist;
36 /* Send a signal to all user processes */
38 static void send_sig_all(int sig, int even_init)
40 struct task_struct *p;
42 for_each_task(p) {
43 if (p->mm) { /* Not swapper nor kernel thread */
44 if (p->pid == 1 && even_init) /* Ugly hack to kill init */
45 p->pid = 0x8000;
46 force_sig(sig, p);
52 * This function is called by the keyboard handler when SysRq is pressed
53 * and any other keycode arrives.
56 void handle_sysrq(int key, struct pt_regs *pt_regs,
57 struct kbd_struct *kbd, struct tty_struct *tty)
59 int orig_log_level = console_loglevel;
61 if (!key)
62 return;
64 console_loglevel = 7;
65 printk(KERN_INFO "SysRq: ");
66 switch (key) {
67 case 'r': /* R -- Reset raw mode */
68 if (kbd) {
69 kbd->kbdmode = VC_XLATE;
70 printk("Keyboard mode set to XLATE\n");
72 break;
73 #ifdef CONFIG_VT
74 case 'k': /* K -- SAK */
75 printk("SAK\n");
76 if (tty)
77 do_SAK(tty);
78 reset_vc(fg_console);
79 break;
80 #endif
81 case 'b': /* B -- boot immediately */
82 printk("Resetting\n");
83 machine_restart(NULL);
84 break;
85 #ifdef CONFIG_APM
86 case 'o': /* O -- power off */
87 printk("Power off\n");
88 apm_power_off();
89 break;
90 #endif
91 case 's': /* S -- emergency sync */
92 printk("Emergency Sync\n");
93 emergency_sync_scheduled = EMERG_SYNC;
94 wakeup_bdflush(0);
95 break;
96 case 'u': /* U -- emergency remount R/O */
97 printk("Emergency Remount R/O\n");
98 emergency_sync_scheduled = EMERG_REMOUNT;
99 wakeup_bdflush(0);
100 break;
101 case 'p': /* P -- show PC */
102 printk("Show Regs\n");
103 if (pt_regs)
104 show_regs(pt_regs);
105 break;
106 case 't': /* T -- show task info */
107 printk("Show State\n");
108 show_state();
109 break;
110 case 'm': /* M -- show memory info */
111 printk("Show Memory\n");
112 show_mem();
113 break;
114 case '0' ... '9': /* 0-9 -- set console logging level */
115 orig_log_level = key - '0';
116 printk("Log level set to %d\n", orig_log_level);
117 break;
118 case 'e': /* E -- terminate all user processes */
119 printk("Terminate All Tasks\n");
120 send_sig_all(SIGTERM, 0);
121 orig_log_level = 8; /* We probably have killed syslogd */
122 break;
123 case 'i': /* I -- kill all user processes */
124 printk("Kill All Tasks\n");
125 send_sig_all(SIGKILL, 0);
126 orig_log_level = 8;
127 break;
128 case 'l': /* L -- kill all processes including init */
129 printk("Kill ALL Tasks (even init)\n");
130 send_sig_all(SIGKILL, 1);
131 orig_log_level = 8;
132 break;
133 default: /* Unknown: help */
134 if (kbd)
135 printk("unRaw ");
136 #ifdef CONFIG_VT
137 if (tty)
138 printk("saK ");
139 #endif
140 printk("Boot "
141 #ifdef CONFIG_APM
142 "Off "
143 #endif
144 "Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n");
145 /* Don't use 'A' as it's handled specially on the Sparc */
148 console_loglevel = orig_log_level;
151 /* Aux routines for the syncer */
153 static int is_local_disk(kdev_t dev) /* Guess if the device is a local hard drive */
155 unsigned int major = MAJOR(dev);
157 switch (major) {
158 case IDE0_MAJOR:
159 case IDE1_MAJOR:
160 case IDE2_MAJOR:
161 case IDE3_MAJOR:
162 case SCSI_DISK0_MAJOR:
163 case SCSI_DISK1_MAJOR:
164 case SCSI_DISK2_MAJOR:
165 case SCSI_DISK3_MAJOR:
166 case SCSI_DISK4_MAJOR:
167 case SCSI_DISK5_MAJOR:
168 case SCSI_DISK6_MAJOR:
169 case SCSI_DISK7_MAJOR:
170 return 1;
171 default:
172 return 0;
176 static void go_sync(kdev_t dev, int remount_flag)
178 printk(KERN_INFO "%sing device %s ... ",
179 remount_flag ? "Remount" : "Sync",
180 kdevname(dev));
182 if (remount_flag) { /* Remount R/O */
183 struct super_block *sb = get_super(dev);
184 struct vfsmount *vfsmnt;
185 int ret, flags;
186 struct list_head *p;
188 if (!sb) {
189 printk("Superblock not found\n");
190 return;
192 if (sb->s_flags & MS_RDONLY) {
193 printk("R/O\n");
194 return;
197 file_list_lock();
198 for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
199 struct file *file = list_entry(p, struct file, f_list);
200 if (file->f_dentry && file_count(file)
201 && S_ISREG(file->f_dentry->d_inode->i_mode))
202 file->f_mode &= ~2;
204 file_list_unlock();
205 DQUOT_OFF(dev);
206 fsync_dev(dev);
207 flags = MS_RDONLY;
208 if (sb->s_op && sb->s_op->remount_fs) {
209 ret = sb->s_op->remount_fs(sb, &flags, NULL);
210 if (ret)
211 printk("error %d\n", ret);
212 else {
213 sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
214 if ((vfsmnt = lookup_vfsmnt(sb->s_dev)))
215 vfsmnt->mnt_flags = sb->s_flags;
216 printk("OK\n");
218 } else
219 printk("nothing to do\n");
220 } else {
221 fsync_dev(dev); /* Sync only */
222 printk("OK\n");
227 * Emergency Sync or Unmount. We cannot do it directly, so we set a special
228 * flag and wake up the bdflush kernel thread which immediately calls this function.
229 * We process all mounted hard drives first to recover from crashed experimental
230 * block devices and malfunctional network filesystems.
233 int emergency_sync_scheduled;
235 void do_emergency_sync(void)
237 struct vfsmount *mnt;
238 int remount_flag;
240 lock_kernel();
241 remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
242 emergency_sync_scheduled = 0;
244 for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next)
245 if (is_local_disk(mnt->mnt_dev))
246 go_sync(mnt->mnt_dev, remount_flag);
248 for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next)
249 if (!is_local_disk(mnt->mnt_dev) && MAJOR(mnt->mnt_dev))
250 go_sync(mnt->mnt_dev, remount_flag);
252 unlock_kernel();
253 printk(KERN_INFO "Done.\n");