* Re: [PATCH] f2fs: split bio cache
@ 2017-05-09 1:49 ` Chao Yu
0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-09 1:49 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel
Hi Jaegeuk,
On 2017/5/9 5:23, Jaegeuk Kim wrote:
> Hi Chao,
>
> I can't see a strong reason to split meta from data/node and rename the existing
> function names. Instead, how about keeping the existing one while adding some
> page types to deal with log types?
Hmm.. before write this patch, I have thought about this implementation which
adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
different temperature log-header being with independent bio cache, io lock, and
io list, eliminating interaction of different temperature IOs, also expanding
f2fs' scalability when adding more log-headers. If we don't split meta from
data/node, it's a little bit hard to approach this. What do you think?
Thanks,
>
> Thanks,
>
> On 05/08, Chao Yu wrote:
>> Split DATA/NODE type bio cache according to different temperature,
>> so write IOs with the same temperature can be merged in corresponding
>> bio cache as much as possible, otherwise, different temperature write
>> IOs submitting into one bio cache will always cause split of bio.
>>
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>> fs/f2fs/checkpoint.c | 10 +++----
>> fs/f2fs/data.c | 78 ++++++++++++++++++++++++++++++++--------------------
>> fs/f2fs/f2fs.h | 15 ++++++----
>> fs/f2fs/gc.c | 5 ++--
>> fs/f2fs/node.c | 8 +++---
>> fs/f2fs/segment.c | 14 +++++++---
>> fs/f2fs/super.c | 16 ++++++-----
>> 7 files changed, 89 insertions(+), 57 deletions(-)
>>
>> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
>> index ea9c317b5916..2a475e83a092 100644
>> --- a/fs/f2fs/checkpoint.c
>> +++ b/fs/f2fs/checkpoint.c
>> @@ -212,7 +212,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
>> f2fs_put_page(page, 0);
>> }
>> out:
>> - f2fs_submit_merged_bio(sbi, META, READ);
>> + f2fs_submit_meta_bio(sbi, META, READ);
>> blk_finish_plug(&plug);
>> return blkno - start;
>> }
>> @@ -249,13 +249,13 @@ static int f2fs_write_meta_page(struct page *page,
>> dec_page_count(sbi, F2FS_DIRTY_META);
>>
>> if (wbc->for_reclaim)
>> - f2fs_submit_merged_bio_cond(sbi, page->mapping->host,
>> + f2fs_submit_meta_bio_cond(sbi, page->mapping->host,
>> 0, page->index, META, WRITE);
>>
>> unlock_page(page);
>>
>> if (unlikely(f2fs_cp_error(sbi)))
>> - f2fs_submit_merged_bio(sbi, META, WRITE);
>> + f2fs_submit_meta_bio(sbi, META, WRITE);
>>
>> return 0;
>>
>> @@ -358,7 +358,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
>> }
>> stop:
>> if (nwritten)
>> - f2fs_submit_merged_bio(sbi, type, WRITE);
>> + f2fs_submit_meta_bio(sbi, type, WRITE);
>>
>> blk_finish_plug(&plug);
>>
>> @@ -906,7 +906,7 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
>> * We should submit bio, since it exists several
>> * wribacking dentry pages in the freeing inode.
>> */
>> - f2fs_submit_merged_bio(sbi, DATA, WRITE);
>> + f2fs_submit_log_bio(sbi, DATA, WRITE);
>> cond_resched();
>> }
>> goto retry;
>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>> index 7c0f6bdf817d..37d0896021c7 100644
>> --- a/fs/f2fs/data.c
>> +++ b/fs/f2fs/data.c
>> @@ -278,28 +278,27 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
>> return false;
>> }
>>
>> -static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
>> - nid_t ino, pgoff_t idx, enum page_type type)
>> +static struct f2fs_bio_info *__get_bio_info(struct f2fs_sb_info *sbi, int rw,
>> + enum page_type type, int seg_type)
>> {
>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>> - bool ret;
>> + struct f2fs_bio_info *io;
>>
>> - down_read(&io->io_rwsem);
>> - ret = __has_merged_page(io, inode, ino, idx);
>> - up_read(&io->io_rwsem);
>> - return ret;
>> + if (btype == META) {
>> + int io_type = is_read_io(rw) ? READ : WRITE;
>> +
>> + io = &sbi->meta_io[io_type];
>> + } else {
>> + io = &sbi->log_io[seg_type];
>> + }
>> +
>> + return io;
>> }
>>
>> -static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
>> +static void __f2fs_submit_merged_bio(struct f2fs_bio_info *io,
>> struct inode *inode, nid_t ino, pgoff_t idx,
>> - enum page_type type, int rw)
>> + enum page_type type)
>> {
>> - enum page_type btype = PAGE_TYPE_OF_BIO(type);
>> - struct f2fs_bio_info *io;
>> -
>> - io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype];
>> -
>> down_write(&io->io_rwsem);
>>
>> if (!__has_merged_page(io, inode, ino, idx))
>> @@ -310,7 +309,7 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
>> io->fio.type = META_FLUSH;
>> io->fio.op = REQ_OP_WRITE;
>> io->fio.op_flags = REQ_META | REQ_PRIO | REQ_SYNC;
>> - if (!test_opt(sbi, NOBARRIER))
>> + if (!test_opt(io->sbi, NOBARRIER))
>> io->fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
>> }
>> __submit_merged_bio(io);
>> @@ -318,25 +317,45 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
>> up_write(&io->io_rwsem);
>> }
>>
>> -void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
>> - int rw)
>> +void f2fs_submit_log_bio_cond(struct f2fs_sb_info *sbi,
>> + struct inode *inode, nid_t ino, pgoff_t idx,
>> + enum page_type type, int rw)
>> +{
>> + bool is_data = (type == DATA);
>> + int i = is_data ? CURSEG_HOT_DATA : CURSEG_HOT_NODE;
>> + int max = is_data ? CURSEG_COLD_DATA : CURSEG_COLD_NODE;
>> +
>> + for (; i <= max; i++)
>> + __f2fs_submit_merged_bio(&sbi->log_io[i],
>> + inode, ino, idx, type);
>> +}
>> +
>> +void f2fs_submit_log_bio(struct f2fs_sb_info *sbi,
>> + enum page_type type, int rw)
>> {
>> - __f2fs_submit_merged_bio(sbi, NULL, 0, 0, type, rw);
>> + f2fs_submit_log_bio_cond(sbi, NULL, 0, 0, type, rw);
>> }
>>
>> -void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi,
>> +void f2fs_submit_meta_bio_cond(struct f2fs_sb_info *sbi,
>> struct inode *inode, nid_t ino, pgoff_t idx,
>> enum page_type type, int rw)
>> {
>> - if (has_merged_page(sbi, inode, ino, idx, type))
>> - __f2fs_submit_merged_bio(sbi, inode, ino, idx, type, rw);
>> + int io_type = is_read_io(rw) ? READ : WRITE;
>> +
>> + __f2fs_submit_merged_bio(&sbi->meta_io[io_type], inode, ino, idx, type);
>> +}
>> +
>> +void f2fs_submit_meta_bio(struct f2fs_sb_info *sbi,
>> + enum page_type type, int rw)
>> +{
>> + f2fs_submit_meta_bio_cond(sbi, NULL, 0, 0, type, rw);
>> }
>>
>> void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi)
>> {
>> - f2fs_submit_merged_bio(sbi, DATA, WRITE);
>> - f2fs_submit_merged_bio(sbi, NODE, WRITE);
>> - f2fs_submit_merged_bio(sbi, META, WRITE);
>> + f2fs_submit_log_bio(sbi, DATA, WRITE);
>> + f2fs_submit_log_bio(sbi, NODE, WRITE);
>> + f2fs_submit_meta_bio(sbi, META, WRITE);
>> }
>>
>> /*
>> @@ -371,13 +390,12 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
>> int f2fs_submit_page_mbio(struct f2fs_io_info *fio)
>> {
>> struct f2fs_sb_info *sbi = fio->sbi;
>> - enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
>> struct f2fs_bio_info *io;
>> bool is_read = is_read_io(fio->op);
>> struct page *bio_page;
>> int err = 0;
>>
>> - io = is_read ? &sbi->read_io : &sbi->write_io[btype];
>> + io = __get_bio_info(sbi, fio->op, fio->type, fio->seg_type);
>>
>> if (fio->old_blkaddr != NEW_ADDR)
>> verify_block_addr(sbi, fio->old_blkaddr);
>> @@ -1513,7 +1531,7 @@ static int __write_data_page(struct page *page, bool *submitted,
>> ClearPageUptodate(page);
>>
>> if (wbc->for_reclaim) {
>> - f2fs_submit_merged_bio_cond(sbi, inode, 0, page->index,
>> + f2fs_submit_log_bio_cond(sbi, inode, 0, page->index,
>> DATA, WRITE);
>> clear_inode_flag(inode, FI_HOT_DATA);
>> remove_dirty_inode(inode);
>> @@ -1525,7 +1543,7 @@ static int __write_data_page(struct page *page, bool *submitted,
>> f2fs_balance_fs(sbi, need_balance_fs);
>>
>> if (unlikely(f2fs_cp_error(sbi))) {
>> - f2fs_submit_merged_bio(sbi, DATA, WRITE);
>> + f2fs_submit_log_bio(sbi, DATA, WRITE);
>> submitted = NULL;
>> }
>>
>> @@ -1684,7 +1702,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
>> mapping->writeback_index = done_index;
>>
>> if (last_idx != ULONG_MAX)
>> - f2fs_submit_merged_bio_cond(F2FS_M_SB(mapping), mapping->host,
>> + f2fs_submit_log_bio_cond(F2FS_M_SB(mapping), mapping->host,
>> 0, last_idx, DATA, WRITE);
>>
>> return ret;
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index e26999a74522..4ab42749fd5f 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -795,6 +795,7 @@ enum page_type {
>> struct f2fs_io_info {
>> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
>> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
>> + int seg_type; /* indicate current segment type */
>> int op; /* contains REQ_OP_ */
>> int op_flags; /* req_flag_bits */
>> block_t new_blkaddr; /* new block address to be written */
>> @@ -879,8 +880,8 @@ struct f2fs_sb_info {
>> struct f2fs_sm_info *sm_info; /* segment manager */
>>
>> /* for bio operations */
>> - struct f2fs_bio_info read_io; /* for read bios */
>> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
>> + struct f2fs_bio_info meta_io[2]; /* for meta bios */
>> + struct f2fs_bio_info log_io[NR_CURSEG_TYPE]; /* for log bios */
>> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
>> int write_io_size_bits; /* Write IO size bits */
>> mempool_t *write_io_dummy; /* Dummy pages */
>> @@ -2325,11 +2326,15 @@ void destroy_checkpoint_caches(void);
>> /*
>> * data.c
>> */
>> -void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
>> - int rw);
>> -void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi,
>> +void f2fs_submit_log_bio_cond(struct f2fs_sb_info *sbi,
>> struct inode *inode, nid_t ino, pgoff_t idx,
>> enum page_type type, int rw);
>> +void f2fs_submit_log_bio(struct f2fs_sb_info *sbi, enum page_type type, int rw);
>> +void f2fs_submit_meta_bio_cond(struct f2fs_sb_info *sbi,
>> + struct inode *inode, nid_t ino, pgoff_t idx,
>> + enum page_type type, int rw);
>> +void f2fs_submit_meta_bio(struct f2fs_sb_info *sbi,
>> + enum page_type type, int rw);
>> void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi);
>> int f2fs_submit_page_bio(struct f2fs_io_info *fio);
>> int f2fs_submit_page_mbio(struct f2fs_io_info *fio);
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 026522107ca3..8b267ca30926 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
>> struct f2fs_io_info fio = {
>> .sbi = F2FS_I_SB(inode),
>> .type = DATA,
>> + .seg_type = CURSEG_COLD_DATA,
>> .op = REQ_OP_READ,
>> .op_flags = 0,
>> .encrypted_page = NULL,
>> @@ -632,7 +633,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
>> fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
>>
>> allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
>> - &sum, CURSEG_COLD_DATA);
>> + &sum, fio.seg_type);
>>
>> fio.encrypted_page = pagecache_get_page(META_MAPPING(fio.sbi), newaddr,
>> FGP_LOCK | FGP_CREAT, GFP_NOFS);
>> @@ -936,7 +937,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>> }
>>
>> if (gc_type == FG_GC)
>> - f2fs_submit_merged_bio(sbi,
>> + f2fs_submit_log_bio(sbi,
>> (type == SUM_TYPE_NODE) ? NODE : DATA, WRITE);
>>
>> blk_finish_plug(&plug);
>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>> index 98351a4a4da3..28f6d1723327 100644
>> --- a/fs/f2fs/node.c
>> +++ b/fs/f2fs/node.c
>> @@ -1373,7 +1373,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
>> up_read(&sbi->node_write);
>>
>> if (wbc->for_reclaim) {
>> - f2fs_submit_merged_bio_cond(sbi, page->mapping->host, 0,
>> + f2fs_submit_log_bio_cond(sbi, page->mapping->host, 0,
>> page->index, NODE, WRITE);
>> submitted = NULL;
>> }
>> @@ -1381,7 +1381,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
>> unlock_page(page);
>>
>> if (unlikely(f2fs_cp_error(sbi))) {
>> - f2fs_submit_merged_bio(sbi, NODE, WRITE);
>> + f2fs_submit_log_bio(sbi, NODE, WRITE);
>> submitted = NULL;
>> }
>> if (submitted)
>> @@ -1518,7 +1518,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
>> }
>> out:
>> if (last_idx != ULONG_MAX)
>> - f2fs_submit_merged_bio_cond(sbi, NULL, ino, last_idx,
>> + f2fs_submit_log_bio_cond(sbi, NULL, ino, last_idx,
>> NODE, WRITE);
>> return ret ? -EIO: 0;
>> }
>> @@ -1625,7 +1625,7 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc)
>> }
>> out:
>> if (nwritten)
>> - f2fs_submit_merged_bio(sbi, NODE, WRITE);
>> + f2fs_submit_log_bio(sbi, NODE, WRITE);
>> return ret;
>> }
>>
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index b084b3a8f2c7..cdf7d61ac213 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -328,7 +328,7 @@ static int __commit_inmem_pages(struct inode *inode,
>> }
>>
>> if (last_idx != ULONG_MAX)
>> - f2fs_submit_merged_bio_cond(sbi, inode, 0, last_idx,
>> + f2fs_submit_log_bio_cond(sbi, inode, 0, last_idx,
>> DATA, WRITE);
>>
>> if (!err)
>> @@ -2141,14 +2141,15 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>>
>> static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
>> {
>> - int type = __get_segment_type(fio->page, fio->type);
>> int err;
>>
>> + fio->seg_type = __get_segment_type(fio->page, fio->type);
>> +
>> if (fio->type == NODE || fio->type == DATA)
>> mutex_lock(&fio->sbi->wio_mutex[fio->type]);
>> reallocate:
>> allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
>> - &fio->new_blkaddr, sum, type);
>> + &fio->new_blkaddr, sum, fio->seg_type);
>>
>> /* writeout dirty page into bdev */
>> err = f2fs_submit_page_mbio(fio);
>> @@ -2297,8 +2298,13 @@ void f2fs_wait_on_page_writeback(struct page *page,
>> if (PageWriteback(page)) {
>> struct f2fs_sb_info *sbi = F2FS_P_SB(page);
>>
>> - f2fs_submit_merged_bio_cond(sbi, page->mapping->host,
>> + if (type == META)
>> + f2fs_submit_meta_bio_cond(sbi, page->mapping->host,
>> + 0, page->index, type, WRITE);
>> + else
>> + f2fs_submit_log_bio_cond(sbi, page->mapping->host,
>> 0, page->index, type, WRITE);
>> +
>> if (ordered)
>> wait_on_page_writeback(page);
>> else
>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>> index 83355ec4a92c..fed25ca609e4 100644
>> --- a/fs/f2fs/super.c
>> +++ b/fs/f2fs/super.c
>> @@ -1950,13 +1950,15 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>> set_sbi_flag(sbi, SBI_POR_DOING);
>> spin_lock_init(&sbi->stat_lock);
>>
>> - init_rwsem(&sbi->read_io.io_rwsem);
>> - sbi->read_io.sbi = sbi;
>> - sbi->read_io.bio = NULL;
>> - for (i = 0; i < NR_PAGE_TYPE; i++) {
>> - init_rwsem(&sbi->write_io[i].io_rwsem);
>> - sbi->write_io[i].sbi = sbi;
>> - sbi->write_io[i].bio = NULL;
>> + for (i = 0; i < 2; i++) {
>> + init_rwsem(&sbi->meta_io[i].io_rwsem);
>> + sbi->meta_io[i].sbi = sbi;
>> + sbi->meta_io[i].bio = NULL;
>> + }
>> + for (i = 0; i < NR_CURSEG_TYPE; i++) {
>> + init_rwsem(&sbi->log_io[i].io_rwsem);
>> + sbi->log_io[i].sbi = sbi;
>> + sbi->log_io[i].bio = NULL;
>> }
>>
>> init_rwsem(&sbi->cp_rwsem);
>> --
>> 2.12.2.510.ge1104a5ee539
>
> .
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
2017-05-09 1:49 ` Chao Yu
@ 2017-05-10 3:19 ` Chao Yu
-1 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-10 3:19 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel, chao
On 2017/5/9 9:49, Chao Yu wrote:
> Hi Jaegeuk,
>
> On 2017/5/9 5:23, Jaegeuk Kim wrote:
>> Hi Chao,
>>
>> I can't see a strong reason to split meta from data/node and rename the existing
>> function names. Instead, how about keeping the existing one while adding some
>> page types to deal with log types?
>
> Hmm.. before write this patch, I have thought about this implementation which
> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> different temperature log-header being with independent bio cache, io lock, and
> io list, eliminating interaction of different temperature IOs, also expanding
> f2fs' scalability when adding more log-headers. If we don't split meta from
> data/node, it's a little bit hard to approach this. What do you think?
Or like this?
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index ea9c317b5916..61191df47a09 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -159,6 +159,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
struct f2fs_io_info fio = {
.sbi = sbi,
.type = META,
+ .btype = META,
.op = REQ_OP_READ,
.op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD,
.encrypted_page = NULL,
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 7c0f6bdf817d..13c351e873d6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -182,16 +182,17 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
}
static inline void __submit_bio(struct f2fs_sb_info *sbi,
- struct bio *bio, enum page_type type)
+ struct bio *bio, enum page_type btype)
{
if (!is_read_io(bio_op(bio))) {
unsigned int start;
if (f2fs_sb_mounted_blkzoned(sbi->sb) &&
- current->plug && (type == DATA || type == NODE))
+ current->plug &&
+ (btype == DATA || btype == NODE || btype <= COLD_NODE))
blk_finish_plug(current->plug);
- if (type != DATA && type != NODE)
+ if (btype > COLD_NODE && btype != DATA && btype != NODE)
goto submit_io;
start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS;
@@ -217,14 +218,14 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
* In the NODE case, we lose next block address chain. So, we
* need to do checkpoint in f2fs_sync_file.
*/
- if (type == NODE)
+ if (btype == DATA || btype == NODE || btype <= COLD_NODE)
set_sbi_flag(sbi, SBI_NEED_CP);
}
submit_io:
if (is_read_io(bio_op(bio)))
- trace_f2fs_submit_read_bio(sbi->sb, type, bio);
+ trace_f2fs_submit_read_bio(sbi->sb, btype, bio);
else
- trace_f2fs_submit_write_bio(sbi->sb, type, bio);
+ trace_f2fs_submit_write_bio(sbi->sb, btype, bio);
submit_bio(bio);
}
@@ -238,11 +239,11 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
if (is_read_io(fio->op))
- trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio);
+ trace_f2fs_prepare_read_bio(io->sbi->sb, fio->btype, io->bio);
else
- trace_f2fs_prepare_write_bio(io->sbi->sb, fio->type, io->bio);
+ trace_f2fs_prepare_write_bio(io->sbi->sb, fio->btype, io->bio);
- __submit_bio(io->sbi, io->bio, fio->type);
+ __submit_bio(io->sbi, io->bio, fio->btype);
io->bio = NULL;
}
@@ -279,12 +280,14 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
}
static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
- nid_t ino, pgoff_t idx, enum page_type type)
+ nid_t ino, pgoff_t idx, enum page_type type, int rw)
{
enum page_type btype = PAGE_TYPE_OF_BIO(type);
- struct f2fs_bio_info *io = &sbi->write_io[btype];
+ struct f2fs_bio_info *io;
bool ret;
+ io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype];
+
down_read(&io->io_rwsem);
ret = __has_merged_page(io, inode, ino, idx);
up_read(&io->io_rwsem);
@@ -318,18 +321,34 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
up_write(&io->io_rwsem);
}
-void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
- int rw)
-{
- __f2fs_submit_merged_bio(sbi, NULL, 0, 0, type, rw);
-}
-
void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi,
struct inode *inode, nid_t ino, pgoff_t idx,
enum page_type type, int rw)
{
- if (has_merged_page(sbi, inode, ino, idx, type))
- __f2fs_submit_merged_bio(sbi, inode, ino, idx, type, rw);
+ int i;
+
+ if (type == DATA) {
+ for (i = HOT_DATA; i <= COLD_DATA; i++) {
+ if (has_merged_page(sbi, inode, ino, idx, i, rw))
+ __f2fs_submit_merged_bio(sbi, inode, ino, idx,
+ i, rw);
+ }
+ } else if (type == NODE) {
+ for (i = HOT_NODE; i <= COLD_NODE; i++) {
+ if (has_merged_page(sbi, inode, ino, idx, i, rw))
+ __f2fs_submit_merged_bio(sbi, inode, ino, idx,
+ i, rw);
+ }
+ } else {
+ if (has_merged_page(sbi, inode, ino, idx, type, rw))
+ __f2fs_submit_merged_bio(sbi, inode, ino, idx, type, rw);
+ }
+}
+
+void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
+ int rw)
+{
+ f2fs_submit_merged_bio_cond(sbi, NULL, 0, 0, type, rw);
}
void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi)
@@ -371,7 +390,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
int f2fs_submit_page_mbio(struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = fio->sbi;
- enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
+ enum page_type btype = PAGE_TYPE_OF_BIO(fio->btype);
struct f2fs_bio_info *io;
bool is_read = is_read_io(fio->op);
struct page *bio_page;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index e26999a74522..177bccfad9ff 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -779,10 +779,16 @@ enum count_type {
*/
#define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type))
enum page_type {
- DATA,
- NODE,
+ HOT_DATA, /* CURSEG_HOT_DATA */
+ WARM_DATA, /* CURSEG_WARM_DATA */
+ COLD_DATA, /* CURSEG_COLD_DATA */
+ HOT_NODE, /* CURSEG_HOT_NODE */
+ WARM_NODE, /* CURSEG_WARM_NODE */
+ COLD_NODE, /* CURSEG_COLD_NODE */
META,
NR_PAGE_TYPE,
+ DATA,
+ NODE,
META_FLUSH,
INMEM, /* the below types are used by tracepoints only. */
INMEM_DROP,
@@ -795,6 +801,7 @@ enum page_type {
struct f2fs_io_info {
struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
+ int btype; /* segment type and meta type */
int op; /* contains REQ_OP_ */
int op_flags; /* req_flag_bits */
block_t new_blkaddr; /* new block address to be written */
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 026522107ca3..94a4a7ab141a 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
.type = DATA,
+ .btype = CURSEG_COLD_DATA,
.op = REQ_OP_READ,
.op_flags = 0,
.encrypted_page = NULL,
@@ -632,7 +633,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
- &sum, CURSEG_COLD_DATA);
+ &sum, fio.btype);
fio.encrypted_page = pagecache_get_page(META_MAPPING(fio.sbi), newaddr,
FGP_LOCK | FGP_CREAT, GFP_NOFS);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index b084b3a8f2c7..7167c502c09a 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2141,14 +2141,15 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
{
- int type = __get_segment_type(fio->page, fio->type);
int err;
+ fio->btype = __get_segment_type(fio->page, fio->type);
+
if (fio->type == NODE || fio->type == DATA)
mutex_lock(&fio->sbi->wio_mutex[fio->type]);
reallocate:
allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
- &fio->new_blkaddr, sum, type);
+ &fio->new_blkaddr, sum, fio->btype);
/* writeout dirty page into bdev */
err = f2fs_submit_page_mbio(fio);
@@ -2166,6 +2167,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
struct f2fs_io_info fio = {
.sbi = sbi,
.type = META,
+ .btype = META,
.op = REQ_OP_WRITE,
.op_flags = REQ_SYNC | REQ_META | REQ_PRIO,
.old_blkaddr = page->index,
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 15da88c5c3a4..d9886c49b05e 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -9,8 +9,14 @@
#define show_dev(dev) MAJOR(dev), MINOR(dev)
#define show_dev_ino(entry) show_dev(entry->dev), (unsigned long)entry->ino
-TRACE_DEFINE_ENUM(NODE);
+TRACE_DEFINE_ENUM(HOT_DATA);
+TRACE_DEFINE_ENUM(WARM_DATA);
+TRACE_DEFINE_ENUM(COLD_DATA);
+TRACE_DEFINE_ENUM(HOT_NODE);
+TRACE_DEFINE_ENUM(WARM_NODE);
+TRACE_DEFINE_ENUM(COLD_NODE);
TRACE_DEFINE_ENUM(DATA);
+TRACE_DEFINE_ENUM(NODE);
TRACE_DEFINE_ENUM(META);
TRACE_DEFINE_ENUM(META_FLUSH);
TRACE_DEFINE_ENUM(INMEM);
@@ -48,9 +54,15 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
#define show_block_type(type) \
__print_symbolic(type, \
- { NODE, "NODE" }, \
- { DATA, "DATA" }, \
+ { HOT_DATA, "HOT_DATA" }, \
+ { WARM_DATA, "WARM_DATA" }, \
+ { COLD_DATA, "COLD_DATA" }, \
+ { HOT_NODE, "HOT_NODE" }, \
+ { WARM_NODE, "WARM_NODE" }, \
+ { COLD_NODE, "COLD_NODE" }, \
{ META, "META" }, \
+ { DATA, "DATA" }, \
+ { NODE, "NODE" }, \
{ META_FLUSH, "META_FLUSH" }, \
{ INMEM, "INMEM" }, \
{ INMEM_DROP, "INMEM_DROP" }, \
@@ -757,7 +769,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__field(block_t, new_blkaddr)
__field(int, op)
__field(int, op_flags)
- __field(int, type)
+ __field(int, btype)
),
TP_fast_assign(
@@ -768,7 +780,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__entry->new_blkaddr = fio->new_blkaddr;
__entry->op = fio->op;
__entry->op_flags = fio->op_flags;
- __entry->type = fio->type;
+ __entry->btype = fio->btype;
),
TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
@@ -778,7 +790,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
(unsigned long long)__entry->old_blkaddr,
(unsigned long long)__entry->new_blkaddr,
show_bio_type(__entry->op, __entry->op_flags),
- show_block_type(__entry->type))
+ show_block_type(__entry->btype))
);
DEFINE_EVENT_CONDITION(f2fs__submit_page_bio, f2fs_submit_page_bio,
@@ -810,7 +822,7 @@ DECLARE_EVENT_CLASS(f2fs__bio,
__field(dev_t, target)
__field(int, op)
__field(int, op_flags)
- __field(int, type)
+ __field(int, btype)
__field(sector_t, sector)
__field(unsigned int, size)
),
@@ -820,7 +832,7 @@ DECLARE_EVENT_CLASS(f2fs__bio,
__entry->target = bio->bi_bdev->bd_dev;
__entry->op = bio_op(bio);
__entry->op_flags = bio->bi_opf;
- __entry->type = type;
+ __entry->btype = btype;
__entry->sector = bio->bi_iter.bi_sector;
__entry->size = bio->bi_iter.bi_size;
),
@@ -829,7 +841,7 @@ DECLARE_EVENT_CLASS(f2fs__bio,
show_dev(__entry->target),
show_dev(__entry->dev),
show_bio_type(__entry->op, __entry->op_flags),
- show_block_type(__entry->type),
+ show_block_type(__entry->btype),
(unsigned long long)__entry->sector,
__entry->size)
);
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
@ 2017-05-10 3:19 ` Chao Yu
0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-10 3:19 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel
On 2017/5/9 9:49, Chao Yu wrote:
> Hi Jaegeuk,
>
> On 2017/5/9 5:23, Jaegeuk Kim wrote:
>> Hi Chao,
>>
>> I can't see a strong reason to split meta from data/node and rename the existing
>> function names. Instead, how about keeping the existing one while adding some
>> page types to deal with log types?
>
> Hmm.. before write this patch, I have thought about this implementation which
> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> different temperature log-header being with independent bio cache, io lock, and
> io list, eliminating interaction of different temperature IOs, also expanding
> f2fs' scalability when adding more log-headers. If we don't split meta from
> data/node, it's a little bit hard to approach this. What do you think?
Or like this?
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index ea9c317b5916..61191df47a09 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -159,6 +159,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
struct f2fs_io_info fio = {
.sbi = sbi,
.type = META,
+ .btype = META,
.op = REQ_OP_READ,
.op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD,
.encrypted_page = NULL,
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 7c0f6bdf817d..13c351e873d6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -182,16 +182,17 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
}
static inline void __submit_bio(struct f2fs_sb_info *sbi,
- struct bio *bio, enum page_type type)
+ struct bio *bio, enum page_type btype)
{
if (!is_read_io(bio_op(bio))) {
unsigned int start;
if (f2fs_sb_mounted_blkzoned(sbi->sb) &&
- current->plug && (type == DATA || type == NODE))
+ current->plug &&
+ (btype == DATA || btype == NODE || btype <= COLD_NODE))
blk_finish_plug(current->plug);
- if (type != DATA && type != NODE)
+ if (btype > COLD_NODE && btype != DATA && btype != NODE)
goto submit_io;
start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS;
@@ -217,14 +218,14 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
* In the NODE case, we lose next block address chain. So, we
* need to do checkpoint in f2fs_sync_file.
*/
- if (type == NODE)
+ if (btype == DATA || btype == NODE || btype <= COLD_NODE)
set_sbi_flag(sbi, SBI_NEED_CP);
}
submit_io:
if (is_read_io(bio_op(bio)))
- trace_f2fs_submit_read_bio(sbi->sb, type, bio);
+ trace_f2fs_submit_read_bio(sbi->sb, btype, bio);
else
- trace_f2fs_submit_write_bio(sbi->sb, type, bio);
+ trace_f2fs_submit_write_bio(sbi->sb, btype, bio);
submit_bio(bio);
}
@@ -238,11 +239,11 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
if (is_read_io(fio->op))
- trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio);
+ trace_f2fs_prepare_read_bio(io->sbi->sb, fio->btype, io->bio);
else
- trace_f2fs_prepare_write_bio(io->sbi->sb, fio->type, io->bio);
+ trace_f2fs_prepare_write_bio(io->sbi->sb, fio->btype, io->bio);
- __submit_bio(io->sbi, io->bio, fio->type);
+ __submit_bio(io->sbi, io->bio, fio->btype);
io->bio = NULL;
}
@@ -279,12 +280,14 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
}
static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
- nid_t ino, pgoff_t idx, enum page_type type)
+ nid_t ino, pgoff_t idx, enum page_type type, int rw)
{
enum page_type btype = PAGE_TYPE_OF_BIO(type);
- struct f2fs_bio_info *io = &sbi->write_io[btype];
+ struct f2fs_bio_info *io;
bool ret;
+ io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype];
+
down_read(&io->io_rwsem);
ret = __has_merged_page(io, inode, ino, idx);
up_read(&io->io_rwsem);
@@ -318,18 +321,34 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
up_write(&io->io_rwsem);
}
-void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
- int rw)
-{
- __f2fs_submit_merged_bio(sbi, NULL, 0, 0, type, rw);
-}
-
void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi,
struct inode *inode, nid_t ino, pgoff_t idx,
enum page_type type, int rw)
{
- if (has_merged_page(sbi, inode, ino, idx, type))
- __f2fs_submit_merged_bio(sbi, inode, ino, idx, type, rw);
+ int i;
+
+ if (type == DATA) {
+ for (i = HOT_DATA; i <= COLD_DATA; i++) {
+ if (has_merged_page(sbi, inode, ino, idx, i, rw))
+ __f2fs_submit_merged_bio(sbi, inode, ino, idx,
+ i, rw);
+ }
+ } else if (type == NODE) {
+ for (i = HOT_NODE; i <= COLD_NODE; i++) {
+ if (has_merged_page(sbi, inode, ino, idx, i, rw))
+ __f2fs_submit_merged_bio(sbi, inode, ino, idx,
+ i, rw);
+ }
+ } else {
+ if (has_merged_page(sbi, inode, ino, idx, type, rw))
+ __f2fs_submit_merged_bio(sbi, inode, ino, idx, type, rw);
+ }
+}
+
+void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
+ int rw)
+{
+ f2fs_submit_merged_bio_cond(sbi, NULL, 0, 0, type, rw);
}
void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi)
@@ -371,7 +390,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
int f2fs_submit_page_mbio(struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = fio->sbi;
- enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
+ enum page_type btype = PAGE_TYPE_OF_BIO(fio->btype);
struct f2fs_bio_info *io;
bool is_read = is_read_io(fio->op);
struct page *bio_page;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index e26999a74522..177bccfad9ff 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -779,10 +779,16 @@ enum count_type {
*/
#define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type))
enum page_type {
- DATA,
- NODE,
+ HOT_DATA, /* CURSEG_HOT_DATA */
+ WARM_DATA, /* CURSEG_WARM_DATA */
+ COLD_DATA, /* CURSEG_COLD_DATA */
+ HOT_NODE, /* CURSEG_HOT_NODE */
+ WARM_NODE, /* CURSEG_WARM_NODE */
+ COLD_NODE, /* CURSEG_COLD_NODE */
META,
NR_PAGE_TYPE,
+ DATA,
+ NODE,
META_FLUSH,
INMEM, /* the below types are used by tracepoints only. */
INMEM_DROP,
@@ -795,6 +801,7 @@ enum page_type {
struct f2fs_io_info {
struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
+ int btype; /* segment type and meta type */
int op; /* contains REQ_OP_ */
int op_flags; /* req_flag_bits */
block_t new_blkaddr; /* new block address to be written */
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 026522107ca3..94a4a7ab141a 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
.type = DATA,
+ .btype = CURSEG_COLD_DATA,
.op = REQ_OP_READ,
.op_flags = 0,
.encrypted_page = NULL,
@@ -632,7 +633,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
- &sum, CURSEG_COLD_DATA);
+ &sum, fio.btype);
fio.encrypted_page = pagecache_get_page(META_MAPPING(fio.sbi), newaddr,
FGP_LOCK | FGP_CREAT, GFP_NOFS);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index b084b3a8f2c7..7167c502c09a 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2141,14 +2141,15 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
{
- int type = __get_segment_type(fio->page, fio->type);
int err;
+ fio->btype = __get_segment_type(fio->page, fio->type);
+
if (fio->type == NODE || fio->type == DATA)
mutex_lock(&fio->sbi->wio_mutex[fio->type]);
reallocate:
allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
- &fio->new_blkaddr, sum, type);
+ &fio->new_blkaddr, sum, fio->btype);
/* writeout dirty page into bdev */
err = f2fs_submit_page_mbio(fio);
@@ -2166,6 +2167,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
struct f2fs_io_info fio = {
.sbi = sbi,
.type = META,
+ .btype = META,
.op = REQ_OP_WRITE,
.op_flags = REQ_SYNC | REQ_META | REQ_PRIO,
.old_blkaddr = page->index,
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 15da88c5c3a4..d9886c49b05e 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -9,8 +9,14 @@
#define show_dev(dev) MAJOR(dev), MINOR(dev)
#define show_dev_ino(entry) show_dev(entry->dev), (unsigned long)entry->ino
-TRACE_DEFINE_ENUM(NODE);
+TRACE_DEFINE_ENUM(HOT_DATA);
+TRACE_DEFINE_ENUM(WARM_DATA);
+TRACE_DEFINE_ENUM(COLD_DATA);
+TRACE_DEFINE_ENUM(HOT_NODE);
+TRACE_DEFINE_ENUM(WARM_NODE);
+TRACE_DEFINE_ENUM(COLD_NODE);
TRACE_DEFINE_ENUM(DATA);
+TRACE_DEFINE_ENUM(NODE);
TRACE_DEFINE_ENUM(META);
TRACE_DEFINE_ENUM(META_FLUSH);
TRACE_DEFINE_ENUM(INMEM);
@@ -48,9 +54,15 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
#define show_block_type(type) \
__print_symbolic(type, \
- { NODE, "NODE" }, \
- { DATA, "DATA" }, \
+ { HOT_DATA, "HOT_DATA" }, \
+ { WARM_DATA, "WARM_DATA" }, \
+ { COLD_DATA, "COLD_DATA" }, \
+ { HOT_NODE, "HOT_NODE" }, \
+ { WARM_NODE, "WARM_NODE" }, \
+ { COLD_NODE, "COLD_NODE" }, \
{ META, "META" }, \
+ { DATA, "DATA" }, \
+ { NODE, "NODE" }, \
{ META_FLUSH, "META_FLUSH" }, \
{ INMEM, "INMEM" }, \
{ INMEM_DROP, "INMEM_DROP" }, \
@@ -757,7 +769,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__field(block_t, new_blkaddr)
__field(int, op)
__field(int, op_flags)
- __field(int, type)
+ __field(int, btype)
),
TP_fast_assign(
@@ -768,7 +780,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__entry->new_blkaddr = fio->new_blkaddr;
__entry->op = fio->op;
__entry->op_flags = fio->op_flags;
- __entry->type = fio->type;
+ __entry->btype = fio->btype;
),
TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
@@ -778,7 +790,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
(unsigned long long)__entry->old_blkaddr,
(unsigned long long)__entry->new_blkaddr,
show_bio_type(__entry->op, __entry->op_flags),
- show_block_type(__entry->type))
+ show_block_type(__entry->btype))
);
DEFINE_EVENT_CONDITION(f2fs__submit_page_bio, f2fs_submit_page_bio,
@@ -810,7 +822,7 @@ DECLARE_EVENT_CLASS(f2fs__bio,
__field(dev_t, target)
__field(int, op)
__field(int, op_flags)
- __field(int, type)
+ __field(int, btype)
__field(sector_t, sector)
__field(unsigned int, size)
),
@@ -820,7 +832,7 @@ DECLARE_EVENT_CLASS(f2fs__bio,
__entry->target = bio->bi_bdev->bd_dev;
__entry->op = bio_op(bio);
__entry->op_flags = bio->bi_opf;
- __entry->type = type;
+ __entry->btype = btype;
__entry->sector = bio->bi_iter.bi_sector;
__entry->size = bio->bi_iter.bi_size;
),
@@ -829,7 +841,7 @@ DECLARE_EVENT_CLASS(f2fs__bio,
show_dev(__entry->target),
show_dev(__entry->dev),
show_bio_type(__entry->op, __entry->op_flags),
- show_block_type(__entry->type),
+ show_block_type(__entry->btype),
(unsigned long long)__entry->sector,
__entry->size)
);
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
2017-05-09 1:49 ` Chao Yu
(?)
(?)
@ 2017-05-10 23:50 ` Jaegeuk Kim
2017-05-11 2:20 ` Chao Yu
-1 siblings, 1 reply; 16+ messages in thread
From: Jaegeuk Kim @ 2017-05-10 23:50 UTC (permalink / raw)
To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel, chao
On 05/09, Chao Yu wrote:
> Hi Jaegeuk,
>
> On 2017/5/9 5:23, Jaegeuk Kim wrote:
> > Hi Chao,
> >
> > I can't see a strong reason to split meta from data/node and rename the existing
> > function names. Instead, how about keeping the existing one while adding some
> > page types to deal with log types?
>
> Hmm.. before write this patch, I have thought about this implementation which
> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> different temperature log-header being with independent bio cache, io lock, and
> io list, eliminating interaction of different temperature IOs, also expanding
> f2fs' scalability when adding more log-headers. If we don't split meta from
> data/node, it's a little bit hard to approach this. What do you think?
I submitted clean-up patches. How about this on top of them?
---
fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
fs/f2fs/f2fs.h | 10 ++++++++-
fs/f2fs/gc.c | 2 ++
fs/f2fs/segment.c | 24 +++++++++++++++------
fs/f2fs/segment.h | 4 ++++
fs/f2fs/super.c | 21 ++++++++++++++++---
include/trace/events/f2fs.h | 14 ++++++++++++-
7 files changed, 102 insertions(+), 24 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 06bb2042385e..49b7e3918484 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
nid_t ino, pgoff_t idx, enum page_type type)
{
enum page_type btype = PAGE_TYPE_OF_BIO(type);
- struct f2fs_bio_info *io = &sbi->write_io[btype];
- bool ret;
+ enum temp_type temp;
+ struct f2fs_bio_info *io;
+ bool ret = false;
- down_read(&io->io_rwsem);
- ret = __has_merged_page(io, inode, ino, idx);
- up_read(&io->io_rwsem);
+ for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
+ io = sbi->write_io[btype] + temp;
+
+ down_read(&io->io_rwsem);
+ ret = __has_merged_page(io, inode, ino, idx);
+ up_read(&io->io_rwsem);
+
+ /* TODO: use HOT temp only for meta pages now. */
+ if (ret || btype == META)
+ break;
+ }
return ret;
}
static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
struct inode *inode, nid_t ino, pgoff_t idx,
- enum page_type type)
+ enum page_type type, enum temp_type temp)
{
enum page_type btype = PAGE_TYPE_OF_BIO(type);
- struct f2fs_bio_info *io = &sbi->write_io[btype];
+ struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
down_write(&io->io_rwsem);
@@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
up_write(&io->io_rwsem);
}
+static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
+ struct inode *inode, nid_t ino, pgoff_t idx,
+ enum page_type type, bool force)
+{
+ enum temp_type temp;
+
+ if (!force && !has_merged_page(sbi, inode, ino, idx, type))
+ return;
+
+ for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
+ __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
+
+ /* TODO: use HOT temp only for meta pages now. */
+ if (type >= META)
+ break;
+ }
+}
+
void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
{
- __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
+ __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
}
void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
struct inode *inode, nid_t ino, pgoff_t idx,
enum page_type type)
{
- if (has_merged_page(sbi, inode, ino, idx, type))
- __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
+ __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
}
void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
@@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = fio->sbi;
enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
- struct f2fs_bio_info *io = &sbi->write_io[btype];
+ struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
struct page *bio_page;
int err = 0;
@@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
io->fio = *fio;
}
- if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
- PAGE_SIZE) {
+ if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
__submit_merged_bio(io);
goto alloc_new;
}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index bf837458cb18..90e97bc11972 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -792,9 +792,17 @@ enum page_type {
OPU,
};
+enum temp_type {
+ HOT = 0, /* must be zero for meta bio */
+ WARM,
+ COLD,
+ NR_TEMP_TYPE,
+};
+
struct f2fs_io_info {
struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
+ enum temp_type temp; /* contains HOT/WARM/COLD */
int op; /* contains REQ_OP_ */
int op_flags; /* req_flag_bits */
block_t new_blkaddr; /* new block address to be written */
@@ -880,7 +888,7 @@ struct f2fs_sb_info {
/* for bio operations */
struct f2fs_bio_info read_io; /* for read bios */
- struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
+ struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
int write_io_size_bits; /* Write IO size bits */
mempool_t *write_io_dummy; /* Dummy pages */
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 67b87155bc48..e2b13558a915 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
.type = DATA,
+ .temp = COLD,
.op = REQ_OP_READ,
.op_flags = 0,
.encrypted_page = NULL,
@@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
.type = DATA,
+ .temp = COLD,
.op = REQ_OP_WRITE,
.op_flags = REQ_SYNC,
.old_blkaddr = NULL_ADDR,
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c9f3a2faee21..da4fd2c29e86 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
static int __get_segment_type(struct f2fs_io_info *fio)
{
+ int type;
+
switch (fio->sbi->active_logs) {
case 2:
- return __get_segment_type_2(fio);
+ type = __get_segment_type_2(fio);
+ break;
case 4:
- return __get_segment_type_4(fio);
+ type = __get_segment_type_4(fio);
+ break;
+ case 6:
+ type = __get_segment_type_6(fio);
+ break;
+ default:
+ f2fs_bug_on(fio->sbi, true);
}
- /* NR_CURSEG_TYPE(6) logs by default */
- f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
-
- return __get_segment_type_6(fio);
+ if (IS_HOT(type))
+ fio->temp = HOT;
+ else if (IS_WARM(type))
+ fio->temp = WARM;
+ else
+ fio->temp = COLD;
+ return type;
}
void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 10bf05d4cff4..e9ba1f1d9723 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -27,6 +27,10 @@
#define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
+#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
+#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
+#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
+
#define IS_CURSEG(sbi, seg) \
(((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 104a571a41c0..91599c9c3ef6 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
static void f2fs_put_super(struct super_block *sb)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
+ int i;
if (sbi->s_proc) {
remove_proc_entry("segment_info", sbi->s_proc);
@@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
destroy_device_list(sbi);
mempool_destroy(sbi->write_io_dummy);
destroy_percpu_info(sbi);
+ for (i = 0; i < NR_PAGE_TYPE; i++)
+ kfree(sbi->write_io[i]);
kfree(sbi);
}
@@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
sbi->read_io.sbi = sbi;
sbi->read_io.bio = NULL;
for (i = 0; i < NR_PAGE_TYPE; i++) {
- init_rwsem(&sbi->write_io[i].io_rwsem);
- sbi->write_io[i].sbi = sbi;
- sbi->write_io[i].bio = NULL;
+ int n = (i == META) ? 1: NR_TEMP_TYPE;
+ int j;
+
+ sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
+ GFP_KERNEL);
+ if (!sbi->write_io[i])
+ goto free_options;
+
+ for (j = HOT; j < n; j++) {
+ init_rwsem(&sbi->write_io[i][j].io_rwsem);
+ sbi->write_io[i][j].sbi = sbi;
+ sbi->write_io[i][j].bio = NULL;
+ }
}
init_rwsem(&sbi->cp_rwsem);
@@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
free_io_dummy:
mempool_destroy(sbi->write_io_dummy);
free_options:
+ for (i = 0; i < NR_PAGE_TYPE; i++)
+ kfree(sbi->write_io[i]);
destroy_percpu_info(sbi);
kfree(options);
free_sb_buf:
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 5805d92893a8..6f77a2755abb 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
TRACE_DEFINE_ENUM(INMEM_REVOKE);
TRACE_DEFINE_ENUM(IPU);
TRACE_DEFINE_ENUM(OPU);
+TRACE_DEFINE_ENUM(HOT);
+TRACE_DEFINE_ENUM(WARM);
+TRACE_DEFINE_ENUM(COLD);
TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
@@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
{ IPU, "IN-PLACE" }, \
{ OPU, "OUT-OF-PLACE" })
+#define show_block_temp(temp) \
+ __print_symbolic(temp, \
+ { HOT, "HOT" }, \
+ { WARM, "WARM" }, \
+ { COLD, "COLD" })
+
#define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
REQ_PREFLUSH | REQ_FUA)
#define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
@@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__field(block_t, new_blkaddr)
__field(int, op)
__field(int, op_flags)
+ __field(int, temp)
__field(int, type)
),
@@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__entry->new_blkaddr = fio->new_blkaddr;
__entry->op = fio->op;
__entry->op_flags = fio->op_flags;
+ __entry->temp = fio->temp;
__entry->type = fio->type;
),
TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
- "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
+ "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
show_dev_ino(__entry),
(unsigned long)__entry->index,
(unsigned long long)__entry->old_blkaddr,
(unsigned long long)__entry->new_blkaddr,
show_bio_type(__entry->op, __entry->op_flags),
+ show_block_temp(__entry->temp),
show_block_type(__entry->type))
);
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
2017-05-10 23:50 ` Jaegeuk Kim
@ 2017-05-11 2:20 ` Chao Yu
0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-11 2:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel, chao
On 2017/5/11 7:50, Jaegeuk Kim wrote:
> On 05/09, Chao Yu wrote:
>> Hi Jaegeuk,
>>
>> On 2017/5/9 5:23, Jaegeuk Kim wrote:
>>> Hi Chao,
>>>
>>> I can't see a strong reason to split meta from data/node and rename the existing
>>> function names. Instead, how about keeping the existing one while adding some
>>> page types to deal with log types?
>>
>> Hmm.. before write this patch, I have thought about this implementation which
>> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
>> different temperature log-header being with independent bio cache, io lock, and
>> io list, eliminating interaction of different temperature IOs, also expanding
>> f2fs' scalability when adding more log-headers. If we don't split meta from
>> data/node, it's a little bit hard to approach this. What do you think?
>
> I submitted clean-up patches. How about this on top of them?
After splitting, bio caches is connected to log-header, so why not moving bio
cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
- we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
we have seg_type enum instead.
- once we add special log-header like journal log or random IO log making
DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
codes to adjust it.
How do you think?
Thanks,
>
> ---
> fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
> fs/f2fs/f2fs.h | 10 ++++++++-
> fs/f2fs/gc.c | 2 ++
> fs/f2fs/segment.c | 24 +++++++++++++++------
> fs/f2fs/segment.h | 4 ++++
> fs/f2fs/super.c | 21 ++++++++++++++++---
> include/trace/events/f2fs.h | 14 ++++++++++++-
> 7 files changed, 102 insertions(+), 24 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 06bb2042385e..49b7e3918484 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
> nid_t ino, pgoff_t idx, enum page_type type)
> {
> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> - bool ret;
> + enum temp_type temp;
> + struct f2fs_bio_info *io;
> + bool ret = false;
>
> - down_read(&io->io_rwsem);
> - ret = __has_merged_page(io, inode, ino, idx);
> - up_read(&io->io_rwsem);
> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> + io = sbi->write_io[btype] + temp;
> +
> + down_read(&io->io_rwsem);
> + ret = __has_merged_page(io, inode, ino, idx);
> + up_read(&io->io_rwsem);
> +
> + /* TODO: use HOT temp only for meta pages now. */
> + if (ret || btype == META)
> + break;
> + }
> return ret;
> }
>
> static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> struct inode *inode, nid_t ino, pgoff_t idx,
> - enum page_type type)
> + enum page_type type, enum temp_type temp)
> {
> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
>
> down_write(&io->io_rwsem);
>
> @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> up_write(&io->io_rwsem);
> }
>
> +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
> + struct inode *inode, nid_t ino, pgoff_t idx,
> + enum page_type type, bool force)
> +{
> + enum temp_type temp;
> +
> + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
> + return;
> +
> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
> +
> + /* TODO: use HOT temp only for meta pages now. */
> + if (type >= META)
> + break;
> + }
> +}
> +
> void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
> {
> - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
> + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
> }
>
> void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> struct inode *inode, nid_t ino, pgoff_t idx,
> enum page_type type)
> {
> - if (has_merged_page(sbi, inode, ino, idx, type))
> - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
> + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
> }
>
> void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
> @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> {
> struct f2fs_sb_info *sbi = fio->sbi;
> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> struct page *bio_page;
> int err = 0;
>
> @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> io->fio = *fio;
> }
>
> - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
> - PAGE_SIZE) {
> + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
> __submit_merged_bio(io);
> goto alloc_new;
> }
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index bf837458cb18..90e97bc11972 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -792,9 +792,17 @@ enum page_type {
> OPU,
> };
>
> +enum temp_type {
> + HOT = 0, /* must be zero for meta bio */
> + WARM,
> + COLD,
> + NR_TEMP_TYPE,
> +};
> +
> struct f2fs_io_info {
> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
> + enum temp_type temp; /* contains HOT/WARM/COLD */
> int op; /* contains REQ_OP_ */
> int op_flags; /* req_flag_bits */
> block_t new_blkaddr; /* new block address to be written */
> @@ -880,7 +888,7 @@ struct f2fs_sb_info {
>
> /* for bio operations */
> struct f2fs_bio_info read_io; /* for read bios */
> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
> + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
> int write_io_size_bits; /* Write IO size bits */
> mempool_t *write_io_dummy; /* Dummy pages */
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 67b87155bc48..e2b13558a915 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
> struct f2fs_io_info fio = {
> .sbi = F2FS_I_SB(inode),
> .type = DATA,
> + .temp = COLD,
> .op = REQ_OP_READ,
> .op_flags = 0,
> .encrypted_page = NULL,
> @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
> struct f2fs_io_info fio = {
> .sbi = F2FS_I_SB(inode),
> .type = DATA,
> + .temp = COLD,
> .op = REQ_OP_WRITE,
> .op_flags = REQ_SYNC,
> .old_blkaddr = NULL_ADDR,
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index c9f3a2faee21..da4fd2c29e86 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
>
> static int __get_segment_type(struct f2fs_io_info *fio)
> {
> + int type;
> +
> switch (fio->sbi->active_logs) {
> case 2:
> - return __get_segment_type_2(fio);
> + type = __get_segment_type_2(fio);
> + break;
> case 4:
> - return __get_segment_type_4(fio);
> + type = __get_segment_type_4(fio);
> + break;
> + case 6:
> + type = __get_segment_type_6(fio);
> + break;
> + default:
> + f2fs_bug_on(fio->sbi, true);
> }
>
> - /* NR_CURSEG_TYPE(6) logs by default */
> - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
> -
> - return __get_segment_type_6(fio);
> + if (IS_HOT(type))
> + fio->temp = HOT;
> + else if (IS_WARM(type))
> + fio->temp = WARM;
> + else
> + fio->temp = COLD;
> + return type;
> }
>
> void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index 10bf05d4cff4..e9ba1f1d9723 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -27,6 +27,10 @@
> #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
> #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
>
> +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
> +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
> +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
> +
> #define IS_CURSEG(sbi, seg) \
> (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
> ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 104a571a41c0..91599c9c3ef6 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
> static void f2fs_put_super(struct super_block *sb)
> {
> struct f2fs_sb_info *sbi = F2FS_SB(sb);
> + int i;
>
> if (sbi->s_proc) {
> remove_proc_entry("segment_info", sbi->s_proc);
> @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
> destroy_device_list(sbi);
> mempool_destroy(sbi->write_io_dummy);
> destroy_percpu_info(sbi);
> + for (i = 0; i < NR_PAGE_TYPE; i++)
> + kfree(sbi->write_io[i]);
> kfree(sbi);
> }
>
> @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> sbi->read_io.sbi = sbi;
> sbi->read_io.bio = NULL;
> for (i = 0; i < NR_PAGE_TYPE; i++) {
> - init_rwsem(&sbi->write_io[i].io_rwsem);
> - sbi->write_io[i].sbi = sbi;
> - sbi->write_io[i].bio = NULL;
> + int n = (i == META) ? 1: NR_TEMP_TYPE;
> + int j;
> +
> + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
> + GFP_KERNEL);
> + if (!sbi->write_io[i])
> + goto free_options;
> +
> + for (j = HOT; j < n; j++) {
> + init_rwsem(&sbi->write_io[i][j].io_rwsem);
> + sbi->write_io[i][j].sbi = sbi;
> + sbi->write_io[i][j].bio = NULL;
> + }
> }
>
> init_rwsem(&sbi->cp_rwsem);
> @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> free_io_dummy:
> mempool_destroy(sbi->write_io_dummy);
> free_options:
> + for (i = 0; i < NR_PAGE_TYPE; i++)
> + kfree(sbi->write_io[i]);
> destroy_percpu_info(sbi);
> kfree(options);
> free_sb_buf:
> diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> index 5805d92893a8..6f77a2755abb 100644
> --- a/include/trace/events/f2fs.h
> +++ b/include/trace/events/f2fs.h
> @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
> TRACE_DEFINE_ENUM(INMEM_REVOKE);
> TRACE_DEFINE_ENUM(IPU);
> TRACE_DEFINE_ENUM(OPU);
> +TRACE_DEFINE_ENUM(HOT);
> +TRACE_DEFINE_ENUM(WARM);
> +TRACE_DEFINE_ENUM(COLD);
> TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
> TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
> TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
> @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
> { IPU, "IN-PLACE" }, \
> { OPU, "OUT-OF-PLACE" })
>
> +#define show_block_temp(temp) \
> + __print_symbolic(temp, \
> + { HOT, "HOT" }, \
> + { WARM, "WARM" }, \
> + { COLD, "COLD" })
> +
> #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
> REQ_PREFLUSH | REQ_FUA)
> #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
> @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> __field(block_t, new_blkaddr)
> __field(int, op)
> __field(int, op_flags)
> + __field(int, temp)
> __field(int, type)
> ),
>
> @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> __entry->new_blkaddr = fio->new_blkaddr;
> __entry->op = fio->op;
> __entry->op_flags = fio->op_flags;
> + __entry->temp = fio->temp;
> __entry->type = fio->type;
> ),
>
> TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
> - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
> + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
> show_dev_ino(__entry),
> (unsigned long)__entry->index,
> (unsigned long long)__entry->old_blkaddr,
> (unsigned long long)__entry->new_blkaddr,
> show_bio_type(__entry->op, __entry->op_flags),
> + show_block_temp(__entry->temp),
> show_block_type(__entry->type))
> );
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
@ 2017-05-11 2:20 ` Chao Yu
0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-11 2:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel
On 2017/5/11 7:50, Jaegeuk Kim wrote:
> On 05/09, Chao Yu wrote:
>> Hi Jaegeuk,
>>
>> On 2017/5/9 5:23, Jaegeuk Kim wrote:
>>> Hi Chao,
>>>
>>> I can't see a strong reason to split meta from data/node and rename the existing
>>> function names. Instead, how about keeping the existing one while adding some
>>> page types to deal with log types?
>>
>> Hmm.. before write this patch, I have thought about this implementation which
>> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
>> different temperature log-header being with independent bio cache, io lock, and
>> io list, eliminating interaction of different temperature IOs, also expanding
>> f2fs' scalability when adding more log-headers. If we don't split meta from
>> data/node, it's a little bit hard to approach this. What do you think?
>
> I submitted clean-up patches. How about this on top of them?
After splitting, bio caches is connected to log-header, so why not moving bio
cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
- we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
we have seg_type enum instead.
- once we add special log-header like journal log or random IO log making
DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
codes to adjust it.
How do you think?
Thanks,
>
> ---
> fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
> fs/f2fs/f2fs.h | 10 ++++++++-
> fs/f2fs/gc.c | 2 ++
> fs/f2fs/segment.c | 24 +++++++++++++++------
> fs/f2fs/segment.h | 4 ++++
> fs/f2fs/super.c | 21 ++++++++++++++++---
> include/trace/events/f2fs.h | 14 ++++++++++++-
> 7 files changed, 102 insertions(+), 24 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 06bb2042385e..49b7e3918484 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
> nid_t ino, pgoff_t idx, enum page_type type)
> {
> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> - bool ret;
> + enum temp_type temp;
> + struct f2fs_bio_info *io;
> + bool ret = false;
>
> - down_read(&io->io_rwsem);
> - ret = __has_merged_page(io, inode, ino, idx);
> - up_read(&io->io_rwsem);
> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> + io = sbi->write_io[btype] + temp;
> +
> + down_read(&io->io_rwsem);
> + ret = __has_merged_page(io, inode, ino, idx);
> + up_read(&io->io_rwsem);
> +
> + /* TODO: use HOT temp only for meta pages now. */
> + if (ret || btype == META)
> + break;
> + }
> return ret;
> }
>
> static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> struct inode *inode, nid_t ino, pgoff_t idx,
> - enum page_type type)
> + enum page_type type, enum temp_type temp)
> {
> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
>
> down_write(&io->io_rwsem);
>
> @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> up_write(&io->io_rwsem);
> }
>
> +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
> + struct inode *inode, nid_t ino, pgoff_t idx,
> + enum page_type type, bool force)
> +{
> + enum temp_type temp;
> +
> + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
> + return;
> +
> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
> +
> + /* TODO: use HOT temp only for meta pages now. */
> + if (type >= META)
> + break;
> + }
> +}
> +
> void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
> {
> - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
> + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
> }
>
> void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> struct inode *inode, nid_t ino, pgoff_t idx,
> enum page_type type)
> {
> - if (has_merged_page(sbi, inode, ino, idx, type))
> - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
> + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
> }
>
> void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
> @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> {
> struct f2fs_sb_info *sbi = fio->sbi;
> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> struct page *bio_page;
> int err = 0;
>
> @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> io->fio = *fio;
> }
>
> - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
> - PAGE_SIZE) {
> + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
> __submit_merged_bio(io);
> goto alloc_new;
> }
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index bf837458cb18..90e97bc11972 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -792,9 +792,17 @@ enum page_type {
> OPU,
> };
>
> +enum temp_type {
> + HOT = 0, /* must be zero for meta bio */
> + WARM,
> + COLD,
> + NR_TEMP_TYPE,
> +};
> +
> struct f2fs_io_info {
> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
> + enum temp_type temp; /* contains HOT/WARM/COLD */
> int op; /* contains REQ_OP_ */
> int op_flags; /* req_flag_bits */
> block_t new_blkaddr; /* new block address to be written */
> @@ -880,7 +888,7 @@ struct f2fs_sb_info {
>
> /* for bio operations */
> struct f2fs_bio_info read_io; /* for read bios */
> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
> + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
> int write_io_size_bits; /* Write IO size bits */
> mempool_t *write_io_dummy; /* Dummy pages */
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 67b87155bc48..e2b13558a915 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
> struct f2fs_io_info fio = {
> .sbi = F2FS_I_SB(inode),
> .type = DATA,
> + .temp = COLD,
> .op = REQ_OP_READ,
> .op_flags = 0,
> .encrypted_page = NULL,
> @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
> struct f2fs_io_info fio = {
> .sbi = F2FS_I_SB(inode),
> .type = DATA,
> + .temp = COLD,
> .op = REQ_OP_WRITE,
> .op_flags = REQ_SYNC,
> .old_blkaddr = NULL_ADDR,
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index c9f3a2faee21..da4fd2c29e86 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
>
> static int __get_segment_type(struct f2fs_io_info *fio)
> {
> + int type;
> +
> switch (fio->sbi->active_logs) {
> case 2:
> - return __get_segment_type_2(fio);
> + type = __get_segment_type_2(fio);
> + break;
> case 4:
> - return __get_segment_type_4(fio);
> + type = __get_segment_type_4(fio);
> + break;
> + case 6:
> + type = __get_segment_type_6(fio);
> + break;
> + default:
> + f2fs_bug_on(fio->sbi, true);
> }
>
> - /* NR_CURSEG_TYPE(6) logs by default */
> - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
> -
> - return __get_segment_type_6(fio);
> + if (IS_HOT(type))
> + fio->temp = HOT;
> + else if (IS_WARM(type))
> + fio->temp = WARM;
> + else
> + fio->temp = COLD;
> + return type;
> }
>
> void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index 10bf05d4cff4..e9ba1f1d9723 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -27,6 +27,10 @@
> #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
> #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
>
> +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
> +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
> +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
> +
> #define IS_CURSEG(sbi, seg) \
> (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
> ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 104a571a41c0..91599c9c3ef6 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
> static void f2fs_put_super(struct super_block *sb)
> {
> struct f2fs_sb_info *sbi = F2FS_SB(sb);
> + int i;
>
> if (sbi->s_proc) {
> remove_proc_entry("segment_info", sbi->s_proc);
> @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
> destroy_device_list(sbi);
> mempool_destroy(sbi->write_io_dummy);
> destroy_percpu_info(sbi);
> + for (i = 0; i < NR_PAGE_TYPE; i++)
> + kfree(sbi->write_io[i]);
> kfree(sbi);
> }
>
> @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> sbi->read_io.sbi = sbi;
> sbi->read_io.bio = NULL;
> for (i = 0; i < NR_PAGE_TYPE; i++) {
> - init_rwsem(&sbi->write_io[i].io_rwsem);
> - sbi->write_io[i].sbi = sbi;
> - sbi->write_io[i].bio = NULL;
> + int n = (i == META) ? 1: NR_TEMP_TYPE;
> + int j;
> +
> + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
> + GFP_KERNEL);
> + if (!sbi->write_io[i])
> + goto free_options;
> +
> + for (j = HOT; j < n; j++) {
> + init_rwsem(&sbi->write_io[i][j].io_rwsem);
> + sbi->write_io[i][j].sbi = sbi;
> + sbi->write_io[i][j].bio = NULL;
> + }
> }
>
> init_rwsem(&sbi->cp_rwsem);
> @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> free_io_dummy:
> mempool_destroy(sbi->write_io_dummy);
> free_options:
> + for (i = 0; i < NR_PAGE_TYPE; i++)
> + kfree(sbi->write_io[i]);
> destroy_percpu_info(sbi);
> kfree(options);
> free_sb_buf:
> diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> index 5805d92893a8..6f77a2755abb 100644
> --- a/include/trace/events/f2fs.h
> +++ b/include/trace/events/f2fs.h
> @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
> TRACE_DEFINE_ENUM(INMEM_REVOKE);
> TRACE_DEFINE_ENUM(IPU);
> TRACE_DEFINE_ENUM(OPU);
> +TRACE_DEFINE_ENUM(HOT);
> +TRACE_DEFINE_ENUM(WARM);
> +TRACE_DEFINE_ENUM(COLD);
> TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
> TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
> TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
> @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
> { IPU, "IN-PLACE" }, \
> { OPU, "OUT-OF-PLACE" })
>
> +#define show_block_temp(temp) \
> + __print_symbolic(temp, \
> + { HOT, "HOT" }, \
> + { WARM, "WARM" }, \
> + { COLD, "COLD" })
> +
> #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
> REQ_PREFLUSH | REQ_FUA)
> #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
> @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> __field(block_t, new_blkaddr)
> __field(int, op)
> __field(int, op_flags)
> + __field(int, temp)
> __field(int, type)
> ),
>
> @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> __entry->new_blkaddr = fio->new_blkaddr;
> __entry->op = fio->op;
> __entry->op_flags = fio->op_flags;
> + __entry->temp = fio->temp;
> __entry->type = fio->type;
> ),
>
> TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
> - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
> + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
> show_dev_ino(__entry),
> (unsigned long)__entry->index,
> (unsigned long long)__entry->old_blkaddr,
> (unsigned long long)__entry->new_blkaddr,
> show_bio_type(__entry->op, __entry->op_flags),
> + show_block_temp(__entry->temp),
> show_block_type(__entry->type))
> );
>
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
2017-05-11 2:20 ` Chao Yu
@ 2017-05-11 2:35 ` Jaegeuk Kim
-1 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2017-05-11 2:35 UTC (permalink / raw)
To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel, chao
On 05/11, Chao Yu wrote:
> On 2017/5/11 7:50, Jaegeuk Kim wrote:
> > On 05/09, Chao Yu wrote:
> >> Hi Jaegeuk,
> >>
> >> On 2017/5/9 5:23, Jaegeuk Kim wrote:
> >>> Hi Chao,
> >>>
> >>> I can't see a strong reason to split meta from data/node and rename the existing
> >>> function names. Instead, how about keeping the existing one while adding some
> >>> page types to deal with log types?
> >>
> >> Hmm.. before write this patch, I have thought about this implementation which
> >> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> >> different temperature log-header being with independent bio cache, io lock, and
> >> io list, eliminating interaction of different temperature IOs, also expanding
> >> f2fs' scalability when adding more log-headers. If we don't split meta from
> >> data/node, it's a little bit hard to approach this. What do you think?
> >
> > I submitted clean-up patches. How about this on top of them?
>
> After splitting, bio caches is connected to log-header, so why not moving bio
> cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
> - we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
> we have seg_type enum instead.
> - once we add special log-header like journal log or random IO log making
> DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
> codes to adjust it.
Well, I perfer to keep block allocation and IO control in a separate way as is.
Moreover, I don't think performance gain would be large enough comparing to what
we need to change both of whole flows.
Thanks,
>
> How do you think?
>
> Thanks,
>
> >
> > ---
> > fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
> > fs/f2fs/f2fs.h | 10 ++++++++-
> > fs/f2fs/gc.c | 2 ++
> > fs/f2fs/segment.c | 24 +++++++++++++++------
> > fs/f2fs/segment.h | 4 ++++
> > fs/f2fs/super.c | 21 ++++++++++++++++---
> > include/trace/events/f2fs.h | 14 ++++++++++++-
> > 7 files changed, 102 insertions(+), 24 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index 06bb2042385e..49b7e3918484 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
> > nid_t ino, pgoff_t idx, enum page_type type)
> > {
> > enum page_type btype = PAGE_TYPE_OF_BIO(type);
> > - struct f2fs_bio_info *io = &sbi->write_io[btype];
> > - bool ret;
> > + enum temp_type temp;
> > + struct f2fs_bio_info *io;
> > + bool ret = false;
> >
> > - down_read(&io->io_rwsem);
> > - ret = __has_merged_page(io, inode, ino, idx);
> > - up_read(&io->io_rwsem);
> > + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> > + io = sbi->write_io[btype] + temp;
> > +
> > + down_read(&io->io_rwsem);
> > + ret = __has_merged_page(io, inode, ino, idx);
> > + up_read(&io->io_rwsem);
> > +
> > + /* TODO: use HOT temp only for meta pages now. */
> > + if (ret || btype == META)
> > + break;
> > + }
> > return ret;
> > }
> >
> > static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> > struct inode *inode, nid_t ino, pgoff_t idx,
> > - enum page_type type)
> > + enum page_type type, enum temp_type temp)
> > {
> > enum page_type btype = PAGE_TYPE_OF_BIO(type);
> > - struct f2fs_bio_info *io = &sbi->write_io[btype];
> > + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
> >
> > down_write(&io->io_rwsem);
> >
> > @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> > up_write(&io->io_rwsem);
> > }
> >
> > +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
> > + struct inode *inode, nid_t ino, pgoff_t idx,
> > + enum page_type type, bool force)
> > +{
> > + enum temp_type temp;
> > +
> > + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
> > + return;
> > +
> > + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> > + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
> > +
> > + /* TODO: use HOT temp only for meta pages now. */
> > + if (type >= META)
> > + break;
> > + }
> > +}
> > +
> > void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
> > {
> > - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
> > + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
> > }
> >
> > void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> > struct inode *inode, nid_t ino, pgoff_t idx,
> > enum page_type type)
> > {
> > - if (has_merged_page(sbi, inode, ino, idx, type))
> > - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
> > + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
> > }
> >
> > void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
> > @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> > {
> > struct f2fs_sb_info *sbi = fio->sbi;
> > enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> > - struct f2fs_bio_info *io = &sbi->write_io[btype];
> > + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> > struct page *bio_page;
> > int err = 0;
> >
> > @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> > io->fio = *fio;
> > }
> >
> > - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
> > - PAGE_SIZE) {
> > + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
> > __submit_merged_bio(io);
> > goto alloc_new;
> > }
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index bf837458cb18..90e97bc11972 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -792,9 +792,17 @@ enum page_type {
> > OPU,
> > };
> >
> > +enum temp_type {
> > + HOT = 0, /* must be zero for meta bio */
> > + WARM,
> > + COLD,
> > + NR_TEMP_TYPE,
> > +};
> > +
> > struct f2fs_io_info {
> > struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
> > enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
> > + enum temp_type temp; /* contains HOT/WARM/COLD */
> > int op; /* contains REQ_OP_ */
> > int op_flags; /* req_flag_bits */
> > block_t new_blkaddr; /* new block address to be written */
> > @@ -880,7 +888,7 @@ struct f2fs_sb_info {
> >
> > /* for bio operations */
> > struct f2fs_bio_info read_io; /* for read bios */
> > - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
> > + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
> > struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
> > int write_io_size_bits; /* Write IO size bits */
> > mempool_t *write_io_dummy; /* Dummy pages */
> > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > index 67b87155bc48..e2b13558a915 100644
> > --- a/fs/f2fs/gc.c
> > +++ b/fs/f2fs/gc.c
> > @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
> > struct f2fs_io_info fio = {
> > .sbi = F2FS_I_SB(inode),
> > .type = DATA,
> > + .temp = COLD,
> > .op = REQ_OP_READ,
> > .op_flags = 0,
> > .encrypted_page = NULL,
> > @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
> > struct f2fs_io_info fio = {
> > .sbi = F2FS_I_SB(inode),
> > .type = DATA,
> > + .temp = COLD,
> > .op = REQ_OP_WRITE,
> > .op_flags = REQ_SYNC,
> > .old_blkaddr = NULL_ADDR,
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index c9f3a2faee21..da4fd2c29e86 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
> >
> > static int __get_segment_type(struct f2fs_io_info *fio)
> > {
> > + int type;
> > +
> > switch (fio->sbi->active_logs) {
> > case 2:
> > - return __get_segment_type_2(fio);
> > + type = __get_segment_type_2(fio);
> > + break;
> > case 4:
> > - return __get_segment_type_4(fio);
> > + type = __get_segment_type_4(fio);
> > + break;
> > + case 6:
> > + type = __get_segment_type_6(fio);
> > + break;
> > + default:
> > + f2fs_bug_on(fio->sbi, true);
> > }
> >
> > - /* NR_CURSEG_TYPE(6) logs by default */
> > - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
> > -
> > - return __get_segment_type_6(fio);
> > + if (IS_HOT(type))
> > + fio->temp = HOT;
> > + else if (IS_WARM(type))
> > + fio->temp = WARM;
> > + else
> > + fio->temp = COLD;
> > + return type;
> > }
> >
> > void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> > diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> > index 10bf05d4cff4..e9ba1f1d9723 100644
> > --- a/fs/f2fs/segment.h
> > +++ b/fs/f2fs/segment.h
> > @@ -27,6 +27,10 @@
> > #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
> > #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
> >
> > +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
> > +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
> > +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
> > +
> > #define IS_CURSEG(sbi, seg) \
> > (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
> > ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index 104a571a41c0..91599c9c3ef6 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
> > static void f2fs_put_super(struct super_block *sb)
> > {
> > struct f2fs_sb_info *sbi = F2FS_SB(sb);
> > + int i;
> >
> > if (sbi->s_proc) {
> > remove_proc_entry("segment_info", sbi->s_proc);
> > @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
> > destroy_device_list(sbi);
> > mempool_destroy(sbi->write_io_dummy);
> > destroy_percpu_info(sbi);
> > + for (i = 0; i < NR_PAGE_TYPE; i++)
> > + kfree(sbi->write_io[i]);
> > kfree(sbi);
> > }
> >
> > @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > sbi->read_io.sbi = sbi;
> > sbi->read_io.bio = NULL;
> > for (i = 0; i < NR_PAGE_TYPE; i++) {
> > - init_rwsem(&sbi->write_io[i].io_rwsem);
> > - sbi->write_io[i].sbi = sbi;
> > - sbi->write_io[i].bio = NULL;
> > + int n = (i == META) ? 1: NR_TEMP_TYPE;
> > + int j;
> > +
> > + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
> > + GFP_KERNEL);
> > + if (!sbi->write_io[i])
> > + goto free_options;
> > +
> > + for (j = HOT; j < n; j++) {
> > + init_rwsem(&sbi->write_io[i][j].io_rwsem);
> > + sbi->write_io[i][j].sbi = sbi;
> > + sbi->write_io[i][j].bio = NULL;
> > + }
> > }
> >
> > init_rwsem(&sbi->cp_rwsem);
> > @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > free_io_dummy:
> > mempool_destroy(sbi->write_io_dummy);
> > free_options:
> > + for (i = 0; i < NR_PAGE_TYPE; i++)
> > + kfree(sbi->write_io[i]);
> > destroy_percpu_info(sbi);
> > kfree(options);
> > free_sb_buf:
> > diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> > index 5805d92893a8..6f77a2755abb 100644
> > --- a/include/trace/events/f2fs.h
> > +++ b/include/trace/events/f2fs.h
> > @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
> > TRACE_DEFINE_ENUM(INMEM_REVOKE);
> > TRACE_DEFINE_ENUM(IPU);
> > TRACE_DEFINE_ENUM(OPU);
> > +TRACE_DEFINE_ENUM(HOT);
> > +TRACE_DEFINE_ENUM(WARM);
> > +TRACE_DEFINE_ENUM(COLD);
> > TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
> > TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
> > TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
> > @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
> > { IPU, "IN-PLACE" }, \
> > { OPU, "OUT-OF-PLACE" })
> >
> > +#define show_block_temp(temp) \
> > + __print_symbolic(temp, \
> > + { HOT, "HOT" }, \
> > + { WARM, "WARM" }, \
> > + { COLD, "COLD" })
> > +
> > #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
> > REQ_PREFLUSH | REQ_FUA)
> > #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
> > @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> > __field(block_t, new_blkaddr)
> > __field(int, op)
> > __field(int, op_flags)
> > + __field(int, temp)
> > __field(int, type)
> > ),
> >
> > @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> > __entry->new_blkaddr = fio->new_blkaddr;
> > __entry->op = fio->op;
> > __entry->op_flags = fio->op_flags;
> > + __entry->temp = fio->temp;
> > __entry->type = fio->type;
> > ),
> >
> > TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
> > - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
> > + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
> > show_dev_ino(__entry),
> > (unsigned long)__entry->index,
> > (unsigned long long)__entry->old_blkaddr,
> > (unsigned long long)__entry->new_blkaddr,
> > show_bio_type(__entry->op, __entry->op_flags),
> > + show_block_temp(__entry->temp),
> > show_block_type(__entry->type))
> > );
> >
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
@ 2017-05-11 2:35 ` Jaegeuk Kim
0 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2017-05-11 2:35 UTC (permalink / raw)
To: Chao Yu; +Cc: chao, linux-kernel, linux-f2fs-devel
On 05/11, Chao Yu wrote:
> On 2017/5/11 7:50, Jaegeuk Kim wrote:
> > On 05/09, Chao Yu wrote:
> >> Hi Jaegeuk,
> >>
> >> On 2017/5/9 5:23, Jaegeuk Kim wrote:
> >>> Hi Chao,
> >>>
> >>> I can't see a strong reason to split meta from data/node and rename the existing
> >>> function names. Instead, how about keeping the existing one while adding some
> >>> page types to deal with log types?
> >>
> >> Hmm.. before write this patch, I have thought about this implementation which
> >> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> >> different temperature log-header being with independent bio cache, io lock, and
> >> io list, eliminating interaction of different temperature IOs, also expanding
> >> f2fs' scalability when adding more log-headers. If we don't split meta from
> >> data/node, it's a little bit hard to approach this. What do you think?
> >
> > I submitted clean-up patches. How about this on top of them?
>
> After splitting, bio caches is connected to log-header, so why not moving bio
> cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
> - we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
> we have seg_type enum instead.
> - once we add special log-header like journal log or random IO log making
> DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
> codes to adjust it.
Well, I perfer to keep block allocation and IO control in a separate way as is.
Moreover, I don't think performance gain would be large enough comparing to what
we need to change both of whole flows.
Thanks,
>
> How do you think?
>
> Thanks,
>
> >
> > ---
> > fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
> > fs/f2fs/f2fs.h | 10 ++++++++-
> > fs/f2fs/gc.c | 2 ++
> > fs/f2fs/segment.c | 24 +++++++++++++++------
> > fs/f2fs/segment.h | 4 ++++
> > fs/f2fs/super.c | 21 ++++++++++++++++---
> > include/trace/events/f2fs.h | 14 ++++++++++++-
> > 7 files changed, 102 insertions(+), 24 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index 06bb2042385e..49b7e3918484 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
> > nid_t ino, pgoff_t idx, enum page_type type)
> > {
> > enum page_type btype = PAGE_TYPE_OF_BIO(type);
> > - struct f2fs_bio_info *io = &sbi->write_io[btype];
> > - bool ret;
> > + enum temp_type temp;
> > + struct f2fs_bio_info *io;
> > + bool ret = false;
> >
> > - down_read(&io->io_rwsem);
> > - ret = __has_merged_page(io, inode, ino, idx);
> > - up_read(&io->io_rwsem);
> > + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> > + io = sbi->write_io[btype] + temp;
> > +
> > + down_read(&io->io_rwsem);
> > + ret = __has_merged_page(io, inode, ino, idx);
> > + up_read(&io->io_rwsem);
> > +
> > + /* TODO: use HOT temp only for meta pages now. */
> > + if (ret || btype == META)
> > + break;
> > + }
> > return ret;
> > }
> >
> > static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> > struct inode *inode, nid_t ino, pgoff_t idx,
> > - enum page_type type)
> > + enum page_type type, enum temp_type temp)
> > {
> > enum page_type btype = PAGE_TYPE_OF_BIO(type);
> > - struct f2fs_bio_info *io = &sbi->write_io[btype];
> > + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
> >
> > down_write(&io->io_rwsem);
> >
> > @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> > up_write(&io->io_rwsem);
> > }
> >
> > +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
> > + struct inode *inode, nid_t ino, pgoff_t idx,
> > + enum page_type type, bool force)
> > +{
> > + enum temp_type temp;
> > +
> > + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
> > + return;
> > +
> > + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> > + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
> > +
> > + /* TODO: use HOT temp only for meta pages now. */
> > + if (type >= META)
> > + break;
> > + }
> > +}
> > +
> > void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
> > {
> > - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
> > + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
> > }
> >
> > void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> > struct inode *inode, nid_t ino, pgoff_t idx,
> > enum page_type type)
> > {
> > - if (has_merged_page(sbi, inode, ino, idx, type))
> > - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
> > + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
> > }
> >
> > void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
> > @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> > {
> > struct f2fs_sb_info *sbi = fio->sbi;
> > enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> > - struct f2fs_bio_info *io = &sbi->write_io[btype];
> > + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> > struct page *bio_page;
> > int err = 0;
> >
> > @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> > io->fio = *fio;
> > }
> >
> > - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
> > - PAGE_SIZE) {
> > + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
> > __submit_merged_bio(io);
> > goto alloc_new;
> > }
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index bf837458cb18..90e97bc11972 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -792,9 +792,17 @@ enum page_type {
> > OPU,
> > };
> >
> > +enum temp_type {
> > + HOT = 0, /* must be zero for meta bio */
> > + WARM,
> > + COLD,
> > + NR_TEMP_TYPE,
> > +};
> > +
> > struct f2fs_io_info {
> > struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
> > enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
> > + enum temp_type temp; /* contains HOT/WARM/COLD */
> > int op; /* contains REQ_OP_ */
> > int op_flags; /* req_flag_bits */
> > block_t new_blkaddr; /* new block address to be written */
> > @@ -880,7 +888,7 @@ struct f2fs_sb_info {
> >
> > /* for bio operations */
> > struct f2fs_bio_info read_io; /* for read bios */
> > - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
> > + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
> > struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
> > int write_io_size_bits; /* Write IO size bits */
> > mempool_t *write_io_dummy; /* Dummy pages */
> > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > index 67b87155bc48..e2b13558a915 100644
> > --- a/fs/f2fs/gc.c
> > +++ b/fs/f2fs/gc.c
> > @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
> > struct f2fs_io_info fio = {
> > .sbi = F2FS_I_SB(inode),
> > .type = DATA,
> > + .temp = COLD,
> > .op = REQ_OP_READ,
> > .op_flags = 0,
> > .encrypted_page = NULL,
> > @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
> > struct f2fs_io_info fio = {
> > .sbi = F2FS_I_SB(inode),
> > .type = DATA,
> > + .temp = COLD,
> > .op = REQ_OP_WRITE,
> > .op_flags = REQ_SYNC,
> > .old_blkaddr = NULL_ADDR,
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index c9f3a2faee21..da4fd2c29e86 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
> >
> > static int __get_segment_type(struct f2fs_io_info *fio)
> > {
> > + int type;
> > +
> > switch (fio->sbi->active_logs) {
> > case 2:
> > - return __get_segment_type_2(fio);
> > + type = __get_segment_type_2(fio);
> > + break;
> > case 4:
> > - return __get_segment_type_4(fio);
> > + type = __get_segment_type_4(fio);
> > + break;
> > + case 6:
> > + type = __get_segment_type_6(fio);
> > + break;
> > + default:
> > + f2fs_bug_on(fio->sbi, true);
> > }
> >
> > - /* NR_CURSEG_TYPE(6) logs by default */
> > - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
> > -
> > - return __get_segment_type_6(fio);
> > + if (IS_HOT(type))
> > + fio->temp = HOT;
> > + else if (IS_WARM(type))
> > + fio->temp = WARM;
> > + else
> > + fio->temp = COLD;
> > + return type;
> > }
> >
> > void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> > diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> > index 10bf05d4cff4..e9ba1f1d9723 100644
> > --- a/fs/f2fs/segment.h
> > +++ b/fs/f2fs/segment.h
> > @@ -27,6 +27,10 @@
> > #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
> > #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
> >
> > +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
> > +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
> > +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
> > +
> > #define IS_CURSEG(sbi, seg) \
> > (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
> > ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index 104a571a41c0..91599c9c3ef6 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
> > static void f2fs_put_super(struct super_block *sb)
> > {
> > struct f2fs_sb_info *sbi = F2FS_SB(sb);
> > + int i;
> >
> > if (sbi->s_proc) {
> > remove_proc_entry("segment_info", sbi->s_proc);
> > @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
> > destroy_device_list(sbi);
> > mempool_destroy(sbi->write_io_dummy);
> > destroy_percpu_info(sbi);
> > + for (i = 0; i < NR_PAGE_TYPE; i++)
> > + kfree(sbi->write_io[i]);
> > kfree(sbi);
> > }
> >
> > @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > sbi->read_io.sbi = sbi;
> > sbi->read_io.bio = NULL;
> > for (i = 0; i < NR_PAGE_TYPE; i++) {
> > - init_rwsem(&sbi->write_io[i].io_rwsem);
> > - sbi->write_io[i].sbi = sbi;
> > - sbi->write_io[i].bio = NULL;
> > + int n = (i == META) ? 1: NR_TEMP_TYPE;
> > + int j;
> > +
> > + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
> > + GFP_KERNEL);
> > + if (!sbi->write_io[i])
> > + goto free_options;
> > +
> > + for (j = HOT; j < n; j++) {
> > + init_rwsem(&sbi->write_io[i][j].io_rwsem);
> > + sbi->write_io[i][j].sbi = sbi;
> > + sbi->write_io[i][j].bio = NULL;
> > + }
> > }
> >
> > init_rwsem(&sbi->cp_rwsem);
> > @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > free_io_dummy:
> > mempool_destroy(sbi->write_io_dummy);
> > free_options:
> > + for (i = 0; i < NR_PAGE_TYPE; i++)
> > + kfree(sbi->write_io[i]);
> > destroy_percpu_info(sbi);
> > kfree(options);
> > free_sb_buf:
> > diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> > index 5805d92893a8..6f77a2755abb 100644
> > --- a/include/trace/events/f2fs.h
> > +++ b/include/trace/events/f2fs.h
> > @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
> > TRACE_DEFINE_ENUM(INMEM_REVOKE);
> > TRACE_DEFINE_ENUM(IPU);
> > TRACE_DEFINE_ENUM(OPU);
> > +TRACE_DEFINE_ENUM(HOT);
> > +TRACE_DEFINE_ENUM(WARM);
> > +TRACE_DEFINE_ENUM(COLD);
> > TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
> > TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
> > TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
> > @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
> > { IPU, "IN-PLACE" }, \
> > { OPU, "OUT-OF-PLACE" })
> >
> > +#define show_block_temp(temp) \
> > + __print_symbolic(temp, \
> > + { HOT, "HOT" }, \
> > + { WARM, "WARM" }, \
> > + { COLD, "COLD" })
> > +
> > #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
> > REQ_PREFLUSH | REQ_FUA)
> > #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
> > @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> > __field(block_t, new_blkaddr)
> > __field(int, op)
> > __field(int, op_flags)
> > + __field(int, temp)
> > __field(int, type)
> > ),
> >
> > @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> > __entry->new_blkaddr = fio->new_blkaddr;
> > __entry->op = fio->op;
> > __entry->op_flags = fio->op_flags;
> > + __entry->temp = fio->temp;
> > __entry->type = fio->type;
> > ),
> >
> > TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
> > - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
> > + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
> > show_dev_ino(__entry),
> > (unsigned long)__entry->index,
> > (unsigned long long)__entry->old_blkaddr,
> > (unsigned long long)__entry->new_blkaddr,
> > show_bio_type(__entry->op, __entry->op_flags),
> > + show_block_temp(__entry->temp),
> > show_block_type(__entry->type))
> > );
> >
> >
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
2017-05-11 2:35 ` Jaegeuk Kim
@ 2017-05-12 3:19 ` Chao Yu
-1 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-12 3:19 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel, chao
On 2017/5/11 10:35, Jaegeuk Kim wrote:
> On 05/11, Chao Yu wrote:
>> On 2017/5/11 7:50, Jaegeuk Kim wrote:
>>> On 05/09, Chao Yu wrote:
>>>> Hi Jaegeuk,
>>>>
>>>> On 2017/5/9 5:23, Jaegeuk Kim wrote:
>>>>> Hi Chao,
>>>>>
>>>>> I can't see a strong reason to split meta from data/node and rename the existing
>>>>> function names. Instead, how about keeping the existing one while adding some
>>>>> page types to deal with log types?
>>>>
>>>> Hmm.. before write this patch, I have thought about this implementation which
>>>> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
>>>> different temperature log-header being with independent bio cache, io lock, and
>>>> io list, eliminating interaction of different temperature IOs, also expanding
>>>> f2fs' scalability when adding more log-headers. If we don't split meta from
>>>> data/node, it's a little bit hard to approach this. What do you think?
>>>
>>> I submitted clean-up patches. How about this on top of them?
>>
>> After splitting, bio caches is connected to log-header, so why not moving bio
>> cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
>> - we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
>> we have seg_type enum instead.
>> - once we add special log-header like journal log or random IO log making
>> DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
>> codes to adjust it.
>
> Well, I perfer to keep block allocation and IO control in a separate way as is.
> Moreover, I don't think performance gain would be large enough comparing to what
> we need to change both of whole flows.
Alright, let's use your implementation. ;)
Could you resend this patch? and then I will rebase my patch on this one.
Thanks,
>
> Thanks,
>
>>
>> How do you think?
>>
>> Thanks,
>>
>>>
>>> ---
>>> fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
>>> fs/f2fs/f2fs.h | 10 ++++++++-
>>> fs/f2fs/gc.c | 2 ++
>>> fs/f2fs/segment.c | 24 +++++++++++++++------
>>> fs/f2fs/segment.h | 4 ++++
>>> fs/f2fs/super.c | 21 ++++++++++++++++---
>>> include/trace/events/f2fs.h | 14 ++++++++++++-
>>> 7 files changed, 102 insertions(+), 24 deletions(-)
>>>
>>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>>> index 06bb2042385e..49b7e3918484 100644
>>> --- a/fs/f2fs/data.c
>>> +++ b/fs/f2fs/data.c
>>> @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
>>> nid_t ino, pgoff_t idx, enum page_type type)
>>> {
>>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
>>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>>> - bool ret;
>>> + enum temp_type temp;
>>> + struct f2fs_bio_info *io;
>>> + bool ret = false;
>>>
>>> - down_read(&io->io_rwsem);
>>> - ret = __has_merged_page(io, inode, ino, idx);
>>> - up_read(&io->io_rwsem);
>>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
>>> + io = sbi->write_io[btype] + temp;
>>> +
>>> + down_read(&io->io_rwsem);
>>> + ret = __has_merged_page(io, inode, ino, idx);
>>> + up_read(&io->io_rwsem);
>>> +
>>> + /* TODO: use HOT temp only for meta pages now. */
>>> + if (ret || btype == META)
>>> + break;
>>> + }
>>> return ret;
>>> }
>>>
>>> static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
>>> struct inode *inode, nid_t ino, pgoff_t idx,
>>> - enum page_type type)
>>> + enum page_type type, enum temp_type temp)
>>> {
>>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
>>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>>> + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
>>>
>>> down_write(&io->io_rwsem);
>>>
>>> @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
>>> up_write(&io->io_rwsem);
>>> }
>>>
>>> +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
>>> + struct inode *inode, nid_t ino, pgoff_t idx,
>>> + enum page_type type, bool force)
>>> +{
>>> + enum temp_type temp;
>>> +
>>> + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
>>> + return;
>>> +
>>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
>>> + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
>>> +
>>> + /* TODO: use HOT temp only for meta pages now. */
>>> + if (type >= META)
>>> + break;
>>> + }
>>> +}
>>> +
>>> void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
>>> {
>>> - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
>>> + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
>>> }
>>>
>>> void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
>>> struct inode *inode, nid_t ino, pgoff_t idx,
>>> enum page_type type)
>>> {
>>> - if (has_merged_page(sbi, inode, ino, idx, type))
>>> - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
>>> + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
>>> }
>>>
>>> void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
>>> @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
>>> {
>>> struct f2fs_sb_info *sbi = fio->sbi;
>>> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
>>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>>> + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
>>> struct page *bio_page;
>>> int err = 0;
>>>
>>> @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
>>> io->fio = *fio;
>>> }
>>>
>>> - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
>>> - PAGE_SIZE) {
>>> + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
>>> __submit_merged_bio(io);
>>> goto alloc_new;
>>> }
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index bf837458cb18..90e97bc11972 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -792,9 +792,17 @@ enum page_type {
>>> OPU,
>>> };
>>>
>>> +enum temp_type {
>>> + HOT = 0, /* must be zero for meta bio */
>>> + WARM,
>>> + COLD,
>>> + NR_TEMP_TYPE,
>>> +};
>>> +
>>> struct f2fs_io_info {
>>> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
>>> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
>>> + enum temp_type temp; /* contains HOT/WARM/COLD */
>>> int op; /* contains REQ_OP_ */
>>> int op_flags; /* req_flag_bits */
>>> block_t new_blkaddr; /* new block address to be written */
>>> @@ -880,7 +888,7 @@ struct f2fs_sb_info {
>>>
>>> /* for bio operations */
>>> struct f2fs_bio_info read_io; /* for read bios */
>>> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
>>> + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
>>> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
>>> int write_io_size_bits; /* Write IO size bits */
>>> mempool_t *write_io_dummy; /* Dummy pages */
>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>> index 67b87155bc48..e2b13558a915 100644
>>> --- a/fs/f2fs/gc.c
>>> +++ b/fs/f2fs/gc.c
>>> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
>>> struct f2fs_io_info fio = {
>>> .sbi = F2FS_I_SB(inode),
>>> .type = DATA,
>>> + .temp = COLD,
>>> .op = REQ_OP_READ,
>>> .op_flags = 0,
>>> .encrypted_page = NULL,
>>> @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
>>> struct f2fs_io_info fio = {
>>> .sbi = F2FS_I_SB(inode),
>>> .type = DATA,
>>> + .temp = COLD,
>>> .op = REQ_OP_WRITE,
>>> .op_flags = REQ_SYNC,
>>> .old_blkaddr = NULL_ADDR,
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index c9f3a2faee21..da4fd2c29e86 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
>>>
>>> static int __get_segment_type(struct f2fs_io_info *fio)
>>> {
>>> + int type;
>>> +
>>> switch (fio->sbi->active_logs) {
>>> case 2:
>>> - return __get_segment_type_2(fio);
>>> + type = __get_segment_type_2(fio);
>>> + break;
>>> case 4:
>>> - return __get_segment_type_4(fio);
>>> + type = __get_segment_type_4(fio);
>>> + break;
>>> + case 6:
>>> + type = __get_segment_type_6(fio);
>>> + break;
>>> + default:
>>> + f2fs_bug_on(fio->sbi, true);
>>> }
>>>
>>> - /* NR_CURSEG_TYPE(6) logs by default */
>>> - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
>>> -
>>> - return __get_segment_type_6(fio);
>>> + if (IS_HOT(type))
>>> + fio->temp = HOT;
>>> + else if (IS_WARM(type))
>>> + fio->temp = WARM;
>>> + else
>>> + fio->temp = COLD;
>>> + return type;
>>> }
>>>
>>> void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>>> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
>>> index 10bf05d4cff4..e9ba1f1d9723 100644
>>> --- a/fs/f2fs/segment.h
>>> +++ b/fs/f2fs/segment.h
>>> @@ -27,6 +27,10 @@
>>> #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
>>> #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
>>>
>>> +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
>>> +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
>>> +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
>>> +
>>> #define IS_CURSEG(sbi, seg) \
>>> (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
>>> ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>> index 104a571a41c0..91599c9c3ef6 100644
>>> --- a/fs/f2fs/super.c
>>> +++ b/fs/f2fs/super.c
>>> @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
>>> static void f2fs_put_super(struct super_block *sb)
>>> {
>>> struct f2fs_sb_info *sbi = F2FS_SB(sb);
>>> + int i;
>>>
>>> if (sbi->s_proc) {
>>> remove_proc_entry("segment_info", sbi->s_proc);
>>> @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
>>> destroy_device_list(sbi);
>>> mempool_destroy(sbi->write_io_dummy);
>>> destroy_percpu_info(sbi);
>>> + for (i = 0; i < NR_PAGE_TYPE; i++)
>>> + kfree(sbi->write_io[i]);
>>> kfree(sbi);
>>> }
>>>
>>> @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>>> sbi->read_io.sbi = sbi;
>>> sbi->read_io.bio = NULL;
>>> for (i = 0; i < NR_PAGE_TYPE; i++) {
>>> - init_rwsem(&sbi->write_io[i].io_rwsem);
>>> - sbi->write_io[i].sbi = sbi;
>>> - sbi->write_io[i].bio = NULL;
>>> + int n = (i == META) ? 1: NR_TEMP_TYPE;
>>> + int j;
>>> +
>>> + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
>>> + GFP_KERNEL);
>>> + if (!sbi->write_io[i])
>>> + goto free_options;
>>> +
>>> + for (j = HOT; j < n; j++) {
>>> + init_rwsem(&sbi->write_io[i][j].io_rwsem);
>>> + sbi->write_io[i][j].sbi = sbi;
>>> + sbi->write_io[i][j].bio = NULL;
>>> + }
>>> }
>>>
>>> init_rwsem(&sbi->cp_rwsem);
>>> @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>>> free_io_dummy:
>>> mempool_destroy(sbi->write_io_dummy);
>>> free_options:
>>> + for (i = 0; i < NR_PAGE_TYPE; i++)
>>> + kfree(sbi->write_io[i]);
>>> destroy_percpu_info(sbi);
>>> kfree(options);
>>> free_sb_buf:
>>> diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
>>> index 5805d92893a8..6f77a2755abb 100644
>>> --- a/include/trace/events/f2fs.h
>>> +++ b/include/trace/events/f2fs.h
>>> @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
>>> TRACE_DEFINE_ENUM(INMEM_REVOKE);
>>> TRACE_DEFINE_ENUM(IPU);
>>> TRACE_DEFINE_ENUM(OPU);
>>> +TRACE_DEFINE_ENUM(HOT);
>>> +TRACE_DEFINE_ENUM(WARM);
>>> +TRACE_DEFINE_ENUM(COLD);
>>> TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
>>> TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
>>> TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
>>> @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
>>> { IPU, "IN-PLACE" }, \
>>> { OPU, "OUT-OF-PLACE" })
>>>
>>> +#define show_block_temp(temp) \
>>> + __print_symbolic(temp, \
>>> + { HOT, "HOT" }, \
>>> + { WARM, "WARM" }, \
>>> + { COLD, "COLD" })
>>> +
>>> #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
>>> REQ_PREFLUSH | REQ_FUA)
>>> #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
>>> @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
>>> __field(block_t, new_blkaddr)
>>> __field(int, op)
>>> __field(int, op_flags)
>>> + __field(int, temp)
>>> __field(int, type)
>>> ),
>>>
>>> @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
>>> __entry->new_blkaddr = fio->new_blkaddr;
>>> __entry->op = fio->op;
>>> __entry->op_flags = fio->op_flags;
>>> + __entry->temp = fio->temp;
>>> __entry->type = fio->type;
>>> ),
>>>
>>> TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
>>> - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
>>> + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
>>> show_dev_ino(__entry),
>>> (unsigned long)__entry->index,
>>> (unsigned long long)__entry->old_blkaddr,
>>> (unsigned long long)__entry->new_blkaddr,
>>> show_bio_type(__entry->op, __entry->op_flags),
>>> + show_block_temp(__entry->temp),
>>> show_block_type(__entry->type))
>>> );
>>>
>>>
>
> .
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
@ 2017-05-12 3:19 ` Chao Yu
0 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-05-12 3:19 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel
On 2017/5/11 10:35, Jaegeuk Kim wrote:
> On 05/11, Chao Yu wrote:
>> On 2017/5/11 7:50, Jaegeuk Kim wrote:
>>> On 05/09, Chao Yu wrote:
>>>> Hi Jaegeuk,
>>>>
>>>> On 2017/5/9 5:23, Jaegeuk Kim wrote:
>>>>> Hi Chao,
>>>>>
>>>>> I can't see a strong reason to split meta from data/node and rename the existing
>>>>> function names. Instead, how about keeping the existing one while adding some
>>>>> page types to deal with log types?
>>>>
>>>> Hmm.. before write this patch, I have thought about this implementation which
>>>> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
>>>> different temperature log-header being with independent bio cache, io lock, and
>>>> io list, eliminating interaction of different temperature IOs, also expanding
>>>> f2fs' scalability when adding more log-headers. If we don't split meta from
>>>> data/node, it's a little bit hard to approach this. What do you think?
>>>
>>> I submitted clean-up patches. How about this on top of them?
>>
>> After splitting, bio caches is connected to log-header, so why not moving bio
>> cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
>> - we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
>> we have seg_type enum instead.
>> - once we add special log-header like journal log or random IO log making
>> DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
>> codes to adjust it.
>
> Well, I perfer to keep block allocation and IO control in a separate way as is.
> Moreover, I don't think performance gain would be large enough comparing to what
> we need to change both of whole flows.
Alright, let's use your implementation. ;)
Could you resend this patch? and then I will rebase my patch on this one.
Thanks,
>
> Thanks,
>
>>
>> How do you think?
>>
>> Thanks,
>>
>>>
>>> ---
>>> fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
>>> fs/f2fs/f2fs.h | 10 ++++++++-
>>> fs/f2fs/gc.c | 2 ++
>>> fs/f2fs/segment.c | 24 +++++++++++++++------
>>> fs/f2fs/segment.h | 4 ++++
>>> fs/f2fs/super.c | 21 ++++++++++++++++---
>>> include/trace/events/f2fs.h | 14 ++++++++++++-
>>> 7 files changed, 102 insertions(+), 24 deletions(-)
>>>
>>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>>> index 06bb2042385e..49b7e3918484 100644
>>> --- a/fs/f2fs/data.c
>>> +++ b/fs/f2fs/data.c
>>> @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
>>> nid_t ino, pgoff_t idx, enum page_type type)
>>> {
>>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
>>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>>> - bool ret;
>>> + enum temp_type temp;
>>> + struct f2fs_bio_info *io;
>>> + bool ret = false;
>>>
>>> - down_read(&io->io_rwsem);
>>> - ret = __has_merged_page(io, inode, ino, idx);
>>> - up_read(&io->io_rwsem);
>>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
>>> + io = sbi->write_io[btype] + temp;
>>> +
>>> + down_read(&io->io_rwsem);
>>> + ret = __has_merged_page(io, inode, ino, idx);
>>> + up_read(&io->io_rwsem);
>>> +
>>> + /* TODO: use HOT temp only for meta pages now. */
>>> + if (ret || btype == META)
>>> + break;
>>> + }
>>> return ret;
>>> }
>>>
>>> static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
>>> struct inode *inode, nid_t ino, pgoff_t idx,
>>> - enum page_type type)
>>> + enum page_type type, enum temp_type temp)
>>> {
>>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
>>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>>> + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
>>>
>>> down_write(&io->io_rwsem);
>>>
>>> @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
>>> up_write(&io->io_rwsem);
>>> }
>>>
>>> +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
>>> + struct inode *inode, nid_t ino, pgoff_t idx,
>>> + enum page_type type, bool force)
>>> +{
>>> + enum temp_type temp;
>>> +
>>> + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
>>> + return;
>>> +
>>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
>>> + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
>>> +
>>> + /* TODO: use HOT temp only for meta pages now. */
>>> + if (type >= META)
>>> + break;
>>> + }
>>> +}
>>> +
>>> void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
>>> {
>>> - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
>>> + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
>>> }
>>>
>>> void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
>>> struct inode *inode, nid_t ino, pgoff_t idx,
>>> enum page_type type)
>>> {
>>> - if (has_merged_page(sbi, inode, ino, idx, type))
>>> - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
>>> + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
>>> }
>>>
>>> void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
>>> @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
>>> {
>>> struct f2fs_sb_info *sbi = fio->sbi;
>>> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
>>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
>>> + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
>>> struct page *bio_page;
>>> int err = 0;
>>>
>>> @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
>>> io->fio = *fio;
>>> }
>>>
>>> - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
>>> - PAGE_SIZE) {
>>> + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
>>> __submit_merged_bio(io);
>>> goto alloc_new;
>>> }
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index bf837458cb18..90e97bc11972 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -792,9 +792,17 @@ enum page_type {
>>> OPU,
>>> };
>>>
>>> +enum temp_type {
>>> + HOT = 0, /* must be zero for meta bio */
>>> + WARM,
>>> + COLD,
>>> + NR_TEMP_TYPE,
>>> +};
>>> +
>>> struct f2fs_io_info {
>>> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
>>> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
>>> + enum temp_type temp; /* contains HOT/WARM/COLD */
>>> int op; /* contains REQ_OP_ */
>>> int op_flags; /* req_flag_bits */
>>> block_t new_blkaddr; /* new block address to be written */
>>> @@ -880,7 +888,7 @@ struct f2fs_sb_info {
>>>
>>> /* for bio operations */
>>> struct f2fs_bio_info read_io; /* for read bios */
>>> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
>>> + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
>>> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
>>> int write_io_size_bits; /* Write IO size bits */
>>> mempool_t *write_io_dummy; /* Dummy pages */
>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>> index 67b87155bc48..e2b13558a915 100644
>>> --- a/fs/f2fs/gc.c
>>> +++ b/fs/f2fs/gc.c
>>> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
>>> struct f2fs_io_info fio = {
>>> .sbi = F2FS_I_SB(inode),
>>> .type = DATA,
>>> + .temp = COLD,
>>> .op = REQ_OP_READ,
>>> .op_flags = 0,
>>> .encrypted_page = NULL,
>>> @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
>>> struct f2fs_io_info fio = {
>>> .sbi = F2FS_I_SB(inode),
>>> .type = DATA,
>>> + .temp = COLD,
>>> .op = REQ_OP_WRITE,
>>> .op_flags = REQ_SYNC,
>>> .old_blkaddr = NULL_ADDR,
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index c9f3a2faee21..da4fd2c29e86 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
>>>
>>> static int __get_segment_type(struct f2fs_io_info *fio)
>>> {
>>> + int type;
>>> +
>>> switch (fio->sbi->active_logs) {
>>> case 2:
>>> - return __get_segment_type_2(fio);
>>> + type = __get_segment_type_2(fio);
>>> + break;
>>> case 4:
>>> - return __get_segment_type_4(fio);
>>> + type = __get_segment_type_4(fio);
>>> + break;
>>> + case 6:
>>> + type = __get_segment_type_6(fio);
>>> + break;
>>> + default:
>>> + f2fs_bug_on(fio->sbi, true);
>>> }
>>>
>>> - /* NR_CURSEG_TYPE(6) logs by default */
>>> - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
>>> -
>>> - return __get_segment_type_6(fio);
>>> + if (IS_HOT(type))
>>> + fio->temp = HOT;
>>> + else if (IS_WARM(type))
>>> + fio->temp = WARM;
>>> + else
>>> + fio->temp = COLD;
>>> + return type;
>>> }
>>>
>>> void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>>> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
>>> index 10bf05d4cff4..e9ba1f1d9723 100644
>>> --- a/fs/f2fs/segment.h
>>> +++ b/fs/f2fs/segment.h
>>> @@ -27,6 +27,10 @@
>>> #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
>>> #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
>>>
>>> +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
>>> +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
>>> +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
>>> +
>>> #define IS_CURSEG(sbi, seg) \
>>> (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
>>> ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>> index 104a571a41c0..91599c9c3ef6 100644
>>> --- a/fs/f2fs/super.c
>>> +++ b/fs/f2fs/super.c
>>> @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
>>> static void f2fs_put_super(struct super_block *sb)
>>> {
>>> struct f2fs_sb_info *sbi = F2FS_SB(sb);
>>> + int i;
>>>
>>> if (sbi->s_proc) {
>>> remove_proc_entry("segment_info", sbi->s_proc);
>>> @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
>>> destroy_device_list(sbi);
>>> mempool_destroy(sbi->write_io_dummy);
>>> destroy_percpu_info(sbi);
>>> + for (i = 0; i < NR_PAGE_TYPE; i++)
>>> + kfree(sbi->write_io[i]);
>>> kfree(sbi);
>>> }
>>>
>>> @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>>> sbi->read_io.sbi = sbi;
>>> sbi->read_io.bio = NULL;
>>> for (i = 0; i < NR_PAGE_TYPE; i++) {
>>> - init_rwsem(&sbi->write_io[i].io_rwsem);
>>> - sbi->write_io[i].sbi = sbi;
>>> - sbi->write_io[i].bio = NULL;
>>> + int n = (i == META) ? 1: NR_TEMP_TYPE;
>>> + int j;
>>> +
>>> + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
>>> + GFP_KERNEL);
>>> + if (!sbi->write_io[i])
>>> + goto free_options;
>>> +
>>> + for (j = HOT; j < n; j++) {
>>> + init_rwsem(&sbi->write_io[i][j].io_rwsem);
>>> + sbi->write_io[i][j].sbi = sbi;
>>> + sbi->write_io[i][j].bio = NULL;
>>> + }
>>> }
>>>
>>> init_rwsem(&sbi->cp_rwsem);
>>> @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>>> free_io_dummy:
>>> mempool_destroy(sbi->write_io_dummy);
>>> free_options:
>>> + for (i = 0; i < NR_PAGE_TYPE; i++)
>>> + kfree(sbi->write_io[i]);
>>> destroy_percpu_info(sbi);
>>> kfree(options);
>>> free_sb_buf:
>>> diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
>>> index 5805d92893a8..6f77a2755abb 100644
>>> --- a/include/trace/events/f2fs.h
>>> +++ b/include/trace/events/f2fs.h
>>> @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
>>> TRACE_DEFINE_ENUM(INMEM_REVOKE);
>>> TRACE_DEFINE_ENUM(IPU);
>>> TRACE_DEFINE_ENUM(OPU);
>>> +TRACE_DEFINE_ENUM(HOT);
>>> +TRACE_DEFINE_ENUM(WARM);
>>> +TRACE_DEFINE_ENUM(COLD);
>>> TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
>>> TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
>>> TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
>>> @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
>>> { IPU, "IN-PLACE" }, \
>>> { OPU, "OUT-OF-PLACE" })
>>>
>>> +#define show_block_temp(temp) \
>>> + __print_symbolic(temp, \
>>> + { HOT, "HOT" }, \
>>> + { WARM, "WARM" }, \
>>> + { COLD, "COLD" })
>>> +
>>> #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
>>> REQ_PREFLUSH | REQ_FUA)
>>> #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
>>> @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
>>> __field(block_t, new_blkaddr)
>>> __field(int, op)
>>> __field(int, op_flags)
>>> + __field(int, temp)
>>> __field(int, type)
>>> ),
>>>
>>> @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
>>> __entry->new_blkaddr = fio->new_blkaddr;
>>> __entry->op = fio->op;
>>> __entry->op_flags = fio->op_flags;
>>> + __entry->temp = fio->temp;
>>> __entry->type = fio->type;
>>> ),
>>>
>>> TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
>>> - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
>>> + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
>>> show_dev_ino(__entry),
>>> (unsigned long)__entry->index,
>>> (unsigned long long)__entry->old_blkaddr,
>>> (unsigned long long)__entry->new_blkaddr,
>>> show_bio_type(__entry->op, __entry->op_flags),
>>> + show_block_temp(__entry->temp),
>>> show_block_type(__entry->type))
>>> );
>>>
>>>
>
> .
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs: split bio cache
2017-05-12 3:19 ` Chao Yu
@ 2017-05-12 17:43 ` Jaegeuk Kim
-1 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2017-05-12 17:43 UTC (permalink / raw)
To: Chao Yu; +Cc: chao, linux-kernel, linux-f2fs-devel
On 05/12, Chao Yu wrote:
> On 2017/5/11 10:35, Jaegeuk Kim wrote:
> > On 05/11, Chao Yu wrote:
> >> On 2017/5/11 7:50, Jaegeuk Kim wrote:
> >>> On 05/09, Chao Yu wrote:
> >>>> Hi Jaegeuk,
> >>>>
> >>>> On 2017/5/9 5:23, Jaegeuk Kim wrote:
> >>>>> Hi Chao,
> >>>>>
> >>>>> I can't see a strong reason to split meta from data/node and rename the existing
> >>>>> function names. Instead, how about keeping the existing one while adding some
> >>>>> page types to deal with log types?
> >>>>
> >>>> Hmm.. before write this patch, I have thought about this implementation which
> >>>> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> >>>> different temperature log-header being with independent bio cache, io lock, and
> >>>> io list, eliminating interaction of different temperature IOs, also expanding
> >>>> f2fs' scalability when adding more log-headers. If we don't split meta from
> >>>> data/node, it's a little bit hard to approach this. What do you think?
> >>>
> >>> I submitted clean-up patches. How about this on top of them?
> >>
> >> After splitting, bio caches is connected to log-header, so why not moving bio
> >> cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
> >> - we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
> >> we have seg_type enum instead.
> >> - once we add special log-header like journal log or random IO log making
> >> DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
> >> codes to adjust it.
> >
> > Well, I perfer to keep block allocation and IO control in a separate way as is.
> > Moreover, I don't think performance gain would be large enough comparing to what
> > we need to change both of whole flows.
>
> Alright, let's use your implementation. ;)
>
> Could you resend this patch? and then I will rebase my patch on this one.
I just pushed them into dev-test branch, and have been conducting stress tests.
Thanks,
>
> Thanks,
>
> >
> > Thanks,
> >
> >>
> >> How do you think?
> >>
> >> Thanks,
> >>
> >>>
> >>> ---
> >>> fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
> >>> fs/f2fs/f2fs.h | 10 ++++++++-
> >>> fs/f2fs/gc.c | 2 ++
> >>> fs/f2fs/segment.c | 24 +++++++++++++++------
> >>> fs/f2fs/segment.h | 4 ++++
> >>> fs/f2fs/super.c | 21 ++++++++++++++++---
> >>> include/trace/events/f2fs.h | 14 ++++++++++++-
> >>> 7 files changed, 102 insertions(+), 24 deletions(-)
> >>>
> >>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >>> index 06bb2042385e..49b7e3918484 100644
> >>> --- a/fs/f2fs/data.c
> >>> +++ b/fs/f2fs/data.c
> >>> @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
> >>> nid_t ino, pgoff_t idx, enum page_type type)
> >>> {
> >>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> >>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> >>> - bool ret;
> >>> + enum temp_type temp;
> >>> + struct f2fs_bio_info *io;
> >>> + bool ret = false;
> >>>
> >>> - down_read(&io->io_rwsem);
> >>> - ret = __has_merged_page(io, inode, ino, idx);
> >>> - up_read(&io->io_rwsem);
> >>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> >>> + io = sbi->write_io[btype] + temp;
> >>> +
> >>> + down_read(&io->io_rwsem);
> >>> + ret = __has_merged_page(io, inode, ino, idx);
> >>> + up_read(&io->io_rwsem);
> >>> +
> >>> + /* TODO: use HOT temp only for meta pages now. */
> >>> + if (ret || btype == META)
> >>> + break;
> >>> + }
> >>> return ret;
> >>> }
> >>>
> >>> static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> >>> struct inode *inode, nid_t ino, pgoff_t idx,
> >>> - enum page_type type)
> >>> + enum page_type type, enum temp_type temp)
> >>> {
> >>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> >>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> >>> + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
> >>>
> >>> down_write(&io->io_rwsem);
> >>>
> >>> @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> >>> up_write(&io->io_rwsem);
> >>> }
> >>>
> >>> +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
> >>> + struct inode *inode, nid_t ino, pgoff_t idx,
> >>> + enum page_type type, bool force)
> >>> +{
> >>> + enum temp_type temp;
> >>> +
> >>> + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
> >>> + return;
> >>> +
> >>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> >>> + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
> >>> +
> >>> + /* TODO: use HOT temp only for meta pages now. */
> >>> + if (type >= META)
> >>> + break;
> >>> + }
> >>> +}
> >>> +
> >>> void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
> >>> {
> >>> - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
> >>> + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
> >>> }
> >>>
> >>> void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> >>> struct inode *inode, nid_t ino, pgoff_t idx,
> >>> enum page_type type)
> >>> {
> >>> - if (has_merged_page(sbi, inode, ino, idx, type))
> >>> - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
> >>> + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
> >>> }
> >>>
> >>> void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
> >>> @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> >>> {
> >>> struct f2fs_sb_info *sbi = fio->sbi;
> >>> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> >>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> >>> + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> >>> struct page *bio_page;
> >>> int err = 0;
> >>>
> >>> @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> >>> io->fio = *fio;
> >>> }
> >>>
> >>> - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
> >>> - PAGE_SIZE) {
> >>> + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
> >>> __submit_merged_bio(io);
> >>> goto alloc_new;
> >>> }
> >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> >>> index bf837458cb18..90e97bc11972 100644
> >>> --- a/fs/f2fs/f2fs.h
> >>> +++ b/fs/f2fs/f2fs.h
> >>> @@ -792,9 +792,17 @@ enum page_type {
> >>> OPU,
> >>> };
> >>>
> >>> +enum temp_type {
> >>> + HOT = 0, /* must be zero for meta bio */
> >>> + WARM,
> >>> + COLD,
> >>> + NR_TEMP_TYPE,
> >>> +};
> >>> +
> >>> struct f2fs_io_info {
> >>> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
> >>> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
> >>> + enum temp_type temp; /* contains HOT/WARM/COLD */
> >>> int op; /* contains REQ_OP_ */
> >>> int op_flags; /* req_flag_bits */
> >>> block_t new_blkaddr; /* new block address to be written */
> >>> @@ -880,7 +888,7 @@ struct f2fs_sb_info {
> >>>
> >>> /* for bio operations */
> >>> struct f2fs_bio_info read_io; /* for read bios */
> >>> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
> >>> + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
> >>> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
> >>> int write_io_size_bits; /* Write IO size bits */
> >>> mempool_t *write_io_dummy; /* Dummy pages */
> >>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> >>> index 67b87155bc48..e2b13558a915 100644
> >>> --- a/fs/f2fs/gc.c
> >>> +++ b/fs/f2fs/gc.c
> >>> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
> >>> struct f2fs_io_info fio = {
> >>> .sbi = F2FS_I_SB(inode),
> >>> .type = DATA,
> >>> + .temp = COLD,
> >>> .op = REQ_OP_READ,
> >>> .op_flags = 0,
> >>> .encrypted_page = NULL,
> >>> @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
> >>> struct f2fs_io_info fio = {
> >>> .sbi = F2FS_I_SB(inode),
> >>> .type = DATA,
> >>> + .temp = COLD,
> >>> .op = REQ_OP_WRITE,
> >>> .op_flags = REQ_SYNC,
> >>> .old_blkaddr = NULL_ADDR,
> >>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> >>> index c9f3a2faee21..da4fd2c29e86 100644
> >>> --- a/fs/f2fs/segment.c
> >>> +++ b/fs/f2fs/segment.c
> >>> @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
> >>>
> >>> static int __get_segment_type(struct f2fs_io_info *fio)
> >>> {
> >>> + int type;
> >>> +
> >>> switch (fio->sbi->active_logs) {
> >>> case 2:
> >>> - return __get_segment_type_2(fio);
> >>> + type = __get_segment_type_2(fio);
> >>> + break;
> >>> case 4:
> >>> - return __get_segment_type_4(fio);
> >>> + type = __get_segment_type_4(fio);
> >>> + break;
> >>> + case 6:
> >>> + type = __get_segment_type_6(fio);
> >>> + break;
> >>> + default:
> >>> + f2fs_bug_on(fio->sbi, true);
> >>> }
> >>>
> >>> - /* NR_CURSEG_TYPE(6) logs by default */
> >>> - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
> >>> -
> >>> - return __get_segment_type_6(fio);
> >>> + if (IS_HOT(type))
> >>> + fio->temp = HOT;
> >>> + else if (IS_WARM(type))
> >>> + fio->temp = WARM;
> >>> + else
> >>> + fio->temp = COLD;
> >>> + return type;
> >>> }
> >>>
> >>> void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >>> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> >>> index 10bf05d4cff4..e9ba1f1d9723 100644
> >>> --- a/fs/f2fs/segment.h
> >>> +++ b/fs/f2fs/segment.h
> >>> @@ -27,6 +27,10 @@
> >>> #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
> >>> #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
> >>>
> >>> +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
> >>> +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
> >>> +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
> >>> +
> >>> #define IS_CURSEG(sbi, seg) \
> >>> (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
> >>> ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
> >>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> >>> index 104a571a41c0..91599c9c3ef6 100644
> >>> --- a/fs/f2fs/super.c
> >>> +++ b/fs/f2fs/super.c
> >>> @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
> >>> static void f2fs_put_super(struct super_block *sb)
> >>> {
> >>> struct f2fs_sb_info *sbi = F2FS_SB(sb);
> >>> + int i;
> >>>
> >>> if (sbi->s_proc) {
> >>> remove_proc_entry("segment_info", sbi->s_proc);
> >>> @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
> >>> destroy_device_list(sbi);
> >>> mempool_destroy(sbi->write_io_dummy);
> >>> destroy_percpu_info(sbi);
> >>> + for (i = 0; i < NR_PAGE_TYPE; i++)
> >>> + kfree(sbi->write_io[i]);
> >>> kfree(sbi);
> >>> }
> >>>
> >>> @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> >>> sbi->read_io.sbi = sbi;
> >>> sbi->read_io.bio = NULL;
> >>> for (i = 0; i < NR_PAGE_TYPE; i++) {
> >>> - init_rwsem(&sbi->write_io[i].io_rwsem);
> >>> - sbi->write_io[i].sbi = sbi;
> >>> - sbi->write_io[i].bio = NULL;
> >>> + int n = (i == META) ? 1: NR_TEMP_TYPE;
> >>> + int j;
> >>> +
> >>> + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
> >>> + GFP_KERNEL);
> >>> + if (!sbi->write_io[i])
> >>> + goto free_options;
> >>> +
> >>> + for (j = HOT; j < n; j++) {
> >>> + init_rwsem(&sbi->write_io[i][j].io_rwsem);
> >>> + sbi->write_io[i][j].sbi = sbi;
> >>> + sbi->write_io[i][j].bio = NULL;
> >>> + }
> >>> }
> >>>
> >>> init_rwsem(&sbi->cp_rwsem);
> >>> @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> >>> free_io_dummy:
> >>> mempool_destroy(sbi->write_io_dummy);
> >>> free_options:
> >>> + for (i = 0; i < NR_PAGE_TYPE; i++)
> >>> + kfree(sbi->write_io[i]);
> >>> destroy_percpu_info(sbi);
> >>> kfree(options);
> >>> free_sb_buf:
> >>> diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> >>> index 5805d92893a8..6f77a2755abb 100644
> >>> --- a/include/trace/events/f2fs.h
> >>> +++ b/include/trace/events/f2fs.h
> >>> @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
> >>> TRACE_DEFINE_ENUM(INMEM_REVOKE);
> >>> TRACE_DEFINE_ENUM(IPU);
> >>> TRACE_DEFINE_ENUM(OPU);
> >>> +TRACE_DEFINE_ENUM(HOT);
> >>> +TRACE_DEFINE_ENUM(WARM);
> >>> +TRACE_DEFINE_ENUM(COLD);
> >>> TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
> >>> TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
> >>> TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
> >>> @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
> >>> { IPU, "IN-PLACE" }, \
> >>> { OPU, "OUT-OF-PLACE" })
> >>>
> >>> +#define show_block_temp(temp) \
> >>> + __print_symbolic(temp, \
> >>> + { HOT, "HOT" }, \
> >>> + { WARM, "WARM" }, \
> >>> + { COLD, "COLD" })
> >>> +
> >>> #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
> >>> REQ_PREFLUSH | REQ_FUA)
> >>> #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
> >>> @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> >>> __field(block_t, new_blkaddr)
> >>> __field(int, op)
> >>> __field(int, op_flags)
> >>> + __field(int, temp)
> >>> __field(int, type)
> >>> ),
> >>>
> >>> @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> >>> __entry->new_blkaddr = fio->new_blkaddr;
> >>> __entry->op = fio->op;
> >>> __entry->op_flags = fio->op_flags;
> >>> + __entry->temp = fio->temp;
> >>> __entry->type = fio->type;
> >>> ),
> >>>
> >>> TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
> >>> - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
> >>> + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
> >>> show_dev_ino(__entry),
> >>> (unsigned long)__entry->index,
> >>> (unsigned long long)__entry->old_blkaddr,
> >>> (unsigned long long)__entry->new_blkaddr,
> >>> show_bio_type(__entry->op, __entry->op_flags),
> >>> + show_block_temp(__entry->temp),
> >>> show_block_type(__entry->type))
> >>> );
> >>>
> >>>
> >
> > .
> >
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] f2fs: split bio cache
@ 2017-05-12 17:43 ` Jaegeuk Kim
0 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2017-05-12 17:43 UTC (permalink / raw)
To: Chao Yu; +Cc: chao, linux-kernel, linux-f2fs-devel
On 05/12, Chao Yu wrote:
> On 2017/5/11 10:35, Jaegeuk Kim wrote:
> > On 05/11, Chao Yu wrote:
> >> On 2017/5/11 7:50, Jaegeuk Kim wrote:
> >>> On 05/09, Chao Yu wrote:
> >>>> Hi Jaegeuk,
> >>>>
> >>>> On 2017/5/9 5:23, Jaegeuk Kim wrote:
> >>>>> Hi Chao,
> >>>>>
> >>>>> I can't see a strong reason to split meta from data/node and rename the existing
> >>>>> function names. Instead, how about keeping the existing one while adding some
> >>>>> page types to deal with log types?
> >>>>
> >>>> Hmm.. before write this patch, I have thought about this implementation which
> >>>> adds HOT_DATA/WARM_DATA/.. into page_type enum, but the final target is making
> >>>> different temperature log-header being with independent bio cache, io lock, and
> >>>> io list, eliminating interaction of different temperature IOs, also expanding
> >>>> f2fs' scalability when adding more log-headers. If we don't split meta from
> >>>> data/node, it's a little bit hard to approach this. What do you think?
> >>>
> >>> I submitted clean-up patches. How about this on top of them?
> >>
> >> After splitting, bio caches is connected to log-header, so why not moving bio
> >> cache into log-header (SM_I(sbi)->curseg_array)? after the merging:
> >> - we could avoid redundant enum. e.g. temp_type, page_type::{DATA/NODE}, since
> >> we have seg_type enum instead.
> >> - once we add special log-header like journal log or random IO log making
> >> DATA/NODE and HOT/WARM/COLD non-orthogonalization, we just need to change few
> >> codes to adjust it.
> >
> > Well, I perfer to keep block allocation and IO control in a separate way as is.
> > Moreover, I don't think performance gain would be large enough comparing to what
> > we need to change both of whole flows.
>
> Alright, let's use your implementation. ;)
>
> Could you resend this patch? and then I will rebase my patch on this one.
I just pushed them into dev-test branch, and have been conducting stress tests.
Thanks,
>
> Thanks,
>
> >
> > Thanks,
> >
> >>
> >> How do you think?
> >>
> >> Thanks,
> >>
> >>>
> >>> ---
> >>> fs/f2fs/data.c | 51 +++++++++++++++++++++++++++++++++------------
> >>> fs/f2fs/f2fs.h | 10 ++++++++-
> >>> fs/f2fs/gc.c | 2 ++
> >>> fs/f2fs/segment.c | 24 +++++++++++++++------
> >>> fs/f2fs/segment.h | 4 ++++
> >>> fs/f2fs/super.c | 21 ++++++++++++++++---
> >>> include/trace/events/f2fs.h | 14 ++++++++++++-
> >>> 7 files changed, 102 insertions(+), 24 deletions(-)
> >>>
> >>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >>> index 06bb2042385e..49b7e3918484 100644
> >>> --- a/fs/f2fs/data.c
> >>> +++ b/fs/f2fs/data.c
> >>> @@ -282,21 +282,30 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
> >>> nid_t ino, pgoff_t idx, enum page_type type)
> >>> {
> >>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> >>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> >>> - bool ret;
> >>> + enum temp_type temp;
> >>> + struct f2fs_bio_info *io;
> >>> + bool ret = false;
> >>>
> >>> - down_read(&io->io_rwsem);
> >>> - ret = __has_merged_page(io, inode, ino, idx);
> >>> - up_read(&io->io_rwsem);
> >>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> >>> + io = sbi->write_io[btype] + temp;
> >>> +
> >>> + down_read(&io->io_rwsem);
> >>> + ret = __has_merged_page(io, inode, ino, idx);
> >>> + up_read(&io->io_rwsem);
> >>> +
> >>> + /* TODO: use HOT temp only for meta pages now. */
> >>> + if (ret || btype == META)
> >>> + break;
> >>> + }
> >>> return ret;
> >>> }
> >>>
> >>> static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> >>> struct inode *inode, nid_t ino, pgoff_t idx,
> >>> - enum page_type type)
> >>> + enum page_type type, enum temp_type temp)
> >>> {
> >>> enum page_type btype = PAGE_TYPE_OF_BIO(type);
> >>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> >>> + struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
> >>>
> >>> down_write(&io->io_rwsem);
> >>>
> >>> @@ -316,17 +325,34 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
> >>> up_write(&io->io_rwsem);
> >>> }
> >>>
> >>> +static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
> >>> + struct inode *inode, nid_t ino, pgoff_t idx,
> >>> + enum page_type type, bool force)
> >>> +{
> >>> + enum temp_type temp;
> >>> +
> >>> + if (!force && !has_merged_page(sbi, inode, ino, idx, type))
> >>> + return;
> >>> +
> >>> + for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
> >>> + __f2fs_submit_merged_write(sbi, inode, ino, idx, type, temp);
> >>> +
> >>> + /* TODO: use HOT temp only for meta pages now. */
> >>> + if (type >= META)
> >>> + break;
> >>> + }
> >>> +}
> >>> +
> >>> void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
> >>> {
> >>> - __f2fs_submit_merged_write(sbi, NULL, 0, 0, type);
> >>> + __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
> >>> }
> >>>
> >>> void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
> >>> struct inode *inode, nid_t ino, pgoff_t idx,
> >>> enum page_type type)
> >>> {
> >>> - if (has_merged_page(sbi, inode, ino, idx, type))
> >>> - __f2fs_submit_merged_write(sbi, inode, ino, idx, type);
> >>> + __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
> >>> }
> >>>
> >>> void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
> >>> @@ -369,7 +395,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> >>> {
> >>> struct f2fs_sb_info *sbi = fio->sbi;
> >>> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> >>> - struct f2fs_bio_info *io = &sbi->write_io[btype];
> >>> + struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> >>> struct page *bio_page;
> >>> int err = 0;
> >>>
> >>> @@ -405,8 +431,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
> >>> io->fio = *fio;
> >>> }
> >>>
> >>> - if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) <
> >>> - PAGE_SIZE) {
> >>> + if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
> >>> __submit_merged_bio(io);
> >>> goto alloc_new;
> >>> }
> >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> >>> index bf837458cb18..90e97bc11972 100644
> >>> --- a/fs/f2fs/f2fs.h
> >>> +++ b/fs/f2fs/f2fs.h
> >>> @@ -792,9 +792,17 @@ enum page_type {
> >>> OPU,
> >>> };
> >>>
> >>> +enum temp_type {
> >>> + HOT = 0, /* must be zero for meta bio */
> >>> + WARM,
> >>> + COLD,
> >>> + NR_TEMP_TYPE,
> >>> +};
> >>> +
> >>> struct f2fs_io_info {
> >>> struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */
> >>> enum page_type type; /* contains DATA/NODE/META/META_FLUSH */
> >>> + enum temp_type temp; /* contains HOT/WARM/COLD */
> >>> int op; /* contains REQ_OP_ */
> >>> int op_flags; /* req_flag_bits */
> >>> block_t new_blkaddr; /* new block address to be written */
> >>> @@ -880,7 +888,7 @@ struct f2fs_sb_info {
> >>>
> >>> /* for bio operations */
> >>> struct f2fs_bio_info read_io; /* for read bios */
> >>> - struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
> >>> + struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
> >>> struct mutex wio_mutex[NODE + 1]; /* bio ordering for NODE/DATA */
> >>> int write_io_size_bits; /* Write IO size bits */
> >>> mempool_t *write_io_dummy; /* Dummy pages */
> >>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> >>> index 67b87155bc48..e2b13558a915 100644
> >>> --- a/fs/f2fs/gc.c
> >>> +++ b/fs/f2fs/gc.c
> >>> @@ -586,6 +586,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
> >>> struct f2fs_io_info fio = {
> >>> .sbi = F2FS_I_SB(inode),
> >>> .type = DATA,
> >>> + .temp = COLD,
> >>> .op = REQ_OP_READ,
> >>> .op_flags = 0,
> >>> .encrypted_page = NULL,
> >>> @@ -712,6 +713,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
> >>> struct f2fs_io_info fio = {
> >>> .sbi = F2FS_I_SB(inode),
> >>> .type = DATA,
> >>> + .temp = COLD,
> >>> .op = REQ_OP_WRITE,
> >>> .op_flags = REQ_SYNC,
> >>> .old_blkaddr = NULL_ADDR,
> >>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> >>> index c9f3a2faee21..da4fd2c29e86 100644
> >>> --- a/fs/f2fs/segment.c
> >>> +++ b/fs/f2fs/segment.c
> >>> @@ -2084,17 +2084,29 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
> >>>
> >>> static int __get_segment_type(struct f2fs_io_info *fio)
> >>> {
> >>> + int type;
> >>> +
> >>> switch (fio->sbi->active_logs) {
> >>> case 2:
> >>> - return __get_segment_type_2(fio);
> >>> + type = __get_segment_type_2(fio);
> >>> + break;
> >>> case 4:
> >>> - return __get_segment_type_4(fio);
> >>> + type = __get_segment_type_4(fio);
> >>> + break;
> >>> + case 6:
> >>> + type = __get_segment_type_6(fio);
> >>> + break;
> >>> + default:
> >>> + f2fs_bug_on(fio->sbi, true);
> >>> }
> >>>
> >>> - /* NR_CURSEG_TYPE(6) logs by default */
> >>> - f2fs_bug_on(fio->sbi, fio->sbi->active_logs != NR_CURSEG_TYPE);
> >>> -
> >>> - return __get_segment_type_6(fio);
> >>> + if (IS_HOT(type))
> >>> + fio->temp = HOT;
> >>> + else if (IS_WARM(type))
> >>> + fio->temp = WARM;
> >>> + else
> >>> + fio->temp = COLD;
> >>> + return type;
> >>> }
> >>>
> >>> void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >>> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> >>> index 10bf05d4cff4..e9ba1f1d9723 100644
> >>> --- a/fs/f2fs/segment.h
> >>> +++ b/fs/f2fs/segment.h
> >>> @@ -27,6 +27,10 @@
> >>> #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
> >>> #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
> >>>
> >>> +#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
> >>> +#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
> >>> +#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
> >>> +
> >>> #define IS_CURSEG(sbi, seg) \
> >>> (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
> >>> ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
> >>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> >>> index 104a571a41c0..91599c9c3ef6 100644
> >>> --- a/fs/f2fs/super.c
> >>> +++ b/fs/f2fs/super.c
> >>> @@ -768,6 +768,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
> >>> static void f2fs_put_super(struct super_block *sb)
> >>> {
> >>> struct f2fs_sb_info *sbi = F2FS_SB(sb);
> >>> + int i;
> >>>
> >>> if (sbi->s_proc) {
> >>> remove_proc_entry("segment_info", sbi->s_proc);
> >>> @@ -838,6 +839,8 @@ static void f2fs_put_super(struct super_block *sb)
> >>> destroy_device_list(sbi);
> >>> mempool_destroy(sbi->write_io_dummy);
> >>> destroy_percpu_info(sbi);
> >>> + for (i = 0; i < NR_PAGE_TYPE; i++)
> >>> + kfree(sbi->write_io[i]);
> >>> kfree(sbi);
> >>> }
> >>>
> >>> @@ -1954,9 +1957,19 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> >>> sbi->read_io.sbi = sbi;
> >>> sbi->read_io.bio = NULL;
> >>> for (i = 0; i < NR_PAGE_TYPE; i++) {
> >>> - init_rwsem(&sbi->write_io[i].io_rwsem);
> >>> - sbi->write_io[i].sbi = sbi;
> >>> - sbi->write_io[i].bio = NULL;
> >>> + int n = (i == META) ? 1: NR_TEMP_TYPE;
> >>> + int j;
> >>> +
> >>> + sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info),
> >>> + GFP_KERNEL);
> >>> + if (!sbi->write_io[i])
> >>> + goto free_options;
> >>> +
> >>> + for (j = HOT; j < n; j++) {
> >>> + init_rwsem(&sbi->write_io[i][j].io_rwsem);
> >>> + sbi->write_io[i][j].sbi = sbi;
> >>> + sbi->write_io[i][j].bio = NULL;
> >>> + }
> >>> }
> >>>
> >>> init_rwsem(&sbi->cp_rwsem);
> >>> @@ -2202,6 +2215,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> >>> free_io_dummy:
> >>> mempool_destroy(sbi->write_io_dummy);
> >>> free_options:
> >>> + for (i = 0; i < NR_PAGE_TYPE; i++)
> >>> + kfree(sbi->write_io[i]);
> >>> destroy_percpu_info(sbi);
> >>> kfree(options);
> >>> free_sb_buf:
> >>> diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> >>> index 5805d92893a8..6f77a2755abb 100644
> >>> --- a/include/trace/events/f2fs.h
> >>> +++ b/include/trace/events/f2fs.h
> >>> @@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
> >>> TRACE_DEFINE_ENUM(INMEM_REVOKE);
> >>> TRACE_DEFINE_ENUM(IPU);
> >>> TRACE_DEFINE_ENUM(OPU);
> >>> +TRACE_DEFINE_ENUM(HOT);
> >>> +TRACE_DEFINE_ENUM(WARM);
> >>> +TRACE_DEFINE_ENUM(COLD);
> >>> TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
> >>> TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
> >>> TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
> >>> @@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
> >>> { IPU, "IN-PLACE" }, \
> >>> { OPU, "OUT-OF-PLACE" })
> >>>
> >>> +#define show_block_temp(temp) \
> >>> + __print_symbolic(temp, \
> >>> + { HOT, "HOT" }, \
> >>> + { WARM, "WARM" }, \
> >>> + { COLD, "COLD" })
> >>> +
> >>> #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
> >>> REQ_PREFLUSH | REQ_FUA)
> >>> #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
> >>> @@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> >>> __field(block_t, new_blkaddr)
> >>> __field(int, op)
> >>> __field(int, op_flags)
> >>> + __field(int, temp)
> >>> __field(int, type)
> >>> ),
> >>>
> >>> @@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
> >>> __entry->new_blkaddr = fio->new_blkaddr;
> >>> __entry->op = fio->op;
> >>> __entry->op_flags = fio->op_flags;
> >>> + __entry->temp = fio->temp;
> >>> __entry->type = fio->type;
> >>> ),
> >>>
> >>> TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
> >>> - "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s",
> >>> + "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
> >>> show_dev_ino(__entry),
> >>> (unsigned long)__entry->index,
> >>> (unsigned long long)__entry->old_blkaddr,
> >>> (unsigned long long)__entry->new_blkaddr,
> >>> show_bio_type(__entry->op, __entry->op_flags),
> >>> + show_block_temp(__entry->temp),
> >>> show_block_type(__entry->type))
> >>> );
> >>>
> >>>
> >
> > .
> >
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 16+ messages in thread