[PATCH 3/3] f2fs: add reclaiming control by sysfs

From: Jaegeuk Kim
Date: Thu Oct 24 2013 - 03:59:00 EST


This patch adds a control method in sysfs to reclaim prefree segments.

Signed-off-by: Changman Lee <cm224.lee@xxxxxxxxxxx>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@xxxxxxxxxxx>
---
Documentation/filesystems/f2fs.txt | 6 +++++
fs/f2fs/super.c | 50 +++++++++++++++++++++++++++-----------
2 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index 3cd27be..4c647c2 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -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
================================================================================
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 9a09459..e42351c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -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,
};

--
1.8.4.474.g128a96c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/