1692 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * f2fs sysfs interface4 *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#include <linux/unicode.h>14#include <linux/ioprio.h>15#include <linux/sysfs.h>16 17#include "f2fs.h"18#include "segment.h"19#include "gc.h"20#include "iostat.h"21#include <trace/events/f2fs.h>22 23static struct proc_dir_entry *f2fs_proc_root;24 25/* Sysfs support for f2fs */26enum {27 GC_THREAD, /* struct f2fs_gc_thread */28 SM_INFO, /* struct f2fs_sm_info */29 DCC_INFO, /* struct discard_cmd_control */30 NM_INFO, /* struct f2fs_nm_info */31 F2FS_SBI, /* struct f2fs_sb_info */32#ifdef CONFIG_F2FS_STAT_FS33 STAT_INFO, /* struct f2fs_stat_info */34#endif35#ifdef CONFIG_F2FS_FAULT_INJECTION36 FAULT_INFO_RATE, /* struct f2fs_fault_info */37 FAULT_INFO_TYPE, /* struct f2fs_fault_info */38#endif39 RESERVED_BLOCKS, /* struct f2fs_sb_info */40 CPRC_INFO, /* struct ckpt_req_control */41 ATGC_INFO, /* struct atgc_management */42};43 44static const char *gc_mode_names[MAX_GC_MODE] = {45 "GC_NORMAL",46 "GC_IDLE_CB",47 "GC_IDLE_GREEDY",48 "GC_IDLE_AT",49 "GC_URGENT_HIGH",50 "GC_URGENT_LOW",51 "GC_URGENT_MID"52};53 54struct f2fs_attr {55 struct attribute attr;56 ssize_t (*show)(struct f2fs_attr *a, struct f2fs_sb_info *sbi, char *buf);57 ssize_t (*store)(struct f2fs_attr *a, struct f2fs_sb_info *sbi,58 const char *buf, size_t len);59 int struct_type;60 int offset;61 int id;62};63 64static ssize_t f2fs_sbi_show(struct f2fs_attr *a,65 struct f2fs_sb_info *sbi, char *buf);66 67static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)68{69 if (struct_type == GC_THREAD)70 return (unsigned char *)sbi->gc_thread;71 else if (struct_type == SM_INFO)72 return (unsigned char *)SM_I(sbi);73 else if (struct_type == DCC_INFO)74 return (unsigned char *)SM_I(sbi)->dcc_info;75 else if (struct_type == NM_INFO)76 return (unsigned char *)NM_I(sbi);77 else if (struct_type == F2FS_SBI || struct_type == RESERVED_BLOCKS)78 return (unsigned char *)sbi;79#ifdef CONFIG_F2FS_FAULT_INJECTION80 else if (struct_type == FAULT_INFO_RATE ||81 struct_type == FAULT_INFO_TYPE)82 return (unsigned char *)&F2FS_OPTION(sbi).fault_info;83#endif84#ifdef CONFIG_F2FS_STAT_FS85 else if (struct_type == STAT_INFO)86 return (unsigned char *)F2FS_STAT(sbi);87#endif88 else if (struct_type == CPRC_INFO)89 return (unsigned char *)&sbi->cprc_info;90 else if (struct_type == ATGC_INFO)91 return (unsigned char *)&sbi->am;92 return NULL;93}94 95static ssize_t dirty_segments_show(struct f2fs_attr *a,96 struct f2fs_sb_info *sbi, char *buf)97{98 return sysfs_emit(buf, "%llu\n",99 (unsigned long long)(dirty_segments(sbi)));100}101 102static ssize_t free_segments_show(struct f2fs_attr *a,103 struct f2fs_sb_info *sbi, char *buf)104{105 return sysfs_emit(buf, "%llu\n",106 (unsigned long long)(free_segments(sbi)));107}108 109static ssize_t ovp_segments_show(struct f2fs_attr *a,110 struct f2fs_sb_info *sbi, char *buf)111{112 return sysfs_emit(buf, "%llu\n",113 (unsigned long long)(overprovision_segments(sbi)));114}115 116static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,117 struct f2fs_sb_info *sbi, char *buf)118{119 return sysfs_emit(buf, "%llu\n",120 (unsigned long long)(sbi->kbytes_written +121 ((f2fs_get_sectors_written(sbi) -122 sbi->sectors_written_start) >> 1)));123}124 125static ssize_t sb_status_show(struct f2fs_attr *a,126 struct f2fs_sb_info *sbi, char *buf)127{128 return sysfs_emit(buf, "%lx\n", sbi->s_flag);129}130 131static ssize_t cp_status_show(struct f2fs_attr *a,132 struct f2fs_sb_info *sbi, char *buf)133{134 return sysfs_emit(buf, "%x\n", le32_to_cpu(F2FS_CKPT(sbi)->ckpt_flags));135}136 137static ssize_t pending_discard_show(struct f2fs_attr *a,138 struct f2fs_sb_info *sbi, char *buf)139{140 if (!SM_I(sbi)->dcc_info)141 return -EINVAL;142 return sysfs_emit(buf, "%llu\n", (unsigned long long)atomic_read(143 &SM_I(sbi)->dcc_info->discard_cmd_cnt));144}145 146static ssize_t issued_discard_show(struct f2fs_attr *a,147 struct f2fs_sb_info *sbi, char *buf)148{149 if (!SM_I(sbi)->dcc_info)150 return -EINVAL;151 return sysfs_emit(buf, "%llu\n", (unsigned long long)atomic_read(152 &SM_I(sbi)->dcc_info->issued_discard));153}154 155static ssize_t queued_discard_show(struct f2fs_attr *a,156 struct f2fs_sb_info *sbi, char *buf)157{158 if (!SM_I(sbi)->dcc_info)159 return -EINVAL;160 return sysfs_emit(buf, "%llu\n", (unsigned long long)atomic_read(161 &SM_I(sbi)->dcc_info->queued_discard));162}163 164static ssize_t undiscard_blks_show(struct f2fs_attr *a,165 struct f2fs_sb_info *sbi, char *buf)166{167 if (!SM_I(sbi)->dcc_info)168 return -EINVAL;169 return sysfs_emit(buf, "%u\n",170 SM_I(sbi)->dcc_info->undiscard_blks);171}172 173static ssize_t atgc_enabled_show(struct f2fs_attr *a,174 struct f2fs_sb_info *sbi, char *buf)175{176 return sysfs_emit(buf, "%d\n", sbi->am.atgc_enabled ? 1 : 0);177}178 179static ssize_t gc_mode_show(struct f2fs_attr *a,180 struct f2fs_sb_info *sbi, char *buf)181{182 return sysfs_emit(buf, "%s\n", gc_mode_names[sbi->gc_mode]);183}184 185static ssize_t features_show(struct f2fs_attr *a,186 struct f2fs_sb_info *sbi, char *buf)187{188 int len = 0;189 190 if (f2fs_sb_has_encrypt(sbi))191 len += sysfs_emit_at(buf, len, "%s",192 "encryption");193 if (f2fs_sb_has_blkzoned(sbi))194 len += sysfs_emit_at(buf, len, "%s%s",195 len ? ", " : "", "blkzoned");196 if (f2fs_sb_has_extra_attr(sbi))197 len += sysfs_emit_at(buf, len, "%s%s",198 len ? ", " : "", "extra_attr");199 if (f2fs_sb_has_project_quota(sbi))200 len += sysfs_emit_at(buf, len, "%s%s",201 len ? ", " : "", "projquota");202 if (f2fs_sb_has_inode_chksum(sbi))203 len += sysfs_emit_at(buf, len, "%s%s",204 len ? ", " : "", "inode_checksum");205 if (f2fs_sb_has_flexible_inline_xattr(sbi))206 len += sysfs_emit_at(buf, len, "%s%s",207 len ? ", " : "", "flexible_inline_xattr");208 if (f2fs_sb_has_quota_ino(sbi))209 len += sysfs_emit_at(buf, len, "%s%s",210 len ? ", " : "", "quota_ino");211 if (f2fs_sb_has_inode_crtime(sbi))212 len += sysfs_emit_at(buf, len, "%s%s",213 len ? ", " : "", "inode_crtime");214 if (f2fs_sb_has_lost_found(sbi))215 len += sysfs_emit_at(buf, len, "%s%s",216 len ? ", " : "", "lost_found");217 if (f2fs_sb_has_verity(sbi))218 len += sysfs_emit_at(buf, len, "%s%s",219 len ? ", " : "", "verity");220 if (f2fs_sb_has_sb_chksum(sbi))221 len += sysfs_emit_at(buf, len, "%s%s",222 len ? ", " : "", "sb_checksum");223 if (f2fs_sb_has_casefold(sbi))224 len += sysfs_emit_at(buf, len, "%s%s",225 len ? ", " : "", "casefold");226 if (f2fs_sb_has_readonly(sbi))227 len += sysfs_emit_at(buf, len, "%s%s",228 len ? ", " : "", "readonly");229 if (f2fs_sb_has_compression(sbi))230 len += sysfs_emit_at(buf, len, "%s%s",231 len ? ", " : "", "compression");232 len += sysfs_emit_at(buf, len, "%s%s",233 len ? ", " : "", "pin_file");234 len += sysfs_emit_at(buf, len, "\n");235 return len;236}237 238static ssize_t current_reserved_blocks_show(struct f2fs_attr *a,239 struct f2fs_sb_info *sbi, char *buf)240{241 return sysfs_emit(buf, "%u\n", sbi->current_reserved_blocks);242}243 244static ssize_t unusable_show(struct f2fs_attr *a,245 struct f2fs_sb_info *sbi, char *buf)246{247 block_t unusable;248 249 if (test_opt(sbi, DISABLE_CHECKPOINT))250 unusable = sbi->unusable_block_count;251 else252 unusable = f2fs_get_unusable_blocks(sbi);253 return sysfs_emit(buf, "%llu\n", (unsigned long long)unusable);254}255 256static ssize_t encoding_show(struct f2fs_attr *a,257 struct f2fs_sb_info *sbi, char *buf)258{259#if IS_ENABLED(CONFIG_UNICODE)260 struct super_block *sb = sbi->sb;261 262 if (f2fs_sb_has_casefold(sbi))263 return sysfs_emit(buf, "UTF-8 (%d.%d.%d)\n",264 (sb->s_encoding->version >> 16) & 0xff,265 (sb->s_encoding->version >> 8) & 0xff,266 sb->s_encoding->version & 0xff);267#endif268 return sysfs_emit(buf, "(none)\n");269}270 271static ssize_t mounted_time_sec_show(struct f2fs_attr *a,272 struct f2fs_sb_info *sbi, char *buf)273{274 return sysfs_emit(buf, "%llu\n", SIT_I(sbi)->mounted_time);275}276 277#ifdef CONFIG_F2FS_STAT_FS278static ssize_t moved_blocks_foreground_show(struct f2fs_attr *a,279 struct f2fs_sb_info *sbi, char *buf)280{281 struct f2fs_stat_info *si = F2FS_STAT(sbi);282 283 return sysfs_emit(buf, "%llu\n",284 (unsigned long long)(si->tot_blks -285 (si->bg_data_blks + si->bg_node_blks)));286}287 288static ssize_t moved_blocks_background_show(struct f2fs_attr *a,289 struct f2fs_sb_info *sbi, char *buf)290{291 struct f2fs_stat_info *si = F2FS_STAT(sbi);292 293 return sysfs_emit(buf, "%llu\n",294 (unsigned long long)(si->bg_data_blks + si->bg_node_blks));295}296 297static ssize_t avg_vblocks_show(struct f2fs_attr *a,298 struct f2fs_sb_info *sbi, char *buf)299{300 struct f2fs_stat_info *si = F2FS_STAT(sbi);301 302 si->dirty_count = dirty_segments(sbi);303 f2fs_update_sit_info(sbi);304 return sysfs_emit(buf, "%llu\n", (unsigned long long)(si->avg_vblocks));305}306#endif307 308static ssize_t main_blkaddr_show(struct f2fs_attr *a,309 struct f2fs_sb_info *sbi, char *buf)310{311 return sysfs_emit(buf, "%llu\n",312 (unsigned long long)MAIN_BLKADDR(sbi));313}314 315static ssize_t f2fs_sbi_show(struct f2fs_attr *a,316 struct f2fs_sb_info *sbi, char *buf)317{318 unsigned char *ptr = NULL;319 unsigned int *ui;320 321 ptr = __struct_ptr(sbi, a->struct_type);322 if (!ptr)323 return -EINVAL;324 325 if (!strcmp(a->attr.name, "extension_list")) {326 __u8 (*extlist)[F2FS_EXTENSION_LEN] =327 sbi->raw_super->extension_list;328 int cold_count = le32_to_cpu(sbi->raw_super->extension_count);329 int hot_count = sbi->raw_super->hot_ext_count;330 int len = 0, i;331 332 len += sysfs_emit_at(buf, len, "cold file extension:\n");333 for (i = 0; i < cold_count; i++)334 len += sysfs_emit_at(buf, len, "%s\n", extlist[i]);335 336 len += sysfs_emit_at(buf, len, "hot file extension:\n");337 for (i = cold_count; i < cold_count + hot_count; i++)338 len += sysfs_emit_at(buf, len, "%s\n", extlist[i]);339 340 return len;341 }342 343 if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {344 struct ckpt_req_control *cprc = &sbi->cprc_info;345 int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio);346 int level = IOPRIO_PRIO_LEVEL(cprc->ckpt_thread_ioprio);347 348 if (class != IOPRIO_CLASS_RT && class != IOPRIO_CLASS_BE)349 return -EINVAL;350 351 return sysfs_emit(buf, "%s,%d\n",352 class == IOPRIO_CLASS_RT ? "rt" : "be", level);353 }354 355#ifdef CONFIG_F2FS_FS_COMPRESSION356 if (!strcmp(a->attr.name, "compr_written_block"))357 return sysfs_emit(buf, "%llu\n", sbi->compr_written_block);358 359 if (!strcmp(a->attr.name, "compr_saved_block"))360 return sysfs_emit(buf, "%llu\n", sbi->compr_saved_block);361 362 if (!strcmp(a->attr.name, "compr_new_inode"))363 return sysfs_emit(buf, "%u\n", sbi->compr_new_inode);364#endif365 366 if (!strcmp(a->attr.name, "gc_segment_mode"))367 return sysfs_emit(buf, "%u\n", sbi->gc_segment_mode);368 369 if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {370 return sysfs_emit(buf, "%u\n",371 sbi->gc_reclaimed_segs[sbi->gc_segment_mode]);372 }373 374 if (!strcmp(a->attr.name, "current_atomic_write")) {375 s64 current_write = atomic64_read(&sbi->current_atomic_write);376 377 return sysfs_emit(buf, "%lld\n", current_write);378 }379 380 if (!strcmp(a->attr.name, "peak_atomic_write"))381 return sysfs_emit(buf, "%lld\n", sbi->peak_atomic_write);382 383 if (!strcmp(a->attr.name, "committed_atomic_block"))384 return sysfs_emit(buf, "%llu\n", sbi->committed_atomic_block);385 386 if (!strcmp(a->attr.name, "revoked_atomic_block"))387 return sysfs_emit(buf, "%llu\n", sbi->revoked_atomic_block);388 389#ifdef CONFIG_F2FS_STAT_FS390 if (!strcmp(a->attr.name, "cp_foreground_calls"))391 return sysfs_emit(buf, "%d\n",392 atomic_read(&sbi->cp_call_count[TOTAL_CALL]) -393 atomic_read(&sbi->cp_call_count[BACKGROUND]));394 if (!strcmp(a->attr.name, "cp_background_calls"))395 return sysfs_emit(buf, "%d\n",396 atomic_read(&sbi->cp_call_count[BACKGROUND]));397#endif398 399 ui = (unsigned int *)(ptr + a->offset);400 401 return sysfs_emit(buf, "%u\n", *ui);402}403 404static ssize_t __sbi_store(struct f2fs_attr *a,405 struct f2fs_sb_info *sbi,406 const char *buf, size_t count)407{408 unsigned char *ptr;409 unsigned long t;410 unsigned int *ui;411 ssize_t ret;412 413 ptr = __struct_ptr(sbi, a->struct_type);414 if (!ptr)415 return -EINVAL;416 417 if (!strcmp(a->attr.name, "extension_list")) {418 const char *name = strim((char *)buf);419 bool set = true, hot;420 421 if (!strncmp(name, "[h]", 3))422 hot = true;423 else if (!strncmp(name, "[c]", 3))424 hot = false;425 else426 return -EINVAL;427 428 name += 3;429 430 if (*name == '!') {431 name++;432 set = false;433 }434 435 if (!strlen(name) || strlen(name) >= F2FS_EXTENSION_LEN)436 return -EINVAL;437 438 f2fs_down_write(&sbi->sb_lock);439 440 ret = f2fs_update_extension_list(sbi, name, hot, set);441 if (ret)442 goto out;443 444 ret = f2fs_commit_super(sbi, false);445 if (ret)446 f2fs_update_extension_list(sbi, name, hot, !set);447out:448 f2fs_up_write(&sbi->sb_lock);449 return ret ? ret : count;450 }451 452 if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {453 const char *name = strim((char *)buf);454 struct ckpt_req_control *cprc = &sbi->cprc_info;455 int class;456 long level;457 int ret;458 459 if (!strncmp(name, "rt,", 3))460 class = IOPRIO_CLASS_RT;461 else if (!strncmp(name, "be,", 3))462 class = IOPRIO_CLASS_BE;463 else464 return -EINVAL;465 466 name += 3;467 ret = kstrtol(name, 10, &level);468 if (ret)469 return ret;470 if (level >= IOPRIO_NR_LEVELS || level < 0)471 return -EINVAL;472 473 cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, level);474 if (test_opt(sbi, MERGE_CHECKPOINT)) {475 ret = set_task_ioprio(cprc->f2fs_issue_ckpt,476 cprc->ckpt_thread_ioprio);477 if (ret)478 return ret;479 }480 481 return count;482 }483 484 ui = (unsigned int *)(ptr + a->offset);485 486 ret = kstrtoul(skip_spaces(buf), 0, &t);487 if (ret < 0)488 return ret;489#ifdef CONFIG_F2FS_FAULT_INJECTION490 if (a->struct_type == FAULT_INFO_TYPE) {491 if (f2fs_build_fault_attr(sbi, 0, t))492 return -EINVAL;493 return count;494 }495 if (a->struct_type == FAULT_INFO_RATE) {496 if (f2fs_build_fault_attr(sbi, t, 0))497 return -EINVAL;498 return count;499 }500#endif501 if (a->struct_type == RESERVED_BLOCKS) {502 spin_lock(&sbi->stat_lock);503 if (t > (unsigned long)(sbi->user_block_count -504 F2FS_OPTION(sbi).root_reserved_blocks -505 SEGS_TO_BLKS(sbi,506 SM_I(sbi)->additional_reserved_segments))) {507 spin_unlock(&sbi->stat_lock);508 return -EINVAL;509 }510 *ui = t;511 sbi->current_reserved_blocks = min(sbi->reserved_blocks,512 sbi->user_block_count - valid_user_blocks(sbi));513 spin_unlock(&sbi->stat_lock);514 return count;515 }516 517 if (!strcmp(a->attr.name, "discard_io_aware_gran")) {518 if (t > MAX_PLIST_NUM)519 return -EINVAL;520 if (!f2fs_block_unit_discard(sbi))521 return -EINVAL;522 if (t == *ui)523 return count;524 *ui = t;525 return count;526 }527 528 if (!strcmp(a->attr.name, "discard_granularity")) {529 if (t == 0 || t > MAX_PLIST_NUM)530 return -EINVAL;531 if (!f2fs_block_unit_discard(sbi))532 return -EINVAL;533 if (t == *ui)534 return count;535 *ui = t;536 return count;537 }538 539 if (!strcmp(a->attr.name, "max_ordered_discard")) {540 if (t == 0 || t > MAX_PLIST_NUM)541 return -EINVAL;542 if (!f2fs_block_unit_discard(sbi))543 return -EINVAL;544 *ui = t;545 return count;546 }547 548 if (!strcmp(a->attr.name, "discard_urgent_util")) {549 if (t > 100)550 return -EINVAL;551 *ui = t;552 return count;553 }554 555 if (!strcmp(a->attr.name, "discard_io_aware")) {556 if (t >= DPOLICY_IO_AWARE_MAX)557 return -EINVAL;558 *ui = t;559 return count;560 }561 562 if (!strcmp(a->attr.name, "migration_granularity")) {563 if (t == 0 || t > SEGS_PER_SEC(sbi))564 return -EINVAL;565 }566 567 if (!strcmp(a->attr.name, "migration_window_granularity")) {568 if (t == 0 || t > SEGS_PER_SEC(sbi))569 return -EINVAL;570 }571 572 if (!strcmp(a->attr.name, "gc_urgent")) {573 if (t == 0) {574 sbi->gc_mode = GC_NORMAL;575 } else if (t == 1) {576 sbi->gc_mode = GC_URGENT_HIGH;577 if (sbi->gc_thread) {578 sbi->gc_thread->gc_wake = true;579 wake_up_interruptible_all(580 &sbi->gc_thread->gc_wait_queue_head);581 wake_up_discard_thread(sbi, true);582 }583 } else if (t == 2) {584 sbi->gc_mode = GC_URGENT_LOW;585 } else if (t == 3) {586 sbi->gc_mode = GC_URGENT_MID;587 if (sbi->gc_thread) {588 sbi->gc_thread->gc_wake = true;589 wake_up_interruptible_all(590 &sbi->gc_thread->gc_wait_queue_head);591 }592 } else {593 return -EINVAL;594 }595 return count;596 }597 if (!strcmp(a->attr.name, "gc_idle")) {598 if (t == GC_IDLE_CB) {599 sbi->gc_mode = GC_IDLE_CB;600 } else if (t == GC_IDLE_GREEDY) {601 sbi->gc_mode = GC_IDLE_GREEDY;602 } else if (t == GC_IDLE_AT) {603 if (!sbi->am.atgc_enabled)604 return -EINVAL;605 sbi->gc_mode = GC_IDLE_AT;606 } else {607 sbi->gc_mode = GC_NORMAL;608 }609 return count;610 }611 612 if (!strcmp(a->attr.name, "gc_remaining_trials")) {613 spin_lock(&sbi->gc_remaining_trials_lock);614 sbi->gc_remaining_trials = t;615 spin_unlock(&sbi->gc_remaining_trials_lock);616 617 return count;618 }619 620#ifdef CONFIG_F2FS_IOSTAT621 if (!strcmp(a->attr.name, "iostat_enable")) {622 sbi->iostat_enable = !!t;623 if (!sbi->iostat_enable)624 f2fs_reset_iostat(sbi);625 return count;626 }627 628 if (!strcmp(a->attr.name, "iostat_period_ms")) {629 if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS)630 return -EINVAL;631 spin_lock_irq(&sbi->iostat_lock);632 sbi->iostat_period_ms = (unsigned int)t;633 spin_unlock_irq(&sbi->iostat_lock);634 return count;635 }636#endif637 638#ifdef CONFIG_BLK_DEV_ZONED639 if (!strcmp(a->attr.name, "blkzone_alloc_policy")) {640 if (t < BLKZONE_ALLOC_PRIOR_SEQ || t > BLKZONE_ALLOC_PRIOR_CONV)641 return -EINVAL;642 sbi->blkzone_alloc_policy = t;643 return count;644 }645#endif646 647#ifdef CONFIG_F2FS_FS_COMPRESSION648 if (!strcmp(a->attr.name, "compr_written_block") ||649 !strcmp(a->attr.name, "compr_saved_block")) {650 if (t != 0)651 return -EINVAL;652 sbi->compr_written_block = 0;653 sbi->compr_saved_block = 0;654 return count;655 }656 657 if (!strcmp(a->attr.name, "compr_new_inode")) {658 if (t != 0)659 return -EINVAL;660 sbi->compr_new_inode = 0;661 return count;662 }663 664 if (!strcmp(a->attr.name, "compress_percent")) {665 if (t == 0 || t > 100)666 return -EINVAL;667 *ui = t;668 return count;669 }670 671 if (!strcmp(a->attr.name, "compress_watermark")) {672 if (t == 0 || t > 100)673 return -EINVAL;674 *ui = t;675 return count;676 }677#endif678 679 if (!strcmp(a->attr.name, "atgc_candidate_ratio")) {680 if (t > 100)681 return -EINVAL;682 sbi->am.candidate_ratio = t;683 return count;684 }685 686 if (!strcmp(a->attr.name, "atgc_age_weight")) {687 if (t > 100)688 return -EINVAL;689 sbi->am.age_weight = t;690 return count;691 }692 693 if (!strcmp(a->attr.name, "gc_segment_mode")) {694 if (t < MAX_GC_MODE)695 sbi->gc_segment_mode = t;696 else697 return -EINVAL;698 return count;699 }700 701 if (!strcmp(a->attr.name, "gc_pin_file_threshold")) {702 if (t > MAX_GC_FAILED_PINNED_FILES)703 return -EINVAL;704 sbi->gc_pin_file_threshold = t;705 return count;706 }707 708 if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {709 if (t != 0)710 return -EINVAL;711 sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0;712 return count;713 }714 715 if (!strcmp(a->attr.name, "seq_file_ra_mul")) {716 if (t >= MIN_RA_MUL && t <= MAX_RA_MUL)717 sbi->seq_file_ra_mul = t;718 else719 return -EINVAL;720 return count;721 }722 723 if (!strcmp(a->attr.name, "max_fragment_chunk")) {724 if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE)725 sbi->max_fragment_chunk = t;726 else727 return -EINVAL;728 return count;729 }730 731 if (!strcmp(a->attr.name, "max_fragment_hole")) {732 if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE)733 sbi->max_fragment_hole = t;734 else735 return -EINVAL;736 return count;737 }738 739 if (!strcmp(a->attr.name, "peak_atomic_write")) {740 if (t != 0)741 return -EINVAL;742 sbi->peak_atomic_write = 0;743 return count;744 }745 746 if (!strcmp(a->attr.name, "committed_atomic_block")) {747 if (t != 0)748 return -EINVAL;749 sbi->committed_atomic_block = 0;750 return count;751 }752 753 if (!strcmp(a->attr.name, "revoked_atomic_block")) {754 if (t != 0)755 return -EINVAL;756 sbi->revoked_atomic_block = 0;757 return count;758 }759 760 if (!strcmp(a->attr.name, "readdir_ra")) {761 sbi->readdir_ra = !!t;762 return count;763 }764 765 if (!strcmp(a->attr.name, "hot_data_age_threshold")) {766 if (t == 0 || t >= sbi->warm_data_age_threshold)767 return -EINVAL;768 if (t == *ui)769 return count;770 *ui = (unsigned int)t;771 return count;772 }773 774 if (!strcmp(a->attr.name, "warm_data_age_threshold")) {775 if (t <= sbi->hot_data_age_threshold)776 return -EINVAL;777 if (t == *ui)778 return count;779 *ui = (unsigned int)t;780 return count;781 }782 783 if (!strcmp(a->attr.name, "last_age_weight")) {784 if (t > 100)785 return -EINVAL;786 if (t == *ui)787 return count;788 *ui = (unsigned int)t;789 return count;790 }791 792 if (!strcmp(a->attr.name, "ipu_policy")) {793 if (t >= BIT(F2FS_IPU_MAX))794 return -EINVAL;795 /* allow F2FS_IPU_NOCACHE only for IPU in the pinned file */796 if (f2fs_lfs_mode(sbi) && (t & ~BIT(F2FS_IPU_NOCACHE)))797 return -EINVAL;798 SM_I(sbi)->ipu_policy = (unsigned int)t;799 return count;800 }801 802 if (!strcmp(a->attr.name, "dir_level")) {803 if (t > MAX_DIR_HASH_DEPTH)804 return -EINVAL;805 sbi->dir_level = t;806 return count;807 }808 809 *ui = (unsigned int)t;810 811 return count;812}813 814static ssize_t f2fs_sbi_store(struct f2fs_attr *a,815 struct f2fs_sb_info *sbi,816 const char *buf, size_t count)817{818 ssize_t ret;819 bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||820 a->struct_type == GC_THREAD);821 822 if (gc_entry) {823 if (!down_read_trylock(&sbi->sb->s_umount))824 return -EAGAIN;825 }826 ret = __sbi_store(a, sbi, buf, count);827 if (gc_entry)828 up_read(&sbi->sb->s_umount);829 830 return ret;831}832 833static ssize_t f2fs_attr_show(struct kobject *kobj,834 struct attribute *attr, char *buf)835{836 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,837 s_kobj);838 struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);839 840 return a->show ? a->show(a, sbi, buf) : 0;841}842 843static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr,844 const char *buf, size_t len)845{846 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,847 s_kobj);848 struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);849 850 return a->store ? a->store(a, sbi, buf, len) : 0;851}852 853static void f2fs_sb_release(struct kobject *kobj)854{855 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,856 s_kobj);857 complete(&sbi->s_kobj_unregister);858}859 860/*861 * Note that there are three feature list entries:862 * 1) /sys/fs/f2fs/features863 * : shows runtime features supported by in-kernel f2fs along with Kconfig.864 * - ref. F2FS_FEATURE_RO_ATTR()865 *866 * 2) /sys/fs/f2fs/$s_id/features <deprecated>867 * : shows on-disk features enabled by mkfs.f2fs, used for old kernels. This868 * won't add new feature anymore, and thus, users should check entries in 3)869 * instead of this 2).870 *871 * 3) /sys/fs/f2fs/$s_id/feature_list872 * : shows on-disk features enabled by mkfs.f2fs per instance, which follows873 * sysfs entry rule where each entry should expose single value.874 * This list covers old feature list provided by 2) and beyond. Therefore,875 * please add new on-disk feature in this list only.876 * - ref. F2FS_SB_FEATURE_RO_ATTR()877 */878static ssize_t f2fs_feature_show(struct f2fs_attr *a,879 struct f2fs_sb_info *sbi, char *buf)880{881 return sysfs_emit(buf, "supported\n");882}883 884#define F2FS_FEATURE_RO_ATTR(_name) \885static struct f2fs_attr f2fs_attr_##_name = { \886 .attr = {.name = __stringify(_name), .mode = 0444 }, \887 .show = f2fs_feature_show, \888}889 890static ssize_t f2fs_sb_feature_show(struct f2fs_attr *a,891 struct f2fs_sb_info *sbi, char *buf)892{893 if (F2FS_HAS_FEATURE(sbi, a->id))894 return sysfs_emit(buf, "supported\n");895 return sysfs_emit(buf, "unsupported\n");896}897 898#define F2FS_SB_FEATURE_RO_ATTR(_name, _feat) \899static struct f2fs_attr f2fs_attr_sb_##_name = { \900 .attr = {.name = __stringify(_name), .mode = 0444 }, \901 .show = f2fs_sb_feature_show, \902 .id = F2FS_FEATURE_##_feat, \903}904 905#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \906static struct f2fs_attr f2fs_attr_##_name = { \907 .attr = {.name = __stringify(_name), .mode = _mode }, \908 .show = _show, \909 .store = _store, \910 .struct_type = _struct_type, \911 .offset = _offset \912}913 914#define F2FS_RO_ATTR(struct_type, struct_name, name, elname) \915 F2FS_ATTR_OFFSET(struct_type, name, 0444, \916 f2fs_sbi_show, NULL, \917 offsetof(struct struct_name, elname))918 919#define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \920 F2FS_ATTR_OFFSET(struct_type, name, 0644, \921 f2fs_sbi_show, f2fs_sbi_store, \922 offsetof(struct struct_name, elname))923 924#define F2FS_GENERAL_RO_ATTR(name) \925static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)926 927#ifdef CONFIG_F2FS_STAT_FS928#define STAT_INFO_RO_ATTR(name, elname) \929 F2FS_RO_ATTR(STAT_INFO, f2fs_stat_info, name, elname)930#endif931 932#define GC_THREAD_RW_ATTR(name, elname) \933 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, name, elname)934 935#define SM_INFO_RW_ATTR(name, elname) \936 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, name, elname)937 938#define SM_INFO_GENERAL_RW_ATTR(elname) \939 SM_INFO_RW_ATTR(elname, elname)940 941#define DCC_INFO_RW_ATTR(name, elname) \942 F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, name, elname)943 944#define DCC_INFO_GENERAL_RW_ATTR(elname) \945 DCC_INFO_RW_ATTR(elname, elname)946 947#define NM_INFO_RW_ATTR(name, elname) \948 F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, name, elname)949 950#define NM_INFO_GENERAL_RW_ATTR(elname) \951 NM_INFO_RW_ATTR(elname, elname)952 953#define F2FS_SBI_RW_ATTR(name, elname) \954 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, name, elname)955 956#define F2FS_SBI_GENERAL_RW_ATTR(elname) \957 F2FS_SBI_RW_ATTR(elname, elname)958 959#define F2FS_SBI_GENERAL_RO_ATTR(elname) \960 F2FS_RO_ATTR(F2FS_SBI, f2fs_sb_info, elname, elname)961 962#ifdef CONFIG_F2FS_FAULT_INJECTION963#define FAULT_INFO_GENERAL_RW_ATTR(type, elname) \964 F2FS_RW_ATTR(type, f2fs_fault_info, elname, elname)965#endif966 967#define RESERVED_BLOCKS_GENERAL_RW_ATTR(elname) \968 F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, elname, elname)969 970#define CPRC_INFO_GENERAL_RW_ATTR(elname) \971 F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, elname, elname)972 973#define ATGC_INFO_RW_ATTR(name, elname) \974 F2FS_RW_ATTR(ATGC_INFO, atgc_management, name, elname)975 976/* GC_THREAD ATTR */977GC_THREAD_RW_ATTR(gc_urgent_sleep_time, urgent_sleep_time);978GC_THREAD_RW_ATTR(gc_min_sleep_time, min_sleep_time);979GC_THREAD_RW_ATTR(gc_max_sleep_time, max_sleep_time);980GC_THREAD_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time);981GC_THREAD_RW_ATTR(gc_no_zoned_gc_percent, no_zoned_gc_percent);982GC_THREAD_RW_ATTR(gc_boost_zoned_gc_percent, boost_zoned_gc_percent);983GC_THREAD_RW_ATTR(gc_valid_thresh_ratio, valid_thresh_ratio);984 985/* SM_INFO ATTR */986SM_INFO_RW_ATTR(reclaim_segments, rec_prefree_segments);987SM_INFO_GENERAL_RW_ATTR(ipu_policy);988SM_INFO_GENERAL_RW_ATTR(min_ipu_util);989SM_INFO_GENERAL_RW_ATTR(min_fsync_blocks);990SM_INFO_GENERAL_RW_ATTR(min_seq_blocks);991SM_INFO_GENERAL_RW_ATTR(min_hot_blocks);992SM_INFO_GENERAL_RW_ATTR(min_ssr_sections);993SM_INFO_GENERAL_RW_ATTR(reserved_segments);994 995/* DCC_INFO ATTR */996DCC_INFO_RW_ATTR(max_small_discards, max_discards);997DCC_INFO_GENERAL_RW_ATTR(max_discard_request);998DCC_INFO_GENERAL_RW_ATTR(min_discard_issue_time);999DCC_INFO_GENERAL_RW_ATTR(mid_discard_issue_time);1000DCC_INFO_GENERAL_RW_ATTR(max_discard_issue_time);1001DCC_INFO_GENERAL_RW_ATTR(discard_io_aware_gran);1002DCC_INFO_GENERAL_RW_ATTR(discard_urgent_util);1003DCC_INFO_GENERAL_RW_ATTR(discard_granularity);1004DCC_INFO_GENERAL_RW_ATTR(max_ordered_discard);1005DCC_INFO_GENERAL_RW_ATTR(discard_io_aware);1006 1007/* NM_INFO ATTR */1008NM_INFO_RW_ATTR(max_roll_forward_node_blocks, max_rf_node_blocks);1009NM_INFO_GENERAL_RW_ATTR(ram_thresh);1010NM_INFO_GENERAL_RW_ATTR(ra_nid_pages);1011NM_INFO_GENERAL_RW_ATTR(dirty_nats_ratio);1012 1013/* F2FS_SBI ATTR */1014F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);1015F2FS_SBI_RW_ATTR(gc_idle, gc_mode);1016F2FS_SBI_RW_ATTR(gc_urgent, gc_mode);1017F2FS_SBI_RW_ATTR(cp_interval, interval_time[CP_TIME]);1018F2FS_SBI_RW_ATTR(idle_interval, interval_time[REQ_TIME]);1019F2FS_SBI_RW_ATTR(discard_idle_interval, interval_time[DISCARD_TIME]);1020F2FS_SBI_RW_ATTR(gc_idle_interval, interval_time[GC_TIME]);1021F2FS_SBI_RW_ATTR(umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);1022F2FS_SBI_RW_ATTR(gc_pin_file_thresh, gc_pin_file_threshold);1023F2FS_SBI_RW_ATTR(gc_reclaimed_segments, gc_reclaimed_segs);1024F2FS_SBI_GENERAL_RW_ATTR(max_victim_search);1025F2FS_SBI_GENERAL_RW_ATTR(migration_granularity);1026F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity);1027F2FS_SBI_GENERAL_RW_ATTR(dir_level);1028#ifdef CONFIG_F2FS_IOSTAT1029F2FS_SBI_GENERAL_RW_ATTR(iostat_enable);1030F2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms);1031#endif1032F2FS_SBI_GENERAL_RW_ATTR(readdir_ra);1033F2FS_SBI_GENERAL_RW_ATTR(max_io_bytes);1034F2FS_SBI_GENERAL_RW_ATTR(data_io_flag);1035F2FS_SBI_GENERAL_RW_ATTR(node_io_flag);1036F2FS_SBI_GENERAL_RW_ATTR(gc_remaining_trials);1037F2FS_SBI_GENERAL_RW_ATTR(seq_file_ra_mul);1038F2FS_SBI_GENERAL_RW_ATTR(gc_segment_mode);1039F2FS_SBI_GENERAL_RW_ATTR(max_fragment_chunk);1040F2FS_SBI_GENERAL_RW_ATTR(max_fragment_hole);1041#ifdef CONFIG_F2FS_FS_COMPRESSION1042F2FS_SBI_GENERAL_RW_ATTR(compr_written_block);1043F2FS_SBI_GENERAL_RW_ATTR(compr_saved_block);1044F2FS_SBI_GENERAL_RW_ATTR(compr_new_inode);1045F2FS_SBI_GENERAL_RW_ATTR(compress_percent);1046F2FS_SBI_GENERAL_RW_ATTR(compress_watermark);1047#endif1048/* atomic write */1049F2FS_SBI_GENERAL_RO_ATTR(current_atomic_write);1050F2FS_SBI_GENERAL_RW_ATTR(peak_atomic_write);1051F2FS_SBI_GENERAL_RW_ATTR(committed_atomic_block);1052F2FS_SBI_GENERAL_RW_ATTR(revoked_atomic_block);1053/* block age extent cache */1054F2FS_SBI_GENERAL_RW_ATTR(hot_data_age_threshold);1055F2FS_SBI_GENERAL_RW_ATTR(warm_data_age_threshold);1056F2FS_SBI_GENERAL_RW_ATTR(last_age_weight);1057#ifdef CONFIG_BLK_DEV_ZONED1058F2FS_SBI_GENERAL_RO_ATTR(unusable_blocks_per_sec);1059F2FS_SBI_GENERAL_RW_ATTR(blkzone_alloc_policy);1060#endif1061 1062/* STAT_INFO ATTR */1063#ifdef CONFIG_F2FS_STAT_FS1064STAT_INFO_RO_ATTR(cp_foreground_calls, cp_call_count[FOREGROUND]);1065STAT_INFO_RO_ATTR(cp_background_calls, cp_call_count[BACKGROUND]);1066STAT_INFO_RO_ATTR(gc_foreground_calls, gc_call_count[FOREGROUND]);1067STAT_INFO_RO_ATTR(gc_background_calls, gc_call_count[BACKGROUND]);1068#endif1069 1070/* FAULT_INFO ATTR */1071#ifdef CONFIG_F2FS_FAULT_INJECTION1072FAULT_INFO_GENERAL_RW_ATTR(FAULT_INFO_RATE, inject_rate);1073FAULT_INFO_GENERAL_RW_ATTR(FAULT_INFO_TYPE, inject_type);1074#endif1075 1076/* RESERVED_BLOCKS ATTR */1077RESERVED_BLOCKS_GENERAL_RW_ATTR(reserved_blocks);1078 1079/* CPRC_INFO ATTR */1080CPRC_INFO_GENERAL_RW_ATTR(ckpt_thread_ioprio);1081 1082/* ATGC_INFO ATTR */1083ATGC_INFO_RW_ATTR(atgc_candidate_ratio, candidate_ratio);1084ATGC_INFO_RW_ATTR(atgc_candidate_count, max_candidate_count);1085ATGC_INFO_RW_ATTR(atgc_age_weight, age_weight);1086ATGC_INFO_RW_ATTR(atgc_age_threshold, age_threshold);1087 1088F2FS_GENERAL_RO_ATTR(dirty_segments);1089F2FS_GENERAL_RO_ATTR(free_segments);1090F2FS_GENERAL_RO_ATTR(ovp_segments);1091F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);1092F2FS_GENERAL_RO_ATTR(features);1093F2FS_GENERAL_RO_ATTR(current_reserved_blocks);1094F2FS_GENERAL_RO_ATTR(unusable);1095F2FS_GENERAL_RO_ATTR(encoding);1096F2FS_GENERAL_RO_ATTR(mounted_time_sec);1097F2FS_GENERAL_RO_ATTR(main_blkaddr);1098F2FS_GENERAL_RO_ATTR(pending_discard);1099F2FS_GENERAL_RO_ATTR(atgc_enabled);1100F2FS_GENERAL_RO_ATTR(gc_mode);1101#ifdef CONFIG_F2FS_STAT_FS1102F2FS_GENERAL_RO_ATTR(moved_blocks_background);1103F2FS_GENERAL_RO_ATTR(moved_blocks_foreground);1104F2FS_GENERAL_RO_ATTR(avg_vblocks);1105#endif1106 1107#ifdef CONFIG_FS_ENCRYPTION1108F2FS_FEATURE_RO_ATTR(encryption);1109F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2);1110#if IS_ENABLED(CONFIG_UNICODE)1111F2FS_FEATURE_RO_ATTR(encrypted_casefold);1112#endif1113#endif /* CONFIG_FS_ENCRYPTION */1114#ifdef CONFIG_BLK_DEV_ZONED1115F2FS_FEATURE_RO_ATTR(block_zoned);1116#endif1117F2FS_FEATURE_RO_ATTR(atomic_write);1118F2FS_FEATURE_RO_ATTR(extra_attr);1119F2FS_FEATURE_RO_ATTR(project_quota);1120F2FS_FEATURE_RO_ATTR(inode_checksum);1121F2FS_FEATURE_RO_ATTR(flexible_inline_xattr);1122F2FS_FEATURE_RO_ATTR(quota_ino);1123F2FS_FEATURE_RO_ATTR(inode_crtime);1124F2FS_FEATURE_RO_ATTR(lost_found);1125#ifdef CONFIG_FS_VERITY1126F2FS_FEATURE_RO_ATTR(verity);1127#endif1128F2FS_FEATURE_RO_ATTR(sb_checksum);1129#if IS_ENABLED(CONFIG_UNICODE)1130F2FS_FEATURE_RO_ATTR(casefold);1131#endif1132F2FS_FEATURE_RO_ATTR(readonly);1133#ifdef CONFIG_F2FS_FS_COMPRESSION1134F2FS_FEATURE_RO_ATTR(compression);1135#endif1136F2FS_FEATURE_RO_ATTR(pin_file);1137 1138#define ATTR_LIST(name) (&f2fs_attr_##name.attr)1139static struct attribute *f2fs_attrs[] = {1140 ATTR_LIST(gc_urgent_sleep_time),1141 ATTR_LIST(gc_min_sleep_time),1142 ATTR_LIST(gc_max_sleep_time),1143 ATTR_LIST(gc_no_gc_sleep_time),1144 ATTR_LIST(gc_no_zoned_gc_percent),1145 ATTR_LIST(gc_boost_zoned_gc_percent),1146 ATTR_LIST(gc_valid_thresh_ratio),1147 ATTR_LIST(gc_idle),1148 ATTR_LIST(gc_urgent),1149 ATTR_LIST(reclaim_segments),1150 ATTR_LIST(main_blkaddr),1151 ATTR_LIST(max_small_discards),1152 ATTR_LIST(max_discard_request),1153 ATTR_LIST(min_discard_issue_time),1154 ATTR_LIST(mid_discard_issue_time),1155 ATTR_LIST(max_discard_issue_time),1156 ATTR_LIST(discard_io_aware_gran),1157 ATTR_LIST(discard_urgent_util),1158 ATTR_LIST(discard_granularity),1159 ATTR_LIST(max_ordered_discard),1160 ATTR_LIST(discard_io_aware),1161 ATTR_LIST(pending_discard),1162 ATTR_LIST(gc_mode),1163 ATTR_LIST(ipu_policy),1164 ATTR_LIST(min_ipu_util),1165 ATTR_LIST(min_fsync_blocks),1166 ATTR_LIST(min_seq_blocks),1167 ATTR_LIST(min_hot_blocks),1168 ATTR_LIST(min_ssr_sections),1169 ATTR_LIST(reserved_segments),1170 ATTR_LIST(max_victim_search),1171 ATTR_LIST(migration_granularity),1172 ATTR_LIST(migration_window_granularity),1173 ATTR_LIST(dir_level),1174 ATTR_LIST(ram_thresh),1175 ATTR_LIST(ra_nid_pages),1176 ATTR_LIST(dirty_nats_ratio),1177 ATTR_LIST(max_roll_forward_node_blocks),1178 ATTR_LIST(cp_interval),1179 ATTR_LIST(idle_interval),1180 ATTR_LIST(discard_idle_interval),1181 ATTR_LIST(gc_idle_interval),1182 ATTR_LIST(umount_discard_timeout),1183#ifdef CONFIG_F2FS_IOSTAT1184 ATTR_LIST(iostat_enable),1185 ATTR_LIST(iostat_period_ms),1186#endif1187 ATTR_LIST(readdir_ra),1188 ATTR_LIST(max_io_bytes),1189 ATTR_LIST(gc_pin_file_thresh),1190 ATTR_LIST(extension_list),1191#ifdef CONFIG_F2FS_FAULT_INJECTION1192 ATTR_LIST(inject_rate),1193 ATTR_LIST(inject_type),1194#endif1195 ATTR_LIST(data_io_flag),1196 ATTR_LIST(node_io_flag),1197 ATTR_LIST(gc_remaining_trials),1198 ATTR_LIST(ckpt_thread_ioprio),1199 ATTR_LIST(dirty_segments),1200 ATTR_LIST(free_segments),1201 ATTR_LIST(ovp_segments),1202 ATTR_LIST(unusable),1203 ATTR_LIST(lifetime_write_kbytes),1204 ATTR_LIST(features),1205 ATTR_LIST(reserved_blocks),1206 ATTR_LIST(current_reserved_blocks),1207 ATTR_LIST(encoding),1208 ATTR_LIST(mounted_time_sec),1209#ifdef CONFIG_F2FS_STAT_FS1210 ATTR_LIST(cp_foreground_calls),1211 ATTR_LIST(cp_background_calls),1212 ATTR_LIST(gc_foreground_calls),1213 ATTR_LIST(gc_background_calls),1214 ATTR_LIST(moved_blocks_foreground),1215 ATTR_LIST(moved_blocks_background),1216 ATTR_LIST(avg_vblocks),1217#endif1218#ifdef CONFIG_BLK_DEV_ZONED1219 ATTR_LIST(unusable_blocks_per_sec),1220 ATTR_LIST(blkzone_alloc_policy),1221#endif1222#ifdef CONFIG_F2FS_FS_COMPRESSION1223 ATTR_LIST(compr_written_block),1224 ATTR_LIST(compr_saved_block),1225 ATTR_LIST(compr_new_inode),1226 ATTR_LIST(compress_percent),1227 ATTR_LIST(compress_watermark),1228#endif1229 /* For ATGC */1230 ATTR_LIST(atgc_candidate_ratio),1231 ATTR_LIST(atgc_candidate_count),1232 ATTR_LIST(atgc_age_weight),1233 ATTR_LIST(atgc_age_threshold),1234 ATTR_LIST(atgc_enabled),1235 ATTR_LIST(seq_file_ra_mul),1236 ATTR_LIST(gc_segment_mode),1237 ATTR_LIST(gc_reclaimed_segments),1238 ATTR_LIST(max_fragment_chunk),1239 ATTR_LIST(max_fragment_hole),1240 ATTR_LIST(current_atomic_write),1241 ATTR_LIST(peak_atomic_write),1242 ATTR_LIST(committed_atomic_block),1243 ATTR_LIST(revoked_atomic_block),1244 ATTR_LIST(hot_data_age_threshold),1245 ATTR_LIST(warm_data_age_threshold),1246 ATTR_LIST(last_age_weight),1247 NULL,1248};1249ATTRIBUTE_GROUPS(f2fs);1250 1251static struct attribute *f2fs_feat_attrs[] = {1252#ifdef CONFIG_FS_ENCRYPTION1253 ATTR_LIST(encryption),1254 ATTR_LIST(test_dummy_encryption_v2),1255#if IS_ENABLED(CONFIG_UNICODE)1256 ATTR_LIST(encrypted_casefold),1257#endif1258#endif /* CONFIG_FS_ENCRYPTION */1259#ifdef CONFIG_BLK_DEV_ZONED1260 ATTR_LIST(block_zoned),1261#endif1262 ATTR_LIST(atomic_write),1263 ATTR_LIST(extra_attr),1264 ATTR_LIST(project_quota),1265 ATTR_LIST(inode_checksum),1266 ATTR_LIST(flexible_inline_xattr),1267 ATTR_LIST(quota_ino),1268 ATTR_LIST(inode_crtime),1269 ATTR_LIST(lost_found),1270#ifdef CONFIG_FS_VERITY1271 ATTR_LIST(verity),1272#endif1273 ATTR_LIST(sb_checksum),1274#if IS_ENABLED(CONFIG_UNICODE)1275 ATTR_LIST(casefold),1276#endif1277 ATTR_LIST(readonly),1278#ifdef CONFIG_F2FS_FS_COMPRESSION1279 ATTR_LIST(compression),1280#endif1281 ATTR_LIST(pin_file),1282 NULL,1283};1284ATTRIBUTE_GROUPS(f2fs_feat);1285 1286F2FS_GENERAL_RO_ATTR(sb_status);1287F2FS_GENERAL_RO_ATTR(cp_status);1288F2FS_GENERAL_RO_ATTR(issued_discard);1289F2FS_GENERAL_RO_ATTR(queued_discard);1290F2FS_GENERAL_RO_ATTR(undiscard_blks);1291 1292static struct attribute *f2fs_stat_attrs[] = {1293 ATTR_LIST(sb_status),1294 ATTR_LIST(cp_status),1295 ATTR_LIST(issued_discard),1296 ATTR_LIST(queued_discard),1297 ATTR_LIST(undiscard_blks),1298 NULL,1299};1300ATTRIBUTE_GROUPS(f2fs_stat);1301 1302F2FS_SB_FEATURE_RO_ATTR(encryption, ENCRYPT);1303F2FS_SB_FEATURE_RO_ATTR(block_zoned, BLKZONED);1304F2FS_SB_FEATURE_RO_ATTR(extra_attr, EXTRA_ATTR);1305F2FS_SB_FEATURE_RO_ATTR(project_quota, PRJQUOTA);1306F2FS_SB_FEATURE_RO_ATTR(inode_checksum, INODE_CHKSUM);1307F2FS_SB_FEATURE_RO_ATTR(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR);1308F2FS_SB_FEATURE_RO_ATTR(quota_ino, QUOTA_INO);1309F2FS_SB_FEATURE_RO_ATTR(inode_crtime, INODE_CRTIME);1310F2FS_SB_FEATURE_RO_ATTR(lost_found, LOST_FOUND);1311F2FS_SB_FEATURE_RO_ATTR(verity, VERITY);1312F2FS_SB_FEATURE_RO_ATTR(sb_checksum, SB_CHKSUM);1313F2FS_SB_FEATURE_RO_ATTR(casefold, CASEFOLD);1314F2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION);1315F2FS_SB_FEATURE_RO_ATTR(readonly, RO);1316 1317static struct attribute *f2fs_sb_feat_attrs[] = {1318 ATTR_LIST(sb_encryption),1319 ATTR_LIST(sb_block_zoned),1320 ATTR_LIST(sb_extra_attr),1321 ATTR_LIST(sb_project_quota),1322 ATTR_LIST(sb_inode_checksum),1323 ATTR_LIST(sb_flexible_inline_xattr),1324 ATTR_LIST(sb_quota_ino),1325 ATTR_LIST(sb_inode_crtime),1326 ATTR_LIST(sb_lost_found),1327 ATTR_LIST(sb_verity),1328 ATTR_LIST(sb_sb_checksum),1329 ATTR_LIST(sb_casefold),1330 ATTR_LIST(sb_compression),1331 ATTR_LIST(sb_readonly),1332 NULL,1333};1334ATTRIBUTE_GROUPS(f2fs_sb_feat);1335 1336static const struct sysfs_ops f2fs_attr_ops = {1337 .show = f2fs_attr_show,1338 .store = f2fs_attr_store,1339};1340 1341static const struct kobj_type f2fs_sb_ktype = {1342 .default_groups = f2fs_groups,1343 .sysfs_ops = &f2fs_attr_ops,1344 .release = f2fs_sb_release,1345};1346 1347static const struct kobj_type f2fs_ktype = {1348 .sysfs_ops = &f2fs_attr_ops,1349};1350 1351static struct kset f2fs_kset = {1352 .kobj = {.ktype = &f2fs_ktype},1353};1354 1355static const struct kobj_type f2fs_feat_ktype = {1356 .default_groups = f2fs_feat_groups,1357 .sysfs_ops = &f2fs_attr_ops,1358};1359 1360static struct kobject f2fs_feat = {1361 .kset = &f2fs_kset,1362};1363 1364static ssize_t f2fs_stat_attr_show(struct kobject *kobj,1365 struct attribute *attr, char *buf)1366{1367 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,1368 s_stat_kobj);1369 struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);1370 1371 return a->show ? a->show(a, sbi, buf) : 0;1372}1373 1374static ssize_t f2fs_stat_attr_store(struct kobject *kobj, struct attribute *attr,1375 const char *buf, size_t len)1376{1377 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,1378 s_stat_kobj);1379 struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);1380 1381 return a->store ? a->store(a, sbi, buf, len) : 0;1382}1383 1384static void f2fs_stat_kobj_release(struct kobject *kobj)1385{1386 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,1387 s_stat_kobj);1388 complete(&sbi->s_stat_kobj_unregister);1389}1390 1391static const struct sysfs_ops f2fs_stat_attr_ops = {1392 .show = f2fs_stat_attr_show,1393 .store = f2fs_stat_attr_store,1394};1395 1396static const struct kobj_type f2fs_stat_ktype = {1397 .default_groups = f2fs_stat_groups,1398 .sysfs_ops = &f2fs_stat_attr_ops,1399 .release = f2fs_stat_kobj_release,1400};1401 1402static ssize_t f2fs_sb_feat_attr_show(struct kobject *kobj,1403 struct attribute *attr, char *buf)1404{1405 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,1406 s_feature_list_kobj);1407 struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);1408 1409 return a->show ? a->show(a, sbi, buf) : 0;1410}1411 1412static void f2fs_feature_list_kobj_release(struct kobject *kobj)1413{1414 struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,1415 s_feature_list_kobj);1416 complete(&sbi->s_feature_list_kobj_unregister);1417}1418 1419static const struct sysfs_ops f2fs_feature_list_attr_ops = {1420 .show = f2fs_sb_feat_attr_show,1421};1422 1423static const struct kobj_type f2fs_feature_list_ktype = {1424 .default_groups = f2fs_sb_feat_groups,1425 .sysfs_ops = &f2fs_feature_list_attr_ops,1426 .release = f2fs_feature_list_kobj_release,1427};1428 1429static int __maybe_unused segment_info_seq_show(struct seq_file *seq,1430 void *offset)1431{1432 struct super_block *sb = seq->private;1433 struct f2fs_sb_info *sbi = F2FS_SB(sb);1434 unsigned int total_segs =1435 le32_to_cpu(sbi->raw_super->segment_count_main);1436 int i;1437 1438 seq_puts(seq, "format: segment_type|valid_blocks\n"1439 "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");1440 1441 for (i = 0; i < total_segs; i++) {1442 struct seg_entry *se = get_seg_entry(sbi, i);1443 1444 if ((i % 10) == 0)1445 seq_printf(seq, "%-10d", i);1446 seq_printf(seq, "%d|%-3u", se->type, se->valid_blocks);1447 if ((i % 10) == 9 || i == (total_segs - 1))1448 seq_putc(seq, '\n');1449 else1450 seq_putc(seq, ' ');1451 }1452 1453 return 0;1454}1455 1456static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,1457 void *offset)1458{1459 struct super_block *sb = seq->private;1460 struct f2fs_sb_info *sbi = F2FS_SB(sb);1461 unsigned int total_segs =1462 le32_to_cpu(sbi->raw_super->segment_count_main);1463 int i, j;1464 1465 seq_puts(seq, "format: segment_type|valid_blocks|bitmaps\n"1466 "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");1467 1468 for (i = 0; i < total_segs; i++) {1469 struct seg_entry *se = get_seg_entry(sbi, i);1470 1471 seq_printf(seq, "%-10d", i);1472 seq_printf(seq, "%d|%-3u|", se->type, se->valid_blocks);1473 for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++)1474 seq_printf(seq, " %.2x", se->cur_valid_map[j]);1475 seq_putc(seq, '\n');1476 }1477 return 0;1478}1479 1480static int __maybe_unused victim_bits_seq_show(struct seq_file *seq,1481 void *offset)1482{1483 struct super_block *sb = seq->private;1484 struct f2fs_sb_info *sbi = F2FS_SB(sb);1485 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);1486 int i;1487 1488 seq_puts(seq, "format: victim_secmap bitmaps\n");1489 1490 for (i = 0; i < MAIN_SECS(sbi); i++) {1491 if ((i % 10) == 0)1492 seq_printf(seq, "%-10d", i);1493 seq_printf(seq, "%d", test_bit(i, dirty_i->victim_secmap) ? 1 : 0);1494 if ((i % 10) == 9 || i == (MAIN_SECS(sbi) - 1))1495 seq_putc(seq, '\n');1496 else1497 seq_putc(seq, ' ');1498 }1499 return 0;1500}1501 1502static int __maybe_unused discard_plist_seq_show(struct seq_file *seq,1503 void *offset)1504{1505 struct super_block *sb = seq->private;1506 struct f2fs_sb_info *sbi = F2FS_SB(sb);1507 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;1508 int i, count;1509 1510 seq_puts(seq, "Discard pend list(Show diacrd_cmd count on each entry, .:not exist):\n");1511 if (!f2fs_realtime_discard_enable(sbi))1512 return 0;1513 1514 if (dcc) {1515 mutex_lock(&dcc->cmd_lock);1516 for (i = 0; i < MAX_PLIST_NUM; i++) {1517 struct list_head *pend_list;1518 struct discard_cmd *dc, *tmp;1519 1520 if (i % 8 == 0)1521 seq_printf(seq, " %-3d", i);1522 count = 0;1523 pend_list = &dcc->pend_list[i];1524 list_for_each_entry_safe(dc, tmp, pend_list, list)1525 count++;1526 if (count)1527 seq_printf(seq, " %7d", count);1528 else1529 seq_puts(seq, " .");1530 if (i % 8 == 7)1531 seq_putc(seq, '\n');1532 }1533 seq_putc(seq, '\n');1534 mutex_unlock(&dcc->cmd_lock);1535 }1536 1537 return 0;1538}1539 1540static int __maybe_unused disk_map_seq_show(struct seq_file *seq,1541 void *offset)1542{1543 struct super_block *sb = seq->private;1544 struct f2fs_sb_info *sbi = F2FS_SB(sb);1545 int i;1546 1547 seq_printf(seq, "Address Layout : %5luB Block address (# of Segments)\n",1548 F2FS_BLKSIZE);1549 seq_printf(seq, " SB : %12s\n", "0/1024B");1550 seq_printf(seq, " seg0_blkaddr : 0x%010x\n", SEG0_BLKADDR(sbi));1551 seq_printf(seq, " Checkpoint : 0x%010x (%10d)\n",1552 le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr), 2);1553 seq_printf(seq, " SIT : 0x%010x (%10d)\n",1554 SIT_I(sbi)->sit_base_addr,1555 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_sit));1556 seq_printf(seq, " NAT : 0x%010x (%10d)\n",1557 NM_I(sbi)->nat_blkaddr,1558 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_nat));1559 seq_printf(seq, " SSA : 0x%010x (%10d)\n",1560 SM_I(sbi)->ssa_blkaddr,1561 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_ssa));1562 seq_printf(seq, " Main : 0x%010x (%10d)\n",1563 SM_I(sbi)->main_blkaddr,1564 le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_main));1565 seq_printf(seq, " # of Sections : %12d\n",1566 le32_to_cpu(F2FS_RAW_SUPER(sbi)->section_count));1567 seq_printf(seq, " Segs/Sections : %12d\n",1568 SEGS_PER_SEC(sbi));1569 seq_printf(seq, " Section size : %12d MB\n",1570 SEGS_PER_SEC(sbi) << 1);1571 1572 if (!f2fs_is_multi_device(sbi))1573 return 0;1574 1575 seq_puts(seq, "\nDisk Map for multi devices:\n");1576 for (i = 0; i < sbi->s_ndevs; i++)1577 seq_printf(seq, "Disk:%2d (zoned=%d): 0x%010x - 0x%010x on %s\n",1578 i, bdev_is_zoned(FDEV(i).bdev),1579 FDEV(i).start_blk, FDEV(i).end_blk,1580 FDEV(i).path);1581 return 0;1582}1583 1584int __init f2fs_init_sysfs(void)1585{1586 int ret;1587 1588 kobject_set_name(&f2fs_kset.kobj, "f2fs");1589 f2fs_kset.kobj.parent = fs_kobj;1590 ret = kset_register(&f2fs_kset);1591 if (ret)1592 return ret;1593 1594 ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype,1595 NULL, "features");1596 if (ret)1597 goto put_kobject;1598 1599 f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);1600 if (!f2fs_proc_root) {1601 ret = -ENOMEM;1602 goto put_kobject;1603 }1604 1605 return 0;1606put_kobject:1607 kobject_put(&f2fs_feat);1608 kset_unregister(&f2fs_kset);1609 return ret;1610}1611 1612void f2fs_exit_sysfs(void)1613{1614 kobject_put(&f2fs_feat);1615 kset_unregister(&f2fs_kset);1616 remove_proc_entry("fs/f2fs", NULL);1617 f2fs_proc_root = NULL;1618}1619 1620int f2fs_register_sysfs(struct f2fs_sb_info *sbi)1621{1622 struct super_block *sb = sbi->sb;1623 int err;1624 1625 sbi->s_kobj.kset = &f2fs_kset;1626 init_completion(&sbi->s_kobj_unregister);1627 err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL,1628 "%s", sb->s_id);1629 if (err)1630 goto put_sb_kobj;1631 1632 sbi->s_stat_kobj.kset = &f2fs_kset;1633 init_completion(&sbi->s_stat_kobj_unregister);1634 err = kobject_init_and_add(&sbi->s_stat_kobj, &f2fs_stat_ktype,1635 &sbi->s_kobj, "stat");1636 if (err)1637 goto put_stat_kobj;1638 1639 sbi->s_feature_list_kobj.kset = &f2fs_kset;1640 init_completion(&sbi->s_feature_list_kobj_unregister);1641 err = kobject_init_and_add(&sbi->s_feature_list_kobj,1642 &f2fs_feature_list_ktype,1643 &sbi->s_kobj, "feature_list");1644 if (err)1645 goto put_feature_list_kobj;1646 1647 sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);1648 if (!sbi->s_proc) {1649 err = -ENOMEM;1650 goto put_feature_list_kobj;1651 }1652 1653 proc_create_single_data("segment_info", 0444, sbi->s_proc,1654 segment_info_seq_show, sb);1655 proc_create_single_data("segment_bits", 0444, sbi->s_proc,1656 segment_bits_seq_show, sb);1657#ifdef CONFIG_F2FS_IOSTAT1658 proc_create_single_data("iostat_info", 0444, sbi->s_proc,1659 iostat_info_seq_show, sb);1660#endif1661 proc_create_single_data("victim_bits", 0444, sbi->s_proc,1662 victim_bits_seq_show, sb);1663 proc_create_single_data("discard_plist_info", 0444, sbi->s_proc,1664 discard_plist_seq_show, sb);1665 proc_create_single_data("disk_map", 0444, sbi->s_proc,1666 disk_map_seq_show, sb);1667 return 0;1668put_feature_list_kobj:1669 kobject_put(&sbi->s_feature_list_kobj);1670 wait_for_completion(&sbi->s_feature_list_kobj_unregister);1671put_stat_kobj:1672 kobject_put(&sbi->s_stat_kobj);1673 wait_for_completion(&sbi->s_stat_kobj_unregister);1674put_sb_kobj:1675 kobject_put(&sbi->s_kobj);1676 wait_for_completion(&sbi->s_kobj_unregister);1677 return err;1678}1679 1680void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)1681{1682 remove_proc_subtree(sbi->sb->s_id, f2fs_proc_root);1683 1684 kobject_put(&sbi->s_stat_kobj);1685 wait_for_completion(&sbi->s_stat_kobj_unregister);1686 kobject_put(&sbi->s_feature_list_kobj);1687 wait_for_completion(&sbi->s_feature_list_kobj_unregister);1688 1689 kobject_put(&sbi->s_kobj);1690 wait_for_completion(&sbi->s_kobj_unregister);1691}1692