Message ID | 20170202225924.19301-4-tytso@mit.edu |
---|---|
State | Superseded, archived |
Headers | show |
On Thu, Feb 02, 2017 at 05:59:24PM -0500, Theodore Ts'o wrote: > 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> > --- > fs/ext4/ext4.h | 10 ++++++++++ > fs/ext4/ioctl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ > fs/ext4/super.c | 2 +- > 3 files changed, 53 insertions(+), 1 deletion(-) > > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > index 94064b7ce16c..eae92f1a52e1 100644 > --- a/fs/ext4/ext4.h > +++ b/fs/ext4/ext4.h > @@ -679,6 +679,16 @@ struct fsxattr { > #define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR > #define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR > > +#define EXT4_IOC_GOiNGDOWN _IOR ('X', 125, __u32) Lowercase 'i'? ISTR Dave asking if we could rename it IOC_SHUTDOWN way back when f2fs was trying to implement it. > + > +/* > + * Flags for going down operation > + */ > +#define EXT4_GOING_FLAGS_DEFAULT 0x0 /* going down */ > +#define EXT4_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */ > +#define EXT4_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */ > + > + > #if defined(__KERNEL__) && defined(CONFIG_COMPAT) > /* > * ioctl commands in 32 bit emulation > diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c > index d534399cf607..6d5443cf4a47 100644 > --- a/fs/ext4/ioctl.c > +++ b/fs/ext4/ioctl.c > @@ -442,6 +442,45 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags) > return iflags; > } > > +int ext4_goingdown(struct super_block *sb, unsigned long arg) > +{ > + struct ext4_sb_info *sbi = EXT4_SB(sb); > + __u32 flags; > + > + if (!capable(CAP_SYS_ADMIN)) > + return -EPERM; > + > + if (get_user(flags, (__u32 __user *)arg)) > + return -EFAULT; > + > + if (flags > EXT4_GOING_FLAGS_NOLOGFLUSH) > + return -EINVAL; > + > + if (ext4_forced_shutdown(sbi)) > + return 0; > + > + switch (flags) { > + case EXT4_GOING_FLAGS_DEFAULT: > + freeze_bdev(sb->s_bdev); > + set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); > + thaw_bdev(sb->s_bdev, sb); > + break; > + case EXT4_GOING_FLAGS_LOGFLUSH: > + if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) > + (void) ext4_force_commit(sb); > + /* fall through */ > + case EXT4_GOING_FLAGS_NOLOGFLUSH: > + if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) > + (void) jbd2_journal_destroy(sbi->s_journal); > + sbi->s_journal = NULL; > + set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); > + break; > + default: > + return -EINVAL; > + } > + return 0; /me wonders if mount -o errors=shutdown follows from this? :) (Something a little less drastic than errors=panic that stops everything in its tracks.) --D > +} > + > long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > { > struct inode *inode = file_inode(filp); > @@ -893,6 +932,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > > return 0; > } > + case EXT4_IOC_GOiNGDOWN: > + return ext4_goingdown(sb, arg); > default: > return -ENOTTY; > } > @@ -959,6 +1000,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > case EXT4_IOC_SET_ENCRYPTION_POLICY: > case EXT4_IOC_GET_ENCRYPTION_PWSALT: > case EXT4_IOC_GET_ENCRYPTION_POLICY: > + case EXT4_IOC_GOiNGDOWN: > break; > default: > return -ENOIOCTLCMD; > diff --git a/fs/ext4/super.c b/fs/ext4/super.c > index 829e4a7b59e4..8db181c4dad6 100644 > --- a/fs/ext4/super.c > +++ b/fs/ext4/super.c > @@ -4797,7 +4797,7 @@ static int ext4_freeze(struct super_block *sb) > */ > static int ext4_unfreeze(struct super_block *sb) > { > - if (sb->s_flags & MS_RDONLY) > + if ((sb->s_flags & MS_RDONLY) || ext4_forced_shutdown(EXT4_SB(sb))) > return 0; > > if (EXT4_SB(sb)->s_journal) { > -- > 2.11.0.rc0.7.gbe5a750 >
On Thu, Feb 02, 2017 at 04:02:04PM -0800, Darrick J. Wong wrote: > > > > +#define EXT4_IOC_GOiNGDOWN _IOR ('X', 125, __u32) > > Lowercase 'i'? Yeah, oops. Already fixed. > ISTR Dave asking if we could rename it IOC_SHUTDOWN way back when f2fs > was trying to implement it. Yeah, I decided to evade the whole discussion about which names should land in include/uapi/fs.h. (e.g., xxx_GOING_FLAGS_LOGFLUSH vs xxx_GOING_FLAGS_METAFLUsh, etc.) Once we have names that everyone is happy with, it'll be simple enough to do the rename the identifiers. > > /me wonders if mount -o errors=shutdown follows from this? :) > > (Something a little less drastic than errors=panic that stops everything > in its tracks.) Yeah, I was thinking about that. We have errors=readonly already, which is actually not _that_ different from errors=shutdown. (I noticed for example that xfs doesn't have a shutdown check in xfs_vm_readpage and and xfs_vm_readpages.) One of the things we probably should do is make clear what are the semantics with FS_IOC_SHUTDOWN. For example, should readpages() return an error on a shutdown file system, or not? And as I've observed already, there are a number of tests in xfstsests that are enabled when the fs supports shutdown that are very specific to how delayed allocation and writes are handled. How much this needs to be fundamental to the shutdown API? A lot of this depends on which applications would actually be using shutdown, and whether they care about what happens with a write followed by truncate followed shutdown. - Ted
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 94064b7ce16c..eae92f1a52e1 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -679,6 +679,16 @@ struct fsxattr { #define EXT4_IOC_FSGETXATTR FS_IOC_FSGETXATTR #define EXT4_IOC_FSSETXATTR FS_IOC_FSSETXATTR +#define EXT4_IOC_GOiNGDOWN _IOR ('X', 125, __u32) + +/* + * Flags for going down operation + */ +#define EXT4_GOING_FLAGS_DEFAULT 0x0 /* going down */ +#define EXT4_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */ +#define EXT4_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */ + + #if defined(__KERNEL__) && defined(CONFIG_COMPAT) /* * ioctl commands in 32 bit emulation diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index d534399cf607..6d5443cf4a47 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -442,6 +442,45 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags) return iflags; } +int ext4_goingdown(struct super_block *sb, unsigned long arg) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + __u32 flags; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(flags, (__u32 __user *)arg)) + return -EFAULT; + + if (flags > EXT4_GOING_FLAGS_NOLOGFLUSH) + return -EINVAL; + + if (ext4_forced_shutdown(sbi)) + return 0; + + switch (flags) { + case EXT4_GOING_FLAGS_DEFAULT: + freeze_bdev(sb->s_bdev); + set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); + thaw_bdev(sb->s_bdev, sb); + break; + case EXT4_GOING_FLAGS_LOGFLUSH: + if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) + (void) ext4_force_commit(sb); + /* fall through */ + case EXT4_GOING_FLAGS_NOLOGFLUSH: + if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) + (void) jbd2_journal_destroy(sbi->s_journal); + sbi->s_journal = NULL; + set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); + break; + default: + return -EINVAL; + } + return 0; +} + long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -893,6 +932,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return 0; } + case EXT4_IOC_GOiNGDOWN: + return ext4_goingdown(sb, arg); default: return -ENOTTY; } @@ -959,6 +1000,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EXT4_IOC_SET_ENCRYPTION_POLICY: case EXT4_IOC_GET_ENCRYPTION_PWSALT: case EXT4_IOC_GET_ENCRYPTION_POLICY: + case EXT4_IOC_GOiNGDOWN: break; default: return -ENOIOCTLCMD; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 829e4a7b59e4..8db181c4dad6 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4797,7 +4797,7 @@ static int ext4_freeze(struct super_block *sb) */ static int ext4_unfreeze(struct super_block *sb) { - if (sb->s_flags & MS_RDONLY) + if ((sb->s_flags & MS_RDONLY) || ext4_forced_shutdown(EXT4_SB(sb))) return 0; if (EXT4_SB(sb)->s_journal) {
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> --- fs/ext4/ext4.h | 10 ++++++++++ fs/ext4/ioctl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ fs/ext4/super.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-)