f2fs: support synchronous gc in ioctl
authorChao Yu <chao2.yu@samsung.com>
Mon, 5 Oct 2015 14:22:44 +0000 (22:22 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 9 Oct 2015 23:20:56 +0000 (16:20 -0700)
This patch drops in batches gc triggered through ioctl, since user
can easily control the gc by designing the loop around the ->ioctl.

We support synchronous gc by forcing using FG_GC in f2fs_gc, so with
it, user can make sure that in this round all blocks gced were
persistent in the device until ioctl returned.

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/gc.h
fs/f2fs/segment.c

index 1fa0555d1c2cada148e0e8f8459aae66a4964d38..1b2fc2389a562745185b81545a56c71bb00db102 100644 (file)
@@ -1830,7 +1830,7 @@ int f2fs_release_page(struct page *, gfp_t);
 int start_gc_thread(struct f2fs_sb_info *);
 void stop_gc_thread(struct f2fs_sb_info *);
 block_t start_bidx_of_node(unsigned int, struct f2fs_inode_info *);
-int f2fs_gc(struct f2fs_sb_info *);
+int f2fs_gc(struct f2fs_sb_info *, bool);
 void build_gc_manager(struct f2fs_sb_info *);
 
 /*
index a350c2aeccaedf7ec5e2f6fdcaa6df284fc771bf..c26996646bc7ff96507904e60f7bab4340b0aebc 100644 (file)
@@ -1618,29 +1618,25 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       __u32 i, count;
+       __u32 sync;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (get_user(count, (__u32 __user *)arg))
+       if (get_user(sync, (__u32 __user *)arg))
                return -EFAULT;
 
-       if (!count || count > F2FS_BATCH_GC_MAX_NUM)
-               return -EINVAL;
+       if (f2fs_readonly(sbi->sb))
+               return -EROFS;
 
-       for (i = 0; i < count; i++) {
+       if (!sync) {
                if (!mutex_trylock(&sbi->gc_mutex))
-                       break;
-
-               if (f2fs_gc(sbi))
-                       break;
+                       return -EBUSY;
+       } else {
+               mutex_lock(&sbi->gc_mutex);
        }
 
-       if (put_user(i, (__u32 __user *)arg))
-               return -EFAULT;
-
-       return 0;
+       return f2fs_gc(sbi, sync);
 }
 
 long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
index d844a80285279d501211b2c64b5d8a3158c265c7..830d27770a32eed976d4eb50497213b12c19f050 100644 (file)
@@ -78,7 +78,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))
+               if (f2fs_gc(sbi, false))
                        wait_ms = gc_th->no_gc_sleep_time;
 
                /* balancing f2fs's metadata periodically */
@@ -803,12 +803,12 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
        return nfree;
 }
 
-int f2fs_gc(struct f2fs_sb_info *sbi)
+int f2fs_gc(struct f2fs_sb_info *sbi, bool sync)
 {
        unsigned int segno, i;
-       int gc_type = BG_GC;
+       int gc_type = sync ? FG_GC : BG_GC;
        int sec_freed = 0;
-       int ret = -1;
+       int ret = -EINVAL;
        struct cp_control cpc;
        struct gc_inode_list gc_list = {
                .ilist = LIST_HEAD_INIT(gc_list.ilist),
@@ -855,15 +855,20 @@ gc_more:
        if (gc_type == FG_GC)
                sbi->cur_victim_sec = NULL_SEGNO;
 
-       if (has_not_enough_free_secs(sbi, sec_freed))
-               goto gc_more;
+       if (!sync) {
+               if (has_not_enough_free_secs(sbi, sec_freed))
+                       goto gc_more;
 
-       if (gc_type == FG_GC)
-               write_checkpoint(sbi, &cpc);
+               if (gc_type == FG_GC)
+                       write_checkpoint(sbi, &cpc);
+       }
 stop:
        mutex_unlock(&sbi->gc_mutex);
 
        put_gc_inode(&gc_list);
+
+       if (sync)
+               ret = sec_freed ? 0 : -EAGAIN;
        return ret;
 }
 
index c5a055b3376e6b518d4f5082106bc157bfe3696e..b4a65be9f7d3fc03a9b1836873f392fea1cfd646 100644 (file)
 #define LIMIT_INVALID_BLOCK    40 /* percentage over total user space */
 #define LIMIT_FREE_BLOCK       40 /* percentage over invalid + free space */
 
-/*
- * with this macro, we can control the max time we do garbage collection,
- * when user triggers batch mode gc by ioctl.
- */
-#define F2FS_BATCH_GC_MAX_NUM          16
-
 /* Search max. number of dirty segments to select a victim segment */
 #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */
 
index 0ceff2891625e71275412d1608767f27c086f6c9..6b8edf21a15211fef49dd0fea0bad0152f1aa57c 100644 (file)
@@ -295,7 +295,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi)
         */
        if (has_not_enough_free_secs(sbi, 0)) {
                mutex_lock(&sbi->gc_mutex);
-               f2fs_gc(sbi);
+               f2fs_gc(sbi, false);
        }
 }