Commit 7643f3fe authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: assign the write hint per stream by default

This reverts commit 930e2607 ("f2fs: remove obsolete whint_mode"), as we
decide to pass write hints to the disk.

Cc: Hyunchul Lee <cheol.lee@lge.com>
Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent b2cf5a1f
......@@ -774,6 +774,35 @@ In order to identify whether the data in the victim segment are valid or not,
F2FS manages a bitmap. Each bit represents the validity of a block, and the
bitmap is composed of a bit stream covering whole blocks in main area.
Write-hint Policy
-----------------
F2FS sets the whint all the time with the below policy.
===================== ======================== ===================
User F2FS Block
===================== ======================== ===================
N/A META WRITE_LIFE_NONE|REQ_META
N/A HOT_NODE WRITE_LIFE_NONE
N/A WARM_NODE WRITE_LIFE_MEDIUM
N/A COLD_NODE WRITE_LIFE_LONG
ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME
extension list " "
-- buffered io
N/A COLD_DATA WRITE_LIFE_EXTREME
N/A HOT_DATA WRITE_LIFE_SHORT
N/A WARM_DATA WRITE_LIFE_NOT_SET
-- 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
===================== ======================== ===================
Fallocate(2) Policy
-------------------
......
......@@ -465,6 +465,8 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
} else {
bio->bi_end_io = f2fs_write_end_io;
bio->bi_private = sbi;
bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi,
fio->type, fio->temp);
}
iostat_alloc_and_bind_ctx(sbi, bio, NULL);
......
......@@ -3722,6 +3722,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
block_t old_addr, block_t new_addr,
unsigned char version, bool recover_curseg,
bool recover_newaddr);
int f2fs_get_segment_temp(int seg_type);
int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type,
......@@ -3745,6 +3746,8 @@ void f2fs_destroy_segment_manager(struct f2fs_sb_info *sbi);
int __init f2fs_create_segment_manager_caches(void);
void f2fs_destroy_segment_manager_caches(void);
int f2fs_rw_hint_to_seg_type(enum rw_hint hint);
enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
enum page_type type, enum temp_type temp);
unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi,
unsigned int segno);
unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
......
......@@ -4685,8 +4685,21 @@ static int f2fs_dio_write_end_io(struct kiocb *iocb, ssize_t size, int error,
return 0;
}
static void f2fs_dio_write_submit_io(const struct iomap_iter *iter,
struct bio *bio, loff_t file_offset)
{
struct inode *inode = iter->inode;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int seg_type = f2fs_rw_hint_to_seg_type(inode->i_write_hint);
enum temp_type temp = f2fs_get_segment_temp(seg_type);
bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, DATA, temp);
submit_bio(bio);
}
static const struct iomap_dio_ops f2fs_iomap_dio_write_ops = {
.end_io = f2fs_dio_write_end_io,
.end_io = f2fs_dio_write_end_io,
.submit_io = f2fs_dio_write_submit_io,
};
static void f2fs_flush_buffered_write(struct address_space *mapping,
......
......@@ -3364,6 +3364,65 @@ int f2fs_rw_hint_to_seg_type(enum rw_hint hint)
}
}
/*
* This returns write hints for each segment type. This hints will be
* passed down to block layer as below by default.
*
* User F2FS Block
* ---- ---- -----
* META WRITE_LIFE_NONE|REQ_META
* HOT_NODE WRITE_LIFE_NONE
* WARM_NODE WRITE_LIFE_MEDIUM
* COLD_NODE WRITE_LIFE_LONG
* ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME
* extension list " "
*
* -- buffered io
* COLD_DATA WRITE_LIFE_EXTREME
* HOT_DATA WRITE_LIFE_SHORT
* WARM_DATA WRITE_LIFE_NOT_SET
*
* -- 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 f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
enum page_type type, enum temp_type temp)
{
switch (type) {
case DATA:
switch (temp) {
case WARM:
return WRITE_LIFE_NOT_SET;
case HOT:
return WRITE_LIFE_SHORT;
case COLD:
return WRITE_LIFE_EXTREME;
default:
return WRITE_LIFE_NONE;
}
case NODE:
switch (temp) {
case WARM:
return WRITE_LIFE_MEDIUM;
case HOT:
return WRITE_LIFE_NONE;
case COLD:
return WRITE_LIFE_LONG;
default:
return WRITE_LIFE_NONE;
}
case META:
return WRITE_LIFE_NONE;
default:
return WRITE_LIFE_NONE;
}
}
static int __get_segment_type_2(struct f2fs_io_info *fio)
{
if (fio->type == DATA)
......@@ -3443,6 +3502,15 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
}
}
int f2fs_get_segment_temp(int seg_type)
{
if (IS_HOT(seg_type))
return HOT;
else if (IS_WARM(seg_type))
return WARM;
return COLD;
}
static int __get_segment_type(struct f2fs_io_info *fio)
{
int type = 0;
......@@ -3461,12 +3529,8 @@ static int __get_segment_type(struct f2fs_io_info *fio)
f2fs_bug_on(fio->sbi, true);
}
if (IS_HOT(type))
fio->temp = HOT;
else if (IS_WARM(type))
fio->temp = WARM;
else
fio->temp = COLD;
fio->temp = f2fs_get_segment_temp(type);
return type;
}
......
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