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