mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-07 09:55:19 +02:00
f2fs: support .shutdown in f2fs_sops
[ Upstream commitee745e4736
] 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: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Stable-dep-of:c7f114d864
("f2fs: fix to avoid use-after-free in f2fs_stop_gc_thread()") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
783b6ca342
commit
f2971778b2
|
@ -3507,6 +3507,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,
|
||||||
|
|
|
@ -2256,34 +2256,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 = freeze_bdev(sb->s_bdev);
|
ret = freeze_bdev(sb->s_bdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -2317,6 +2296,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);
|
||||||
|
|
||||||
|
@ -2325,10 +2307,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2543,6 +2543,11 @@ restore_opts:
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -3142,6 +3147,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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user