Re: [f2fs-dev] [PATCH RFC] f2fs: introduce a method to make nat journal more fresh

2018-02-13 Thread Chao Yu
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

2018-02-11 Thread Yunlei He
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,