~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/f2fs/sysfs.c

Version: ~ [ linux-5.7-rc7 ] ~ [ linux-5.6.14 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.42 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.124 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.181 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.224 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.224 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.84 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * f2fs sysfs interface
  4  *
  5  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  6  *             http://www.samsung.com/
  7  * Copyright (c) 2017 Chao Yu <chao@kernel.org>
  8  */
  9 #include <linux/compiler.h>
 10 #include <linux/proc_fs.h>
 11 #include <linux/f2fs_fs.h>
 12 #include <linux/seq_file.h>
 13 
 14 #include "f2fs.h"
 15 #include "segment.h"
 16 #include "gc.h"
 17 
 18 static struct proc_dir_entry *f2fs_proc_root;
 19 
 20 /* Sysfs support for f2fs */
 21 enum {
 22         GC_THREAD,      /* struct f2fs_gc_thread */
 23         SM_INFO,        /* struct f2fs_sm_info */
 24         DCC_INFO,       /* struct discard_cmd_control */
 25         NM_INFO,        /* struct f2fs_nm_info */
 26         F2FS_SBI,       /* struct f2fs_sb_info */
 27 #ifdef CONFIG_F2FS_FAULT_INJECTION
 28         FAULT_INFO_RATE,        /* struct f2fs_fault_info */
 29         FAULT_INFO_TYPE,        /* struct f2fs_fault_info */
 30 #endif
 31         RESERVED_BLOCKS,        /* struct f2fs_sb_info */
 32 };
 33 
 34 struct f2fs_attr {
 35         struct attribute attr;
 36         ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *);
 37         ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *,
 38                          const char *, size_t);
 39         int struct_type;
 40         int offset;
 41         int id;
 42 };
 43 
 44 static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
 45 {
 46         if (struct_type == GC_THREAD)
 47                 return (unsigned char *)sbi->gc_thread;
 48         else if (struct_type == SM_INFO)
 49                 return (unsigned char *)SM_I(sbi);
 50         else if (struct_type == DCC_INFO)
 51                 return (unsigned char *)SM_I(sbi)->dcc_info;
 52         else if (struct_type == NM_INFO)
 53                 return (unsigned char *)NM_I(sbi);
 54         else if (struct_type == F2FS_SBI || struct_type == RESERVED_BLOCKS)
 55                 return (unsigned char *)sbi;
 56 #ifdef CONFIG_F2FS_FAULT_INJECTION
 57         else if (struct_type == FAULT_INFO_RATE ||
 58                                         struct_type == FAULT_INFO_TYPE)
 59                 return (unsigned char *)&F2FS_OPTION(sbi).fault_info;
 60 #endif
 61         return NULL;
 62 }
 63 
 64 static ssize_t dirty_segments_show(struct f2fs_attr *a,
 65                 struct f2fs_sb_info *sbi, char *buf)
 66 {
 67         return snprintf(buf, PAGE_SIZE, "%llu\n",
 68                 (unsigned long long)(dirty_segments(sbi)));
 69 }
 70 
 71 static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,
 72                 struct f2fs_sb_info *sbi, char *buf)
 73 {
 74         struct super_block *sb = sbi->sb;
 75 
 76         if (!sb->s_bdev->bd_part)
 77                 return snprintf(buf, PAGE_SIZE, "\n");
 78 
 79         return snprintf(buf, PAGE_SIZE, "%llu\n",
 80                 (unsigned long long)(sbi->kbytes_written +
 81                         BD_PART_WRITTEN(sbi)));
 82 }
 83 
 84 static ssize_t features_show(struct f2fs_attr *a,
 85                 struct f2fs_sb_info *sbi, char *buf)
 86 {
 87         struct super_block *sb = sbi->sb;
 88         int len = 0;
 89 
 90         if (!sb->s_bdev->bd_part)
 91                 return snprintf(buf, PAGE_SIZE, "\n");
 92 
 93         if (f2fs_sb_has_encrypt(sbi))
 94                 len += snprintf(buf, PAGE_SIZE - len, "%s",
 95                                                 "encryption");
 96         if (f2fs_sb_has_blkzoned(sbi))
 97                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
 98                                 len ? ", " : "", "blkzoned");
 99         if (f2fs_sb_has_extra_attr(sbi))
100                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
101                                 len ? ", " : "", "extra_attr");
102         if (f2fs_sb_has_project_quota(sbi))
103                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
104                                 len ? ", " : "", "projquota");
105         if (f2fs_sb_has_inode_chksum(sbi))
106                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
107                                 len ? ", " : "", "inode_checksum");
108         if (f2fs_sb_has_flexible_inline_xattr(sbi))
109                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
110                                 len ? ", " : "", "flexible_inline_xattr");
111         if (f2fs_sb_has_quota_ino(sbi))
112                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
113                                 len ? ", " : "", "quota_ino");
114         if (f2fs_sb_has_inode_crtime(sbi))
115                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
116                                 len ? ", " : "", "inode_crtime");
117         if (f2fs_sb_has_lost_found(sbi))
118                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
119                                 len ? ", " : "", "lost_found");
120         if (f2fs_sb_has_sb_chksum(sbi))
121                 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
122                                 len ? ", " : "", "sb_checksum");
123         len += snprintf(buf + len, PAGE_SIZE - len, "\n");
124         return len;
125 }
126 
127 static ssize_t current_reserved_blocks_show(struct f2fs_attr *a,
128                                         struct f2fs_sb_info *sbi, char *buf)
129 {
130         return snprintf(buf, PAGE_SIZE, "%u\n", sbi->current_reserved_blocks);
131 }
132 
133 static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
134                         struct f2fs_sb_info *sbi, char *buf)
135 {
136         unsigned char *ptr = NULL;
137         unsigned int *ui;
138 
139         ptr = __struct_ptr(sbi, a->struct_type);
140         if (!ptr)
141                 return -EINVAL;
142 
143         if (!strcmp(a->attr.name, "extension_list")) {
144                 __u8 (*extlist)[F2FS_EXTENSION_LEN] =
145                                         sbi->raw_super->extension_list;
146                 int cold_count = le32_to_cpu(sbi->raw_super->extension_count);
147                 int hot_count = sbi->raw_super->hot_ext_count;
148                 int len = 0, i;
149 
150                 len += snprintf(buf + len, PAGE_SIZE - len,
151                                                 "cold file extension:\n");
152                 for (i = 0; i < cold_count; i++)
153                         len += snprintf(buf + len, PAGE_SIZE - len, "%s\n",
154                                                                 extlist[i]);
155 
156                 len += snprintf(buf + len, PAGE_SIZE - len,
157                                                 "hot file extension:\n");
158                 for (i = cold_count; i < cold_count + hot_count; i++)
159                         len += snprintf(buf + len, PAGE_SIZE - len, "%s\n",
160                                                                 extlist[i]);
161                 return len;
162         }
163 
164         ui = (unsigned int *)(ptr + a->offset);
165 
166         return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
167 }
168 
169 static ssize_t __sbi_store(struct f2fs_attr *a,
170                         struct f2fs_sb_info *sbi,
171                         const char *buf, size_t count)
172 {
173         unsigned char *ptr;
174         unsigned long t;
175         unsigned int *ui;
176         ssize_t ret;
177 
178         ptr = __struct_ptr(sbi, a->struct_type);
179         if (!ptr)
180                 return -EINVAL;
181 
182         if (!strcmp(a->attr.name, "extension_list")) {
183                 const char *name = strim((char *)buf);
184                 bool set = true, hot;
185 
186                 if (!strncmp(name, "[h]", 3))
187                         hot = true;
188                 else if (!strncmp(name, "[c]", 3))
189                         hot = false;
190                 else
191                         return -EINVAL;
192 
193                 name += 3;
194 
195                 if (*name == '!') {
196                         name++;
197                         set = false;
198                 }
199 
200                 if (strlen(name) >= F2FS_EXTENSION_LEN)
201                         return -EINVAL;
202 
203                 down_write(&sbi->sb_lock);
204 
205                 ret = f2fs_update_extension_list(sbi, name, hot, set);
206                 if (ret)
207                         goto out;
208 
209                 ret = f2fs_commit_super(sbi, false);
210                 if (ret)
211                         f2fs_update_extension_list(sbi, name, hot, !set);
212 out:
213                 up_write(&sbi->sb_lock);
214                 return ret ? ret : count;
215         }
216 
217         ui = (unsigned int *)(ptr + a->offset);
218 
219         ret = kstrtoul(skip_spaces(buf), 0, &t);
220         if (ret < 0)
221                 return ret;
222 #ifdef CONFIG_F2FS_FAULT_INJECTION
223         if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX))
224                 return -EINVAL;
225 #endif
226         if (a->struct_type == RESERVED_BLOCKS) {
227                 spin_lock(&sbi->stat_lock);
228                 if (t > (unsigned long)(sbi->user_block_count -
229                                 F2FS_OPTION(sbi).root_reserved_blocks)) {
230                         spin_unlock(&sbi->stat_lock);
231                         return -EINVAL;
232                 }
233                 *ui = t;
234                 sbi->current_reserved_blocks = min(sbi->reserved_blocks,
235                                 sbi->user_block_count - valid_user_blocks(sbi));
236                 spin_unlock(&sbi->stat_lock);
237                 return count;
238         }
239 
240         if (!strcmp(a->attr.name, "discard_granularity")) {
241                 if (t == 0 || t > MAX_PLIST_NUM)
242                         return -EINVAL;
243                 if (t == *ui)
244                         return count;
245                 *ui = t;
246                 return count;
247         }
248 
249         if (!strcmp(a->attr.name, "migration_granularity")) {
250                 if (t == 0 || t > sbi->segs_per_sec)
251                         return -EINVAL;
252         }
253 
254         if (!strcmp(a->attr.name, "trim_sections"))
255                 return -EINVAL;
256 
257         if (!strcmp(a->attr.name, "gc_urgent")) {
258                 if (t >= 1) {
259                         sbi->gc_mode = GC_URGENT;
260                         if (sbi->gc_thread) {
261                                 sbi->gc_thread->gc_wake = 1;
262                                 wake_up_interruptible_all(
263                                         &sbi->gc_thread->gc_wait_queue_head);
264                                 wake_up_discard_thread(sbi, true);
265                         }
266                 } else {
267                         sbi->gc_mode = GC_NORMAL;
268                 }
269                 return count;
270         }
271         if (!strcmp(a->attr.name, "gc_idle")) {
272                 if (t == GC_IDLE_CB)
273                         sbi->gc_mode = GC_IDLE_CB;
274                 else if (t == GC_IDLE_GREEDY)
275                         sbi->gc_mode = GC_IDLE_GREEDY;
276                 else
277                         sbi->gc_mode = GC_NORMAL;
278                 return count;
279         }
280 
281 
282         if (!strcmp(a->attr.name, "iostat_enable")) {
283                 sbi->iostat_enable = !!t;
284                 if (!sbi->iostat_enable)
285                         f2fs_reset_iostat(sbi);
286                 return count;
287         }
288 
289         *ui = (unsigned int)t;
290 
291         return count;
292 }
293 
294 static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
295                         struct f2fs_sb_info *sbi,
296                         const char *buf, size_t count)
297 {
298         ssize_t ret;
299         bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||
300                                         a->struct_type == GC_THREAD);
301 
302         if (gc_entry) {
303                 if (!down_read_trylock(&sbi->sb->s_umount))
304                         return -EAGAIN;
305         }
306         ret = __sbi_store(a, sbi, buf, count);
307         if (gc_entry)
308                 up_read(&sbi->sb->s_umount);
309 
310         return ret;
311 }
312 
313 static ssize_t f2fs_attr_show(struct kobject *kobj,
314                                 struct attribute *attr, char *buf)
315 {
316         struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
317                                                                 s_kobj);
318         struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
319 
320         return a->show ? a->show(a, sbi, buf) : 0;
321 }
322 
323 static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr,
324                                                 const char *buf, size_t len)
325 {
326         struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
327                                                                         s_kobj);
328         struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
329 
330         return a->store ? a->store(a, sbi, buf, len) : 0;
331 }
332 
333 static void f2fs_sb_release(struct kobject *kobj)
334 {
335         struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
336                                                                 s_kobj);
337         complete(&sbi->s_kobj_unregister);
338 }
339 
340 enum feat_id {
341         FEAT_CRYPTO = 0,
342         FEAT_BLKZONED,
343         FEAT_ATOMIC_WRITE,
344         FEAT_EXTRA_ATTR,
345         FEAT_PROJECT_QUOTA,
346         FEAT_INODE_CHECKSUM,
347         FEAT_FLEXIBLE_INLINE_XATTR,
348         FEAT_QUOTA_INO,
349         FEAT_INODE_CRTIME,
350         FEAT_LOST_FOUND,
351         FEAT_SB_CHECKSUM,
352 };
353 
354 static ssize_t f2fs_feature_show(struct f2fs_attr *a,
355                 struct f2fs_sb_info *sbi, char *buf)
356 {
357         switch (a->id) {
358         case FEAT_CRYPTO:
359         case FEAT_BLKZONED:
360         case FEAT_ATOMIC_WRITE:
361         case FEAT_EXTRA_ATTR:
362         case FEAT_PROJECT_QUOTA:
363         case FEAT_INODE_CHECKSUM:
364         case FEAT_FLEXIBLE_INLINE_XATTR:
365         case FEAT_QUOTA_INO:
366         case FEAT_INODE_CRTIME:
367         case FEAT_LOST_FOUND:
368         case FEAT_SB_CHECKSUM:
369                 return snprintf(buf, PAGE_SIZE, "supported\n");
370         }
371         return 0;
372 }
373 
374 #define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
375 static struct f2fs_attr f2fs_attr_##_name = {                   \
376         .attr = {.name = __stringify(_name), .mode = _mode },   \
377         .show   = _show,                                        \
378         .store  = _store,                                       \
379         .struct_type = _struct_type,                            \
380         .offset = _offset                                       \
381 }
382 
383 #define F2FS_RW_ATTR(struct_type, struct_name, name, elname)    \
384         F2FS_ATTR_OFFSET(struct_type, name, 0644,               \
385                 f2fs_sbi_show, f2fs_sbi_store,                  \
386                 offsetof(struct struct_name, elname))
387 
388 #define F2FS_GENERAL_RO_ATTR(name) \
389 static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)
390 
391 #define F2FS_FEATURE_RO_ATTR(_name, _id)                        \
392 static struct f2fs_attr f2fs_attr_##_name = {                   \
393         .attr = {.name = __stringify(_name), .mode = 0444 },    \
394         .show   = f2fs_feature_show,                            \
395         .id     = _id,                                          \
396 }
397 
398 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
399                                                         urgent_sleep_time);
400 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
401 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
402 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
403 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode);
404 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode);
405 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
406 F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
407 F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
408 F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, reserved_blocks, reserved_blocks);
409 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections);
410 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
411 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
412 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks);
413 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_seq_blocks, min_seq_blocks);
414 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_hot_blocks, min_hot_blocks);
415 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ssr_sections, min_ssr_sections);
416 F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh);
417 F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages);
418 F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, dirty_nats_ratio, dirty_nats_ratio);
419 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
420 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, migration_granularity, migration_granularity);
421 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
422 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
423 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
424 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval,
425                                         interval_time[DISCARD_TIME]);
426 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
427 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
428 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
429 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
430 F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);
431 #ifdef CONFIG_F2FS_FAULT_INJECTION
432 F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate);
433 F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
434 #endif
435 F2FS_GENERAL_RO_ATTR(dirty_segments);
436 F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
437 F2FS_GENERAL_RO_ATTR(features);
438 F2FS_GENERAL_RO_ATTR(current_reserved_blocks);
439 
440 #ifdef CONFIG_F2FS_FS_ENCRYPTION
441 F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO);
442 #endif
443 #ifdef CONFIG_BLK_DEV_ZONED
444 F2FS_FEATURE_RO_ATTR(block_zoned, FEAT_BLKZONED);
445 #endif
446 F2FS_FEATURE_RO_ATTR(atomic_write, FEAT_ATOMIC_WRITE);
447 F2FS_FEATURE_RO_ATTR(extra_attr, FEAT_EXTRA_ATTR);
448 F2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA);
449 F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM);
450 F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
451 F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
452 F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
453 F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND);
454 F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
455 
456 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
457 static struct attribute *f2fs_attrs[] = {
458         ATTR_LIST(gc_urgent_sleep_time),
459         ATTR_LIST(gc_min_sleep_time),
460         ATTR_LIST(gc_max_sleep_time),
461         ATTR_LIST(gc_no_gc_sleep_time),
462         ATTR_LIST(gc_idle),
463         ATTR_LIST(gc_urgent),
464         ATTR_LIST(reclaim_segments),
465         ATTR_LIST(max_small_discards),
466         ATTR_LIST(discard_granularity),
467         ATTR_LIST(batched_trim_sections),
468         ATTR_LIST(ipu_policy),
469         ATTR_LIST(min_ipu_util),
470         ATTR_LIST(min_fsync_blocks),
471         ATTR_LIST(min_seq_blocks),
472         ATTR_LIST(min_hot_blocks),
473         ATTR_LIST(min_ssr_sections),
474         ATTR_LIST(max_victim_search),
475         ATTR_LIST(migration_granularity),
476         ATTR_LIST(dir_level),
477         ATTR_LIST(ram_thresh),
478         ATTR_LIST(ra_nid_pages),
479         ATTR_LIST(dirty_nats_ratio),
480         ATTR_LIST(cp_interval),
481         ATTR_LIST(idle_interval),
482         ATTR_LIST(discard_idle_interval),
483         ATTR_LIST(gc_idle_interval),
484         ATTR_LIST(iostat_enable),
485         ATTR_LIST(readdir_ra),
486         ATTR_LIST(gc_pin_file_thresh),
487         ATTR_LIST(extension_list),
488 #ifdef CONFIG_F2FS_FAULT_INJECTION
489         ATTR_LIST(inject_rate),
490         ATTR_LIST(inject_type),
491 #endif
492         ATTR_LIST(dirty_segments),
493         ATTR_LIST(lifetime_write_kbytes),
494         ATTR_LIST(features),
495         ATTR_LIST(reserved_blocks),
496         ATTR_LIST(current_reserved_blocks),
497         NULL,
498 };
499 
500 static struct attribute *f2fs_feat_attrs[] = {
501 #ifdef CONFIG_F2FS_FS_ENCRYPTION
502         ATTR_LIST(encryption),
503 #endif
504 #ifdef CONFIG_BLK_DEV_ZONED
505         ATTR_LIST(block_zoned),
506 #endif
507         ATTR_LIST(atomic_write),
508         ATTR_LIST(extra_attr),
509         ATTR_LIST(project_quota),
510         ATTR_LIST(inode_checksum),
511         ATTR_LIST(flexible_inline_xattr),
512         ATTR_LIST(quota_ino),
513         ATTR_LIST(inode_crtime),
514         ATTR_LIST(lost_found),
515         ATTR_LIST(sb_checksum),
516         NULL,
517 };
518 
519 static const struct sysfs_ops f2fs_attr_ops = {
520         .show   = f2fs_attr_show,
521         .store  = f2fs_attr_store,
522 };
523 
524 static struct kobj_type f2fs_sb_ktype = {
525         .default_attrs  = f2fs_attrs,
526         .sysfs_ops      = &f2fs_attr_ops,
527         .release        = f2fs_sb_release,
528 };
529 
530 static struct kobj_type f2fs_ktype = {
531         .sysfs_ops      = &f2fs_attr_ops,
532 };
533 
534 static struct kset f2fs_kset = {
535         .kobj   = {.ktype = &f2fs_ktype},
536 };
537 
538 static struct kobj_type f2fs_feat_ktype = {
539         .default_attrs  = f2fs_feat_attrs,
540         .sysfs_ops      = &f2fs_attr_ops,
541 };
542 
543 static struct kobject f2fs_feat = {
544         .kset   = &f2fs_kset,
545 };
546 
547 static int __maybe_unused segment_info_seq_show(struct seq_file *seq,
548                                                 void *offset)
549 {
550         struct super_block *sb = seq->private;
551         struct f2fs_sb_info *sbi = F2FS_SB(sb);
552         unsigned int total_segs =
553                         le32_to_cpu(sbi->raw_super->segment_count_main);
554         int i;
555 
556         seq_puts(seq, "format: segment_type|valid_blocks\n"
557                 "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
558 
559         for (i = 0; i < total_segs; i++) {
560                 struct seg_entry *se = get_seg_entry(sbi, i);
561 
562                 if ((i % 10) == 0)
563                         seq_printf(seq, "%-10d", i);
564                 seq_printf(seq, "%d|%-3u", se->type,
565                                         get_valid_blocks(sbi, i, false));
566                 if ((i % 10) == 9 || i == (total_segs - 1))
567                         seq_putc(seq, '\n');
568                 else
569                         seq_putc(seq, ' ');
570         }
571 
572         return 0;
573 }
574 
575 static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,
576                                                 void *offset)
577 {
578         struct super_block *sb = seq->private;
579         struct f2fs_sb_info *sbi = F2FS_SB(sb);
580         unsigned int total_segs =
581                         le32_to_cpu(sbi->raw_super->segment_count_main);
582         int i, j;
583 
584         seq_puts(seq, "format: segment_type|valid_blocks|bitmaps\n"
585                 "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
586 
587         for (i = 0; i < total_segs; i++) {
588                 struct seg_entry *se = get_seg_entry(sbi, i);
589 
590                 seq_printf(seq, "%-10d", i);
591                 seq_printf(seq, "%d|%-3u|", se->type,
592                                         get_valid_blocks(sbi, i, false));
593                 for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++)
594                         seq_printf(seq, " %.2x", se->cur_valid_map[j]);
595                 seq_putc(seq, '\n');
596         }
597         return 0;
598 }
599 
600 static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
601                                                void *offset)
602 {
603         struct super_block *sb = seq->private;
604         struct f2fs_sb_info *sbi = F2FS_SB(sb);
605         time64_t now = ktime_get_real_seconds();
606 
607         if (!sbi->iostat_enable)
608                 return 0;
609 
610         seq_printf(seq, "time:          %-16llu\n", now);
611 
612         /* print app IOs */
613         seq_printf(seq, "app buffered:  %-16llu\n",
614                                 sbi->write_iostat[APP_BUFFERED_IO]);
615         seq_printf(seq, "app direct:    %-16llu\n",
616                                 sbi->write_iostat[APP_DIRECT_IO]);
617         seq_printf(seq, "app mapped:    %-16llu\n",
618                                 sbi->write_iostat[APP_MAPPED_IO]);
619 
620         /* print fs IOs */
621         seq_printf(seq, "fs data:       %-16llu\n",
622                                 sbi->write_iostat[FS_DATA_IO]);
623         seq_printf(seq, "fs node:       %-16llu\n",
624                                 sbi->write_iostat[FS_NODE_IO]);
625         seq_printf(seq, "fs meta:       %-16llu\n",
626                                 sbi->write_iostat[FS_META_IO]);
627         seq_printf(seq, "fs gc data:    %-16llu\n",
628                                 sbi->write_iostat[FS_GC_DATA_IO]);
629         seq_printf(seq, "fs gc node:    %-16llu\n",
630                                 sbi->write_iostat[FS_GC_NODE_IO]);
631         seq_printf(seq, "fs cp data:    %-16llu\n",
632                                 sbi->write_iostat[FS_CP_DATA_IO]);
633         seq_printf(seq, "fs cp node:    %-16llu\n",
634                                 sbi->write_iostat[FS_CP_NODE_IO]);
635         seq_printf(seq, "fs cp meta:    %-16llu\n",
636                                 sbi->write_iostat[FS_CP_META_IO]);
637         seq_printf(seq, "fs discard:    %-16llu\n",
638                                 sbi->write_iostat[FS_DISCARD]);
639 
640         return 0;
641 }
642 
643 static int __maybe_unused victim_bits_seq_show(struct seq_file *seq,
644                                                 void *offset)
645 {
646         struct super_block *sb = seq->private;
647         struct f2fs_sb_info *sbi = F2FS_SB(sb);
648         struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
649         int i;
650 
651         seq_puts(seq, "format: victim_secmap bitmaps\n");
652 
653         for (i = 0; i < MAIN_SECS(sbi); i++) {
654                 if ((i % 10) == 0)
655                         seq_printf(seq, "%-10d", i);
656                 seq_printf(seq, "%d", test_bit(i, dirty_i->victim_secmap) ? 1 : 0);
657                 if ((i % 10) == 9 || i == (MAIN_SECS(sbi) - 1))
658                         seq_putc(seq, '\n');
659                 else
660                         seq_putc(seq, ' ');
661         }
662         return 0;
663 }
664 
665 int __init f2fs_init_sysfs(void)
666 {
667         int ret;
668 
669         kobject_set_name(&f2fs_kset.kobj, "f2fs");
670         f2fs_kset.kobj.parent = fs_kobj;
671         ret = kset_register(&f2fs_kset);
672         if (ret)
673                 return ret;
674 
675         ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype,
676                                    NULL, "features");
677         if (ret)
678                 kset_unregister(&f2fs_kset);
679         else
680                 f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
681         return ret;
682 }
683 
684 void f2fs_exit_sysfs(void)
685 {
686         kobject_put(&f2fs_feat);
687         kset_unregister(&f2fs_kset);
688         remove_proc_entry("fs/f2fs", NULL);
689         f2fs_proc_root = NULL;
690 }
691 
692 int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
693 {
694         struct super_block *sb = sbi->sb;
695         int err;
696 
697         sbi->s_kobj.kset = &f2fs_kset;
698         init_completion(&sbi->s_kobj_unregister);
699         err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL,
700                                 "%s", sb->s_id);
701         if (err)
702                 return err;
703 
704         if (f2fs_proc_root)
705                 sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
706 
707         if (sbi->s_proc) {
708                 proc_create_single_data("segment_info", S_IRUGO, sbi->s_proc,
709                                 segment_info_seq_show, sb);
710                 proc_create_single_data("segment_bits", S_IRUGO, sbi->s_proc,
711                                 segment_bits_seq_show, sb);
712                 proc_create_single_data("iostat_info", S_IRUGO, sbi->s_proc,
713                                 iostat_info_seq_show, sb);
714                 proc_create_single_data("victim_bits", S_IRUGO, sbi->s_proc,
715                                 victim_bits_seq_show, sb);
716         }
717         return 0;
718 }
719 
720 void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
721 {
722         if (sbi->s_proc) {
723                 remove_proc_entry("iostat_info", sbi->s_proc);
724                 remove_proc_entry("segment_info", sbi->s_proc);
725                 remove_proc_entry("segment_bits", sbi->s_proc);
726                 remove_proc_entry("victim_bits", sbi->s_proc);
727                 remove_proc_entry(sbi->sb->s_id, f2fs_proc_root);
728         }
729         kobject_del(&sbi->s_kobj);
730 }
731 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp