f2fs: give a chance to merge IOs by IO scheduler
[linux-block.git] / fs / f2fs / gc.c
index 136c0f7a670bd3def779f2ae945d30b0aa0d6870..25a1f7e593e02019aafa4e02aafe7946e069fb42 100644 (file)
@@ -23,6 +23,7 @@
 #include "node.h"
 #include "segment.h"
 #include "gc.h"
+#include <trace/events/f2fs.h>
 
 static struct kmem_cache *winode_slab;
 
@@ -81,9 +82,6 @@ static int gc_thread_func(void *data)
                /* if return value is not zero, no victim was selected */
                if (f2fs_gc(sbi))
                        wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
-               else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
-                       wait_ms = GC_THREAD_MAX_SLEEP_TIME;
-
        } while (!kthread_should_stop());
        return 0;
 }
@@ -301,6 +299,10 @@ got_it:
                                set_bit(secno, dirty_i->victim_secmap);
                }
                *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
+
+               trace_f2fs_get_victim(sbi->sb, type, gc_type, &p,
+                               sbi->cur_victim_sec,
+                               prefree_segments(sbi), free_segments(sbi));
        }
        mutex_unlock(&dirty_i->seglist_lock);
 
@@ -384,6 +386,7 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
 
 next_step:
        entry = sum;
+
        for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
                nid_t nid = le32_to_cpu(entry->nid);
                struct page *node_page;
@@ -415,6 +418,7 @@ next_step:
                f2fs_put_page(node_page, 1);
                stat_inc_node_blk_count(sbi, 1);
        }
+
        if (initial) {
                initial = false;
                goto next_step;
@@ -510,7 +514,6 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
                        wait_on_page_writeback(page);
                }
 
-               mutex_lock_op(sbi, DATA_WRITE);
                if (clear_page_dirty_for_io(page) &&
                        S_ISDIR(inode->i_mode)) {
                        dec_page_count(sbi, F2FS_DIRTY_DENTS);
@@ -518,7 +521,6 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
                }
                set_cold_data(page);
                do_write_data_page(page);
-               mutex_unlock_op(sbi, DATA_WRITE);
                clear_cold_data(page);
        }
 out:
@@ -545,6 +547,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 
 next_step:
        entry = sum;
+
        for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
                struct page *data_page;
                struct inode *inode;
@@ -582,7 +585,7 @@ next_step:
                                continue;
 
                        data_page = find_data_page(inode,
-                                       start_bidx + ofs_in_node);
+                                       start_bidx + ofs_in_node, false);
                        if (IS_ERR(data_page))
                                goto next_iput;
 
@@ -603,6 +606,7 @@ next_step:
 next_iput:
                iput(inode);
        }
+
        if (++phase < 4)
                goto next_step;
 
@@ -636,18 +640,15 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
 {
        struct page *sum_page;
        struct f2fs_summary_block *sum;
+       struct blk_plug plug;
 
        /* read segment summary of victim */
        sum_page = get_sum_page(sbi, segno);
        if (IS_ERR(sum_page))
                return;
 
-       /*
-        * CP needs to lock sum_page. In this time, we don't need
-        * to lock this page, because this summary page is not gone anywhere.
-        * Also, this page is not gonna be updated before GC is done.
-        */
-       unlock_page(sum_page);
+       blk_start_plug(&plug);
+
        sum = page_address(sum_page);
 
        switch (GET_SUM_TYPE((&sum->footer))) {
@@ -658,10 +659,12 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
                gc_data_segment(sbi, sum->entries, ilist, segno, gc_type);
                break;
        }
+       blk_finish_plug(&plug);
+
        stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
        stat_inc_call_count(sbi->stat_info);
 
-       f2fs_put_page(sum_page, 0);
+       f2fs_put_page(sum_page, 1);
 }
 
 int f2fs_gc(struct f2fs_sb_info *sbi)
@@ -677,8 +680,10 @@ gc_more:
        if (!(sbi->sb->s_flags & MS_ACTIVE))
                goto stop;
 
-       if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree))
+       if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree)) {
                gc_type = FG_GC;
+               write_checkpoint(sbi, false);
+       }
 
        if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
                goto stop;