linux/fs/f2fs/sysfs.c
<<
>>
Prefs
   1/*
   2 * f2fs sysfs interface
   3 *
   4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
   5 *             http://www.samsung.com/
   6 * Copyright (c) 2017 Chao Yu <chao@kernel.org>
   7 *
   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.
  11 */
  12#include <linux/proc_fs.h>
  13#include <linux/f2fs_fs.h>
  14#include <linux/seq_file.h>
  15
  16#include "f2fs.h"
  17#include "segment.h"
  18#include "gc.h"
  19
  20static struct proc_dir_entry *f2fs_proc_root;
  21
  22/* Sysfs support for f2fs */
  23enum {
  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 */
  32#endif
  33        RESERVED_BLOCKS,        /* struct f2fs_sb_info */
  34};
  35
  36struct f2fs_attr {
  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);
  41        int struct_type;
  42        int offset;
  43        int id;
  44};
  45
  46static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
  47{
  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;
  62#endif
  63        return NULL;
  64}
  65
  66static ssize_t dirty_segments_show(struct f2fs_attr *a,
  67                struct f2fs_sb_info *sbi, char *buf)
  68{
  69        return snprintf(buf, PAGE_SIZE, "%llu\n",
  70                (unsigned long long)(dirty_segments(sbi)));
  71}
  72
  73static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,
  74                struct f2fs_sb_info *sbi, char *buf)
  75{
  76        struct super_block *sb = sbi->sb;
  77
  78        if (!sb->s_bdev->bd_part)
  79                return snprintf(buf, PAGE_SIZE, "0\n");
  80
  81        return snprintf(buf, PAGE_SIZE, "%llu\n",
  82                (unsigned long long)(sbi->kbytes_written +
  83                        BD_PART_WRITTEN(sbi)));
  84}
  85
  86static ssize_t features_show(struct f2fs_attr *a,
  87                struct f2fs_sb_info *sbi, char *buf)
  88{
  89        struct super_block *sb = sbi->sb;
  90        int len = 0;
  91
  92        if (!sb->s_bdev->bd_part)
  93                return snprintf(buf, PAGE_SIZE, "0\n");
  94
  95        if (f2fs_sb_has_encrypt(sb))
  96                len += snprintf(buf, PAGE_SIZE - len, "%s",
  97                                                "encryption");
  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");
 123        return len;
 124}
 125
 126static ssize_t current_reserved_blocks_show(struct f2fs_attr *a,
 127                                        struct f2fs_sb_info *sbi, char *buf)
 128{
 129        return snprintf(buf, PAGE_SIZE, "%u\n", sbi->current_reserved_blocks);
 130}
 131
 132static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
 133                        struct f2fs_sb_info *sbi, char *buf)
 134{
 135        unsigned char *ptr = NULL;
 136        unsigned int *ui;
 137
 138        ptr = __struct_ptr(sbi, a->struct_type);
 139        if (!ptr)
 140                return -EINVAL;
 141
 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;
 147                int len = 0, i;
 148
 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",
 153                                                                extlist[i]);
 154
 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",
 159                                                                extlist[i]);
 160                return len;
 161        }
 162
 163        ui = (unsigned int *)(ptr + a->offset);
 164
 165        return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
 166}
 167
 168static ssize_t __sbi_store(struct f2fs_attr *a,
 169                        struct f2fs_sb_info *sbi,
 170                        const char *buf, size_t count)
 171{
 172        unsigned char *ptr;
 173        unsigned long t;
 174        unsigned int *ui;
 175        ssize_t ret;
 176
 177        ptr = __struct_ptr(sbi, a->struct_type);
 178        if (!ptr)
 179                return -EINVAL;
 180
 181        if (!strcmp(a->attr.name, "extension_list")) {
 182                const char *name = strim((char *)buf);
 183                bool set = true, hot;
 184
 185                if (!strncmp(name, "[h]", 3))
 186                        hot = true;
 187                else if (!strncmp(name, "[c]", 3))
 188                        hot = false;
 189                else
 190                        return -EINVAL;
 191
 192                name += 3;
 193
 194                if (*name == '!') {
 195                        name++;
 196                        set = false;
 197                }
 198
 199                if (strlen(name) >= F2FS_EXTENSION_LEN)
 200                        return -EINVAL;
 201
 202                down_write(&sbi->sb_lock);
 203
 204                ret = f2fs_update_extension_list(sbi, name, hot, set);
 205                if (ret)
 206                        goto out;
 207
 208                ret = f2fs_commit_super(sbi, false);
 209                if (ret)
 210                        f2fs_update_extension_list(sbi, name, hot, !set);
 211out:
 212                up_write(&sbi->sb_lock);
 213                return ret ? ret : count;
 214        }
 215
 216        ui = (unsigned int *)(ptr + a->offset);
 217
 218        ret = kstrtoul(skip_spaces(buf), 0, &t);
 219        if (ret < 0)
 220                return ret;
 221#ifdef CONFIG_F2FS_FAULT_INJECTION
 222        if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX))
 223                return -EINVAL;
 224#endif
 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);
 230                        return -EINVAL;
 231                }
 232                *ui = t;
 233                sbi->current_reserved_blocks = min(sbi->reserved_blocks,
 234                                sbi->user_block_count - valid_user_blocks(sbi));
 235                spin_unlock(&sbi->stat_lock);
 236                return count;
 237        }
 238
 239        if (!strcmp(a->attr.name, "discard_granularity")) {
 240                if (t == 0 || t > MAX_PLIST_NUM)
 241                        return -EINVAL;
 242                if (t == *ui)
 243                        return count;
 244                *ui = t;
 245                return count;
 246        }
 247
 248        if (!strcmp(a->attr.name, "trim_sections"))
 249                return -EINVAL;
 250
 251        if (!strcmp(a->attr.name, "gc_urgent")) {
 252                if (t >= 1) {
 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);
 258                        }
 259                } else {
 260                        sbi->gc_mode = GC_NORMAL;
 261                }
 262                return count;
 263        }
 264        if (!strcmp(a->attr.name, "gc_idle")) {
 265                if (t == GC_IDLE_CB)
 266                        sbi->gc_mode = GC_IDLE_CB;
 267                else if (t == GC_IDLE_GREEDY)
 268                        sbi->gc_mode = GC_IDLE_GREEDY;
 269                else
 270                        sbi->gc_mode = GC_NORMAL;
 271                return count;
 272        }
 273
 274        *ui = t;
 275
 276        if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0)
 277                f2fs_reset_iostat(sbi);
 278        return count;
 279}
 280
 281static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
 282                        struct f2fs_sb_info *sbi,
 283                        const char *buf, size_t count)
 284{
 285        ssize_t ret;
 286        bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||
 287                                        a->struct_type == GC_THREAD);
 288
 289        if (gc_entry)
 290                down_read(&sbi->sb->s_umount);
 291        ret = __sbi_store(a, sbi, buf, count);
 292        if (gc_entry)
 293                up_read(&sbi->sb->s_umount);
 294
 295        return ret;
 296}
 297
 298static ssize_t f2fs_attr_show(struct kobject *kobj,
 299                                struct attribute *attr, char *buf)
 300{
 301        struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
 302                                                                s_kobj);
 303        struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
 304
 305        return a->show ? a->show(a, sbi, buf) : 0;
 306}
 307
 308static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr,
 309                                                const char *buf, size_t len)
 310{
 311        struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
 312                                                                        s_kobj);
 313        struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
 314
 315        return a->store ? a->store(a, sbi, buf, len) : 0;
 316}
 317
 318static void f2fs_sb_release(struct kobject *kobj)
 319{
 320        struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
 321                                                                s_kobj);
 322        complete(&sbi->s_kobj_unregister);
 323}
 324
 325enum feat_id {
 326        FEAT_CRYPTO = 0,
 327        FEAT_BLKZONED,
 328        FEAT_ATOMIC_WRITE,
 329        FEAT_EXTRA_ATTR,
 330        FEAT_PROJECT_QUOTA,
 331        FEAT_INODE_CHECKSUM,
 332        FEAT_FLEXIBLE_INLINE_XATTR,
 333        FEAT_QUOTA_INO,
 334        FEAT_INODE_CRTIME,
 335        FEAT_LOST_FOUND,
 336};
 337
 338static ssize_t f2fs_feature_show(struct f2fs_attr *a,
 339                struct f2fs_sb_info *sbi, char *buf)
 340{
 341        switch (a->id) {
 342        case FEAT_CRYPTO:
 343        case FEAT_BLKZONED:
 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:
 349        case FEAT_QUOTA_INO:
 350        case FEAT_INODE_CRTIME:
 351        case FEAT_LOST_FOUND:
 352                return snprintf(buf, PAGE_SIZE, "supported\n");
 353        }
 354        return 0;
 355}
 356
 357#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
 358static struct f2fs_attr f2fs_attr_##_name = {                   \
 359        .attr = {.name = __stringify(_name), .mode = _mode },   \
 360        .show   = _show,                                        \
 361        .store  = _store,                                       \
 362        .struct_type = _struct_type,                            \
 363        .offset = _offset                                       \
 364}
 365
 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))
 370
 371#define F2FS_GENERAL_RO_ATTR(name) \
 372static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)
 373
 374#define F2FS_FEATURE_RO_ATTR(_name, _id)                        \
 375static struct f2fs_attr f2fs_attr_##_name = {                   \
 376        .attr = {.name = __stringify(_name), .mode = 0444 },    \
 377        .show   = f2fs_feature_show,                            \
 378        .id     = _id,                                          \
 379}
 380
 381F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
 382                                                        urgent_sleep_time);
 383F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
 384F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
 385F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
 386F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode);
 387F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode);
 388F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
 389F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
 390F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
 391F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, reserved_blocks, reserved_blocks);
 392F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections);
 393F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
 394F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
 395F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks);
 396F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_hot_blocks, min_hot_blocks);
 397F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ssr_sections, min_ssr_sections);
 398F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh);
 399F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages);
 400F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, dirty_nats_ratio, dirty_nats_ratio);
 401F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
 402F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
 403F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
 404F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
 405F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
 406F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
 407F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
 408F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);
 409#ifdef CONFIG_F2FS_FAULT_INJECTION
 410F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate);
 411F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
 412#endif
 413F2FS_GENERAL_RO_ATTR(dirty_segments);
 414F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
 415F2FS_GENERAL_RO_ATTR(features);
 416F2FS_GENERAL_RO_ATTR(current_reserved_blocks);
 417
 418#ifdef CONFIG_F2FS_FS_ENCRYPTION
 419F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO);
 420#endif
 421#ifdef CONFIG_BLK_DEV_ZONED
 422F2FS_FEATURE_RO_ATTR(block_zoned, FEAT_BLKZONED);
 423#endif
 424F2FS_FEATURE_RO_ATTR(atomic_write, FEAT_ATOMIC_WRITE);
 425F2FS_FEATURE_RO_ATTR(extra_attr, FEAT_EXTRA_ATTR);
 426F2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA);
 427F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM);
 428F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
 429F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
 430F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
 431F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND);
 432
 433#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 434static 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),
 439        ATTR_LIST(gc_idle),
 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),
 464#endif
 465        ATTR_LIST(dirty_segments),
 466        ATTR_LIST(lifetime_write_kbytes),
 467        ATTR_LIST(features),
 468        ATTR_LIST(reserved_blocks),
 469        ATTR_LIST(current_reserved_blocks),
 470        NULL,
 471};
 472
 473static struct attribute *f2fs_feat_attrs[] = {
 474#ifdef CONFIG_F2FS_FS_ENCRYPTION
 475        ATTR_LIST(encryption),
 476#endif
 477#ifdef CONFIG_BLK_DEV_ZONED
 478        ATTR_LIST(block_zoned),
 479#endif
 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),
 488        NULL,
 489};
 490
 491static const struct sysfs_ops f2fs_attr_ops = {
 492        .show   = f2fs_attr_show,
 493        .store  = f2fs_attr_store,
 494};
 495
 496static struct kobj_type f2fs_sb_ktype = {
 497        .default_attrs  = f2fs_attrs,
 498        .sysfs_ops      = &f2fs_attr_ops,
 499        .release        = f2fs_sb_release,
 500};
 501
 502static struct kobj_type f2fs_ktype = {
 503        .sysfs_ops      = &f2fs_attr_ops,
 504};
 505
 506static struct kset f2fs_kset = {
 507        .kobj   = {.ktype = &f2fs_ktype},
 508};
 509
 510static struct kobj_type f2fs_feat_ktype = {
 511        .default_attrs  = f2fs_feat_attrs,
 512        .sysfs_ops      = &f2fs_attr_ops,
 513};
 514
 515static struct kobject f2fs_feat = {
 516        .kset   = &f2fs_kset,
 517};
 518
 519static int segment_info_seq_show(struct seq_file *seq, void *offset)
 520{
 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);
 525        int i;
 526
 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");
 529
 530        for (i = 0; i < total_segs; i++) {
 531                struct seg_entry *se = get_seg_entry(sbi, i);
 532
 533                if ((i % 10) == 0)
 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))
 538                        seq_putc(seq, '\n');
 539                else
 540                        seq_putc(seq, ' ');
 541        }
 542
 543        return 0;
 544}
 545
 546static int segment_bits_seq_show(struct seq_file *seq, void *offset)
 547{
 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);
 552        int i, j;
 553
 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");
 556
 557        for (i = 0; i < total_segs; i++) {
 558                struct seg_entry *se = get_seg_entry(sbi, i);
 559
 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]);
 565                seq_putc(seq, '\n');
 566        }
 567        return 0;
 568}
 569
 570static int iostat_info_seq_show(struct seq_file *seq, void *offset)
 571{
 572        struct super_block *sb = seq->private;
 573        struct f2fs_sb_info *sbi = F2FS_SB(sb);
 574        time64_t now = ktime_get_real_seconds();
 575
 576        if (!sbi->iostat_enable)
 577                return 0;
 578
 579        seq_printf(seq, "time:          %-16llu\n", now);
 580
 581        /* print app IOs */
 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]);
 588
 589        /* print fs IOs */
 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]);
 608
 609        return 0;
 610}
 611
 612int __init f2fs_init_sysfs(void)
 613{
 614        int ret;
 615
 616        kobject_set_name(&f2fs_kset.kobj, "f2fs");
 617        f2fs_kset.kobj.parent = fs_kobj;
 618        ret = kset_register(&f2fs_kset);
 619        if (ret)
 620                return ret;
 621
 622        ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype,
 623                                   NULL, "features");
 624        if (ret)
 625                kset_unregister(&f2fs_kset);
 626        else
 627                f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
 628        return ret;
 629}
 630
 631void f2fs_exit_sysfs(void)
 632{
 633        kobject_put(&f2fs_feat);
 634        kset_unregister(&f2fs_kset);
 635        remove_proc_entry("fs/f2fs", NULL);
 636        f2fs_proc_root = NULL;
 637}
 638
 639int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
 640{
 641        struct super_block *sb = sbi->sb;
 642        int err;
 643
 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,
 647                                "%s", sb->s_id);
 648        if (err)
 649                return err;
 650
 651        if (f2fs_proc_root)
 652                sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
 653
 654        if (sbi->s_proc) {
 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);
 661        }
 662        return 0;
 663}
 664
 665void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
 666{
 667        if (sbi->s_proc) {
 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);
 672        }
 673        kobject_del(&sbi->s_kobj);
 674}
 675