diff options
author | Hyunchul Lee <cheol.lee@lge.com> | 2018-01-31 11:36:58 +0900 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2018-03-13 08:05:36 +0900 |
commit | f2e703f9a3caa91e4f3f0a8f5d3fe92dbea05623 (patch) | |
tree | 3d9ea8f32f7a00acc87eb544ddaea8ec4dfef962 | |
parent | 0cdd31953967b25c216ddcb630ec9a6bb8a91371 (diff) | |
download | linux-stable-f2e703f9a3caa91e4f3f0a8f5d3fe92dbea05623.tar.gz linux-stable-f2e703f9a3caa91e4f3f0a8f5d3fe92dbea05623.tar.bz2 linux-stable-f2e703f9a3caa91e4f3f0a8f5d3fe92dbea05623.zip |
f2fs: support passing down write hints to block layer with F2FS policy
Add 'whint_mode=fs-based' mount option. In this mode, F2FS passes
down write hints with its policy.
* whint_mode=fs-based. F2FS passes down hints with its policy.
User F2FS Block
---- ---- -----
META WRITE_LIFE_MEDIUM;
HOT_NODE WRITE_LIFE_NOT_SET
WARM_NODE "
COLD_NODE WRITE_LIFE_NONE
ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME
extension list " "
-- buffered io
WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG
WRITE_LIFE_NONE " "
WRITE_LIFE_MEDIUM " "
WRITE_LIFE_LONG " "
-- direct io
WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET
WRITE_LIFE_NONE " WRITE_LIFE_NONE
WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM
WRITE_LIFE_LONG " WRITE_LIFE_LONG
Many thanks to Chao Yu and Jaegeuk Kim for comments to
implement this patch.
Signed-off-by: Hyunchul Lee <cheol.lee@lge.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 57 | ||||
-rw-r--r-- | fs/f2fs/super.c | 5 |
3 files changed, 54 insertions, 9 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 6c4236d348c6..d57b7dd8f1af 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1040,6 +1040,7 @@ enum { enum { WHINT_MODE_OFF, /* not pass down write hints */ WHINT_MODE_USER, /* try to pass down hints given by users */ + WHINT_MODE_FS, /* pass down hints with F2FS policy */ }; struct f2fs_sb_info { diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index c14d5a12b908..427b75ed1e29 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2489,6 +2489,32 @@ int rw_hint_to_seg_type(enum rw_hint hint) * WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM * WRITE_LIFE_LONG " WRITE_LIFE_LONG * + * 3) whint_mode=fs-based. F2FS passes down hints with its policy. + * + * User F2FS Block + * ---- ---- ----- + * META WRITE_LIFE_MEDIUM; + * HOT_NODE WRITE_LIFE_NOT_SET + * WARM_NODE " + * COLD_NODE WRITE_LIFE_NONE + * ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME + * extension list " " + * + * -- buffered io + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG + * WRITE_LIFE_NONE " " + * WRITE_LIFE_MEDIUM " " + * WRITE_LIFE_LONG " " + * + * -- direct io + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET + * WRITE_LIFE_NONE " WRITE_LIFE_NONE + * WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM + * WRITE_LIFE_LONG " WRITE_LIFE_LONG */ enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi, @@ -2496,20 +2522,33 @@ enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi, { if (sbi->whint_mode == WHINT_MODE_USER) { if (type == DATA) { - switch (temp) { - case COLD: - return WRITE_LIFE_EXTREME; - case HOT: - return WRITE_LIFE_SHORT; - default: + if (temp == WARM) return WRITE_LIFE_NOT_SET; - } + else if (temp == HOT) + return WRITE_LIFE_SHORT; + else if (temp == COLD) + return WRITE_LIFE_EXTREME; } else { return WRITE_LIFE_NOT_SET; } - } else { - return WRITE_LIFE_NOT_SET; + } else if (sbi->whint_mode == WHINT_MODE_FS) { + if (type == DATA) { + if (temp == WARM) + return WRITE_LIFE_LONG; + else if (temp == HOT) + return WRITE_LIFE_SHORT; + else if (temp == COLD) + return WRITE_LIFE_EXTREME; + } else if (type == NODE) { + if (temp == WARM || temp == HOT) + return WRITE_LIFE_NOT_SET; + else if (temp == COLD) + return WRITE_LIFE_NONE; + } else if (type == META) { + return WRITE_LIFE_MEDIUM; + } } + return WRITE_LIFE_NOT_SET; } static int __get_segment_type_2(struct f2fs_io_info *fio) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 28b9d605d20f..2e427a15b37e 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -691,6 +691,9 @@ static int parse_options(struct super_block *sb, char *options) } else if (strlen(name) == 3 && !strncmp(name, "off", 3)) { sbi->whint_mode = WHINT_MODE_OFF; + } else if (strlen(name) == 8 && + !strncmp(name, "fs-based", 8)) { + sbi->whint_mode = WHINT_MODE_FS; } else { kfree(name); return -EINVAL; @@ -1258,6 +1261,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) f2fs_show_quota_options(seq, sbi->sb); if (sbi->whint_mode == WHINT_MODE_USER) seq_printf(seq, ",whint_mode=%s", "user-based"); + else if (sbi->whint_mode == WHINT_MODE_FS) + seq_printf(seq, ",whint_mode=%s", "fs-based"); return 0; } |