sysrq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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. #include <linux/config.h>
  15. #include <linux/sched.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/mm.h>
  18. #include <linux/fs.h>
  19. #include <linux/tty.h>
  20. #include <linux/mount.h>
  21. #include <linux/kdev_t.h>
  22. #include <linux/major.h>
  23. #include <linux/reboot.h>
  24. #include <linux/sysrq.h>
  25. #include <linux/kbd_kern.h>
  26. #include <linux/quotaops.h>
  27. #include <linux/smp_lock.h>
  28. #include <linux/module.h>
  29. #include <linux/spinlock.h>
  30. #include <asm/ptrace.h>
  31. extern void reset_vc(unsigned int);
  32. extern struct list_head super_blocks;
  33. /* Whether we react on sysrq keys or just ignore them */
  34. int sysrq_enabled = 1;
  35. /* Machine specific power off function */
  36. void (*sysrq_power_off)(void);
  37. /* Loglevel sysrq handler */
  38. static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
  39. struct kbd_struct *kbd, struct tty_struct *tty) {
  40. int i;
  41. i = key - '0';
  42. console_loglevel = 7;
  43. printk("Loglevel set to %dn", i);
  44. console_loglevel = i;
  45. }
  46. static struct sysrq_key_op sysrq_loglevel_op = {
  47. handler: sysrq_handle_loglevel,
  48. help_msg: "loglevel0-8",
  49. action_msg: "Changing Loglevel",
  50. };
  51. /* SAK sysrq handler */
  52. #ifdef CONFIG_VT
  53. static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
  54. struct kbd_struct *kbd, struct tty_struct *tty) {
  55. if (tty)
  56. do_SAK(tty);
  57. reset_vc(fg_console);
  58. }
  59. static struct sysrq_key_op sysrq_SAK_op = {
  60. handler: sysrq_handle_SAK,
  61. help_msg: "saK",
  62. action_msg: "SAK",
  63. };
  64. #endif
  65. /* unraw sysrq handler */
  66. static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
  67. struct kbd_struct *kbd, struct tty_struct *tty) {
  68. if (kbd)
  69. kbd->kbdmode = VC_XLATE;
  70. }
  71. static struct sysrq_key_op sysrq_unraw_op = {
  72. handler: sysrq_handle_unraw,
  73. help_msg: "unRaw",
  74. action_msg: "Keyboard mode set to XLATE",
  75. };
  76. /* reboot sysrq handler */
  77. static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
  78. struct kbd_struct *kbd, struct tty_struct *tty) {
  79. machine_restart(NULL);
  80. }
  81. static struct sysrq_key_op sysrq_reboot_op = {
  82. handler: sysrq_handle_reboot,
  83. help_msg: "reBoot",
  84. action_msg: "Resetting",
  85. };
  86. /* SYNC SYSRQ HANDLERS BLOCK */
  87. /* do_emergency_sync helper function */
  88. /* Guesses if the device is a local hard drive */
  89. static int is_local_disk(kdev_t dev) {
  90. unsigned int major;
  91. major = MAJOR(dev);
  92. switch (major) {
  93. case IDE0_MAJOR:
  94. case IDE1_MAJOR:
  95. case IDE2_MAJOR:
  96. case IDE3_MAJOR:
  97. case IDE4_MAJOR:
  98. case IDE5_MAJOR:
  99. case IDE6_MAJOR:
  100. case IDE7_MAJOR:
  101. case IDE8_MAJOR:
  102. case IDE9_MAJOR:
  103. case SCSI_DISK0_MAJOR:
  104. case SCSI_DISK1_MAJOR:
  105. case SCSI_DISK2_MAJOR:
  106. case SCSI_DISK3_MAJOR:
  107. case SCSI_DISK4_MAJOR:
  108. case SCSI_DISK5_MAJOR:
  109. case SCSI_DISK6_MAJOR:
  110. case SCSI_DISK7_MAJOR:
  111. case XT_DISK_MAJOR:
  112. return 1;
  113. default:
  114. return 0;
  115. }
  116. }
  117. /* do_emergency_sync helper function */
  118. static void go_sync(struct super_block *sb, int remount_flag)
  119. {
  120. int orig_loglevel;
  121. orig_loglevel = console_loglevel;
  122. console_loglevel = 7;
  123. printk(KERN_INFO "%sing device %s ... ",
  124.        remount_flag ? "Remount" : "Sync",
  125.        kdevname(sb->s_dev));
  126. if (remount_flag) { /* Remount R/O */
  127. int ret, flags;
  128. struct list_head *p;
  129. if (sb->s_flags & MS_RDONLY) {
  130. printk("R/On");
  131. return;
  132. }
  133. file_list_lock();
  134. for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
  135. struct file *file = list_entry(p, struct file, f_list);
  136. if (file->f_dentry && file_count(file)
  137. && S_ISREG(file->f_dentry->d_inode->i_mode))
  138. file->f_mode &= ~2;
  139. }
  140. file_list_unlock();
  141. DQUOT_OFF(sb);
  142. fsync_dev(sb->s_dev);
  143. flags = MS_RDONLY;
  144. if (sb->s_op && sb->s_op->remount_fs) {
  145. ret = sb->s_op->remount_fs(sb, &flags, NULL);
  146. if (ret)
  147. printk("error %dn", ret);
  148. else {
  149. sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
  150. printk("OKn");
  151. }
  152. } else
  153. printk("nothing to don");
  154. } else { /* Sync only */
  155. fsync_dev(sb->s_dev);
  156. printk("OKn");
  157. }
  158. console_loglevel = orig_loglevel;
  159. }
  160. /*
  161.  * Emergency Sync or Unmount. We cannot do it directly, so we set a special
  162.  * flag and wake up the bdflush kernel thread which immediately calls this function.
  163.  * We process all mounted hard drives first to recover from crashed experimental
  164.  * block devices and malfunctional network filesystems.
  165.  */
  166. volatile int emergency_sync_scheduled;
  167. void do_emergency_sync(void) {
  168. struct super_block *sb;
  169. int remount_flag;
  170. int orig_loglevel;
  171. lock_kernel();
  172. remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
  173. emergency_sync_scheduled = 0;
  174. for (sb = sb_entry(super_blocks.next);
  175.      sb != sb_entry(&super_blocks); 
  176.      sb = sb_entry(sb->s_list.next))
  177. if (is_local_disk(sb->s_dev))
  178. go_sync(sb, remount_flag);
  179. for (sb = sb_entry(super_blocks.next);
  180.      sb != sb_entry(&super_blocks); 
  181.      sb = sb_entry(sb->s_list.next))
  182. if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev))
  183. go_sync(sb, remount_flag);
  184. unlock_kernel();
  185. orig_loglevel = console_loglevel;
  186. console_loglevel = 7;
  187. printk(KERN_INFO "Done.n");
  188. console_loglevel = orig_loglevel;
  189. }
  190. static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
  191. struct kbd_struct *kbd, struct tty_struct *tty) {
  192. emergency_sync_scheduled = EMERG_SYNC;
  193. wakeup_bdflush();
  194. }
  195. static struct sysrq_key_op sysrq_sync_op = {
  196. handler: sysrq_handle_sync,
  197. help_msg: "Sync",
  198. action_msg: "Emergency Sync",
  199. };
  200. static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
  201. struct kbd_struct *kbd, struct tty_struct *tty) {
  202. emergency_sync_scheduled = EMERG_REMOUNT;
  203. wakeup_bdflush();
  204. }
  205. static struct sysrq_key_op sysrq_mountro_op = {
  206. handler: sysrq_handle_mountro,
  207. help_msg: "Unmount",
  208. action_msg: "Emergency Remount R/O",
  209. };
  210. /* END SYNC SYSRQ HANDLERS BLOCK */
  211. /* SHOW SYSRQ HANDLERS BLOCK */
  212. static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
  213. struct kbd_struct *kbd, struct tty_struct *tty) {
  214. if (pt_regs)
  215. show_regs(pt_regs);
  216. }
  217. static struct sysrq_key_op sysrq_showregs_op = {
  218. handler: sysrq_handle_showregs,
  219. help_msg: "showPc",
  220. action_msg: "Show Regs",
  221. };
  222. static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
  223. struct kbd_struct *kbd, struct tty_struct *tty) {
  224. show_state();
  225. }
  226. static struct sysrq_key_op sysrq_showstate_op = {
  227. handler: sysrq_handle_showstate,
  228. help_msg: "showTasks",
  229. action_msg: "Show State",
  230. };
  231. static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
  232. struct kbd_struct *kbd, struct tty_struct *tty) {
  233. show_mem();
  234. }
  235. static struct sysrq_key_op sysrq_showmem_op = {
  236. handler: sysrq_handle_showmem,
  237. help_msg: "showMem",
  238. action_msg: "Show Memory",
  239. };
  240. /* SHOW SYSRQ HANDLERS BLOCK */
  241. /* SIGNAL SYSRQ HANDLERS BLOCK */
  242. /* signal sysrq helper function
  243.  * Sends a signal to all user processes */
  244. static void send_sig_all(int sig)
  245. {
  246. struct task_struct *p;
  247. for_each_task(p) {
  248. if (p->mm && p->pid != 1)
  249. /* Not swapper, init nor kernel thread */
  250. force_sig(sig, p);
  251. }
  252. }
  253. static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
  254. struct kbd_struct *kbd, struct tty_struct *tty) {
  255. send_sig_all(SIGTERM);
  256. console_loglevel = 8;
  257. }
  258. static struct sysrq_key_op sysrq_term_op = {
  259. handler: sysrq_handle_term,
  260. help_msg: "tErm",
  261. action_msg: "Terminate All Tasks",
  262. };
  263. static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
  264. struct kbd_struct *kbd, struct tty_struct *tty) {
  265. send_sig_all(SIGKILL);
  266. console_loglevel = 8;
  267. }
  268. static struct sysrq_key_op sysrq_kill_op = {
  269. handler: sysrq_handle_kill,
  270. help_msg: "kIll",
  271. action_msg: "Kill All Tasks",
  272. };
  273. /* END SIGNAL SYSRQ HANDLERS BLOCK */
  274. /* Key Operations table and lock */
  275. static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
  276. #define SYSRQ_KEY_TABLE_LENGTH 36
  277. static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
  278. /* 0 */ &sysrq_loglevel_op,
  279. /* 1 */ &sysrq_loglevel_op,
  280. /* 2 */ &sysrq_loglevel_op,
  281. /* 3 */ &sysrq_loglevel_op,
  282. /* 4 */ &sysrq_loglevel_op,
  283. /* 5 */ &sysrq_loglevel_op,
  284. /* 6 */ &sysrq_loglevel_op,
  285. /* 7 */ &sysrq_loglevel_op,
  286. /* 8 */ &sysrq_loglevel_op,
  287. /* 9 */ &sysrq_loglevel_op,
  288. /* a */ NULL, /* Don't use for system provided sysrqs,
  289.  it is handled specially on the spark
  290.  and will never arive */
  291. /* b */ &sysrq_reboot_op,
  292. /* c */ NULL,
  293. /* d */ NULL,
  294. /* e */ &sysrq_term_op,
  295. /* f */ NULL,
  296. /* g */ NULL,
  297. /* h */ NULL,
  298. /* i */ &sysrq_kill_op,
  299. /* j */ NULL,
  300. #ifdef CONFIG_VT
  301. /* k */ &sysrq_SAK_op,
  302. #else
  303. /* k */ NULL,
  304. #endif
  305. /* l */ NULL,
  306. /* m */ &sysrq_showmem_op,
  307. /* n */ NULL,
  308. /* o */ NULL, /* This will often be registered
  309.  as 'Off' at init time */
  310. /* p */ &sysrq_showregs_op,
  311. /* q */ NULL,
  312. /* r */ &sysrq_unraw_op,
  313. /* s */ &sysrq_sync_op,
  314. /* t */ &sysrq_showstate_op,
  315. /* u */ &sysrq_mountro_op,
  316. /* v */ NULL,
  317. /* w */ NULL,
  318. /* x */ NULL,
  319. /* w */ NULL,
  320. /* z */ NULL
  321. };
  322. /* key2index calculation, -1 on invalid index */
  323. static __inline__ int sysrq_key_table_key2index(int key) {
  324. int retval;
  325. if ((key >= '0') & (key <= '9')) {
  326. retval = key - '0';
  327. } else if ((key >= 'a') & (key <= 'z')) {
  328. retval = key + 10 - 'a';
  329. } else {
  330. retval = -1;
  331. }
  332. return retval;
  333. }
  334. /*
  335.  * table lock and unlocking functions, exposed to modules
  336.  */
  337. void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); }
  338. void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); }
  339. /*
  340.  * get and put functions for the table, exposed to modules.
  341.  */
  342. struct sysrq_key_op *__sysrq_get_key_op (int key) {
  343.         struct sysrq_key_op *op_p;
  344.         int i;
  345. i = sysrq_key_table_key2index(key);
  346.         op_p = (i == -1) ? NULL : sysrq_key_table[i];
  347.         return op_p;
  348. }
  349. void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
  350.         int i;
  351. i = sysrq_key_table_key2index(key);
  352.         if (i != -1)
  353.                 sysrq_key_table[i] = op_p;
  354. }
  355. /*
  356.  * This function is called by the keyboard handler when SysRq is pressed
  357.  * and any other keycode arrives.
  358.  */
  359. void handle_sysrq(int key, struct pt_regs *pt_regs,
  360.   struct kbd_struct *kbd, struct tty_struct *tty) {
  361. if (!sysrq_enabled)
  362. return;
  363. __sysrq_lock_table();
  364. __handle_sysrq_nolock(key, pt_regs, kbd, tty);
  365. __sysrq_unlock_table();
  366. }
  367. /*
  368.  * This is the non-locking version of handle_sysrq
  369.  * It must/can only be called by sysrq key handlers,
  370.  * as they are inside of the lock
  371.  */
  372. void __handle_sysrq_nolock(int key, struct pt_regs *pt_regs,
  373.   struct kbd_struct *kbd, struct tty_struct *tty) {
  374. struct sysrq_key_op *op_p;
  375. int orig_log_level;
  376. int i, j;
  377. if (!sysrq_enabled)
  378. return;
  379. orig_log_level = console_loglevel;
  380. console_loglevel = 7;
  381. printk(KERN_INFO "SysRq : ");
  382.         op_p = __sysrq_get_key_op(key);
  383.         if (op_p) {
  384. printk ("%sn", op_p->action_msg);
  385. console_loglevel = orig_log_level;
  386. op_p->handler(key, pt_regs, kbd, tty);
  387. } else {
  388. printk("HELP : ");
  389. /* Only print the help msg once per handler */
  390. for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 
  391. if (sysrq_key_table[i]) {
  392. for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
  393. if (j == i)
  394. printk ("%s ", sysrq_key_table[i]->help_msg);
  395. }
  396. printk ("n");
  397. console_loglevel = orig_log_level;
  398. }
  399. }
  400. EXPORT_SYMBOL(handle_sysrq);
  401. EXPORT_SYMBOL(__handle_sysrq_nolock);
  402. EXPORT_SYMBOL(__sysrq_lock_table);
  403. EXPORT_SYMBOL(__sysrq_unlock_table);
  404. EXPORT_SYMBOL(__sysrq_get_key_op);
  405. EXPORT_SYMBOL(__sysrq_put_key_op);