Like we optimized nat flushing with bucket sort, in this patch, we introduce a 
bucket 
 f2fs_sm_info->dirty to linked link all nat_entry_set to be flushed by their 
cnt_count.

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

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 88a96bb..198da30 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -733,6 +733,7 @@ struct f2fs_sm_info {
        unsigned int trim_sections;             /* # of sections to trim */
 
        struct list_head sit_entry_set; /* sit entry set list */
+       struct list_head dirty_set[SIT_ENTRY_PER_BLOCK + 1];
 
        unsigned int ipu_policy;        /* in-place-update policy */
        unsigned int min_ipu_util;      /* in-place-update threshold */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 2c99fec..af470d3 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2648,39 +2648,28 @@ static struct sit_entry_set *grab_sit_entry_set(void)
 
        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);
 }
 
-static void adjust_sit_entry_set(struct sit_entry_set *ses,
-                                               struct list_head *head)
-{
-       struct sit_entry_set *next = ses;
-
-       if (list_is_last(&ses->set_list, head))
-               return;
-
-       list_for_each_entry_continue(next, head, set_list)
-               if (ses->entry_cnt <= next->entry_cnt)
-                       break;
-
-       list_move_tail(&ses->set_list, &next->set_list);
-}
-
-static void add_sit_entry(unsigned int segno, struct list_head *head)
+static void add_sit_entry(struct f2fs_sb_info *sbi,
+                                       unsigned int segno, struct list_head 
*head)
 {
        struct sit_entry_set *ses;
+       struct f2fs_sm_info *sm_i = SM_I(sbi);
        unsigned int start_segno = START_SEGNO(segno);
 
        list_for_each_entry(ses, head, set_list) {
                if (ses->start_segno == start_segno) {
                        ses->entry_cnt++;
-                       adjust_sit_entry_set(ses, head);
+                       list_move_tail(&ses->cnt_list, 
&sm_i->dirty_set[ses->entry_cnt]);
                        return;
                }
        }
@@ -2689,6 +2678,7 @@ static void add_sit_entry(unsigned int segno, struct 
list_head *head)
 
        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);
 }
 
@@ -2700,7 +2690,7 @@ static void add_sits_in_set(struct f2fs_sb_info *sbi)
        unsigned int segno;
 
        for_each_set_bit(segno, bitmap, MAIN_SEGS(sbi))
-               add_sit_entry(segno, set_list);
+               add_sit_entry(sbi, segno, set_list);
 }
 
 static void remove_sits_in_journal(struct f2fs_sb_info *sbi)
@@ -2718,7 +2708,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info 
*sbi)
                dirtied = __mark_sit_entry_dirty(sbi, segno);
 
                if (!dirtied)
-                       add_sit_entry(segno, &SM_I(sbi)->sit_entry_set);
+                       add_sit_entry(sbi, segno, &SM_I(sbi)->sit_entry_set);
        }
        update_sits_in_cursum(journal, -i);
        up_write(&curseg->journal_rwsem);
@@ -2794,11 +2784,13 @@ static void __flush_sit_entry_set(struct f2fs_sb_info 
*sbi,
 void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 {
        struct sit_info *sit_i = SIT_I(sbi);
+       struct f2fs_sm_info *sm_i = SM_I(sbi);
        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;
 
        mutex_lock(&sit_i->sentry_lock);
 
@@ -2824,11 +2816,14 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
         * #1, flush sit entries to journal in current cold data summary block.
         * #2, flush sit entries to sit page.
         */
-       list_for_each_entry_safe(ses, tmp, head, set_list) {
-               if (to_journal &&
-                       !__has_cursum_space(journal, ses->entry_cnt, 
SIT_JOURNAL))
-                       to_journal = false;
-               __flush_sit_entry_set(sbi, ses, cpc, to_journal);
+       for (i = 0; i <= SIT_ENTRY_PER_BLOCK; i++) {
+               list_for_each_entry_safe(ses, tmp, &sm_i->dirty_set[i], 
cnt_list) {
+                       if (to_journal &&
+                               !__has_cursum_space(journal, ses->entry_cnt, 
SIT_JOURNAL))
+                               to_journal = false;
+                       __flush_sit_entry_set(sbi, ses, cpc, to_journal);
+               }
+               f2fs_bug_on(sbi, !list_empty(&sm_i->dirty_set[i]));
        }
 
        f2fs_bug_on(sbi, !list_empty(head));
@@ -3196,6 +3191,15 @@ 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)
+{
+       struct f2fs_sm_info *sm_i = SM_I(sbi);
+       int i;
+
+       for (i = 0; i <= SIT_ENTRY_PER_BLOCK; i++)
+               INIT_LIST_HEAD(&sm_i->dirty_set[i]);
+}
+
 int build_segment_manager(struct f2fs_sb_info *sbi)
 {
        struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
@@ -3260,6 +3264,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
                return err;
 
        init_min_max_mtime(sbi);
+       init_sit_dirty_set_list(sbi);
        return 0;
 }
 
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index e9ba1f1..3fca58e 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -294,7 +294,8 @@ struct curseg_info {
 };
 
 struct sit_entry_set {
-       struct list_head set_list;      /* link with all sit sets */
+       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