diff options
author | Chao Yu <chao2.yu@samsung.com> | 2015-10-05 16:22:44 +0200 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-10-10 01:20:56 +0200 |
commit | d530d4d8e237f4d12c93bb76df40b69b8b8a1dcd (patch) | |
tree | a4496eb0dd00eef9caa6b190790502d91f847ff0 /fs/f2fs | |
parent | f2fs: skip searching dirty map if dirty segment is not exist (diff) | |
download | linux-d530d4d8e237f4d12c93bb76df40b69b8b8a1dcd.tar.xz linux-d530d4d8e237f4d12c93bb76df40b69b8b8a1dcd.zip |
f2fs: support synchronous gc in ioctl
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>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
-rw-r--r-- | fs/f2fs/file.c | 22 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 21 | ||||
-rw-r--r-- | fs/f2fs/gc.h | 6 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 2 |
5 files changed, 24 insertions, 29 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 1fa0555d1c2c..1b2fc2389a56 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -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 *); /* diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index a350c2aeccae..c26996646bc7 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -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) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index d844a8028527..830d27770a32 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -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; } diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index c5a055b3376e..b4a65be9f7d3 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h @@ -19,12 +19,6 @@ #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 */ diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 0ceff2891625..6b8edf21a152 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -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); } } |