Currently, we dynamicly alloc sit_entry_set from slab, and link all the 
sit_entry_set
by sit_entry_set->set_list.

It is inefficient, since in add_sit_entry, we may need to travel all the list 
to find
the target sit_entry_set.

This patch fixes this by introducing a static array:

        f2fs_sm_info->sit_sets
        (struct sit_entry_set *sit_sets)

when we can find the target sit_entry_set in O(1) time, and then to update the 
sit_entry_set
info.

What's more there is no need to alloc/free slab memory.

footprint:(64bit machine)

        1T   :  sizeof(struct sit_entry_set) * 1T/(2M*55) = 0.87M
        128G :  sizeof(struct sit_entry_set) * 128G/(2M*55) = 1.16k
        64G  :  0.55k
        32G  :  0.27k
        

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/f2fs.h    |  2 +-
 fs/f2fs/segment.c | 75 +++++++++++++++++++------------------------------------
 fs/f2fs/segment.h |  1 -
 3 files changed, 26 insertions(+), 52 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 198da30..429d33b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -732,7 +732,7 @@ struct f2fs_sm_info {
        /* for batched trimming */
        unsigned int trim_sections;             /* # of sections to trim */
 
-       struct list_head sit_entry_set; /* sit entry set list */
+       struct sit_entry_set *sit_sets; /* # of dirty segment in this 
sit_entry_set */
        struct list_head dirty_set[SIT_ENTRY_PER_BLOCK + 1];
 
        unsigned int ipu_policy;        /* in-place-update policy */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index af470d3..04d6329 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -28,7 +28,6 @@
 
 static struct kmem_cache *discard_entry_slab;
 static struct kmem_cache *discard_cmd_slab;
-static struct kmem_cache *sit_entry_set_slab;
 static struct kmem_cache *inmem_entry_slab;
 
 static unsigned long __reverse_ulong(unsigned char *str)
@@ -2641,56 +2640,30 @@ static struct page *get_next_sit_page(struct 
f2fs_sb_info *sbi,
        return dst_page;
 }
 
-static struct sit_entry_set *grab_sit_entry_set(void)
-{
-       struct sit_entry_set *ses =
-                       f2fs_kmem_cache_alloc(sit_entry_set_slab, GFP_NOFS);
-
-       ses->entry_cnt = 0;
-       INIT_LIST_HEAD(&ses->set_list);
-       INIT_LIST_HEAD(&ses->cnt_list);
-       return ses;
-}
-
 static void release_sit_entry_set(struct sit_entry_set *ses)
 {
-       list_del(&ses->set_list);
        list_del(&ses->cnt_list);
-       kmem_cache_free(sit_entry_set_slab, ses);
+       INIT_LIST_HEAD(&ses->cnt_list);
 }
 
 static void add_sit_entry(struct f2fs_sb_info *sbi,
-                                       unsigned int segno, struct list_head 
*head)
+                                       unsigned int segno)
 {
-       struct sit_entry_set *ses;
        struct f2fs_sm_info *sm_i = SM_I(sbi);
-       unsigned int start_segno = START_SEGNO(segno);
+       unsigned int set = SIT_BLOCK_OFFSET(segno);
+       struct sit_entry_set *ses= &sm_i->sit_sets[set];
 
-       list_for_each_entry(ses, head, set_list) {
-               if (ses->start_segno == start_segno) {
-                       ses->entry_cnt++;
-                       list_move_tail(&ses->cnt_list, 
&sm_i->dirty_set[ses->entry_cnt]);
-                       return;
-               }
-       }
-
-       ses = grab_sit_entry_set();
-
-       ses->start_segno = start_segno;
        ses->entry_cnt++;
        list_move_tail(&ses->cnt_list, &sm_i->dirty_set[ses->entry_cnt]);
-       list_add(&ses->set_list, head);
 }
 
 static void add_sits_in_set(struct f2fs_sb_info *sbi)
 {
-       struct f2fs_sm_info *sm_info = SM_I(sbi);
-       struct list_head *set_list = &sm_info->sit_entry_set;
        unsigned long *bitmap = SIT_I(sbi)->dirty_sentries_bitmap;
        unsigned int segno;
 
        for_each_set_bit(segno, bitmap, MAIN_SEGS(sbi))
-               add_sit_entry(sbi, segno, set_list);
+               add_sit_entry(sbi, segno);
 }
 
 static void remove_sits_in_journal(struct f2fs_sb_info *sbi)
@@ -2708,7 +2681,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info 
*sbi)
                dirtied = __mark_sit_entry_dirty(sbi, segno);
 
                if (!dirtied)
-                       add_sit_entry(sbi, segno, &SM_I(sbi)->sit_entry_set);
+                       add_sit_entry(sbi, segno);
        }
        update_sits_in_cursum(journal, -i);
        up_write(&curseg->journal_rwsem);
@@ -2788,7 +2761,6 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
        struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
        struct f2fs_journal *journal = curseg->journal;
        struct sit_entry_set *ses, *tmp;
-       struct list_head *head = &SM_I(sbi)->sit_entry_set;
        bool to_journal = true;
        int i;
 
@@ -2826,7 +2798,6 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
                f2fs_bug_on(sbi, !list_empty(&sm_i->dirty_set[i]));
        }
 
-       f2fs_bug_on(sbi, !list_empty(head));
        f2fs_bug_on(sbi, sit_i->dirty_sentries);
 out:
        if (cpc->reason & CP_DISCARD) {
@@ -3191,13 +3162,26 @@ static void init_min_max_mtime(struct f2fs_sb_info *sbi)
        mutex_unlock(&sit_i->sentry_lock);
 }
 
-static void init_sit_dirty_set_list(struct f2fs_sb_info *sbi)
+static int init_sit_dirty_set_list(struct f2fs_sb_info *sbi)
 {
        struct f2fs_sm_info *sm_i = SM_I(sbi);
-       int i;
+       int i, entries;
+
+       entries = (MAIN_SEGS(sbi) + SIT_ENTRY_PER_BLOCK - 1) / 
SIT_ENTRY_PER_BLOCK;
+       sm_i->sit_sets = f2fs_kvzalloc(entries *
+                                                       sizeof(struct 
sit_entry_set), GFP_KERNEL);
+       if (!sm_i->sit_sets)
+               return -ENOMEM;
+
+       /* kvzalloc, so no need to init sit_entry_set->entry-cnt */
+       for (i = 0; i < entries; i++) {
+               INIT_LIST_HEAD(&sm_i->sit_sets[i].cnt_list);
+               sm_i->sit_sets[i].start_segno = i * SIT_ENTRY_PER_BLOCK;
+       }
 
        for (i = 0; i <= SIT_ENTRY_PER_BLOCK; i++)
                INIT_LIST_HEAD(&sm_i->dirty_set[i]);
+       return 0;
 }
 
 int build_segment_manager(struct f2fs_sb_info *sbi)
@@ -3233,8 +3217,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
 
        sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS;
 
-       INIT_LIST_HEAD(&sm_info->sit_entry_set);
-
        if (test_opt(sbi, FLUSH_MERGE) && !f2fs_readonly(sbi->sb)) {
                err = create_flush_cmd_control(sbi);
                if (err)
@@ -3264,8 +3246,8 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
                return err;
 
        init_min_max_mtime(sbi);
-       init_sit_dirty_set_list(sbi);
-       return 0;
+       err = init_sit_dirty_set_list(sbi);
+       return err;
 }
 
 static void discard_dirty_segmap(struct f2fs_sb_info *sbi,
@@ -3372,6 +3354,7 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi)
        destroy_curseg(sbi);
        destroy_free_segmap(sbi);
        destroy_sit_info(sbi);
+       kfree(sm_info->sit_sets);
        sbi->sm_info = NULL;
        kfree(sm_info);
 }
@@ -3388,19 +3371,12 @@ int __init create_segment_manager_caches(void)
        if (!discard_cmd_slab)
                goto destroy_discard_entry;
 
-       sit_entry_set_slab = f2fs_kmem_cache_create("sit_entry_set",
-                       sizeof(struct sit_entry_set));
-       if (!sit_entry_set_slab)
-               goto destroy_discard_cmd;
-
        inmem_entry_slab = f2fs_kmem_cache_create("inmem_page_entry",
                        sizeof(struct inmem_pages));
        if (!inmem_entry_slab)
-               goto destroy_sit_entry_set;
+               goto destroy_discard_cmd;
        return 0;
 
-destroy_sit_entry_set:
-       kmem_cache_destroy(sit_entry_set_slab);
 destroy_discard_cmd:
        kmem_cache_destroy(discard_cmd_slab);
 destroy_discard_entry:
@@ -3411,7 +3387,6 @@ int __init create_segment_manager_caches(void)
 
 void destroy_segment_manager_caches(void)
 {
-       kmem_cache_destroy(sit_entry_set_slab);
        kmem_cache_destroy(discard_cmd_slab);
        kmem_cache_destroy(discard_entry_slab);
        kmem_cache_destroy(inmem_entry_slab);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 3fca58e..dfb6ed5 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -294,7 +294,6 @@ struct curseg_info {
 };
 
 struct sit_entry_set {
-       struct list_head set_list;      /* link with all sit sets globally */
        struct list_head cnt_list;  /* link to sets with same # of dirty sit 
entries */
        unsigned int start_segno;       /* start segno of sits in set */
        unsigned int entry_cnt;         /* the # of sit entries in set */
-- 
2.10.1


------------------------------------------------------------------------------
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

Reply via email to