aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2009-03-31 18:23:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 11:59:17 -0400
commitc2d7543851849a6923680cdd7e1047ed1a84a1c5 (patch)
treebf3038819d4be83a1d1e64d7b95bbb3d9d908544
parent55a63998b8967615a15e2211ba0ff3a84a565824 (diff)
filesystem freeze: allow SysRq emergency thaw to thaw frozen filesystems
Now that the filesystem freeze operation has been elevated to the VFS, and is just an ioctl away, some sort of safety net for unintentionally frozen root filesystems may be in order. The timeout thaw originally proposed did not get merged, but perhaps something like this would be useful in emergencies. For example, freeze /path/to/mountpoint may freeze your root filesystem if you forgot that you had that unmounted. I chose 'j' as the last remaining character other than 'h' which is sort of reserved for help (because help is generated on any unknown character). I've tested this on a non-root fs with multiple (nested) freezers, as well as on a system rendered unresponsive due to a frozen root fs. [randy.dunlap@oracle.com: emergency thaw only if CONFIG_BLOCK enabled] Signed-off-by: Eric Sandeen <sandeen@redhat.com> Cc: Takashi Sato <t-sato@yk.jp.nec.com> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/sysrq.txt5
-rw-r--r--drivers/char/sysrq.c19
-rw-r--r--fs/buffer.c33
-rw-r--r--include/linux/fs.h1
4 files changed, 57 insertions, 1 deletions
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 9e592c718af..afa2946892d 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -81,6 +81,8 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
81 81
82'i' - Send a SIGKILL to all processes, except for init. 82'i' - Send a SIGKILL to all processes, except for init.
83 83
84'j' - Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl.
85
84'k' - Secure Access Key (SAK) Kills all programs on the current virtual 86'k' - Secure Access Key (SAK) Kills all programs on the current virtual
85 console. NOTE: See important comments below in SAK section. 87 console. NOTE: See important comments below in SAK section.
86 88
@@ -160,6 +162,9 @@ t'E'rm and k'I'll are useful if you have some sort of runaway process you
160are unable to kill any other way, especially if it's spawning other 162are unable to kill any other way, especially if it's spawning other
161processes. 163processes.
162 164
165"'J'ust thaw it" is useful if your system becomes unresponsive due to a frozen
166(probably root) filesystem via the FIFREEZE ioctl.
167
163* Sometimes SysRq seems to get 'stuck' after using it, what can I do? 168* Sometimes SysRq seems to get 'stuck' after using it, what can I do?
164~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 169~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165That happens to me, also. I've found that tapping shift, alt, and control 170That happens to me, also. I've found that tapping shift, alt, and control
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 33a9351c896..5afe7316c72 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -346,6 +346,19 @@ static struct sysrq_key_op sysrq_moom_op = {
346 .enable_mask = SYSRQ_ENABLE_SIGNAL, 346 .enable_mask = SYSRQ_ENABLE_SIGNAL,
347}; 347};
348 348
349#ifdef CONFIG_BLOCK
350static void sysrq_handle_thaw(int key, struct tty_struct *tty)
351{
352 emergency_thaw_all();
353}
354static struct sysrq_key_op sysrq_thaw_op = {
355 .handler = sysrq_handle_thaw,
356 .help_msg = "thaw-filesystems(J)",
357 .action_msg = "Emergency Thaw of all frozen filesystems",
358 .enable_mask = SYSRQ_ENABLE_SIGNAL,
359};
360#endif
361
349static void sysrq_handle_kill(int key, struct tty_struct *tty) 362static void sysrq_handle_kill(int key, struct tty_struct *tty)
350{ 363{
351 send_sig_all(SIGKILL); 364 send_sig_all(SIGKILL);
@@ -396,9 +409,13 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
396 &sysrq_moom_op, /* f */ 409 &sysrq_moom_op, /* f */
397 /* g: May be registered by ppc for kgdb */ 410 /* g: May be registered by ppc for kgdb */
398 NULL, /* g */ 411 NULL, /* g */
399 NULL, /* h */ 412 NULL, /* h - reserved for help */
400 &sysrq_kill_op, /* i */ 413 &sysrq_kill_op, /* i */
414#ifdef CONFIG_BLOCK
415 &sysrq_thaw_op, /* j */
416#else
401 NULL, /* j */ 417 NULL, /* j */
418#endif
402 &sysrq_SAK_op, /* k */ 419 &sysrq_SAK_op, /* k */
403#ifdef CONFIG_SMP 420#ifdef CONFIG_SMP
404 &sysrq_showallcpus_op, /* l */ 421 &sysrq_showallcpus_op, /* l */
diff --git a/fs/buffer.c b/fs/buffer.c
index c77b848c3d4..f5f8b15a6e4 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -547,6 +547,39 @@ repeat:
547 return err; 547 return err;
548} 548}
549 549
550void do_thaw_all(unsigned long unused)
551{
552 struct super_block *sb;
553 char b[BDEVNAME_SIZE];
554
555 spin_lock(&sb_lock);
556restart:
557 list_for_each_entry(sb, &super_blocks, s_list) {
558 sb->s_count++;
559 spin_unlock(&sb_lock);
560 down_read(&sb->s_umount);
561 while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
562 printk(KERN_WARNING "Emergency Thaw on %s\n",
563 bdevname(sb->s_bdev, b));
564 up_read(&sb->s_umount);
565 spin_lock(&sb_lock);
566 if (__put_super_and_need_restart(sb))
567 goto restart;
568 }
569 spin_unlock(&sb_lock);
570 printk(KERN_WARNING "Emergency Thaw complete\n");
571}
572
573/**
574 * emergency_thaw_all -- forcibly thaw every frozen filesystem
575 *
576 * Used for emergency unfreeze of all filesystems via SysRq
577 */
578void emergency_thaw_all(void)
579{
580 pdflush_operation(do_thaw_all, 0);
581}
582
550/** 583/**
551 * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers 584 * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers
552 * @mapping: the mapping which wants those buffers written 585 * @mapping: the mapping which wants those buffers written
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 87e7bfc5ebd..61211ad823f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1878,6 +1878,7 @@ extern struct block_device *open_by_devnum(dev_t, fmode_t);
1878extern void invalidate_bdev(struct block_device *); 1878extern void invalidate_bdev(struct block_device *);
1879extern int sync_blockdev(struct block_device *bdev); 1879extern int sync_blockdev(struct block_device *bdev);
1880extern struct super_block *freeze_bdev(struct block_device *); 1880extern struct super_block *freeze_bdev(struct block_device *);
1881extern void emergency_thaw_all(void);
1881extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); 1882extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
1882extern int fsync_bdev(struct block_device *); 1883extern int fsync_bdev(struct block_device *);
1883extern int fsync_super(struct super_block *); 1884extern int fsync_super(struct super_block *);