~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/sysrq.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 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>
 24 #include <linux/module.h>
 25 
 26 #include <asm/ptrace.h>
 27 
 28 extern void wakeup_bdflush(int);
 29 extern void reset_vc(unsigned int);
 30 extern struct list_head super_blocks;
 31 
 32 /* Whether we react on sysrq keys or just ignore them */
 33 int sysrq_enabled = 1;
 34 
 35 /* Machine specific power off function */
 36 void (*sysrq_power_off)(void);
 37 
 38 EXPORT_SYMBOL(sysrq_power_off);
 39 
 40 /* Send a signal to all user processes */
 41 
 42 static void send_sig_all(int sig, int even_init)
 43 {
 44         struct task_struct *p;
 45 
 46         for_each_task(p) {
 47                 if (p->mm) {                                /* Not swapper nor kernel thread */
 48                         if (p->pid == 1 && even_init)       /* Ugly hack to kill init */
 49                                 p->pid = 0x8000;
 50                         force_sig(sig, p);
 51                 }
 52         }
 53 }
 54 
 55 /*
 56  * This function is called by the keyboard handler when SysRq is pressed
 57  * and any other keycode arrives.
 58  */
 59 
 60 void handle_sysrq(int key, struct pt_regs *pt_regs,
 61                   struct kbd_struct *kbd, struct tty_struct *tty)
 62 {
 63         int orig_log_level = console_loglevel;
 64 
 65         if (!sysrq_enabled)
 66                 return;
 67 
 68         if (!key)
 69                 return;
 70 
 71         console_loglevel = 7;
 72         printk(KERN_INFO "SysRq: ");
 73         switch (key) {
 74         case 'r':                                           /* R -- Reset raw mode */
 75                 if (kbd) {
 76                         kbd->kbdmode = VC_XLATE;
 77                         printk("Keyboard mode set to XLATE\n");
 78                 }
 79                 break;
 80 #ifdef CONFIG_VT
 81         case 'k':                                           /* K -- SAK */
 82                 printk("SAK\n");
 83                 if (tty)
 84                         do_SAK(tty);
 85                 reset_vc(fg_console);
 86                 break;
 87 #endif
 88         case 'b':                                           /* B -- boot immediately */
 89                 printk("Resetting\n");
 90                 machine_restart(NULL);
 91                 break;
 92         case 'o':                                           /* O -- power off */
 93                 if (sysrq_power_off) {
 94                         printk("Power off\n");
 95                         sysrq_power_off();
 96                 }
 97                 break;
 98         case 's':                                           /* S -- emergency sync */
 99                 printk("Emergency Sync\n");
100                 emergency_sync_scheduled = EMERG_SYNC;
101                 wakeup_bdflush(0);
102                 break;
103         case 'u':                                           /* U -- emergency remount R/O */
104                 printk("Emergency Remount R/O\n");
105                 emergency_sync_scheduled = EMERG_REMOUNT;
106                 wakeup_bdflush(0);
107                 break;
108         case 'p':                                           /* P -- show PC */
109                 printk("Show Regs\n");
110                 if (pt_regs)
111                         show_regs(pt_regs);
112                 break;
113         case 't':                                           /* T -- show task info */
114                 printk("Show State\n");
115                 show_state();
116                 break;
117         case 'm':                                           /* M -- show memory info */
118                 printk("Show Memory\n");
119                 show_mem();
120                 break;
121         case '' ... '9':                                   /* 0-9 -- set console logging level */
122                 orig_log_level = key - '';
123                 printk("Log level set to %d\n", orig_log_level);
124                 break;
125         case 'e':                                           /* E -- terminate all user processes */
126                 printk("Terminate All Tasks\n");
127                 send_sig_all(SIGTERM, 0);
128                 orig_log_level = 8;                         /* We probably have killed syslogd */
129                 break;
130         case 'i':                                           /* I -- kill all user processes */
131                 printk("Kill All Tasks\n");
132                 send_sig_all(SIGKILL, 0);
133                 orig_log_level = 8;
134                 break;
135         case 'l':                                           /* L -- kill all processes including init */
136                 printk("Kill ALL Tasks (even init)\n");
137                 send_sig_all(SIGKILL, 1);
138                 orig_log_level = 8;
139                 break;
140         default:                                            /* Unknown: help */
141                 if (kbd)
142                         printk("unRaw ");
143 #ifdef CONFIG_VT
144                 if (tty)
145                         printk("saK ");
146 #endif
147                 printk("Boot ");
148                 if (sysrq_power_off)
149                         printk("Off ");
150                 printk("Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n");
151                 /* Don't use 'A' as it's handled specially on the Sparc */
152         }
153 
154         console_loglevel = orig_log_level;
155 }
156 
157 /* Aux routines for the syncer */
158 
159 static int is_local_disk(kdev_t dev)        /* Guess if the device is a local hard drive */
160 {
161         unsigned int major = MAJOR(dev);
162 
163         switch (major) {
164         case IDE0_MAJOR:
165         case IDE1_MAJOR:
166         case IDE2_MAJOR:
167         case IDE3_MAJOR:
168         case SCSI_DISK0_MAJOR:
169         case SCSI_DISK1_MAJOR:
170         case SCSI_DISK2_MAJOR:
171         case SCSI_DISK3_MAJOR:
172         case SCSI_DISK4_MAJOR:
173         case SCSI_DISK5_MAJOR:
174         case SCSI_DISK6_MAJOR:
175         case SCSI_DISK7_MAJOR:
176                 return 1;
177         default:
178                 return 0;
179         }
180 }
181 
182 static void go_sync(struct super_block *sb, int remount_flag)
183 {
184         printk(KERN_INFO "%sing device %s ... ",
185                remount_flag ? "Remount" : "Sync",
186                kdevname(sb->s_dev));
187 
188         if (remount_flag) {                                 /* Remount R/O */
189                 int ret, flags;
190                 struct list_head *p;
191 
192                 if (sb->s_flags & MS_RDONLY) {
193                         printk("R/O\n");
194                         return;
195                 }
196 
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;
203                 }
204                 file_list_unlock();
205                 DQUOT_OFF(sb);
206                 fsync_dev(sb->s_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                                 printk("OK\n");
215                         }
216                 } else
217                         printk("nothing to do\n");
218         } else {
219                 fsync_dev(sb->s_dev);                       /* Sync only */
220                 printk("OK\n");
221         }
222 }
223 
224 /*
225  * Emergency Sync or Unmount. We cannot do it directly, so we set a special
226  * flag and wake up the bdflush kernel thread which immediately calls this function.
227  * We process all mounted hard drives first to recover from crashed experimental
228  * block devices and malfunctional network filesystems.
229  */
230 
231 int emergency_sync_scheduled;
232 
233 void do_emergency_sync(void)
234 {
235         struct super_block *sb;
236         int remount_flag;
237 
238         lock_kernel();
239         remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
240         emergency_sync_scheduled = 0;
241 
242         for (sb = sb_entry(super_blocks.next);
243              sb != sb_entry(&super_blocks); 
244              sb = sb_entry(sb->s_list.next))
245                 if (is_local_disk(sb->s_dev))
246                         go_sync(sb, remount_flag);
247 
248         for (sb = sb_entry(super_blocks.next);
249              sb != sb_entry(&super_blocks); 
250              sb = sb_entry(sb->s_list.next))
251                 if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev))
252                         go_sync(sb, remount_flag);
253 
254         unlock_kernel();
255         printk(KERN_INFO "Done.\n");
256 }
257 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.