Commit ee745e47 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

f2fs: support .shutdown in f2fs_sops

Support .shutdown callback in f2fs_sops, then, it can be called to
shut down the file system when underlying block device is marked dead.
Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 928a87ef
...@@ -3497,6 +3497,8 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, ...@@ -3497,6 +3497,8 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr); struct iattr *attr);
int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end); int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end);
void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count); void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count);
int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
bool readonly);
int f2fs_precache_extents(struct inode *inode); int f2fs_precache_extents(struct inode *inode);
int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa); int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
int f2fs_fileattr_set(struct mnt_idmap *idmap, int f2fs_fileattr_set(struct mnt_idmap *idmap,
......
...@@ -2224,34 +2224,13 @@ static int f2fs_ioc_abort_atomic_write(struct file *filp) ...@@ -2224,34 +2224,13 @@ static int f2fs_ioc_abort_atomic_write(struct file *filp)
return ret; return ret;
} }
static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
bool readonly)
{ {
struct inode *inode = file_inode(filp);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct super_block *sb = sbi->sb; struct super_block *sb = sbi->sb;
__u32 in;
int ret = 0; int ret = 0;
if (!capable(CAP_SYS_ADMIN)) switch (flag) {
return -EPERM;
if (get_user(in, (__u32 __user *)arg))
return -EFAULT;
if (in != F2FS_GOING_DOWN_FULLSYNC) {
ret = mnt_want_write_file(filp);
if (ret) {
if (ret == -EROFS) {
ret = 0;
f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_SHUTDOWN);
trace_f2fs_shutdown(sbi, in, ret);
}
return ret;
}
}
switch (in) {
case F2FS_GOING_DOWN_FULLSYNC: case F2FS_GOING_DOWN_FULLSYNC:
ret = bdev_freeze(sb->s_bdev); ret = bdev_freeze(sb->s_bdev);
if (ret) if (ret)
...@@ -2290,6 +2269,9 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -2290,6 +2269,9 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
goto out; goto out;
} }
if (readonly)
goto out;
f2fs_stop_gc_thread(sbi); f2fs_stop_gc_thread(sbi);
f2fs_stop_discard_thread(sbi); f2fs_stop_discard_thread(sbi);
...@@ -2298,10 +2280,44 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -2298,10 +2280,44 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
f2fs_update_time(sbi, REQ_TIME); f2fs_update_time(sbi, REQ_TIME);
out: out:
if (in != F2FS_GOING_DOWN_FULLSYNC)
mnt_drop_write_file(filp);
trace_f2fs_shutdown(sbi, in, ret); trace_f2fs_shutdown(sbi, flag, ret);
return ret;
}
static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
__u32 in;
int ret;
bool need_drop = false, readonly = false;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (get_user(in, (__u32 __user *)arg))
return -EFAULT;
if (in != F2FS_GOING_DOWN_FULLSYNC) {
ret = mnt_want_write_file(filp);
if (ret) {
if (ret != -EROFS)
return ret;
/* fallback to nosync shutdown for readonly fs */
in = F2FS_GOING_DOWN_NOSYNC;
readonly = true;
} else {
need_drop = true;
}
}
ret = f2fs_do_shutdown(sbi, in, readonly);
if (need_drop)
mnt_drop_write_file(filp);
return ret; return ret;
} }
......
...@@ -2547,6 +2547,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) ...@@ -2547,6 +2547,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
return err; return err;
} }
static void f2fs_shutdown(struct super_block *sb)
{
f2fs_do_shutdown(F2FS_SB(sb), F2FS_GOING_DOWN_NOSYNC, false);
}
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
static bool f2fs_need_recovery(struct f2fs_sb_info *sbi) static bool f2fs_need_recovery(struct f2fs_sb_info *sbi)
{ {
...@@ -3146,6 +3151,7 @@ static const struct super_operations f2fs_sops = { ...@@ -3146,6 +3151,7 @@ static const struct super_operations f2fs_sops = {
.unfreeze_fs = f2fs_unfreeze, .unfreeze_fs = f2fs_unfreeze,
.statfs = f2fs_statfs, .statfs = f2fs_statfs,
.remount_fs = f2fs_remount, .remount_fs = f2fs_remount,
.shutdown = f2fs_shutdown,
}; };
#ifdef CONFIG_FS_ENCRYPTION #ifdef CONFIG_FS_ENCRYPTION
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment