4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 * Copyright (c) 2017 Chao Yu <chao@kernel.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 #include <linux/proc_fs.h>
13 #include <linux/f2fs_fs.h>
14 #include <linux/seq_file.h>
20 static struct proc_dir_entry
*f2fs_proc_root
;
22 /* Sysfs support for f2fs */
24 GC_THREAD
, /* struct f2fs_gc_thread */
25 SM_INFO
, /* struct f2fs_sm_info */
26 DCC_INFO
, /* struct discard_cmd_control */
27 NM_INFO
, /* struct f2fs_nm_info */
28 F2FS_SBI
, /* struct f2fs_sb_info */
29 #ifdef CONFIG_F2FS_FAULT_INJECTION
30 FAULT_INFO_RATE
, /* struct f2fs_fault_info */
31 FAULT_INFO_TYPE
, /* struct f2fs_fault_info */
33 RESERVED_BLOCKS
, /* struct f2fs_sb_info */
37 struct attribute attr
;
38 ssize_t (*show
)(struct f2fs_attr
*, struct f2fs_sb_info
*, char *);
39 ssize_t (*store
)(struct f2fs_attr
*, struct f2fs_sb_info
*,
40 const char *, size_t);
46 static unsigned char *__struct_ptr(struct f2fs_sb_info
*sbi
, int struct_type
)
48 if (struct_type
== GC_THREAD
)
49 return (unsigned char *)sbi
->gc_thread
;
50 else if (struct_type
== SM_INFO
)
51 return (unsigned char *)SM_I(sbi
);
52 else if (struct_type
== DCC_INFO
)
53 return (unsigned char *)SM_I(sbi
)->dcc_info
;
54 else if (struct_type
== NM_INFO
)
55 return (unsigned char *)NM_I(sbi
);
56 else if (struct_type
== F2FS_SBI
|| struct_type
== RESERVED_BLOCKS
)
57 return (unsigned char *)sbi
;
58 #ifdef CONFIG_F2FS_FAULT_INJECTION
59 else if (struct_type
== FAULT_INFO_RATE
||
60 struct_type
== FAULT_INFO_TYPE
)
61 return (unsigned char *)&F2FS_OPTION(sbi
).fault_info
;
66 static ssize_t
dirty_segments_show(struct f2fs_attr
*a
,
67 struct f2fs_sb_info
*sbi
, char *buf
)
69 return snprintf(buf
, PAGE_SIZE
, "%llu\n",
70 (unsigned long long)(dirty_segments(sbi
)));
73 static ssize_t
lifetime_write_kbytes_show(struct f2fs_attr
*a
,
74 struct f2fs_sb_info
*sbi
, char *buf
)
76 struct super_block
*sb
= sbi
->sb
;
78 if (!sb
->s_bdev
->bd_part
)
79 return snprintf(buf
, PAGE_SIZE
, "0\n");
81 return snprintf(buf
, PAGE_SIZE
, "%llu\n",
82 (unsigned long long)(sbi
->kbytes_written
+
83 BD_PART_WRITTEN(sbi
)));
86 static ssize_t
features_show(struct f2fs_attr
*a
,
87 struct f2fs_sb_info
*sbi
, char *buf
)
89 struct super_block
*sb
= sbi
->sb
;
92 if (!sb
->s_bdev
->bd_part
)
93 return snprintf(buf
, PAGE_SIZE
, "0\n");
95 if (f2fs_sb_has_encrypt(sb
))
96 len
+= snprintf(buf
, PAGE_SIZE
- len
, "%s",
98 if (f2fs_sb_has_blkzoned(sb
))
99 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
100 len
? ", " : "", "blkzoned");
101 if (f2fs_sb_has_extra_attr(sb
))
102 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
103 len
? ", " : "", "extra_attr");
104 if (f2fs_sb_has_project_quota(sb
))
105 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
106 len
? ", " : "", "projquota");
107 if (f2fs_sb_has_inode_chksum(sb
))
108 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
109 len
? ", " : "", "inode_checksum");
110 if (f2fs_sb_has_flexible_inline_xattr(sb
))
111 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
112 len
? ", " : "", "flexible_inline_xattr");
113 if (f2fs_sb_has_quota_ino(sb
))
114 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
115 len
? ", " : "", "quota_ino");
116 if (f2fs_sb_has_inode_crtime(sb
))
117 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
118 len
? ", " : "", "inode_crtime");
119 if (f2fs_sb_has_lost_found(sb
))
120 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s%s",
121 len
? ", " : "", "lost_found");
122 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "\n");
126 static ssize_t
current_reserved_blocks_show(struct f2fs_attr
*a
,
127 struct f2fs_sb_info
*sbi
, char *buf
)
129 return snprintf(buf
, PAGE_SIZE
, "%u\n", sbi
->current_reserved_blocks
);
132 static ssize_t
f2fs_sbi_show(struct f2fs_attr
*a
,
133 struct f2fs_sb_info
*sbi
, char *buf
)
135 unsigned char *ptr
= NULL
;
138 ptr
= __struct_ptr(sbi
, a
->struct_type
);
142 if (!strcmp(a
->attr
.name
, "extension_list")) {
143 __u8 (*extlist
)[F2FS_EXTENSION_LEN
] =
144 sbi
->raw_super
->extension_list
;
145 int cold_count
= le32_to_cpu(sbi
->raw_super
->extension_count
);
146 int hot_count
= sbi
->raw_super
->hot_ext_count
;
149 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
,
150 "cold file extension:\n");
151 for (i
= 0; i
< cold_count
; i
++)
152 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s\n",
155 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
,
156 "hot file extension:\n");
157 for (i
= cold_count
; i
< cold_count
+ hot_count
; i
++)
158 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%s\n",
163 ui
= (unsigned int *)(ptr
+ a
->offset
);
165 return snprintf(buf
, PAGE_SIZE
, "%u\n", *ui
);
168 static ssize_t
__sbi_store(struct f2fs_attr
*a
,
169 struct f2fs_sb_info
*sbi
,
170 const char *buf
, size_t count
)
177 ptr
= __struct_ptr(sbi
, a
->struct_type
);
181 if (!strcmp(a
->attr
.name
, "extension_list")) {
182 const char *name
= strim((char *)buf
);
183 bool set
= true, hot
;
185 if (!strncmp(name
, "[h]", 3))
187 else if (!strncmp(name
, "[c]", 3))
199 if (strlen(name
) >= F2FS_EXTENSION_LEN
)
202 down_write(&sbi
->sb_lock
);
204 ret
= f2fs_update_extension_list(sbi
, name
, hot
, set
);
208 ret
= f2fs_commit_super(sbi
, false);
210 f2fs_update_extension_list(sbi
, name
, hot
, !set
);
212 up_write(&sbi
->sb_lock
);
213 return ret
? ret
: count
;
216 ui
= (unsigned int *)(ptr
+ a
->offset
);
218 ret
= kstrtoul(skip_spaces(buf
), 0, &t
);
221 #ifdef CONFIG_F2FS_FAULT_INJECTION
222 if (a
->struct_type
== FAULT_INFO_TYPE
&& t
>= (1 << FAULT_MAX
))
225 if (a
->struct_type
== RESERVED_BLOCKS
) {
226 spin_lock(&sbi
->stat_lock
);
227 if (t
> (unsigned long)(sbi
->user_block_count
-
228 F2FS_OPTION(sbi
).root_reserved_blocks
)) {
229 spin_unlock(&sbi
->stat_lock
);
233 sbi
->current_reserved_blocks
= min(sbi
->reserved_blocks
,
234 sbi
->user_block_count
- valid_user_blocks(sbi
));
235 spin_unlock(&sbi
->stat_lock
);
239 if (!strcmp(a
->attr
.name
, "discard_granularity")) {
240 if (t
== 0 || t
> MAX_PLIST_NUM
)
248 if (!strcmp(a
->attr
.name
, "trim_sections"))
251 if (!strcmp(a
->attr
.name
, "gc_urgent")) {
253 sbi
->gc_mode
= GC_URGENT
;
254 if (sbi
->gc_thread
) {
255 wake_up_interruptible_all(
256 &sbi
->gc_thread
->gc_wait_queue_head
);
257 wake_up_discard_thread(sbi
, true);
260 sbi
->gc_mode
= GC_NORMAL
;
264 if (!strcmp(a
->attr
.name
, "gc_idle")) {
266 sbi
->gc_mode
= GC_IDLE_CB
;
267 else if (t
== GC_IDLE_GREEDY
)
268 sbi
->gc_mode
= GC_IDLE_GREEDY
;
270 sbi
->gc_mode
= GC_NORMAL
;
276 if (!strcmp(a
->attr
.name
, "iostat_enable") && *ui
== 0)
277 f2fs_reset_iostat(sbi
);
281 static ssize_t
f2fs_sbi_store(struct f2fs_attr
*a
,
282 struct f2fs_sb_info
*sbi
,
283 const char *buf
, size_t count
)
286 bool gc_entry
= (!strcmp(a
->attr
.name
, "gc_urgent") ||
287 a
->struct_type
== GC_THREAD
);
290 down_read(&sbi
->sb
->s_umount
);
291 ret
= __sbi_store(a
, sbi
, buf
, count
);
293 up_read(&sbi
->sb
->s_umount
);
298 static ssize_t
f2fs_attr_show(struct kobject
*kobj
,
299 struct attribute
*attr
, char *buf
)
301 struct f2fs_sb_info
*sbi
= container_of(kobj
, struct f2fs_sb_info
,
303 struct f2fs_attr
*a
= container_of(attr
, struct f2fs_attr
, attr
);
305 return a
->show
? a
->show(a
, sbi
, buf
) : 0;
308 static ssize_t
f2fs_attr_store(struct kobject
*kobj
, struct attribute
*attr
,
309 const char *buf
, size_t len
)
311 struct f2fs_sb_info
*sbi
= container_of(kobj
, struct f2fs_sb_info
,
313 struct f2fs_attr
*a
= container_of(attr
, struct f2fs_attr
, attr
);
315 return a
->store
? a
->store(a
, sbi
, buf
, len
) : 0;
318 static void f2fs_sb_release(struct kobject
*kobj
)
320 struct f2fs_sb_info
*sbi
= container_of(kobj
, struct f2fs_sb_info
,
322 complete(&sbi
->s_kobj_unregister
);
332 FEAT_FLEXIBLE_INLINE_XATTR
,
338 static ssize_t
f2fs_feature_show(struct f2fs_attr
*a
,
339 struct f2fs_sb_info
*sbi
, char *buf
)
344 case FEAT_ATOMIC_WRITE
:
345 case FEAT_EXTRA_ATTR
:
346 case FEAT_PROJECT_QUOTA
:
347 case FEAT_INODE_CHECKSUM
:
348 case FEAT_FLEXIBLE_INLINE_XATTR
:
350 case FEAT_INODE_CRTIME
:
351 case FEAT_LOST_FOUND
:
352 return snprintf(buf
, PAGE_SIZE
, "supported\n");
357 #define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
358 static struct f2fs_attr f2fs_attr_##_name = { \
359 .attr = {.name = __stringify(_name), .mode = _mode }, \
362 .struct_type = _struct_type, \
366 #define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \
367 F2FS_ATTR_OFFSET(struct_type, name, 0644, \
368 f2fs_sbi_show, f2fs_sbi_store, \
369 offsetof(struct struct_name, elname))
371 #define F2FS_GENERAL_RO_ATTR(name) \
372 static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)
374 #define F2FS_FEATURE_RO_ATTR(_name, _id) \
375 static struct f2fs_attr f2fs_attr_##_name = { \
376 .attr = {.name = __stringify(_name), .mode = 0444 }, \
377 .show = f2fs_feature_show, \
381 F2FS_RW_ATTR(GC_THREAD
, f2fs_gc_kthread
, gc_urgent_sleep_time
,
383 F2FS_RW_ATTR(GC_THREAD
, f2fs_gc_kthread
, gc_min_sleep_time
, min_sleep_time
);
384 F2FS_RW_ATTR(GC_THREAD
, f2fs_gc_kthread
, gc_max_sleep_time
, max_sleep_time
);
385 F2FS_RW_ATTR(GC_THREAD
, f2fs_gc_kthread
, gc_no_gc_sleep_time
, no_gc_sleep_time
);
386 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, gc_idle
, gc_mode
);
387 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, gc_urgent
, gc_mode
);
388 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, reclaim_segments
, rec_prefree_segments
);
389 F2FS_RW_ATTR(DCC_INFO
, discard_cmd_control
, max_small_discards
, max_discards
);
390 F2FS_RW_ATTR(DCC_INFO
, discard_cmd_control
, discard_granularity
, discard_granularity
);
391 F2FS_RW_ATTR(RESERVED_BLOCKS
, f2fs_sb_info
, reserved_blocks
, reserved_blocks
);
392 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, batched_trim_sections
, trim_sections
);
393 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, ipu_policy
, ipu_policy
);
394 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, min_ipu_util
, min_ipu_util
);
395 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, min_fsync_blocks
, min_fsync_blocks
);
396 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, min_hot_blocks
, min_hot_blocks
);
397 F2FS_RW_ATTR(SM_INFO
, f2fs_sm_info
, min_ssr_sections
, min_ssr_sections
);
398 F2FS_RW_ATTR(NM_INFO
, f2fs_nm_info
, ram_thresh
, ram_thresh
);
399 F2FS_RW_ATTR(NM_INFO
, f2fs_nm_info
, ra_nid_pages
, ra_nid_pages
);
400 F2FS_RW_ATTR(NM_INFO
, f2fs_nm_info
, dirty_nats_ratio
, dirty_nats_ratio
);
401 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, max_victim_search
, max_victim_search
);
402 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, dir_level
, dir_level
);
403 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, cp_interval
, interval_time
[CP_TIME
]);
404 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, idle_interval
, interval_time
[REQ_TIME
]);
405 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, iostat_enable
, iostat_enable
);
406 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, readdir_ra
, readdir_ra
);
407 F2FS_RW_ATTR(F2FS_SBI
, f2fs_sb_info
, gc_pin_file_thresh
, gc_pin_file_threshold
);
408 F2FS_RW_ATTR(F2FS_SBI
, f2fs_super_block
, extension_list
, extension_list
);
409 #ifdef CONFIG_F2FS_FAULT_INJECTION
410 F2FS_RW_ATTR(FAULT_INFO_RATE
, f2fs_fault_info
, inject_rate
, inject_rate
);
411 F2FS_RW_ATTR(FAULT_INFO_TYPE
, f2fs_fault_info
, inject_type
, inject_type
);
413 F2FS_GENERAL_RO_ATTR(dirty_segments
);
414 F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes
);
415 F2FS_GENERAL_RO_ATTR(features
);
416 F2FS_GENERAL_RO_ATTR(current_reserved_blocks
);
418 #ifdef CONFIG_F2FS_FS_ENCRYPTION
419 F2FS_FEATURE_RO_ATTR(encryption
, FEAT_CRYPTO
);
421 #ifdef CONFIG_BLK_DEV_ZONED
422 F2FS_FEATURE_RO_ATTR(block_zoned
, FEAT_BLKZONED
);
424 F2FS_FEATURE_RO_ATTR(atomic_write
, FEAT_ATOMIC_WRITE
);
425 F2FS_FEATURE_RO_ATTR(extra_attr
, FEAT_EXTRA_ATTR
);
426 F2FS_FEATURE_RO_ATTR(project_quota
, FEAT_PROJECT_QUOTA
);
427 F2FS_FEATURE_RO_ATTR(inode_checksum
, FEAT_INODE_CHECKSUM
);
428 F2FS_FEATURE_RO_ATTR(flexible_inline_xattr
, FEAT_FLEXIBLE_INLINE_XATTR
);
429 F2FS_FEATURE_RO_ATTR(quota_ino
, FEAT_QUOTA_INO
);
430 F2FS_FEATURE_RO_ATTR(inode_crtime
, FEAT_INODE_CRTIME
);
431 F2FS_FEATURE_RO_ATTR(lost_found
, FEAT_LOST_FOUND
);
433 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
434 static struct attribute
*f2fs_attrs
[] = {
435 ATTR_LIST(gc_urgent_sleep_time
),
436 ATTR_LIST(gc_min_sleep_time
),
437 ATTR_LIST(gc_max_sleep_time
),
438 ATTR_LIST(gc_no_gc_sleep_time
),
440 ATTR_LIST(gc_urgent
),
441 ATTR_LIST(reclaim_segments
),
442 ATTR_LIST(max_small_discards
),
443 ATTR_LIST(discard_granularity
),
444 ATTR_LIST(batched_trim_sections
),
445 ATTR_LIST(ipu_policy
),
446 ATTR_LIST(min_ipu_util
),
447 ATTR_LIST(min_fsync_blocks
),
448 ATTR_LIST(min_hot_blocks
),
449 ATTR_LIST(min_ssr_sections
),
450 ATTR_LIST(max_victim_search
),
451 ATTR_LIST(dir_level
),
452 ATTR_LIST(ram_thresh
),
453 ATTR_LIST(ra_nid_pages
),
454 ATTR_LIST(dirty_nats_ratio
),
455 ATTR_LIST(cp_interval
),
456 ATTR_LIST(idle_interval
),
457 ATTR_LIST(iostat_enable
),
458 ATTR_LIST(readdir_ra
),
459 ATTR_LIST(gc_pin_file_thresh
),
460 ATTR_LIST(extension_list
),
461 #ifdef CONFIG_F2FS_FAULT_INJECTION
462 ATTR_LIST(inject_rate
),
463 ATTR_LIST(inject_type
),
465 ATTR_LIST(dirty_segments
),
466 ATTR_LIST(lifetime_write_kbytes
),
468 ATTR_LIST(reserved_blocks
),
469 ATTR_LIST(current_reserved_blocks
),
473 static struct attribute
*f2fs_feat_attrs
[] = {
474 #ifdef CONFIG_F2FS_FS_ENCRYPTION
475 ATTR_LIST(encryption
),
477 #ifdef CONFIG_BLK_DEV_ZONED
478 ATTR_LIST(block_zoned
),
480 ATTR_LIST(atomic_write
),
481 ATTR_LIST(extra_attr
),
482 ATTR_LIST(project_quota
),
483 ATTR_LIST(inode_checksum
),
484 ATTR_LIST(flexible_inline_xattr
),
485 ATTR_LIST(quota_ino
),
486 ATTR_LIST(inode_crtime
),
487 ATTR_LIST(lost_found
),
491 static const struct sysfs_ops f2fs_attr_ops
= {
492 .show
= f2fs_attr_show
,
493 .store
= f2fs_attr_store
,
496 static struct kobj_type f2fs_sb_ktype
= {
497 .default_attrs
= f2fs_attrs
,
498 .sysfs_ops
= &f2fs_attr_ops
,
499 .release
= f2fs_sb_release
,
502 static struct kobj_type f2fs_ktype
= {
503 .sysfs_ops
= &f2fs_attr_ops
,
506 static struct kset f2fs_kset
= {
507 .kobj
= {.ktype
= &f2fs_ktype
},
510 static struct kobj_type f2fs_feat_ktype
= {
511 .default_attrs
= f2fs_feat_attrs
,
512 .sysfs_ops
= &f2fs_attr_ops
,
515 static struct kobject f2fs_feat
= {
519 static int segment_info_seq_show(struct seq_file
*seq
, void *offset
)
521 struct super_block
*sb
= seq
->private;
522 struct f2fs_sb_info
*sbi
= F2FS_SB(sb
);
523 unsigned int total_segs
=
524 le32_to_cpu(sbi
->raw_super
->segment_count_main
);
527 seq_puts(seq
, "format: segment_type|valid_blocks\n"
528 "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
530 for (i
= 0; i
< total_segs
; i
++) {
531 struct seg_entry
*se
= get_seg_entry(sbi
, i
);
534 seq_printf(seq
, "%-10d", i
);
535 seq_printf(seq
, "%d|%-3u", se
->type
,
536 get_valid_blocks(sbi
, i
, false));
537 if ((i
% 10) == 9 || i
== (total_segs
- 1))
546 static int segment_bits_seq_show(struct seq_file
*seq
, void *offset
)
548 struct super_block
*sb
= seq
->private;
549 struct f2fs_sb_info
*sbi
= F2FS_SB(sb
);
550 unsigned int total_segs
=
551 le32_to_cpu(sbi
->raw_super
->segment_count_main
);
554 seq_puts(seq
, "format: segment_type|valid_blocks|bitmaps\n"
555 "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
557 for (i
= 0; i
< total_segs
; i
++) {
558 struct seg_entry
*se
= get_seg_entry(sbi
, i
);
560 seq_printf(seq
, "%-10d", i
);
561 seq_printf(seq
, "%d|%-3u|", se
->type
,
562 get_valid_blocks(sbi
, i
, false));
563 for (j
= 0; j
< SIT_VBLOCK_MAP_SIZE
; j
++)
564 seq_printf(seq
, " %.2x", se
->cur_valid_map
[j
]);
570 static int iostat_info_seq_show(struct seq_file
*seq
, void *offset
)
572 struct super_block
*sb
= seq
->private;
573 struct f2fs_sb_info
*sbi
= F2FS_SB(sb
);
574 time64_t now
= ktime_get_real_seconds();
576 if (!sbi
->iostat_enable
)
579 seq_printf(seq
, "time: %-16llu\n", now
);
582 seq_printf(seq
, "app buffered: %-16llu\n",
583 sbi
->write_iostat
[APP_BUFFERED_IO
]);
584 seq_printf(seq
, "app direct: %-16llu\n",
585 sbi
->write_iostat
[APP_DIRECT_IO
]);
586 seq_printf(seq
, "app mapped: %-16llu\n",
587 sbi
->write_iostat
[APP_MAPPED_IO
]);
590 seq_printf(seq
, "fs data: %-16llu\n",
591 sbi
->write_iostat
[FS_DATA_IO
]);
592 seq_printf(seq
, "fs node: %-16llu\n",
593 sbi
->write_iostat
[FS_NODE_IO
]);
594 seq_printf(seq
, "fs meta: %-16llu\n",
595 sbi
->write_iostat
[FS_META_IO
]);
596 seq_printf(seq
, "fs gc data: %-16llu\n",
597 sbi
->write_iostat
[FS_GC_DATA_IO
]);
598 seq_printf(seq
, "fs gc node: %-16llu\n",
599 sbi
->write_iostat
[FS_GC_NODE_IO
]);
600 seq_printf(seq
, "fs cp data: %-16llu\n",
601 sbi
->write_iostat
[FS_CP_DATA_IO
]);
602 seq_printf(seq
, "fs cp node: %-16llu\n",
603 sbi
->write_iostat
[FS_CP_NODE_IO
]);
604 seq_printf(seq
, "fs cp meta: %-16llu\n",
605 sbi
->write_iostat
[FS_CP_META_IO
]);
606 seq_printf(seq
, "fs discard: %-16llu\n",
607 sbi
->write_iostat
[FS_DISCARD
]);
612 int __init
f2fs_init_sysfs(void)
616 kobject_set_name(&f2fs_kset
.kobj
, "f2fs");
617 f2fs_kset
.kobj
.parent
= fs_kobj
;
618 ret
= kset_register(&f2fs_kset
);
622 ret
= kobject_init_and_add(&f2fs_feat
, &f2fs_feat_ktype
,
625 kset_unregister(&f2fs_kset
);
627 f2fs_proc_root
= proc_mkdir("fs/f2fs", NULL
);
631 void f2fs_exit_sysfs(void)
633 kobject_put(&f2fs_feat
);
634 kset_unregister(&f2fs_kset
);
635 remove_proc_entry("fs/f2fs", NULL
);
636 f2fs_proc_root
= NULL
;
639 int f2fs_register_sysfs(struct f2fs_sb_info
*sbi
)
641 struct super_block
*sb
= sbi
->sb
;
644 sbi
->s_kobj
.kset
= &f2fs_kset
;
645 init_completion(&sbi
->s_kobj_unregister
);
646 err
= kobject_init_and_add(&sbi
->s_kobj
, &f2fs_sb_ktype
, NULL
,
652 sbi
->s_proc
= proc_mkdir(sb
->s_id
, f2fs_proc_root
);
655 proc_create_single_data("segment_info", S_IRUGO
, sbi
->s_proc
,
656 segment_info_seq_show
, sb
);
657 proc_create_single_data("segment_bits", S_IRUGO
, sbi
->s_proc
,
658 segment_bits_seq_show
, sb
);
659 proc_create_single_data("iostat_info", S_IRUGO
, sbi
->s_proc
,
660 iostat_info_seq_show
, sb
);
665 void f2fs_unregister_sysfs(struct f2fs_sb_info
*sbi
)
668 remove_proc_entry("iostat_info", sbi
->s_proc
);
669 remove_proc_entry("segment_info", sbi
->s_proc
);
670 remove_proc_entry("segment_bits", sbi
->s_proc
);
671 remove_proc_entry(sbi
->sb
->s_id
, f2fs_proc_root
);
673 kobject_del(&sbi
->s_kobj
);