f2fs: add reclaiming control by sysfs
authorJaegeuk Kim <jaegeuk.kim@samsung.com>
Thu, 24 Oct 2013 06:49:07 +0000 (15:49 +0900)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Fri, 25 Oct 2013 07:54:39 +0000 (16:54 +0900)
This patch adds a control method in sysfs to reclaim prefree segments.

Signed-off-by: Changman Lee <cm224.lee@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Documentation/filesystems/f2fs.txt
fs/f2fs/super.c

index 3cd27be..4c647c2 100644 (file)
@@ -164,6 +164,12 @@ Files in /sys/fs/f2fs/<devname>
                               gc_idle = 1 will select the Cost Benefit approach
                               & setting gc_idle = 2 will select the greedy aproach.
 
+ reclaim_segments             This parameter controls the number of prefree
+                              segments to be reclaimed. If the number of prefree
+                             segments is larger than this number, f2fs tries to
+                             conduct checkpoint to reclaim the prefree segments
+                             to free segments. By default, 100 segments, 200MB.
+
 ================================================================================
 USAGE
 ================================================================================
index 9a09459..e42351c 100644 (file)
@@ -69,24 +69,40 @@ static match_table_t f2fs_tokens = {
 };
 
 /* Sysfs support for f2fs */
+enum {
+       GC_THREAD,      /* struct f2fs_gc_thread */
+       SM_INFO,        /* struct f2fs_sm_info */
+};
+
 struct f2fs_attr {
        struct attribute attr;
        ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *);
        ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *,
                         const char *, size_t);
+       int struct_type;
        int offset;
 };
 
+static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
+{
+       if (struct_type == GC_THREAD)
+               return (unsigned char *)sbi->gc_thread;
+       else if (struct_type == SM_INFO)
+               return (unsigned char *)SM_I(sbi);
+       return NULL;
+}
+
 static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
                        struct f2fs_sb_info *sbi, char *buf)
 {
-       struct f2fs_gc_kthread *gc_kth = sbi->gc_thread;
+       unsigned char *ptr = NULL;
        unsigned int *ui;
 
-       if (!gc_kth)
+       ptr = __struct_ptr(sbi, a->struct_type);
+       if (!ptr)
                return -EINVAL;
 
-       ui = (unsigned int *)(((char *)gc_kth) + a->offset);
+       ui = (unsigned int *)(ptr + a->offset);
 
        return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
 }
@@ -95,15 +111,16 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
                        struct f2fs_sb_info *sbi,
                        const char *buf, size_t count)
 {
-       struct f2fs_gc_kthread *gc_kth = sbi->gc_thread;
+       unsigned char *ptr;
        unsigned long t;
        unsigned int *ui;
        ssize_t ret;
 
-       if (!gc_kth)
+       ptr = __struct_ptr(sbi, a->struct_type);
+       if (!ptr)
                return -EINVAL;
 
-       ui = (unsigned int *)(((char *)gc_kth) + a->offset);
+       ui = (unsigned int *)(ptr + a->offset);
 
        ret = kstrtoul(skip_spaces(buf), 0, &t);
        if (ret < 0)
@@ -139,21 +156,25 @@ static void f2fs_sb_release(struct kobject *kobj)
        complete(&sbi->s_kobj_unregister);
 }
 
-#define F2FS_ATTR_OFFSET(_name, _mode, _show, _store, _elname) \
+#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
 static struct f2fs_attr f2fs_attr_##_name = {                  \
        .attr = {.name = __stringify(_name), .mode = _mode },   \
        .show   = _show,                                        \
        .store  = _store,                                       \
-       .offset = offsetof(struct f2fs_gc_kthread, _elname),    \
+       .struct_type = _struct_type,                            \
+       .offset = _offset                                       \
 }
 
-#define F2FS_RW_ATTR(name, elname)     \
-       F2FS_ATTR_OFFSET(name, 0644, f2fs_sbi_show, f2fs_sbi_store, elname)
+#define F2FS_RW_ATTR(struct_type, struct_name, name, elname)   \
+       F2FS_ATTR_OFFSET(struct_type, name, 0644,               \
+               f2fs_sbi_show, f2fs_sbi_store,                  \
+               offsetof(struct struct_name, elname))
 
-F2FS_RW_ATTR(gc_min_sleep_time, min_sleep_time);
-F2FS_RW_ATTR(gc_max_sleep_time, max_sleep_time);
-F2FS_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time);
-F2FS_RW_ATTR(gc_idle, gc_idle);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
+F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
 
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
@@ -161,6 +182,7 @@ static struct attribute *f2fs_attrs[] = {
        ATTR_LIST(gc_max_sleep_time),
        ATTR_LIST(gc_no_gc_sleep_time),
        ATTR_LIST(gc_idle),
+       ATTR_LIST(reclaim_segments),
        NULL,
 };