On 2017/5/20 20:24, Hou Pengyang wrote: > during flush_nat_entries, we do: > 1) gang_lookup a radix tree, find all the dirty nat_entry_set; > 2) sort nat_entry_set by nat_entry_set->entry_cnt, in order to > write to journal as much as possible to avoid unnessary IO. > > This patch optimize the look_up & sort algorithm by introducing an array: > > f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK+1]; > (struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1]) > > dirty_set[1] links all nat_entry_set whose entry_cnt is 1 > dirty_set[2] links all nat_entry_set whose entry_cnt is 2 > ...... > dirty_set[N] links all nat_entry_set whose entry_cnt is N > > as one NAT block has NAT_ENTRY_PER_BLOCK entries at MOST, so there should NOT > be one nat_entry_set whose entry_cnt is larger than NAT_ENTRY_PER_BLOCK. > > So it is enough for f2fs_nm_info->dirty_set to link all nat_entry_sets in > system. > > Update: > we update nat_entry_set in real-time, e.g originally > nat_entry_set->entry_cnt is > 1, and licked by dirty_set[1]; then call __set_nat_cache_dirty to increase > nat_entry'sentry_cnt, we move this nat_entry_set ot dirty_set[2]'s tail, no > need to compare. > > Flush: > when flush dirty nat_entry_set, we just flush nat_entry_set from > f2fs_nm_info->dirty_set[0] to f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK], > where > gang_lookup and sort can be avoid. > > footprint of this algorithm: sizeof(struct list_head)*NAT_ENTRY_PER_BLOCK > = 8*455 = 3.6k bytes > > Signed-off-by: Hou Pengyang <houpengy...@huawei.com> > --- > fs/f2fs/f2fs.h | 2 ++ > fs/f2fs/node.c | 56 ++++++++++++++++++++++---------------------------------- > 2 files changed, 24 insertions(+), 34 deletions(-) > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 093d68a..88a96bb 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -628,6 +628,8 @@ struct f2fs_nm_info { > > /* for checkpoint */ > char *nat_bitmap; /* NAT bitmap pointer */ > + /* list dirty_set whose */ > + struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1]; /* for */ > > unsigned int nat_bits_blocks; /* # of nat bits blocks */ > unsigned char *nat_bits; /* NAT bits blocks */ > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c > index d22db8c..340c33d 100644 > --- a/fs/f2fs/node.c > +++ b/fs/f2fs/node.c > @@ -174,13 +174,14 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info > *nm_i, > list_move_tail(&ne->list, &head->entry_list); > nm_i->dirty_nat_cnt++; > head->entry_cnt++; > + list_move_tail(&head->set_list, &(nm_i->dirty_set[head->entry_cnt])); > set_nat_flag(ne, IS_DIRTY, true); > } > > static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, > struct nat_entry_set *set, struct nat_entry *ne) > { > - list_move_tail(&ne->list, &nm_i->nat_entries); > + list_move_tail(&ne->list, &nm_i->nat_entries); /* to be shrinked */ > set_nat_flag(ne, IS_DIRTY, false); > set->entry_cnt--; > nm_i->dirty_nat_cnt--; > @@ -2340,24 +2341,6 @@ static void remove_nats_in_journal(struct f2fs_sb_info > *sbi) > up_write(&curseg->journal_rwsem); > } > > -static void __adjust_nat_entry_set(struct nat_entry_set *nes, > - struct list_head *head, int max) > -{ > - struct nat_entry_set *cur; > - > - if (nes->entry_cnt >= max) > - goto add_out; > - > - list_for_each_entry(cur, head, set_list) { > - if (cur->entry_cnt >= nes->entry_cnt) { > - list_add(&nes->set_list, cur->set_list.prev); > - return; > - } > - } > -add_out: > - list_add_tail(&nes->set_list, head); > -} > - > static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, > struct page *page) > { > @@ -2460,9 +2443,11 @@ static void __flush_nat_entry_set(struct f2fs_sb_info > *sbi, > > /* Allow dirty nats by node block allocation in write_begin */ > if (!set->entry_cnt) { > + list_del(&set->set_list); > radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); > kmem_cache_free(nat_entry_set_slab, set); > - } > + } else > + f2fs_bug_on(sbi, 1);
Should remove this bug_on, because there will be new nat entries allocated during flush nat entries since we allow buffered write during checkpoint. Thanks, > } > > /* > @@ -2473,10 +2458,8 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, > struct cp_control *cpc) > struct f2fs_nm_info *nm_i = NM_I(sbi); > struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); > struct f2fs_journal *journal = curseg->journal; > - struct nat_entry_set *setvec[SETVEC_SIZE]; > struct nat_entry_set *set, *tmp; > - unsigned int found; > - nid_t set_idx = 0; > + int i; > LIST_HEAD(sets); > > if (!nm_i->dirty_nat_cnt) > @@ -2493,19 +2476,12 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, > struct cp_control *cpc) > !__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL)) > remove_nats_in_journal(sbi); > > - while ((found = __gang_lookup_nat_set(nm_i, > - set_idx, SETVEC_SIZE, setvec))) { > - unsigned idx; > - set_idx = setvec[found - 1]->set + 1; > - for (idx = 0; idx < found; idx++) > - __adjust_nat_entry_set(setvec[idx], &sets, > - MAX_NAT_JENTRIES(journal)); > + for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) { > + list_for_each_entry_safe(set, tmp, &nm_i->dirty_set[i], > set_list) > + __flush_nat_entry_set(sbi, set, cpc); > + f2fs_bug_on(sbi, !list_empty(&nm_i->dirty_set[i])); > } > > - /* flush dirty nats in nat entry set */ > - list_for_each_entry_safe(set, tmp, &sets, set_list) > - __flush_nat_entry_set(sbi, set, cpc); > - > up_write(&nm_i->nat_tree_lock); > /* Allow dirty nats by node block allocation in write_begin */ > } > @@ -2668,6 +2644,15 @@ static int init_free_nid_cache(struct f2fs_sb_info > *sbi) > return 0; > } > > +static void init_dirty_set_list(struct f2fs_sb_info *sbi) > +{ > + struct f2fs_nm_info *nm_i = NM_I(sbi); > + int i; > + > + for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) > + INIT_LIST_HEAD(&nm_i->dirty_set[i]); > +} > + > int build_node_manager(struct f2fs_sb_info *sbi) > { > int err; > @@ -2687,6 +2672,9 @@ int build_node_manager(struct f2fs_sb_info *sbi) > /* load free nid status from nat_bits table */ > load_free_nid_bitmap(sbi); > > + /* init dirty set list */ > + init_dirty_set_list(sbi); > + > build_free_nids(sbi, true, true); > return 0; > } > ------------------------------------------------------------------------------ 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