diff options
-rw-r--r-- | Documentation/filesystems/f2fs.txt | 6 | ||||
-rw-r--r-- | 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 3cd27bed6349..4c647c280dcc 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt | |||
@@ -164,6 +164,12 @@ Files in /sys/fs/f2fs/<devname> | |||
164 | gc_idle = 1 will select the Cost Benefit approach | 164 | gc_idle = 1 will select the Cost Benefit approach |
165 | & setting gc_idle = 2 will select the greedy aproach. | 165 | & setting gc_idle = 2 will select the greedy aproach. |
166 | 166 | ||
167 | reclaim_segments This parameter controls the number of prefree | ||
168 | segments to be reclaimed. If the number of prefree | ||
169 | segments is larger than this number, f2fs tries to | ||
170 | conduct checkpoint to reclaim the prefree segments | ||
171 | to free segments. By default, 100 segments, 200MB. | ||
172 | |||
167 | ================================================================================ | 173 | ================================================================================ |
168 | USAGE | 174 | USAGE |
169 | ================================================================================ | 175 | ================================================================================ |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 9a094596fd21..e42351cbe166 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -69,24 +69,40 @@ static match_table_t f2fs_tokens = { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | /* Sysfs support for f2fs */ | 71 | /* Sysfs support for f2fs */ |
72 | enum { | ||
73 | GC_THREAD, /* struct f2fs_gc_thread */ | ||
74 | SM_INFO, /* struct f2fs_sm_info */ | ||
75 | }; | ||
76 | |||
72 | struct f2fs_attr { | 77 | struct f2fs_attr { |
73 | struct attribute attr; | 78 | struct attribute attr; |
74 | ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); | 79 | ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); |
75 | ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, | 80 | ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, |
76 | const char *, size_t); | 81 | const char *, size_t); |
82 | int struct_type; | ||
77 | int offset; | 83 | int offset; |
78 | }; | 84 | }; |
79 | 85 | ||
86 | static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) | ||
87 | { | ||
88 | if (struct_type == GC_THREAD) | ||
89 | return (unsigned char *)sbi->gc_thread; | ||
90 | else if (struct_type == SM_INFO) | ||
91 | return (unsigned char *)SM_I(sbi); | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
80 | static ssize_t f2fs_sbi_show(struct f2fs_attr *a, | 95 | static ssize_t f2fs_sbi_show(struct f2fs_attr *a, |
81 | struct f2fs_sb_info *sbi, char *buf) | 96 | struct f2fs_sb_info *sbi, char *buf) |
82 | { | 97 | { |
83 | struct f2fs_gc_kthread *gc_kth = sbi->gc_thread; | 98 | unsigned char *ptr = NULL; |
84 | unsigned int *ui; | 99 | unsigned int *ui; |
85 | 100 | ||
86 | if (!gc_kth) | 101 | ptr = __struct_ptr(sbi, a->struct_type); |
102 | if (!ptr) | ||
87 | return -EINVAL; | 103 | return -EINVAL; |
88 | 104 | ||
89 | ui = (unsigned int *)(((char *)gc_kth) + a->offset); | 105 | ui = (unsigned int *)(ptr + a->offset); |
90 | 106 | ||
91 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); | 107 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); |
92 | } | 108 | } |
@@ -95,15 +111,16 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, | |||
95 | struct f2fs_sb_info *sbi, | 111 | struct f2fs_sb_info *sbi, |
96 | const char *buf, size_t count) | 112 | const char *buf, size_t count) |
97 | { | 113 | { |
98 | struct f2fs_gc_kthread *gc_kth = sbi->gc_thread; | 114 | unsigned char *ptr; |
99 | unsigned long t; | 115 | unsigned long t; |
100 | unsigned int *ui; | 116 | unsigned int *ui; |
101 | ssize_t ret; | 117 | ssize_t ret; |
102 | 118 | ||
103 | if (!gc_kth) | 119 | ptr = __struct_ptr(sbi, a->struct_type); |
120 | if (!ptr) | ||
104 | return -EINVAL; | 121 | return -EINVAL; |
105 | 122 | ||
106 | ui = (unsigned int *)(((char *)gc_kth) + a->offset); | 123 | ui = (unsigned int *)(ptr + a->offset); |
107 | 124 | ||
108 | ret = kstrtoul(skip_spaces(buf), 0, &t); | 125 | ret = kstrtoul(skip_spaces(buf), 0, &t); |
109 | if (ret < 0) | 126 | if (ret < 0) |
@@ -139,21 +156,25 @@ static void f2fs_sb_release(struct kobject *kobj) | |||
139 | complete(&sbi->s_kobj_unregister); | 156 | complete(&sbi->s_kobj_unregister); |
140 | } | 157 | } |
141 | 158 | ||
142 | #define F2FS_ATTR_OFFSET(_name, _mode, _show, _store, _elname) \ | 159 | #define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ |
143 | static struct f2fs_attr f2fs_attr_##_name = { \ | 160 | static struct f2fs_attr f2fs_attr_##_name = { \ |
144 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | 161 | .attr = {.name = __stringify(_name), .mode = _mode }, \ |
145 | .show = _show, \ | 162 | .show = _show, \ |
146 | .store = _store, \ | 163 | .store = _store, \ |
147 | .offset = offsetof(struct f2fs_gc_kthread, _elname), \ | 164 | .struct_type = _struct_type, \ |
165 | .offset = _offset \ | ||
148 | } | 166 | } |
149 | 167 | ||
150 | #define F2FS_RW_ATTR(name, elname) \ | 168 | #define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ |
151 | F2FS_ATTR_OFFSET(name, 0644, f2fs_sbi_show, f2fs_sbi_store, elname) | 169 | F2FS_ATTR_OFFSET(struct_type, name, 0644, \ |
170 | f2fs_sbi_show, f2fs_sbi_store, \ | ||
171 | offsetof(struct struct_name, elname)) | ||
152 | 172 | ||
153 | F2FS_RW_ATTR(gc_min_sleep_time, min_sleep_time); | 173 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time); |
154 | F2FS_RW_ATTR(gc_max_sleep_time, max_sleep_time); | 174 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); |
155 | F2FS_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time); | 175 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); |
156 | F2FS_RW_ATTR(gc_idle, gc_idle); | 176 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle); |
177 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); | ||
157 | 178 | ||
158 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) | 179 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) |
159 | static struct attribute *f2fs_attrs[] = { | 180 | static struct attribute *f2fs_attrs[] = { |
@@ -161,6 +182,7 @@ static struct attribute *f2fs_attrs[] = { | |||
161 | ATTR_LIST(gc_max_sleep_time), | 182 | ATTR_LIST(gc_max_sleep_time), |
162 | ATTR_LIST(gc_no_gc_sleep_time), | 183 | ATTR_LIST(gc_no_gc_sleep_time), |
163 | ATTR_LIST(gc_idle), | 184 | ATTR_LIST(gc_idle), |
185 | ATTR_LIST(reclaim_segments), | ||
164 | NULL, | 186 | NULL, |
165 | }; | 187 | }; |
166 | 188 | ||