Commit 93cf93f1 authored by Junling Zheng's avatar Junling Zheng Committed by Jaegeuk Kim

f2fs: introduce mount option for fsync mode

Commit "0a007b97"(f2fs: recover directory operations by fsync)
fixed xfstest generic/342 case, but it also increased the written
data and caused the performance degradation. In most cases, there's
no need to do so heavy fsync actually.

So we introduce new mount option "fsync_mode={posix,strict}" to
control the policy of fsync. "fsync_mode=posix" is set by default,
and means that f2fs uses a light fsync, which follows POSIX semantics.
And "fsync_mode=strict" means that it's a heavy fsync, which behaves
in line with xfs, ext4 and btrfs, where generic/342 will pass, but
the performance will regress.
Signed-off-by: default avatarJunling Zheng <zhengjunling@huawei.com>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent eea52882
...@@ -182,6 +182,13 @@ whint_mode=%s Control which write hints are passed down to block ...@@ -182,6 +182,13 @@ whint_mode=%s Control which write hints are passed down to block
passes down hints with its policy. passes down hints with its policy.
alloc_mode=%s Adjust block allocation policy, which supports "reuse" alloc_mode=%s Adjust block allocation policy, which supports "reuse"
and "default". and "default".
fsync_mode=%s Control the policy of fsync. Currently supports "posix"
and "strict". In "posix" mode, which is default, fsync
will follow POSIX semantics and does a light operation
to improve the filesystem performance. In "strict" mode,
fsync will be heavy and behaves in line with xfs, ext4
and btrfs, where xfstest generic/342 will pass, but the
performance will regress.
================================================================================ ================================================================================
DEBUGFS ENTRIES DEBUGFS ENTRIES
......
...@@ -704,6 +704,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, ...@@ -704,6 +704,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
if (F2FS_I_SB(dir)->fsync_mode == FSYNC_MODE_STRICT)
add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO); add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO);
if (f2fs_has_inline_dentry(dir)) if (f2fs_has_inline_dentry(dir))
......
...@@ -1052,6 +1052,11 @@ enum { ...@@ -1052,6 +1052,11 @@ enum {
ALLOC_MODE_REUSE, /* reuse segments as much as possible */ ALLOC_MODE_REUSE, /* reuse segments as much as possible */
}; };
enum fsync_mode {
FSYNC_MODE_POSIX, /* fsync follows posix semantics */
FSYNC_MODE_STRICT, /* fsync behaves in line with ext4 */
};
struct f2fs_sb_info { struct f2fs_sb_info {
struct super_block *sb; /* pointer to VFS super block */ struct super_block *sb; /* pointer to VFS super block */
struct proc_dir_entry *s_proc; /* proc entry */ struct proc_dir_entry *s_proc; /* proc entry */
...@@ -1241,6 +1246,9 @@ struct f2fs_sb_info { ...@@ -1241,6 +1246,9 @@ struct f2fs_sb_info {
/* segment allocation policy */ /* segment allocation policy */
int alloc_mode; int alloc_mode;
/* fsync policy */
int fsync_mode;
}; };
#ifdef CONFIG_F2FS_FAULT_INJECTION #ifdef CONFIG_F2FS_FAULT_INJECTION
......
...@@ -165,7 +165,8 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode) ...@@ -165,7 +165,8 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode)
cp_reason = CP_FASTBOOT_MODE; cp_reason = CP_FASTBOOT_MODE;
else if (sbi->active_logs == 2) else if (sbi->active_logs == 2)
cp_reason = CP_SPEC_LOG_NUM; cp_reason = CP_SPEC_LOG_NUM;
else if (need_dentry_mark(sbi, inode->i_ino) && else if (sbi->fsync_mode == FSYNC_MODE_STRICT &&
need_dentry_mark(sbi, inode->i_ino) &&
exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO)) exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO))
cp_reason = CP_RECOVER_DIR; cp_reason = CP_RECOVER_DIR;
......
...@@ -970,6 +970,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -970,6 +970,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
f2fs_put_page(old_dir_page, 0); f2fs_put_page(old_dir_page, 0);
f2fs_i_links_write(old_dir, false); f2fs_i_links_write(old_dir, false);
} }
if (sbi->fsync_mode == FSYNC_MODE_STRICT)
add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
...@@ -1120,8 +1121,10 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1120,8 +1121,10 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
f2fs_mark_inode_dirty_sync(new_dir, false); f2fs_mark_inode_dirty_sync(new_dir, false);
if (sbi->fsync_mode == FSYNC_MODE_STRICT) {
add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO); add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO);
add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
}
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
......
...@@ -131,6 +131,7 @@ enum { ...@@ -131,6 +131,7 @@ enum {
Opt_jqfmt_vfsv1, Opt_jqfmt_vfsv1,
Opt_whint, Opt_whint,
Opt_alloc, Opt_alloc,
Opt_fsync,
Opt_err, Opt_err,
}; };
...@@ -186,6 +187,7 @@ static match_table_t f2fs_tokens = { ...@@ -186,6 +187,7 @@ static match_table_t f2fs_tokens = {
{Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
{Opt_whint, "whint_mode=%s"}, {Opt_whint, "whint_mode=%s"},
{Opt_alloc, "alloc_mode=%s"}, {Opt_alloc, "alloc_mode=%s"},
{Opt_fsync, "fsync_mode=%s"},
{Opt_err, NULL}, {Opt_err, NULL},
}; };
...@@ -719,6 +721,22 @@ static int parse_options(struct super_block *sb, char *options) ...@@ -719,6 +721,22 @@ static int parse_options(struct super_block *sb, char *options)
} }
kfree(name); kfree(name);
break; break;
case Opt_fsync:
name = match_strdup(&args[0]);
if (!name)
return -ENOMEM;
if (strlen(name) == 5 &&
!strncmp(name, "posix", 5)) {
sbi->fsync_mode = FSYNC_MODE_POSIX;
} else if (strlen(name) == 6 &&
!strncmp(name, "strict", 6)) {
sbi->fsync_mode = FSYNC_MODE_STRICT;
} else {
kfree(name);
return -EINVAL;
}
kfree(name);
break;
default: default:
f2fs_msg(sb, KERN_ERR, f2fs_msg(sb, KERN_ERR,
"Unrecognized mount option \"%s\" or missing value", "Unrecognized mount option \"%s\" or missing value",
...@@ -1287,6 +1305,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) ...@@ -1287,6 +1305,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
seq_printf(seq, ",alloc_mode=%s", "default"); seq_printf(seq, ",alloc_mode=%s", "default");
else if (sbi->alloc_mode == ALLOC_MODE_REUSE) else if (sbi->alloc_mode == ALLOC_MODE_REUSE)
seq_printf(seq, ",alloc_mode=%s", "reuse"); seq_printf(seq, ",alloc_mode=%s", "reuse");
if (sbi->fsync_mode == FSYNC_MODE_POSIX)
seq_printf(seq, ",fsync_mode=%s", "posix");
else if (sbi->fsync_mode == FSYNC_MODE_STRICT)
seq_printf(seq, ",fsync_mode=%s", "strict");
return 0; return 0;
} }
...@@ -1297,6 +1320,7 @@ static void default_options(struct f2fs_sb_info *sbi) ...@@ -1297,6 +1320,7 @@ static void default_options(struct f2fs_sb_info *sbi)
sbi->inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS; sbi->inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
sbi->whint_mode = WHINT_MODE_OFF; sbi->whint_mode = WHINT_MODE_OFF;
sbi->alloc_mode = ALLOC_MODE_DEFAULT; sbi->alloc_mode = ALLOC_MODE_DEFAULT;
sbi->fsync_mode = FSYNC_MODE_POSIX;
sbi->readdir_ra = 1; sbi->readdir_ra = 1;
set_opt(sbi, BG_GC); set_opt(sbi, BG_GC);
...@@ -1340,6 +1364,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1340,6 +1364,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE);
int old_whint_mode = sbi->whint_mode; int old_whint_mode = sbi->whint_mode;
int old_alloc_mode = sbi->alloc_mode; int old_alloc_mode = sbi->alloc_mode;
int old_fsync_mode = sbi->fsync_mode;
int old_inline_xattr_size = sbi->inline_xattr_size; int old_inline_xattr_size = sbi->inline_xattr_size;
block_t old_root_reserved_blocks = sbi->root_reserved_blocks; block_t old_root_reserved_blocks = sbi->root_reserved_blocks;
kuid_t old_resuid = sbi->s_resuid; kuid_t old_resuid = sbi->s_resuid;
...@@ -1500,6 +1525,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1500,6 +1525,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
sbi->root_reserved_blocks = old_root_reserved_blocks; sbi->root_reserved_blocks = old_root_reserved_blocks;
sbi->inline_xattr_size = old_inline_xattr_size; sbi->inline_xattr_size = old_inline_xattr_size;
sbi->alloc_mode = old_alloc_mode; sbi->alloc_mode = old_alloc_mode;
sbi->fsync_mode = old_fsync_mode;
sbi->whint_mode = old_whint_mode; sbi->whint_mode = old_whint_mode;
sbi->mount_opt = org_mount_opt; sbi->mount_opt = org_mount_opt;
sbi->active_logs = active_logs; sbi->active_logs = active_logs;
......
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