Re: [f2fs-dev] [PATCH RFC] f2fs: introduce a method to make nat journal more fresh
On 2018/2/12 14:55, Yunlei He wrote: > This patch introduce a method to make nat journal more fresh: > i. sort set list using entry # plus cp version difference (last modify > set cp # and current cp #) > ii. if meet with cache hit, update last modify cp # to current cp # As we discuss off-line, I think we can record weighted average of cpver for all dirty nat entries into nat set. Thanks, > > Signed-off-by: Yunlei He> --- > fs/f2fs/f2fs.h | 2 ++ > fs/f2fs/node.c | 57 + > fs/f2fs/node.h | 2 ++ > 3 files changed, 45 insertions(+), 16 deletions(-) > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index b7ba496..bd1e775 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -297,6 +297,8 @@ struct fsync_inode_entry { > block_t last_dentry;/* block address locating the last dentry */ > }; > > +#define DEF_NAT_FACTOR 10 > + > #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats)) > #define sits_in_cursum(jnl) (le16_to_cpu((jnl)->n_sits)) > > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c > index ced986d..f3f89e3 100644 > --- a/fs/f2fs/node.c > +++ b/fs/f2fs/node.c > @@ -195,8 +195,8 @@ static void __del_from_nat_cache(struct f2fs_nm_info > *nm_i, struct nat_entry *e) > __free_nat_entry(e); > } > > -static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, > - struct nat_entry *ne) > +static void __set_nat_cache_dirty(struct f2fs_sb_info *sbi, bool > from_journal, > + struct f2fs_nm_info *nm_i, struct nat_entry *ne) > { > nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); > struct nat_entry_set *head; > @@ -209,9 +209,15 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info > *nm_i, > INIT_LIST_HEAD(>set_list); > head->set = set; > head->entry_cnt = 0; > + head->to_journal = false; > + head->cp_ver = cur_cp_version(F2FS_CKPT(sbi)); > f2fs_radix_tree_insert(_i->nat_set_root, set, head); > } > > + /* journal hit case, try to locate set in journal */ > + if (head->to_journal && !from_journal) > + head->cp_ver = cur_cp_version(F2FS_CKPT(sbi)); > + > if (get_nat_flag(ne, IS_DIRTY)) > goto refresh_list; > > @@ -359,7 +365,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, > struct node_info *ni, > nat_set_blkaddr(e, new_blkaddr); > if (new_blkaddr == NEW_ADDR || new_blkaddr == NULL_ADDR) > set_nat_flag(e, IS_CHECKPOINTED, false); > - __set_nat_cache_dirty(nm_i, e); > + __set_nat_cache_dirty(sbi, false, nm_i, e); > > /* update fsync_mark if its inode nat entry is still alive */ > if (ni->nid != ni->ino) > @@ -2397,14 +2403,30 @@ static void remove_nats_in_journal(struct > f2fs_sb_info *sbi) > spin_unlock(_i->nid_list_lock); > } > > - __set_nat_cache_dirty(nm_i, ne); > + __set_nat_cache_dirty(sbi, true, nm_i, ne); > } > update_nats_in_cursum(journal, -i); > up_write(>journal_rwsem); > } > > -static void __adjust_nat_entry_set(struct nat_entry_set *nes, > - struct list_head *head, int max) > +static bool cost_compare(struct f2fs_sb_info *sbi, > + struct nat_entry_set *nes, struct nat_entry_set * cur) > +{ > + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); > + __u64 cost1 = nes->entry_cnt * DEF_NAT_FACTOR + > + (nes->cp_ver <= cur_cp_version(ckpt)) ? > + cur_cp_version(ckpt) - nes->cp_ver : > + ULONG_MAX - nes->cp_ver + cur_cp_version(ckpt); > + __u64 cost2 = cur->entry_cnt * DEF_NAT_FACTOR + > + (cur->cp_ver <= cur_cp_version(ckpt)) ? > + cur_cp_version(ckpt) - cur->cp_ver : > + ULONG_MAX - cur->cp_ver + cur_cp_version(ckpt); > + > + return cost1 <= cost2; > +} > + > +static void __adjust_nat_entry_set(struct f2fs_sb_info *sbi, > + struct nat_entry_set *nes, struct list_head *head, int > max) > { > struct nat_entry_set *cur; > > @@ -2412,7 +2434,7 @@ static void __adjust_nat_entry_set(struct nat_entry_set > *nes, > goto add_out; > > list_for_each_entry(cur, head, set_list) { > - if (cur->entry_cnt >= nes->entry_cnt) { > + if (cost_compare(sbi, nes, cur)) { > list_add(>set_list, cur->set_list.prev); > return; > } > @@ -2460,7 +2482,6 @@ static void __flush_nat_entry_set(struct f2fs_sb_info > *sbi, > struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); > struct f2fs_journal *journal = curseg->journal; > nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK; > - bool to_journal = true; >
[f2fs-dev] [PATCH RFC] f2fs: introduce a method to make nat journal more fresh
This patch introduce a method to make nat journal more fresh: i. sort set list using entry # plus cp version difference (last modify set cp # and current cp #) ii. if meet with cache hit, update last modify cp # to current cp # Signed-off-by: Yunlei He--- fs/f2fs/f2fs.h | 2 ++ fs/f2fs/node.c | 57 + fs/f2fs/node.h | 2 ++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b7ba496..bd1e775 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -297,6 +297,8 @@ struct fsync_inode_entry { block_t last_dentry;/* block address locating the last dentry */ }; +#define DEF_NAT_FACTOR 10 + #define nats_in_cursum(jnl)(le16_to_cpu((jnl)->n_nats)) #define sits_in_cursum(jnl)(le16_to_cpu((jnl)->n_sits)) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index ced986d..f3f89e3 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -195,8 +195,8 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) __free_nat_entry(e); } -static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, - struct nat_entry *ne) +static void __set_nat_cache_dirty(struct f2fs_sb_info *sbi, bool from_journal, + struct f2fs_nm_info *nm_i, struct nat_entry *ne) { nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); struct nat_entry_set *head; @@ -209,9 +209,15 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, INIT_LIST_HEAD(>set_list); head->set = set; head->entry_cnt = 0; + head->to_journal = false; + head->cp_ver = cur_cp_version(F2FS_CKPT(sbi)); f2fs_radix_tree_insert(_i->nat_set_root, set, head); } + /* journal hit case, try to locate set in journal */ + if (head->to_journal && !from_journal) + head->cp_ver = cur_cp_version(F2FS_CKPT(sbi)); + if (get_nat_flag(ne, IS_DIRTY)) goto refresh_list; @@ -359,7 +365,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, nat_set_blkaddr(e, new_blkaddr); if (new_blkaddr == NEW_ADDR || new_blkaddr == NULL_ADDR) set_nat_flag(e, IS_CHECKPOINTED, false); - __set_nat_cache_dirty(nm_i, e); + __set_nat_cache_dirty(sbi, false, nm_i, e); /* update fsync_mark if its inode nat entry is still alive */ if (ni->nid != ni->ino) @@ -2397,14 +2403,30 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi) spin_unlock(_i->nid_list_lock); } - __set_nat_cache_dirty(nm_i, ne); + __set_nat_cache_dirty(sbi, true, nm_i, ne); } update_nats_in_cursum(journal, -i); up_write(>journal_rwsem); } -static void __adjust_nat_entry_set(struct nat_entry_set *nes, - struct list_head *head, int max) +static bool cost_compare(struct f2fs_sb_info *sbi, + struct nat_entry_set *nes, struct nat_entry_set * cur) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + __u64 cost1 = nes->entry_cnt * DEF_NAT_FACTOR + + (nes->cp_ver <= cur_cp_version(ckpt)) ? + cur_cp_version(ckpt) - nes->cp_ver : + ULONG_MAX - nes->cp_ver + cur_cp_version(ckpt); + __u64 cost2 = cur->entry_cnt * DEF_NAT_FACTOR + + (cur->cp_ver <= cur_cp_version(ckpt)) ? + cur_cp_version(ckpt) - cur->cp_ver : + ULONG_MAX - cur->cp_ver + cur_cp_version(ckpt); + + return cost1 <= cost2; +} + +static void __adjust_nat_entry_set(struct f2fs_sb_info *sbi, + struct nat_entry_set *nes, struct list_head *head, int max) { struct nat_entry_set *cur; @@ -2412,7 +2434,7 @@ static void __adjust_nat_entry_set(struct nat_entry_set *nes, goto add_out; list_for_each_entry(cur, head, set_list) { - if (cur->entry_cnt >= nes->entry_cnt) { + if (cost_compare(sbi, nes, cur)) { list_add(>set_list, cur->set_list.prev); return; } @@ -2460,7 +2482,6 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); struct f2fs_journal *journal = curseg->journal; nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK; - bool to_journal = true; struct f2fs_nat_block *nat_blk; struct nat_entry *ne, *cur; struct page *page = NULL; @@ -2470,11 +2491,13 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, * #1, flush nat entries to journal in current hot data summary block. * #2,