f2fs: check free_sections for defragmentation
authorJaegeuk Kim <jaegeuk@kernel.org>
Thu, 1 Sep 2016 19:02:51 +0000 (12:02 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 12 Sep 2016 17:30:41 +0000 (10:30 -0700)
Fix wrong condition check for defragmentation of a file.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/segment.c
fs/f2fs/segment.h

index 8ffb480935b399fbe08bacdd302cc7beb34cc17c..357a4235dde8efe407f81a11799a0b0d31734604 100644 (file)
@@ -1293,7 +1293,7 @@ write:
 
        if (!wbc->for_reclaim)
                need_balance_fs = true;
-       else if (has_not_enough_free_secs(sbi, 0))
+       else if (has_not_enough_free_secs(sbi, 0, 0))
                goto redirty_out;
 
        err = -EAGAIN;
@@ -1625,7 +1625,7 @@ repeat:
        if (err)
                goto fail;
 
-       if (need_balance && has_not_enough_free_secs(sbi, 0)) {
+       if (need_balance && has_not_enough_free_secs(sbi, 0, 0)) {
                unlock_page(page);
                f2fs_balance_fs(sbi, true);
                lock_page(page);
index 3b62949dfb0739e27c0bb93303fee4cfd29a186e..b8a521f6c2d5ae4d59ba7ce781f1ae59881e9c7d 100644 (file)
@@ -1961,7 +1961,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
         * avoid defragment running in SSR mode when free section are allocated
         * intensively
         */
-       if (has_not_enough_free_secs(sbi, sec_num)) {
+       if (has_not_enough_free_secs(sbi, 0, sec_num)) {
                err = -EAGAIN;
                goto out;
        }
index cdc44a67485fa1d4a0e8d135245541cb5bef2298..24acbbbd0b1dd56fa39dd6e9ffce49b4f751e12a 100644 (file)
@@ -439,7 +439,7 @@ next_step:
                struct node_info ni;
 
                /* stop BG_GC if there is not enough free sections. */
-               if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0))
+               if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
                        return;
 
                if (check_valid_map(sbi, segno, off) == 0)
@@ -715,7 +715,7 @@ next_step:
                nid_t nid = le32_to_cpu(entry->nid);
 
                /* stop BG_GC if there is not enough free sections. */
-               if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0))
+               if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
                        return;
 
                if (check_valid_map(sbi, segno, off) == 0)
@@ -916,7 +916,7 @@ gc_more:
                goto stop;
        }
 
-       if (gc_type == BG_GC && has_not_enough_free_secs(sbi, sec_freed)) {
+       if (gc_type == BG_GC && has_not_enough_free_secs(sbi, sec_freed, 0)) {
                gc_type = FG_GC;
                /*
                 * If there is no victim and no prefree segment but still not
@@ -927,7 +927,7 @@ gc_more:
                                                prefree_segments(sbi)) {
                        write_checkpoint(sbi, &cpc);
                        segno = NULL_SEGNO;
-               } else if (has_not_enough_free_secs(sbi, 0)) {
+               } else if (has_not_enough_free_secs(sbi, 0, 0)) {
                        write_checkpoint(sbi, &cpc);
                }
        }
@@ -944,7 +944,7 @@ gc_more:
                sbi->cur_victim_sec = NULL_SEGNO;
 
        if (!sync) {
-               if (has_not_enough_free_secs(sbi, sec_freed))
+               if (has_not_enough_free_secs(sbi, sec_freed, 0))
                        goto gc_more;
 
                if (gc_type == FG_GC)
index 3ff4621394367409a64c9461a88c0ae8ebaa4da0..101b58f1d63677588f3e30f0555ede9764214f39 100644 (file)
@@ -356,7 +356,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
         * We should do GC or end up with checkpoint, if there are so many dirty
         * dir/node pages without enough free segments.
         */
-       if (has_not_enough_free_secs(sbi, 0)) {
+       if (has_not_enough_free_secs(sbi, 0, 0)) {
                mutex_lock(&sbi->gc_mutex);
                f2fs_gc(sbi, false);
        }
@@ -1278,7 +1278,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
        struct curseg_info *curseg = CURSEG_I(sbi, type);
        const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops;
 
-       if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0))
+       if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0, 0))
                return v_ops->get_victim(sbi,
                                &(curseg)->next_segno, BG_GC, type, SSR);
 
@@ -1477,7 +1477,7 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 
        /* direct_io'ed data is aligned to the segment for better performance */
        if (direct_io && curseg->next_blkoff &&
-                               !has_not_enough_free_secs(sbi, 0))
+                               !has_not_enough_free_secs(sbi, 0, 0))
                __allocate_new_segments(sbi, type);
 
        *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
index 87156c739796bb2933579ef5567ddd9d85f01488..fecb856ad874a87c75e15a1ce9bd169c5dbc6b5a 100644 (file)
@@ -479,7 +479,8 @@ static inline bool need_SSR(struct f2fs_sb_info *sbi)
                                                reserved_sections(sbi) + 1);
 }
 
-static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed)
+static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
+                                       int freed, int needed)
 {
        int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
        int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
@@ -489,8 +490,8 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed)
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                return false;
 
-       return (free_sections(sbi) + freed) <= (node_secs + 2 * dent_secs +
-                                               reserved_sections(sbi));
+       return (free_sections(sbi) + freed) <=
+               (node_secs + 2 * dent_secs + reserved_sections(sbi) + needed);
 }
 
 static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi)