]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/f2fs/gc.c
Merge tag 'for-f2fs-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[mirror_ubuntu-zesty-kernel.git] / fs / f2fs / gc.c
index fcca12b97a2a74ed04f268bb5390217b7ef75da4..88bfc3dff496f9f31166da30293d9bdfe64d25b3 100644 (file)
@@ -82,7 +82,7 @@ static int gc_thread_func(void *data)
                stat_inc_bggc_count(sbi);
 
                /* if return value is not zero, no victim was selected */
-               if (f2fs_gc(sbi, test_opt(sbi, FORCE_FG_GC)))
+               if (f2fs_gc(sbi, test_opt(sbi, FORCE_FG_GC), true))
                        wait_ms = gc_th->no_gc_sleep_time;
 
                trace_f2fs_background_gc(sbi->sb, wait_ms,
@@ -544,7 +544,8 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
        return true;
 }
 
-static void move_encrypted_block(struct inode *inode, block_t bidx)
+static void move_encrypted_block(struct inode *inode, block_t bidx,
+                                                       unsigned int segno, int off)
 {
        struct f2fs_io_info fio = {
                .sbi = F2FS_I_SB(inode),
@@ -565,6 +566,9 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
        if (!page)
                return;
 
+       if (!check_valid_map(F2FS_I_SB(inode), segno, off))
+               goto out;
+
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
        if (err)
@@ -645,7 +649,8 @@ out:
        f2fs_put_page(page, 1);
 }
 
-static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
+static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
+                                                       unsigned int segno, int off)
 {
        struct page *page;
 
@@ -653,6 +658,9 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
        if (IS_ERR(page))
                return;
 
+       if (!check_valid_map(F2FS_I_SB(inode), segno, off))
+               goto out;
+
        if (gc_type == BG_GC) {
                if (PageWriteback(page))
                        goto out;
@@ -673,8 +681,10 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
 retry:
                set_page_dirty(page);
                f2fs_wait_on_page_writeback(page, DATA, true);
-               if (clear_page_dirty_for_io(page))
+               if (clear_page_dirty_for_io(page)) {
                        inode_dec_dirty_pages(inode);
+                       remove_dirty_inode(inode);
+               }
 
                set_cold_data(page);
 
@@ -683,8 +693,6 @@ retry:
                        congestion_wait(BLK_RW_ASYNC, HZ/50);
                        goto retry;
                }
-
-               clear_cold_data(page);
        }
 out:
        f2fs_put_page(page, 1);
@@ -794,9 +802,9 @@ next_step:
                        start_bidx = start_bidx_of_node(nofs, inode)
                                                                + ofs_in_node;
                        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
-                               move_encrypted_block(inode, start_bidx);
+                               move_encrypted_block(inode, start_bidx, segno, off);
                        else
-                               move_data_page(inode, start_bidx, gc_type);
+                               move_data_page(inode, start_bidx, gc_type, segno, off);
 
                        if (locked) {
                                up_write(&fi->dio_rwsem[WRITE]);
@@ -899,7 +907,7 @@ next:
        return sec_freed;
 }
 
-int f2fs_gc(struct f2fs_sb_info *sbi, bool sync)
+int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background)
 {
        unsigned int segno;
        int gc_type = sync ? FG_GC : BG_GC;
@@ -940,6 +948,9 @@ gc_more:
                        if (ret)
                                goto stop;
                }
+       } else if (gc_type == BG_GC && !background) {
+               /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */
+               goto stop;
        }
 
        if (segno == NULL_SEGNO && !__get_victim(sbi, &segno, gc_type))