aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2017-02-05 19:47:14 -0500
committerTheodore Ts'o <tytso@mit.edu>2017-02-05 19:47:14 -0500
commit783d948544993f55bdacc78b127532e8b6e2fc9f (patch)
tree9aa172542294f1d75dc033d10f8756c5832ee1e8
parent0db1ff222d40f1601c961f0edb86d10426992595 (diff)
ext4: add EXT4_IOC_GOINGDOWN ioctl
This ioctl is modeled after the xfs's XFS_IOC_GOINGDOWN ioctl. (In fact, it uses the same code points.) Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/ext4.h10
-rw-r--r--fs/ext4/ioctl.c50
-rw-r--r--fs/ext4/super.c2
3 files changed, 61 insertions, 1 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 35d93ab7f3fb..55b7a77a0444 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -679,6 +679,16 @@ struct fsxattr {
679#define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR 679#define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR
680#define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR 680#define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR
681 681
682#define EXT4_IOC_GOINGDOWN _IOR ('X', 125, __u32)
683
684/*
685 * Flags for going down operation
686 */
687#define EXT4_GOING_FLAGS_DEFAULT 0x0 /* going down */
688#define EXT4_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
689#define EXT4_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
690
691
682#if defined(__KERNEL__) && defined(CONFIG_COMPAT) 692#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
683/* 693/*
684 * ioctl commands in 32 bit emulation 694 * ioctl commands in 32 bit emulation
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index d534399cf607..b383ebf4020c 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -16,6 +16,7 @@
16#include <linux/quotaops.h> 16#include <linux/quotaops.h>
17#include <linux/uuid.h> 17#include <linux/uuid.h>
18#include <linux/uaccess.h> 18#include <linux/uaccess.h>
19#include <linux/delay.h>
19#include "ext4_jbd2.h" 20#include "ext4_jbd2.h"
20#include "ext4.h" 21#include "ext4.h"
21 22
@@ -442,6 +443,52 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
442 return iflags; 443 return iflags;
443} 444}
444 445
446int ext4_goingdown(struct super_block *sb, unsigned long arg)
447{
448 struct ext4_sb_info *sbi = EXT4_SB(sb);
449 __u32 flags;
450
451 if (!capable(CAP_SYS_ADMIN))
452 return -EPERM;
453
454 if (get_user(flags, (__u32 __user *)arg))
455 return -EFAULT;
456
457 if (flags > EXT4_GOING_FLAGS_NOLOGFLUSH)
458 return -EINVAL;
459
460 if (ext4_forced_shutdown(sbi))
461 return 0;
462
463 ext4_msg(sb, KERN_ALERT, "shut down requested (%d)", flags);
464
465 switch (flags) {
466 case EXT4_GOING_FLAGS_DEFAULT:
467 freeze_bdev(sb->s_bdev);
468 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
469 thaw_bdev(sb->s_bdev, sb);
470 break;
471 case EXT4_GOING_FLAGS_LOGFLUSH:
472 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
473 if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
474 (void) ext4_force_commit(sb);
475 jbd2_journal_abort(sbi->s_journal, 0);
476 }
477 break;
478 case EXT4_GOING_FLAGS_NOLOGFLUSH:
479 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
480 if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
481 msleep(100);
482 jbd2_journal_abort(sbi->s_journal, 0);
483 }
484 break;
485 default:
486 return -EINVAL;
487 }
488 clear_opt(sb, DISCARD);
489 return 0;
490}
491
445long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 492long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
446{ 493{
447 struct inode *inode = file_inode(filp); 494 struct inode *inode = file_inode(filp);
@@ -893,6 +940,8 @@ resizefs_out:
893 940
894 return 0; 941 return 0;
895 } 942 }
943 case EXT4_IOC_GOINGDOWN:
944 return ext4_goingdown(sb, arg);
896 default: 945 default:
897 return -ENOTTY; 946 return -ENOTTY;
898 } 947 }
@@ -959,6 +1008,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
959 case EXT4_IOC_SET_ENCRYPTION_POLICY: 1008 case EXT4_IOC_SET_ENCRYPTION_POLICY:
960 case EXT4_IOC_GET_ENCRYPTION_PWSALT: 1009 case EXT4_IOC_GET_ENCRYPTION_PWSALT:
961 case EXT4_IOC_GET_ENCRYPTION_POLICY: 1010 case EXT4_IOC_GET_ENCRYPTION_POLICY:
1011 case EXT4_IOC_GOINGDOWN:
962 break; 1012 break;
963 default: 1013 default:
964 return -ENOIOCTLCMD; 1014 return -ENOIOCTLCMD;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index cfa4ce5a1f80..3db5b6491513 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4821,7 +4821,7 @@ out:
4821 */ 4821 */
4822static int ext4_unfreeze(struct super_block *sb) 4822static int ext4_unfreeze(struct super_block *sb)
4823{ 4823{
4824 if (sb->s_flags & MS_RDONLY) 4824 if ((sb->s_flags & MS_RDONLY) || ext4_forced_shutdown(EXT4_SB(sb)))
4825 return 0; 4825 return 0;
4826 4826
4827 if (EXT4_SB(sb)->s_journal) { 4827 if (EXT4_SB(sb)->s_journal) {