162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * f2fs sysfs interface 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 662306a36Sopenharmony_ci * http://www.samsung.com/ 762306a36Sopenharmony_ci * Copyright (c) 2017 Chao Yu <chao@kernel.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/compiler.h> 1062306a36Sopenharmony_ci#include <linux/proc_fs.h> 1162306a36Sopenharmony_ci#include <linux/f2fs_fs.h> 1262306a36Sopenharmony_ci#include <linux/seq_file.h> 1362306a36Sopenharmony_ci#include <linux/unicode.h> 1462306a36Sopenharmony_ci#include <linux/ioprio.h> 1562306a36Sopenharmony_ci#include <linux/sysfs.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "f2fs.h" 1862306a36Sopenharmony_ci#include "segment.h" 1962306a36Sopenharmony_ci#include "gc.h" 2062306a36Sopenharmony_ci#include "iostat.h" 2162306a36Sopenharmony_ci#include <trace/events/f2fs.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic struct proc_dir_entry *f2fs_proc_root; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Sysfs support for f2fs */ 2662306a36Sopenharmony_cienum { 2762306a36Sopenharmony_ci GC_THREAD, /* struct f2fs_gc_thread */ 2862306a36Sopenharmony_ci SM_INFO, /* struct f2fs_sm_info */ 2962306a36Sopenharmony_ci DCC_INFO, /* struct discard_cmd_control */ 3062306a36Sopenharmony_ci NM_INFO, /* struct f2fs_nm_info */ 3162306a36Sopenharmony_ci F2FS_SBI, /* struct f2fs_sb_info */ 3262306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 3362306a36Sopenharmony_ci STAT_INFO, /* struct f2fs_stat_info */ 3462306a36Sopenharmony_ci#endif 3562306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 3662306a36Sopenharmony_ci FAULT_INFO_RATE, /* struct f2fs_fault_info */ 3762306a36Sopenharmony_ci FAULT_INFO_TYPE, /* struct f2fs_fault_info */ 3862306a36Sopenharmony_ci#endif 3962306a36Sopenharmony_ci RESERVED_BLOCKS, /* struct f2fs_sb_info */ 4062306a36Sopenharmony_ci CPRC_INFO, /* struct ckpt_req_control */ 4162306a36Sopenharmony_ci ATGC_INFO, /* struct atgc_management */ 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const char *gc_mode_names[MAX_GC_MODE] = { 4562306a36Sopenharmony_ci "GC_NORMAL", 4662306a36Sopenharmony_ci "GC_IDLE_CB", 4762306a36Sopenharmony_ci "GC_IDLE_GREEDY", 4862306a36Sopenharmony_ci "GC_IDLE_AT", 4962306a36Sopenharmony_ci "GC_URGENT_HIGH", 5062306a36Sopenharmony_ci "GC_URGENT_LOW", 5162306a36Sopenharmony_ci "GC_URGENT_MID" 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistruct f2fs_attr { 5562306a36Sopenharmony_ci struct attribute attr; 5662306a36Sopenharmony_ci ssize_t (*show)(struct f2fs_attr *a, struct f2fs_sb_info *sbi, char *buf); 5762306a36Sopenharmony_ci ssize_t (*store)(struct f2fs_attr *a, struct f2fs_sb_info *sbi, 5862306a36Sopenharmony_ci const char *buf, size_t len); 5962306a36Sopenharmony_ci int struct_type; 6062306a36Sopenharmony_ci int offset; 6162306a36Sopenharmony_ci int id; 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic ssize_t f2fs_sbi_show(struct f2fs_attr *a, 6562306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci if (struct_type == GC_THREAD) 7062306a36Sopenharmony_ci return (unsigned char *)sbi->gc_thread; 7162306a36Sopenharmony_ci else if (struct_type == SM_INFO) 7262306a36Sopenharmony_ci return (unsigned char *)SM_I(sbi); 7362306a36Sopenharmony_ci else if (struct_type == DCC_INFO) 7462306a36Sopenharmony_ci return (unsigned char *)SM_I(sbi)->dcc_info; 7562306a36Sopenharmony_ci else if (struct_type == NM_INFO) 7662306a36Sopenharmony_ci return (unsigned char *)NM_I(sbi); 7762306a36Sopenharmony_ci else if (struct_type == F2FS_SBI || struct_type == RESERVED_BLOCKS) 7862306a36Sopenharmony_ci return (unsigned char *)sbi; 7962306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 8062306a36Sopenharmony_ci else if (struct_type == FAULT_INFO_RATE || 8162306a36Sopenharmony_ci struct_type == FAULT_INFO_TYPE) 8262306a36Sopenharmony_ci return (unsigned char *)&F2FS_OPTION(sbi).fault_info; 8362306a36Sopenharmony_ci#endif 8462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 8562306a36Sopenharmony_ci else if (struct_type == STAT_INFO) 8662306a36Sopenharmony_ci return (unsigned char *)F2FS_STAT(sbi); 8762306a36Sopenharmony_ci#endif 8862306a36Sopenharmony_ci else if (struct_type == CPRC_INFO) 8962306a36Sopenharmony_ci return (unsigned char *)&sbi->cprc_info; 9062306a36Sopenharmony_ci else if (struct_type == ATGC_INFO) 9162306a36Sopenharmony_ci return (unsigned char *)&sbi->am; 9262306a36Sopenharmony_ci return NULL; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic ssize_t dirty_segments_show(struct f2fs_attr *a, 9662306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 9962306a36Sopenharmony_ci (unsigned long long)(dirty_segments(sbi))); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic ssize_t free_segments_show(struct f2fs_attr *a, 10362306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 10662306a36Sopenharmony_ci (unsigned long long)(free_segments(sbi))); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic ssize_t ovp_segments_show(struct f2fs_attr *a, 11062306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 11362306a36Sopenharmony_ci (unsigned long long)(overprovision_segments(sbi))); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a, 11762306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 12062306a36Sopenharmony_ci (unsigned long long)(sbi->kbytes_written + 12162306a36Sopenharmony_ci ((f2fs_get_sectors_written(sbi) - 12262306a36Sopenharmony_ci sbi->sectors_written_start) >> 1))); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic ssize_t sb_status_show(struct f2fs_attr *a, 12662306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci return sysfs_emit(buf, "%lx\n", sbi->s_flag); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic ssize_t cp_status_show(struct f2fs_attr *a, 13262306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return sysfs_emit(buf, "%x\n", le32_to_cpu(F2FS_CKPT(sbi)->ckpt_flags)); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic ssize_t pending_discard_show(struct f2fs_attr *a, 13862306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci if (!SM_I(sbi)->dcc_info) 14162306a36Sopenharmony_ci return -EINVAL; 14262306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", (unsigned long long)atomic_read( 14362306a36Sopenharmony_ci &SM_I(sbi)->dcc_info->discard_cmd_cnt)); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic ssize_t gc_mode_show(struct f2fs_attr *a, 14762306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", gc_mode_names[sbi->gc_mode]); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic ssize_t features_show(struct f2fs_attr *a, 15362306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci int len = 0; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (f2fs_sb_has_encrypt(sbi)) 15862306a36Sopenharmony_ci len += scnprintf(buf, PAGE_SIZE - len, "%s", 15962306a36Sopenharmony_ci "encryption"); 16062306a36Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi)) 16162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 16262306a36Sopenharmony_ci len ? ", " : "", "blkzoned"); 16362306a36Sopenharmony_ci if (f2fs_sb_has_extra_attr(sbi)) 16462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 16562306a36Sopenharmony_ci len ? ", " : "", "extra_attr"); 16662306a36Sopenharmony_ci if (f2fs_sb_has_project_quota(sbi)) 16762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 16862306a36Sopenharmony_ci len ? ", " : "", "projquota"); 16962306a36Sopenharmony_ci if (f2fs_sb_has_inode_chksum(sbi)) 17062306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 17162306a36Sopenharmony_ci len ? ", " : "", "inode_checksum"); 17262306a36Sopenharmony_ci if (f2fs_sb_has_flexible_inline_xattr(sbi)) 17362306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 17462306a36Sopenharmony_ci len ? ", " : "", "flexible_inline_xattr"); 17562306a36Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi)) 17662306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 17762306a36Sopenharmony_ci len ? ", " : "", "quota_ino"); 17862306a36Sopenharmony_ci if (f2fs_sb_has_inode_crtime(sbi)) 17962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 18062306a36Sopenharmony_ci len ? ", " : "", "inode_crtime"); 18162306a36Sopenharmony_ci if (f2fs_sb_has_lost_found(sbi)) 18262306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 18362306a36Sopenharmony_ci len ? ", " : "", "lost_found"); 18462306a36Sopenharmony_ci if (f2fs_sb_has_verity(sbi)) 18562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 18662306a36Sopenharmony_ci len ? ", " : "", "verity"); 18762306a36Sopenharmony_ci if (f2fs_sb_has_sb_chksum(sbi)) 18862306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 18962306a36Sopenharmony_ci len ? ", " : "", "sb_checksum"); 19062306a36Sopenharmony_ci if (f2fs_sb_has_casefold(sbi)) 19162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 19262306a36Sopenharmony_ci len ? ", " : "", "casefold"); 19362306a36Sopenharmony_ci if (f2fs_sb_has_readonly(sbi)) 19462306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 19562306a36Sopenharmony_ci len ? ", " : "", "readonly"); 19662306a36Sopenharmony_ci if (f2fs_sb_has_compression(sbi)) 19762306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 19862306a36Sopenharmony_ci len ? ", " : "", "compression"); 19962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 20062306a36Sopenharmony_ci len ? ", " : "", "pin_file"); 20162306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); 20262306a36Sopenharmony_ci return len; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic ssize_t current_reserved_blocks_show(struct f2fs_attr *a, 20662306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", sbi->current_reserved_blocks); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic ssize_t unusable_show(struct f2fs_attr *a, 21262306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci block_t unusable; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (test_opt(sbi, DISABLE_CHECKPOINT)) 21762306a36Sopenharmony_ci unusable = sbi->unusable_block_count; 21862306a36Sopenharmony_ci else 21962306a36Sopenharmony_ci unusable = f2fs_get_unusable_blocks(sbi); 22062306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", (unsigned long long)unusable); 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistatic ssize_t encoding_show(struct f2fs_attr *a, 22462306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE) 22762306a36Sopenharmony_ci struct super_block *sb = sbi->sb; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if (f2fs_sb_has_casefold(sbi)) 23062306a36Sopenharmony_ci return sysfs_emit(buf, "UTF-8 (%d.%d.%d)\n", 23162306a36Sopenharmony_ci (sb->s_encoding->version >> 16) & 0xff, 23262306a36Sopenharmony_ci (sb->s_encoding->version >> 8) & 0xff, 23362306a36Sopenharmony_ci sb->s_encoding->version & 0xff); 23462306a36Sopenharmony_ci#endif 23562306a36Sopenharmony_ci return sysfs_emit(buf, "(none)\n"); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic ssize_t mounted_time_sec_show(struct f2fs_attr *a, 23962306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", SIT_I(sbi)->mounted_time); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 24562306a36Sopenharmony_cistatic ssize_t moved_blocks_foreground_show(struct f2fs_attr *a, 24662306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct f2fs_stat_info *si = F2FS_STAT(sbi); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 25162306a36Sopenharmony_ci (unsigned long long)(si->tot_blks - 25262306a36Sopenharmony_ci (si->bg_data_blks + si->bg_node_blks))); 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic ssize_t moved_blocks_background_show(struct f2fs_attr *a, 25662306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct f2fs_stat_info *si = F2FS_STAT(sbi); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 26162306a36Sopenharmony_ci (unsigned long long)(si->bg_data_blks + si->bg_node_blks)); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic ssize_t avg_vblocks_show(struct f2fs_attr *a, 26562306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct f2fs_stat_info *si = F2FS_STAT(sbi); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci si->dirty_count = dirty_segments(sbi); 27062306a36Sopenharmony_ci f2fs_update_sit_info(sbi); 27162306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", (unsigned long long)(si->avg_vblocks)); 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci#endif 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cistatic ssize_t main_blkaddr_show(struct f2fs_attr *a, 27662306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 27962306a36Sopenharmony_ci (unsigned long long)MAIN_BLKADDR(sbi)); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic ssize_t f2fs_sbi_show(struct f2fs_attr *a, 28362306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci unsigned char *ptr = NULL; 28662306a36Sopenharmony_ci unsigned int *ui; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci ptr = __struct_ptr(sbi, a->struct_type); 28962306a36Sopenharmony_ci if (!ptr) 29062306a36Sopenharmony_ci return -EINVAL; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "extension_list")) { 29362306a36Sopenharmony_ci __u8 (*extlist)[F2FS_EXTENSION_LEN] = 29462306a36Sopenharmony_ci sbi->raw_super->extension_list; 29562306a36Sopenharmony_ci int cold_count = le32_to_cpu(sbi->raw_super->extension_count); 29662306a36Sopenharmony_ci int hot_count = sbi->raw_super->hot_ext_count; 29762306a36Sopenharmony_ci int len = 0, i; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 30062306a36Sopenharmony_ci "cold file extension:\n"); 30162306a36Sopenharmony_ci for (i = 0; i < cold_count; i++) 30262306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", 30362306a36Sopenharmony_ci extlist[i]); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 30662306a36Sopenharmony_ci "hot file extension:\n"); 30762306a36Sopenharmony_ci for (i = cold_count; i < cold_count + hot_count; i++) 30862306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", 30962306a36Sopenharmony_ci extlist[i]); 31062306a36Sopenharmony_ci return len; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { 31462306a36Sopenharmony_ci struct ckpt_req_control *cprc = &sbi->cprc_info; 31562306a36Sopenharmony_ci int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio); 31662306a36Sopenharmony_ci int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (class != IOPRIO_CLASS_RT && class != IOPRIO_CLASS_BE) 31962306a36Sopenharmony_ci return -EINVAL; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci return sysfs_emit(buf, "%s,%d\n", 32262306a36Sopenharmony_ci class == IOPRIO_CLASS_RT ? "rt" : "be", data); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 32662306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compr_written_block")) 32762306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", sbi->compr_written_block); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compr_saved_block")) 33062306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", sbi->compr_saved_block); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compr_new_inode")) 33362306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", sbi->compr_new_inode); 33462306a36Sopenharmony_ci#endif 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_segment_mode")) 33762306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", sbi->gc_segment_mode); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_reclaimed_segments")) { 34062306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", 34162306a36Sopenharmony_ci sbi->gc_reclaimed_segs[sbi->gc_segment_mode]); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (!strcmp(a->attr.name, "current_atomic_write")) { 34562306a36Sopenharmony_ci s64 current_write = atomic64_read(&sbi->current_atomic_write); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return sysfs_emit(buf, "%lld\n", current_write); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci if (!strcmp(a->attr.name, "peak_atomic_write")) 35162306a36Sopenharmony_ci return sysfs_emit(buf, "%lld\n", sbi->peak_atomic_write); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (!strcmp(a->attr.name, "committed_atomic_block")) 35462306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", sbi->committed_atomic_block); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (!strcmp(a->attr.name, "revoked_atomic_block")) 35762306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", sbi->revoked_atomic_block); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 36062306a36Sopenharmony_ci if (!strcmp(a->attr.name, "cp_foreground_calls")) 36162306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 36262306a36Sopenharmony_ci atomic_read(&sbi->cp_call_count[TOTAL_CALL]) - 36362306a36Sopenharmony_ci atomic_read(&sbi->cp_call_count[BACKGROUND])); 36462306a36Sopenharmony_ci if (!strcmp(a->attr.name, "cp_background_calls")) 36562306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 36662306a36Sopenharmony_ci atomic_read(&sbi->cp_call_count[BACKGROUND])); 36762306a36Sopenharmony_ci#endif 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ui = (unsigned int *)(ptr + a->offset); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", *ui); 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic ssize_t __sbi_store(struct f2fs_attr *a, 37562306a36Sopenharmony_ci struct f2fs_sb_info *sbi, 37662306a36Sopenharmony_ci const char *buf, size_t count) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci unsigned char *ptr; 37962306a36Sopenharmony_ci unsigned long t; 38062306a36Sopenharmony_ci unsigned int *ui; 38162306a36Sopenharmony_ci ssize_t ret; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci ptr = __struct_ptr(sbi, a->struct_type); 38462306a36Sopenharmony_ci if (!ptr) 38562306a36Sopenharmony_ci return -EINVAL; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (!strcmp(a->attr.name, "extension_list")) { 38862306a36Sopenharmony_ci const char *name = strim((char *)buf); 38962306a36Sopenharmony_ci bool set = true, hot; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (!strncmp(name, "[h]", 3)) 39262306a36Sopenharmony_ci hot = true; 39362306a36Sopenharmony_ci else if (!strncmp(name, "[c]", 3)) 39462306a36Sopenharmony_ci hot = false; 39562306a36Sopenharmony_ci else 39662306a36Sopenharmony_ci return -EINVAL; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci name += 3; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (*name == '!') { 40162306a36Sopenharmony_ci name++; 40262306a36Sopenharmony_ci set = false; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (!strlen(name) || strlen(name) >= F2FS_EXTENSION_LEN) 40662306a36Sopenharmony_ci return -EINVAL; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci f2fs_down_write(&sbi->sb_lock); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci ret = f2fs_update_extension_list(sbi, name, hot, set); 41162306a36Sopenharmony_ci if (ret) 41262306a36Sopenharmony_ci goto out; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci ret = f2fs_commit_super(sbi, false); 41562306a36Sopenharmony_ci if (ret) 41662306a36Sopenharmony_ci f2fs_update_extension_list(sbi, name, hot, !set); 41762306a36Sopenharmony_ciout: 41862306a36Sopenharmony_ci f2fs_up_write(&sbi->sb_lock); 41962306a36Sopenharmony_ci return ret ? ret : count; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { 42362306a36Sopenharmony_ci const char *name = strim((char *)buf); 42462306a36Sopenharmony_ci struct ckpt_req_control *cprc = &sbi->cprc_info; 42562306a36Sopenharmony_ci int class; 42662306a36Sopenharmony_ci long data; 42762306a36Sopenharmony_ci int ret; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci if (!strncmp(name, "rt,", 3)) 43062306a36Sopenharmony_ci class = IOPRIO_CLASS_RT; 43162306a36Sopenharmony_ci else if (!strncmp(name, "be,", 3)) 43262306a36Sopenharmony_ci class = IOPRIO_CLASS_BE; 43362306a36Sopenharmony_ci else 43462306a36Sopenharmony_ci return -EINVAL; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci name += 3; 43762306a36Sopenharmony_ci ret = kstrtol(name, 10, &data); 43862306a36Sopenharmony_ci if (ret) 43962306a36Sopenharmony_ci return ret; 44062306a36Sopenharmony_ci if (data >= IOPRIO_NR_LEVELS || data < 0) 44162306a36Sopenharmony_ci return -EINVAL; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, data); 44462306a36Sopenharmony_ci if (test_opt(sbi, MERGE_CHECKPOINT)) { 44562306a36Sopenharmony_ci ret = set_task_ioprio(cprc->f2fs_issue_ckpt, 44662306a36Sopenharmony_ci cprc->ckpt_thread_ioprio); 44762306a36Sopenharmony_ci if (ret) 44862306a36Sopenharmony_ci return ret; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci return count; 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci ui = (unsigned int *)(ptr + a->offset); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci ret = kstrtoul(skip_spaces(buf), 0, &t); 45762306a36Sopenharmony_ci if (ret < 0) 45862306a36Sopenharmony_ci return ret; 45962306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 46062306a36Sopenharmony_ci if (a->struct_type == FAULT_INFO_TYPE && t >= BIT(FAULT_MAX)) 46162306a36Sopenharmony_ci return -EINVAL; 46262306a36Sopenharmony_ci if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX) 46362306a36Sopenharmony_ci return -EINVAL; 46462306a36Sopenharmony_ci#endif 46562306a36Sopenharmony_ci if (a->struct_type == RESERVED_BLOCKS) { 46662306a36Sopenharmony_ci spin_lock(&sbi->stat_lock); 46762306a36Sopenharmony_ci if (t > (unsigned long)(sbi->user_block_count - 46862306a36Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks - 46962306a36Sopenharmony_ci sbi->blocks_per_seg * 47062306a36Sopenharmony_ci SM_I(sbi)->additional_reserved_segments)) { 47162306a36Sopenharmony_ci spin_unlock(&sbi->stat_lock); 47262306a36Sopenharmony_ci return -EINVAL; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci *ui = t; 47562306a36Sopenharmony_ci sbi->current_reserved_blocks = min(sbi->reserved_blocks, 47662306a36Sopenharmony_ci sbi->user_block_count - valid_user_blocks(sbi)); 47762306a36Sopenharmony_ci spin_unlock(&sbi->stat_lock); 47862306a36Sopenharmony_ci return count; 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (!strcmp(a->attr.name, "discard_io_aware_gran")) { 48262306a36Sopenharmony_ci if (t > MAX_PLIST_NUM) 48362306a36Sopenharmony_ci return -EINVAL; 48462306a36Sopenharmony_ci if (!f2fs_block_unit_discard(sbi)) 48562306a36Sopenharmony_ci return -EINVAL; 48662306a36Sopenharmony_ci if (t == *ui) 48762306a36Sopenharmony_ci return count; 48862306a36Sopenharmony_ci *ui = t; 48962306a36Sopenharmony_ci return count; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "discard_granularity")) { 49362306a36Sopenharmony_ci if (t == 0 || t > MAX_PLIST_NUM) 49462306a36Sopenharmony_ci return -EINVAL; 49562306a36Sopenharmony_ci if (!f2fs_block_unit_discard(sbi)) 49662306a36Sopenharmony_ci return -EINVAL; 49762306a36Sopenharmony_ci if (t == *ui) 49862306a36Sopenharmony_ci return count; 49962306a36Sopenharmony_ci *ui = t; 50062306a36Sopenharmony_ci return count; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (!strcmp(a->attr.name, "max_ordered_discard")) { 50462306a36Sopenharmony_ci if (t == 0 || t > MAX_PLIST_NUM) 50562306a36Sopenharmony_ci return -EINVAL; 50662306a36Sopenharmony_ci if (!f2fs_block_unit_discard(sbi)) 50762306a36Sopenharmony_ci return -EINVAL; 50862306a36Sopenharmony_ci *ui = t; 50962306a36Sopenharmony_ci return count; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "discard_urgent_util")) { 51362306a36Sopenharmony_ci if (t > 100) 51462306a36Sopenharmony_ci return -EINVAL; 51562306a36Sopenharmony_ci *ui = t; 51662306a36Sopenharmony_ci return count; 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "migration_granularity")) { 52062306a36Sopenharmony_ci if (t == 0 || t > sbi->segs_per_sec) 52162306a36Sopenharmony_ci return -EINVAL; 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_urgent")) { 52562306a36Sopenharmony_ci if (t == 0) { 52662306a36Sopenharmony_ci sbi->gc_mode = GC_NORMAL; 52762306a36Sopenharmony_ci } else if (t == 1) { 52862306a36Sopenharmony_ci sbi->gc_mode = GC_URGENT_HIGH; 52962306a36Sopenharmony_ci if (sbi->gc_thread) { 53062306a36Sopenharmony_ci sbi->gc_thread->gc_wake = true; 53162306a36Sopenharmony_ci wake_up_interruptible_all( 53262306a36Sopenharmony_ci &sbi->gc_thread->gc_wait_queue_head); 53362306a36Sopenharmony_ci wake_up_discard_thread(sbi, true); 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci } else if (t == 2) { 53662306a36Sopenharmony_ci sbi->gc_mode = GC_URGENT_LOW; 53762306a36Sopenharmony_ci } else if (t == 3) { 53862306a36Sopenharmony_ci sbi->gc_mode = GC_URGENT_MID; 53962306a36Sopenharmony_ci if (sbi->gc_thread) { 54062306a36Sopenharmony_ci sbi->gc_thread->gc_wake = true; 54162306a36Sopenharmony_ci wake_up_interruptible_all( 54262306a36Sopenharmony_ci &sbi->gc_thread->gc_wait_queue_head); 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci } else { 54562306a36Sopenharmony_ci return -EINVAL; 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci return count; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_idle")) { 55062306a36Sopenharmony_ci if (t == GC_IDLE_CB) { 55162306a36Sopenharmony_ci sbi->gc_mode = GC_IDLE_CB; 55262306a36Sopenharmony_ci } else if (t == GC_IDLE_GREEDY) { 55362306a36Sopenharmony_ci sbi->gc_mode = GC_IDLE_GREEDY; 55462306a36Sopenharmony_ci } else if (t == GC_IDLE_AT) { 55562306a36Sopenharmony_ci if (!sbi->am.atgc_enabled) 55662306a36Sopenharmony_ci return -EINVAL; 55762306a36Sopenharmony_ci sbi->gc_mode = GC_IDLE_AT; 55862306a36Sopenharmony_ci } else { 55962306a36Sopenharmony_ci sbi->gc_mode = GC_NORMAL; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci return count; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_remaining_trials")) { 56562306a36Sopenharmony_ci spin_lock(&sbi->gc_remaining_trials_lock); 56662306a36Sopenharmony_ci sbi->gc_remaining_trials = t; 56762306a36Sopenharmony_ci spin_unlock(&sbi->gc_remaining_trials_lock); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return count; 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci#ifdef CONFIG_F2FS_IOSTAT 57362306a36Sopenharmony_ci if (!strcmp(a->attr.name, "iostat_enable")) { 57462306a36Sopenharmony_ci sbi->iostat_enable = !!t; 57562306a36Sopenharmony_ci if (!sbi->iostat_enable) 57662306a36Sopenharmony_ci f2fs_reset_iostat(sbi); 57762306a36Sopenharmony_ci return count; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci if (!strcmp(a->attr.name, "iostat_period_ms")) { 58162306a36Sopenharmony_ci if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS) 58262306a36Sopenharmony_ci return -EINVAL; 58362306a36Sopenharmony_ci spin_lock_irq(&sbi->iostat_lock); 58462306a36Sopenharmony_ci sbi->iostat_period_ms = (unsigned int)t; 58562306a36Sopenharmony_ci spin_unlock_irq(&sbi->iostat_lock); 58662306a36Sopenharmony_ci return count; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci#endif 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 59162306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compr_written_block") || 59262306a36Sopenharmony_ci !strcmp(a->attr.name, "compr_saved_block")) { 59362306a36Sopenharmony_ci if (t != 0) 59462306a36Sopenharmony_ci return -EINVAL; 59562306a36Sopenharmony_ci sbi->compr_written_block = 0; 59662306a36Sopenharmony_ci sbi->compr_saved_block = 0; 59762306a36Sopenharmony_ci return count; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compr_new_inode")) { 60162306a36Sopenharmony_ci if (t != 0) 60262306a36Sopenharmony_ci return -EINVAL; 60362306a36Sopenharmony_ci sbi->compr_new_inode = 0; 60462306a36Sopenharmony_ci return count; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compress_percent")) { 60862306a36Sopenharmony_ci if (t == 0 || t > 100) 60962306a36Sopenharmony_ci return -EINVAL; 61062306a36Sopenharmony_ci *ui = t; 61162306a36Sopenharmony_ci return count; 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (!strcmp(a->attr.name, "compress_watermark")) { 61562306a36Sopenharmony_ci if (t == 0 || t > 100) 61662306a36Sopenharmony_ci return -EINVAL; 61762306a36Sopenharmony_ci *ui = t; 61862306a36Sopenharmony_ci return count; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci#endif 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { 62362306a36Sopenharmony_ci if (t > 100) 62462306a36Sopenharmony_ci return -EINVAL; 62562306a36Sopenharmony_ci sbi->am.candidate_ratio = t; 62662306a36Sopenharmony_ci return count; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "atgc_age_weight")) { 63062306a36Sopenharmony_ci if (t > 100) 63162306a36Sopenharmony_ci return -EINVAL; 63262306a36Sopenharmony_ci sbi->am.age_weight = t; 63362306a36Sopenharmony_ci return count; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_segment_mode")) { 63762306a36Sopenharmony_ci if (t < MAX_GC_MODE) 63862306a36Sopenharmony_ci sbi->gc_segment_mode = t; 63962306a36Sopenharmony_ci else 64062306a36Sopenharmony_ci return -EINVAL; 64162306a36Sopenharmony_ci return count; 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci if (!strcmp(a->attr.name, "gc_reclaimed_segments")) { 64562306a36Sopenharmony_ci if (t != 0) 64662306a36Sopenharmony_ci return -EINVAL; 64762306a36Sopenharmony_ci sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0; 64862306a36Sopenharmony_ci return count; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci if (!strcmp(a->attr.name, "seq_file_ra_mul")) { 65262306a36Sopenharmony_ci if (t >= MIN_RA_MUL && t <= MAX_RA_MUL) 65362306a36Sopenharmony_ci sbi->seq_file_ra_mul = t; 65462306a36Sopenharmony_ci else 65562306a36Sopenharmony_ci return -EINVAL; 65662306a36Sopenharmony_ci return count; 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "max_fragment_chunk")) { 66062306a36Sopenharmony_ci if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE) 66162306a36Sopenharmony_ci sbi->max_fragment_chunk = t; 66262306a36Sopenharmony_ci else 66362306a36Sopenharmony_ci return -EINVAL; 66462306a36Sopenharmony_ci return count; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (!strcmp(a->attr.name, "max_fragment_hole")) { 66862306a36Sopenharmony_ci if (t >= MIN_FRAGMENT_SIZE && t <= MAX_FRAGMENT_SIZE) 66962306a36Sopenharmony_ci sbi->max_fragment_hole = t; 67062306a36Sopenharmony_ci else 67162306a36Sopenharmony_ci return -EINVAL; 67262306a36Sopenharmony_ci return count; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (!strcmp(a->attr.name, "peak_atomic_write")) { 67662306a36Sopenharmony_ci if (t != 0) 67762306a36Sopenharmony_ci return -EINVAL; 67862306a36Sopenharmony_ci sbi->peak_atomic_write = 0; 67962306a36Sopenharmony_ci return count; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (!strcmp(a->attr.name, "committed_atomic_block")) { 68362306a36Sopenharmony_ci if (t != 0) 68462306a36Sopenharmony_ci return -EINVAL; 68562306a36Sopenharmony_ci sbi->committed_atomic_block = 0; 68662306a36Sopenharmony_ci return count; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "revoked_atomic_block")) { 69062306a36Sopenharmony_ci if (t != 0) 69162306a36Sopenharmony_ci return -EINVAL; 69262306a36Sopenharmony_ci sbi->revoked_atomic_block = 0; 69362306a36Sopenharmony_ci return count; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci if (!strcmp(a->attr.name, "readdir_ra")) { 69762306a36Sopenharmony_ci sbi->readdir_ra = !!t; 69862306a36Sopenharmony_ci return count; 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci if (!strcmp(a->attr.name, "hot_data_age_threshold")) { 70262306a36Sopenharmony_ci if (t == 0 || t >= sbi->warm_data_age_threshold) 70362306a36Sopenharmony_ci return -EINVAL; 70462306a36Sopenharmony_ci if (t == *ui) 70562306a36Sopenharmony_ci return count; 70662306a36Sopenharmony_ci *ui = (unsigned int)t; 70762306a36Sopenharmony_ci return count; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (!strcmp(a->attr.name, "warm_data_age_threshold")) { 71162306a36Sopenharmony_ci if (t <= sbi->hot_data_age_threshold) 71262306a36Sopenharmony_ci return -EINVAL; 71362306a36Sopenharmony_ci if (t == *ui) 71462306a36Sopenharmony_ci return count; 71562306a36Sopenharmony_ci *ui = (unsigned int)t; 71662306a36Sopenharmony_ci return count; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (!strcmp(a->attr.name, "last_age_weight")) { 72062306a36Sopenharmony_ci if (t > 100) 72162306a36Sopenharmony_ci return -EINVAL; 72262306a36Sopenharmony_ci if (t == *ui) 72362306a36Sopenharmony_ci return count; 72462306a36Sopenharmony_ci *ui = (unsigned int)t; 72562306a36Sopenharmony_ci return count; 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (!strcmp(a->attr.name, "ipu_policy")) { 72962306a36Sopenharmony_ci if (t >= BIT(F2FS_IPU_MAX)) 73062306a36Sopenharmony_ci return -EINVAL; 73162306a36Sopenharmony_ci if (t && f2fs_lfs_mode(sbi)) 73262306a36Sopenharmony_ci return -EINVAL; 73362306a36Sopenharmony_ci SM_I(sbi)->ipu_policy = (unsigned int)t; 73462306a36Sopenharmony_ci return count; 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci *ui = (unsigned int)t; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci return count; 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic ssize_t f2fs_sbi_store(struct f2fs_attr *a, 74362306a36Sopenharmony_ci struct f2fs_sb_info *sbi, 74462306a36Sopenharmony_ci const char *buf, size_t count) 74562306a36Sopenharmony_ci{ 74662306a36Sopenharmony_ci ssize_t ret; 74762306a36Sopenharmony_ci bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") || 74862306a36Sopenharmony_ci a->struct_type == GC_THREAD); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci if (gc_entry) { 75162306a36Sopenharmony_ci if (!down_read_trylock(&sbi->sb->s_umount)) 75262306a36Sopenharmony_ci return -EAGAIN; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci ret = __sbi_store(a, sbi, buf, count); 75562306a36Sopenharmony_ci if (gc_entry) 75662306a36Sopenharmony_ci up_read(&sbi->sb->s_umount); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci return ret; 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_cistatic ssize_t f2fs_attr_show(struct kobject *kobj, 76262306a36Sopenharmony_ci struct attribute *attr, char *buf) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 76562306a36Sopenharmony_ci s_kobj); 76662306a36Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci return a->show ? a->show(a, sbi, buf) : 0; 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr, 77262306a36Sopenharmony_ci const char *buf, size_t len) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 77562306a36Sopenharmony_ci s_kobj); 77662306a36Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci return a->store ? a->store(a, sbi, buf, len) : 0; 77962306a36Sopenharmony_ci} 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cistatic void f2fs_sb_release(struct kobject *kobj) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 78462306a36Sopenharmony_ci s_kobj); 78562306a36Sopenharmony_ci complete(&sbi->s_kobj_unregister); 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci/* 78962306a36Sopenharmony_ci * Note that there are three feature list entries: 79062306a36Sopenharmony_ci * 1) /sys/fs/f2fs/features 79162306a36Sopenharmony_ci * : shows runtime features supported by in-kernel f2fs along with Kconfig. 79262306a36Sopenharmony_ci * - ref. F2FS_FEATURE_RO_ATTR() 79362306a36Sopenharmony_ci * 79462306a36Sopenharmony_ci * 2) /sys/fs/f2fs/$s_id/features <deprecated> 79562306a36Sopenharmony_ci * : shows on-disk features enabled by mkfs.f2fs, used for old kernels. This 79662306a36Sopenharmony_ci * won't add new feature anymore, and thus, users should check entries in 3) 79762306a36Sopenharmony_ci * instead of this 2). 79862306a36Sopenharmony_ci * 79962306a36Sopenharmony_ci * 3) /sys/fs/f2fs/$s_id/feature_list 80062306a36Sopenharmony_ci * : shows on-disk features enabled by mkfs.f2fs per instance, which follows 80162306a36Sopenharmony_ci * sysfs entry rule where each entry should expose single value. 80262306a36Sopenharmony_ci * This list covers old feature list provided by 2) and beyond. Therefore, 80362306a36Sopenharmony_ci * please add new on-disk feature in this list only. 80462306a36Sopenharmony_ci * - ref. F2FS_SB_FEATURE_RO_ATTR() 80562306a36Sopenharmony_ci */ 80662306a36Sopenharmony_cistatic ssize_t f2fs_feature_show(struct f2fs_attr *a, 80762306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci return sysfs_emit(buf, "supported\n"); 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci#define F2FS_FEATURE_RO_ATTR(_name) \ 81362306a36Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##_name = { \ 81462306a36Sopenharmony_ci .attr = {.name = __stringify(_name), .mode = 0444 }, \ 81562306a36Sopenharmony_ci .show = f2fs_feature_show, \ 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cistatic ssize_t f2fs_sb_feature_show(struct f2fs_attr *a, 81962306a36Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci if (F2FS_HAS_FEATURE(sbi, a->id)) 82262306a36Sopenharmony_ci return sysfs_emit(buf, "supported\n"); 82362306a36Sopenharmony_ci return sysfs_emit(buf, "unsupported\n"); 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci#define F2FS_SB_FEATURE_RO_ATTR(_name, _feat) \ 82762306a36Sopenharmony_cistatic struct f2fs_attr f2fs_attr_sb_##_name = { \ 82862306a36Sopenharmony_ci .attr = {.name = __stringify(_name), .mode = 0444 }, \ 82962306a36Sopenharmony_ci .show = f2fs_sb_feature_show, \ 83062306a36Sopenharmony_ci .id = F2FS_FEATURE_##_feat, \ 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ 83462306a36Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##_name = { \ 83562306a36Sopenharmony_ci .attr = {.name = __stringify(_name), .mode = _mode }, \ 83662306a36Sopenharmony_ci .show = _show, \ 83762306a36Sopenharmony_ci .store = _store, \ 83862306a36Sopenharmony_ci .struct_type = _struct_type, \ 83962306a36Sopenharmony_ci .offset = _offset \ 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci#define F2FS_RO_ATTR(struct_type, struct_name, name, elname) \ 84362306a36Sopenharmony_ci F2FS_ATTR_OFFSET(struct_type, name, 0444, \ 84462306a36Sopenharmony_ci f2fs_sbi_show, NULL, \ 84562306a36Sopenharmony_ci offsetof(struct struct_name, elname)) 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci#define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ 84862306a36Sopenharmony_ci F2FS_ATTR_OFFSET(struct_type, name, 0644, \ 84962306a36Sopenharmony_ci f2fs_sbi_show, f2fs_sbi_store, \ 85062306a36Sopenharmony_ci offsetof(struct struct_name, elname)) 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci#define F2FS_GENERAL_RO_ATTR(name) \ 85362306a36Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL) 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 85662306a36Sopenharmony_ci#define STAT_INFO_RO_ATTR(name, elname) \ 85762306a36Sopenharmony_ci F2FS_RO_ATTR(STAT_INFO, f2fs_stat_info, name, elname) 85862306a36Sopenharmony_ci#endif 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci#define GC_THREAD_RW_ATTR(name, elname) \ 86162306a36Sopenharmony_ci F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, name, elname) 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci#define SM_INFO_RW_ATTR(name, elname) \ 86462306a36Sopenharmony_ci F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, name, elname) 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci#define SM_INFO_GENERAL_RW_ATTR(elname) \ 86762306a36Sopenharmony_ci SM_INFO_RW_ATTR(elname, elname) 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci#define DCC_INFO_RW_ATTR(name, elname) \ 87062306a36Sopenharmony_ci F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, name, elname) 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci#define DCC_INFO_GENERAL_RW_ATTR(elname) \ 87362306a36Sopenharmony_ci DCC_INFO_RW_ATTR(elname, elname) 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci#define NM_INFO_RW_ATTR(name, elname) \ 87662306a36Sopenharmony_ci F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, name, elname) 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci#define NM_INFO_GENERAL_RW_ATTR(elname) \ 87962306a36Sopenharmony_ci NM_INFO_RW_ATTR(elname, elname) 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci#define F2FS_SBI_RW_ATTR(name, elname) \ 88262306a36Sopenharmony_ci F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, name, elname) 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci#define F2FS_SBI_GENERAL_RW_ATTR(elname) \ 88562306a36Sopenharmony_ci F2FS_SBI_RW_ATTR(elname, elname) 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci#define F2FS_SBI_GENERAL_RO_ATTR(elname) \ 88862306a36Sopenharmony_ci F2FS_RO_ATTR(F2FS_SBI, f2fs_sb_info, elname, elname) 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 89162306a36Sopenharmony_ci#define FAULT_INFO_GENERAL_RW_ATTR(type, elname) \ 89262306a36Sopenharmony_ci F2FS_RW_ATTR(type, f2fs_fault_info, elname, elname) 89362306a36Sopenharmony_ci#endif 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci#define RESERVED_BLOCKS_GENERAL_RW_ATTR(elname) \ 89662306a36Sopenharmony_ci F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, elname, elname) 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci#define CPRC_INFO_GENERAL_RW_ATTR(elname) \ 89962306a36Sopenharmony_ci F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, elname, elname) 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci#define ATGC_INFO_RW_ATTR(name, elname) \ 90262306a36Sopenharmony_ci F2FS_RW_ATTR(ATGC_INFO, atgc_management, name, elname) 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci/* GC_THREAD ATTR */ 90562306a36Sopenharmony_ciGC_THREAD_RW_ATTR(gc_urgent_sleep_time, urgent_sleep_time); 90662306a36Sopenharmony_ciGC_THREAD_RW_ATTR(gc_min_sleep_time, min_sleep_time); 90762306a36Sopenharmony_ciGC_THREAD_RW_ATTR(gc_max_sleep_time, max_sleep_time); 90862306a36Sopenharmony_ciGC_THREAD_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci/* SM_INFO ATTR */ 91162306a36Sopenharmony_ciSM_INFO_RW_ATTR(reclaim_segments, rec_prefree_segments); 91262306a36Sopenharmony_ciSM_INFO_GENERAL_RW_ATTR(ipu_policy); 91362306a36Sopenharmony_ciSM_INFO_GENERAL_RW_ATTR(min_ipu_util); 91462306a36Sopenharmony_ciSM_INFO_GENERAL_RW_ATTR(min_fsync_blocks); 91562306a36Sopenharmony_ciSM_INFO_GENERAL_RW_ATTR(min_seq_blocks); 91662306a36Sopenharmony_ciSM_INFO_GENERAL_RW_ATTR(min_hot_blocks); 91762306a36Sopenharmony_ciSM_INFO_GENERAL_RW_ATTR(min_ssr_sections); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci/* DCC_INFO ATTR */ 92062306a36Sopenharmony_ciDCC_INFO_RW_ATTR(max_small_discards, max_discards); 92162306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(max_discard_request); 92262306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(min_discard_issue_time); 92362306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(mid_discard_issue_time); 92462306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(max_discard_issue_time); 92562306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(discard_io_aware_gran); 92662306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(discard_urgent_util); 92762306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(discard_granularity); 92862306a36Sopenharmony_ciDCC_INFO_GENERAL_RW_ATTR(max_ordered_discard); 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci/* NM_INFO ATTR */ 93162306a36Sopenharmony_ciNM_INFO_RW_ATTR(max_roll_forward_node_blocks, max_rf_node_blocks); 93262306a36Sopenharmony_ciNM_INFO_GENERAL_RW_ATTR(ram_thresh); 93362306a36Sopenharmony_ciNM_INFO_GENERAL_RW_ATTR(ra_nid_pages); 93462306a36Sopenharmony_ciNM_INFO_GENERAL_RW_ATTR(dirty_nats_ratio); 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci/* F2FS_SBI ATTR */ 93762306a36Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list); 93862306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(gc_idle, gc_mode); 93962306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(gc_urgent, gc_mode); 94062306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(cp_interval, interval_time[CP_TIME]); 94162306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(idle_interval, interval_time[REQ_TIME]); 94262306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(discard_idle_interval, interval_time[DISCARD_TIME]); 94362306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(gc_idle_interval, interval_time[GC_TIME]); 94462306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]); 94562306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(gc_pin_file_thresh, gc_pin_file_threshold); 94662306a36Sopenharmony_ciF2FS_SBI_RW_ATTR(gc_reclaimed_segments, gc_reclaimed_segs); 94762306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(max_victim_search); 94862306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(migration_granularity); 94962306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(dir_level); 95062306a36Sopenharmony_ci#ifdef CONFIG_F2FS_IOSTAT 95162306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(iostat_enable); 95262306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(iostat_period_ms); 95362306a36Sopenharmony_ci#endif 95462306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(readdir_ra); 95562306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(max_io_bytes); 95662306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(data_io_flag); 95762306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(node_io_flag); 95862306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(gc_remaining_trials); 95962306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(seq_file_ra_mul); 96062306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(gc_segment_mode); 96162306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(max_fragment_chunk); 96262306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(max_fragment_hole); 96362306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 96462306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(compr_written_block); 96562306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(compr_saved_block); 96662306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(compr_new_inode); 96762306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(compress_percent); 96862306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(compress_watermark); 96962306a36Sopenharmony_ci#endif 97062306a36Sopenharmony_ci/* atomic write */ 97162306a36Sopenharmony_ciF2FS_SBI_GENERAL_RO_ATTR(current_atomic_write); 97262306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(peak_atomic_write); 97362306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(committed_atomic_block); 97462306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(revoked_atomic_block); 97562306a36Sopenharmony_ci/* block age extent cache */ 97662306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(hot_data_age_threshold); 97762306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(warm_data_age_threshold); 97862306a36Sopenharmony_ciF2FS_SBI_GENERAL_RW_ATTR(last_age_weight); 97962306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 98062306a36Sopenharmony_ciF2FS_SBI_GENERAL_RO_ATTR(unusable_blocks_per_sec); 98162306a36Sopenharmony_ci#endif 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci/* STAT_INFO ATTR */ 98462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 98562306a36Sopenharmony_ciSTAT_INFO_RO_ATTR(cp_foreground_calls, cp_call_count[FOREGROUND]); 98662306a36Sopenharmony_ciSTAT_INFO_RO_ATTR(cp_background_calls, cp_call_count[BACKGROUND]); 98762306a36Sopenharmony_ciSTAT_INFO_RO_ATTR(gc_foreground_calls, gc_call_count[FOREGROUND]); 98862306a36Sopenharmony_ciSTAT_INFO_RO_ATTR(gc_background_calls, gc_call_count[BACKGROUND]); 98962306a36Sopenharmony_ci#endif 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci/* FAULT_INFO ATTR */ 99262306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 99362306a36Sopenharmony_ciFAULT_INFO_GENERAL_RW_ATTR(FAULT_INFO_RATE, inject_rate); 99462306a36Sopenharmony_ciFAULT_INFO_GENERAL_RW_ATTR(FAULT_INFO_TYPE, inject_type); 99562306a36Sopenharmony_ci#endif 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci/* RESERVED_BLOCKS ATTR */ 99862306a36Sopenharmony_ciRESERVED_BLOCKS_GENERAL_RW_ATTR(reserved_blocks); 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci/* CPRC_INFO ATTR */ 100162306a36Sopenharmony_ciCPRC_INFO_GENERAL_RW_ATTR(ckpt_thread_ioprio); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci/* ATGC_INFO ATTR */ 100462306a36Sopenharmony_ciATGC_INFO_RW_ATTR(atgc_candidate_ratio, candidate_ratio); 100562306a36Sopenharmony_ciATGC_INFO_RW_ATTR(atgc_candidate_count, max_candidate_count); 100662306a36Sopenharmony_ciATGC_INFO_RW_ATTR(atgc_age_weight, age_weight); 100762306a36Sopenharmony_ciATGC_INFO_RW_ATTR(atgc_age_threshold, age_threshold); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(dirty_segments); 101062306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(free_segments); 101162306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(ovp_segments); 101262306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(lifetime_write_kbytes); 101362306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(features); 101462306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(current_reserved_blocks); 101562306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(unusable); 101662306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(encoding); 101762306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(mounted_time_sec); 101862306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(main_blkaddr); 101962306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(pending_discard); 102062306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(gc_mode); 102162306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 102262306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(moved_blocks_background); 102362306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(moved_blocks_foreground); 102462306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(avg_vblocks); 102562306a36Sopenharmony_ci#endif 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 102862306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(encryption); 102962306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2); 103062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE) 103162306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(encrypted_casefold); 103262306a36Sopenharmony_ci#endif 103362306a36Sopenharmony_ci#endif /* CONFIG_FS_ENCRYPTION */ 103462306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 103562306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(block_zoned); 103662306a36Sopenharmony_ci#endif 103762306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(atomic_write); 103862306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(extra_attr); 103962306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(project_quota); 104062306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(inode_checksum); 104162306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(flexible_inline_xattr); 104262306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(quota_ino); 104362306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(inode_crtime); 104462306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(lost_found); 104562306a36Sopenharmony_ci#ifdef CONFIG_FS_VERITY 104662306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(verity); 104762306a36Sopenharmony_ci#endif 104862306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(sb_checksum); 104962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE) 105062306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(casefold); 105162306a36Sopenharmony_ci#endif 105262306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(readonly); 105362306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 105462306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(compression); 105562306a36Sopenharmony_ci#endif 105662306a36Sopenharmony_ciF2FS_FEATURE_RO_ATTR(pin_file); 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci#define ATTR_LIST(name) (&f2fs_attr_##name.attr) 105962306a36Sopenharmony_cistatic struct attribute *f2fs_attrs[] = { 106062306a36Sopenharmony_ci ATTR_LIST(gc_urgent_sleep_time), 106162306a36Sopenharmony_ci ATTR_LIST(gc_min_sleep_time), 106262306a36Sopenharmony_ci ATTR_LIST(gc_max_sleep_time), 106362306a36Sopenharmony_ci ATTR_LIST(gc_no_gc_sleep_time), 106462306a36Sopenharmony_ci ATTR_LIST(gc_idle), 106562306a36Sopenharmony_ci ATTR_LIST(gc_urgent), 106662306a36Sopenharmony_ci ATTR_LIST(reclaim_segments), 106762306a36Sopenharmony_ci ATTR_LIST(main_blkaddr), 106862306a36Sopenharmony_ci ATTR_LIST(max_small_discards), 106962306a36Sopenharmony_ci ATTR_LIST(max_discard_request), 107062306a36Sopenharmony_ci ATTR_LIST(min_discard_issue_time), 107162306a36Sopenharmony_ci ATTR_LIST(mid_discard_issue_time), 107262306a36Sopenharmony_ci ATTR_LIST(max_discard_issue_time), 107362306a36Sopenharmony_ci ATTR_LIST(discard_io_aware_gran), 107462306a36Sopenharmony_ci ATTR_LIST(discard_urgent_util), 107562306a36Sopenharmony_ci ATTR_LIST(discard_granularity), 107662306a36Sopenharmony_ci ATTR_LIST(max_ordered_discard), 107762306a36Sopenharmony_ci ATTR_LIST(pending_discard), 107862306a36Sopenharmony_ci ATTR_LIST(gc_mode), 107962306a36Sopenharmony_ci ATTR_LIST(ipu_policy), 108062306a36Sopenharmony_ci ATTR_LIST(min_ipu_util), 108162306a36Sopenharmony_ci ATTR_LIST(min_fsync_blocks), 108262306a36Sopenharmony_ci ATTR_LIST(min_seq_blocks), 108362306a36Sopenharmony_ci ATTR_LIST(min_hot_blocks), 108462306a36Sopenharmony_ci ATTR_LIST(min_ssr_sections), 108562306a36Sopenharmony_ci ATTR_LIST(max_victim_search), 108662306a36Sopenharmony_ci ATTR_LIST(migration_granularity), 108762306a36Sopenharmony_ci ATTR_LIST(dir_level), 108862306a36Sopenharmony_ci ATTR_LIST(ram_thresh), 108962306a36Sopenharmony_ci ATTR_LIST(ra_nid_pages), 109062306a36Sopenharmony_ci ATTR_LIST(dirty_nats_ratio), 109162306a36Sopenharmony_ci ATTR_LIST(max_roll_forward_node_blocks), 109262306a36Sopenharmony_ci ATTR_LIST(cp_interval), 109362306a36Sopenharmony_ci ATTR_LIST(idle_interval), 109462306a36Sopenharmony_ci ATTR_LIST(discard_idle_interval), 109562306a36Sopenharmony_ci ATTR_LIST(gc_idle_interval), 109662306a36Sopenharmony_ci ATTR_LIST(umount_discard_timeout), 109762306a36Sopenharmony_ci#ifdef CONFIG_F2FS_IOSTAT 109862306a36Sopenharmony_ci ATTR_LIST(iostat_enable), 109962306a36Sopenharmony_ci ATTR_LIST(iostat_period_ms), 110062306a36Sopenharmony_ci#endif 110162306a36Sopenharmony_ci ATTR_LIST(readdir_ra), 110262306a36Sopenharmony_ci ATTR_LIST(max_io_bytes), 110362306a36Sopenharmony_ci ATTR_LIST(gc_pin_file_thresh), 110462306a36Sopenharmony_ci ATTR_LIST(extension_list), 110562306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 110662306a36Sopenharmony_ci ATTR_LIST(inject_rate), 110762306a36Sopenharmony_ci ATTR_LIST(inject_type), 110862306a36Sopenharmony_ci#endif 110962306a36Sopenharmony_ci ATTR_LIST(data_io_flag), 111062306a36Sopenharmony_ci ATTR_LIST(node_io_flag), 111162306a36Sopenharmony_ci ATTR_LIST(gc_remaining_trials), 111262306a36Sopenharmony_ci ATTR_LIST(ckpt_thread_ioprio), 111362306a36Sopenharmony_ci ATTR_LIST(dirty_segments), 111462306a36Sopenharmony_ci ATTR_LIST(free_segments), 111562306a36Sopenharmony_ci ATTR_LIST(ovp_segments), 111662306a36Sopenharmony_ci ATTR_LIST(unusable), 111762306a36Sopenharmony_ci ATTR_LIST(lifetime_write_kbytes), 111862306a36Sopenharmony_ci ATTR_LIST(features), 111962306a36Sopenharmony_ci ATTR_LIST(reserved_blocks), 112062306a36Sopenharmony_ci ATTR_LIST(current_reserved_blocks), 112162306a36Sopenharmony_ci ATTR_LIST(encoding), 112262306a36Sopenharmony_ci ATTR_LIST(mounted_time_sec), 112362306a36Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 112462306a36Sopenharmony_ci ATTR_LIST(cp_foreground_calls), 112562306a36Sopenharmony_ci ATTR_LIST(cp_background_calls), 112662306a36Sopenharmony_ci ATTR_LIST(gc_foreground_calls), 112762306a36Sopenharmony_ci ATTR_LIST(gc_background_calls), 112862306a36Sopenharmony_ci ATTR_LIST(moved_blocks_foreground), 112962306a36Sopenharmony_ci ATTR_LIST(moved_blocks_background), 113062306a36Sopenharmony_ci ATTR_LIST(avg_vblocks), 113162306a36Sopenharmony_ci#endif 113262306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 113362306a36Sopenharmony_ci ATTR_LIST(unusable_blocks_per_sec), 113462306a36Sopenharmony_ci#endif 113562306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 113662306a36Sopenharmony_ci ATTR_LIST(compr_written_block), 113762306a36Sopenharmony_ci ATTR_LIST(compr_saved_block), 113862306a36Sopenharmony_ci ATTR_LIST(compr_new_inode), 113962306a36Sopenharmony_ci ATTR_LIST(compress_percent), 114062306a36Sopenharmony_ci ATTR_LIST(compress_watermark), 114162306a36Sopenharmony_ci#endif 114262306a36Sopenharmony_ci /* For ATGC */ 114362306a36Sopenharmony_ci ATTR_LIST(atgc_candidate_ratio), 114462306a36Sopenharmony_ci ATTR_LIST(atgc_candidate_count), 114562306a36Sopenharmony_ci ATTR_LIST(atgc_age_weight), 114662306a36Sopenharmony_ci ATTR_LIST(atgc_age_threshold), 114762306a36Sopenharmony_ci ATTR_LIST(seq_file_ra_mul), 114862306a36Sopenharmony_ci ATTR_LIST(gc_segment_mode), 114962306a36Sopenharmony_ci ATTR_LIST(gc_reclaimed_segments), 115062306a36Sopenharmony_ci ATTR_LIST(max_fragment_chunk), 115162306a36Sopenharmony_ci ATTR_LIST(max_fragment_hole), 115262306a36Sopenharmony_ci ATTR_LIST(current_atomic_write), 115362306a36Sopenharmony_ci ATTR_LIST(peak_atomic_write), 115462306a36Sopenharmony_ci ATTR_LIST(committed_atomic_block), 115562306a36Sopenharmony_ci ATTR_LIST(revoked_atomic_block), 115662306a36Sopenharmony_ci ATTR_LIST(hot_data_age_threshold), 115762306a36Sopenharmony_ci ATTR_LIST(warm_data_age_threshold), 115862306a36Sopenharmony_ci ATTR_LIST(last_age_weight), 115962306a36Sopenharmony_ci NULL, 116062306a36Sopenharmony_ci}; 116162306a36Sopenharmony_ciATTRIBUTE_GROUPS(f2fs); 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_cistatic struct attribute *f2fs_feat_attrs[] = { 116462306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 116562306a36Sopenharmony_ci ATTR_LIST(encryption), 116662306a36Sopenharmony_ci ATTR_LIST(test_dummy_encryption_v2), 116762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE) 116862306a36Sopenharmony_ci ATTR_LIST(encrypted_casefold), 116962306a36Sopenharmony_ci#endif 117062306a36Sopenharmony_ci#endif /* CONFIG_FS_ENCRYPTION */ 117162306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 117262306a36Sopenharmony_ci ATTR_LIST(block_zoned), 117362306a36Sopenharmony_ci#endif 117462306a36Sopenharmony_ci ATTR_LIST(atomic_write), 117562306a36Sopenharmony_ci ATTR_LIST(extra_attr), 117662306a36Sopenharmony_ci ATTR_LIST(project_quota), 117762306a36Sopenharmony_ci ATTR_LIST(inode_checksum), 117862306a36Sopenharmony_ci ATTR_LIST(flexible_inline_xattr), 117962306a36Sopenharmony_ci ATTR_LIST(quota_ino), 118062306a36Sopenharmony_ci ATTR_LIST(inode_crtime), 118162306a36Sopenharmony_ci ATTR_LIST(lost_found), 118262306a36Sopenharmony_ci#ifdef CONFIG_FS_VERITY 118362306a36Sopenharmony_ci ATTR_LIST(verity), 118462306a36Sopenharmony_ci#endif 118562306a36Sopenharmony_ci ATTR_LIST(sb_checksum), 118662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE) 118762306a36Sopenharmony_ci ATTR_LIST(casefold), 118862306a36Sopenharmony_ci#endif 118962306a36Sopenharmony_ci ATTR_LIST(readonly), 119062306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 119162306a36Sopenharmony_ci ATTR_LIST(compression), 119262306a36Sopenharmony_ci#endif 119362306a36Sopenharmony_ci ATTR_LIST(pin_file), 119462306a36Sopenharmony_ci NULL, 119562306a36Sopenharmony_ci}; 119662306a36Sopenharmony_ciATTRIBUTE_GROUPS(f2fs_feat); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(sb_status); 119962306a36Sopenharmony_ciF2FS_GENERAL_RO_ATTR(cp_status); 120062306a36Sopenharmony_cistatic struct attribute *f2fs_stat_attrs[] = { 120162306a36Sopenharmony_ci ATTR_LIST(sb_status), 120262306a36Sopenharmony_ci ATTR_LIST(cp_status), 120362306a36Sopenharmony_ci NULL, 120462306a36Sopenharmony_ci}; 120562306a36Sopenharmony_ciATTRIBUTE_GROUPS(f2fs_stat); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(encryption, ENCRYPT); 120862306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(block_zoned, BLKZONED); 120962306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(extra_attr, EXTRA_ATTR); 121062306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(project_quota, PRJQUOTA); 121162306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(inode_checksum, INODE_CHKSUM); 121262306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR); 121362306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(quota_ino, QUOTA_INO); 121462306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(inode_crtime, INODE_CRTIME); 121562306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(lost_found, LOST_FOUND); 121662306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(verity, VERITY); 121762306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(sb_checksum, SB_CHKSUM); 121862306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(casefold, CASEFOLD); 121962306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION); 122062306a36Sopenharmony_ciF2FS_SB_FEATURE_RO_ATTR(readonly, RO); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic struct attribute *f2fs_sb_feat_attrs[] = { 122362306a36Sopenharmony_ci ATTR_LIST(sb_encryption), 122462306a36Sopenharmony_ci ATTR_LIST(sb_block_zoned), 122562306a36Sopenharmony_ci ATTR_LIST(sb_extra_attr), 122662306a36Sopenharmony_ci ATTR_LIST(sb_project_quota), 122762306a36Sopenharmony_ci ATTR_LIST(sb_inode_checksum), 122862306a36Sopenharmony_ci ATTR_LIST(sb_flexible_inline_xattr), 122962306a36Sopenharmony_ci ATTR_LIST(sb_quota_ino), 123062306a36Sopenharmony_ci ATTR_LIST(sb_inode_crtime), 123162306a36Sopenharmony_ci ATTR_LIST(sb_lost_found), 123262306a36Sopenharmony_ci ATTR_LIST(sb_verity), 123362306a36Sopenharmony_ci ATTR_LIST(sb_sb_checksum), 123462306a36Sopenharmony_ci ATTR_LIST(sb_casefold), 123562306a36Sopenharmony_ci ATTR_LIST(sb_compression), 123662306a36Sopenharmony_ci ATTR_LIST(sb_readonly), 123762306a36Sopenharmony_ci NULL, 123862306a36Sopenharmony_ci}; 123962306a36Sopenharmony_ciATTRIBUTE_GROUPS(f2fs_sb_feat); 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_cistatic const struct sysfs_ops f2fs_attr_ops = { 124262306a36Sopenharmony_ci .show = f2fs_attr_show, 124362306a36Sopenharmony_ci .store = f2fs_attr_store, 124462306a36Sopenharmony_ci}; 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_cistatic const struct kobj_type f2fs_sb_ktype = { 124762306a36Sopenharmony_ci .default_groups = f2fs_groups, 124862306a36Sopenharmony_ci .sysfs_ops = &f2fs_attr_ops, 124962306a36Sopenharmony_ci .release = f2fs_sb_release, 125062306a36Sopenharmony_ci}; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_cistatic const struct kobj_type f2fs_ktype = { 125362306a36Sopenharmony_ci .sysfs_ops = &f2fs_attr_ops, 125462306a36Sopenharmony_ci}; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_cistatic struct kset f2fs_kset = { 125762306a36Sopenharmony_ci .kobj = {.ktype = &f2fs_ktype}, 125862306a36Sopenharmony_ci}; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_cistatic const struct kobj_type f2fs_feat_ktype = { 126162306a36Sopenharmony_ci .default_groups = f2fs_feat_groups, 126262306a36Sopenharmony_ci .sysfs_ops = &f2fs_attr_ops, 126362306a36Sopenharmony_ci}; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_cistatic struct kobject f2fs_feat = { 126662306a36Sopenharmony_ci .kset = &f2fs_kset, 126762306a36Sopenharmony_ci}; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_cistatic ssize_t f2fs_stat_attr_show(struct kobject *kobj, 127062306a36Sopenharmony_ci struct attribute *attr, char *buf) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 127362306a36Sopenharmony_ci s_stat_kobj); 127462306a36Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci return a->show ? a->show(a, sbi, buf) : 0; 127762306a36Sopenharmony_ci} 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_cistatic ssize_t f2fs_stat_attr_store(struct kobject *kobj, struct attribute *attr, 128062306a36Sopenharmony_ci const char *buf, size_t len) 128162306a36Sopenharmony_ci{ 128262306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 128362306a36Sopenharmony_ci s_stat_kobj); 128462306a36Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci return a->store ? a->store(a, sbi, buf, len) : 0; 128762306a36Sopenharmony_ci} 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_cistatic void f2fs_stat_kobj_release(struct kobject *kobj) 129062306a36Sopenharmony_ci{ 129162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 129262306a36Sopenharmony_ci s_stat_kobj); 129362306a36Sopenharmony_ci complete(&sbi->s_stat_kobj_unregister); 129462306a36Sopenharmony_ci} 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_cistatic const struct sysfs_ops f2fs_stat_attr_ops = { 129762306a36Sopenharmony_ci .show = f2fs_stat_attr_show, 129862306a36Sopenharmony_ci .store = f2fs_stat_attr_store, 129962306a36Sopenharmony_ci}; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_cistatic const struct kobj_type f2fs_stat_ktype = { 130262306a36Sopenharmony_ci .default_groups = f2fs_stat_groups, 130362306a36Sopenharmony_ci .sysfs_ops = &f2fs_stat_attr_ops, 130462306a36Sopenharmony_ci .release = f2fs_stat_kobj_release, 130562306a36Sopenharmony_ci}; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_cistatic ssize_t f2fs_sb_feat_attr_show(struct kobject *kobj, 130862306a36Sopenharmony_ci struct attribute *attr, char *buf) 130962306a36Sopenharmony_ci{ 131062306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 131162306a36Sopenharmony_ci s_feature_list_kobj); 131262306a36Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci return a->show ? a->show(a, sbi, buf) : 0; 131562306a36Sopenharmony_ci} 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_cistatic void f2fs_feature_list_kobj_release(struct kobject *kobj) 131862306a36Sopenharmony_ci{ 131962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 132062306a36Sopenharmony_ci s_feature_list_kobj); 132162306a36Sopenharmony_ci complete(&sbi->s_feature_list_kobj_unregister); 132262306a36Sopenharmony_ci} 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_cistatic const struct sysfs_ops f2fs_feature_list_attr_ops = { 132562306a36Sopenharmony_ci .show = f2fs_sb_feat_attr_show, 132662306a36Sopenharmony_ci}; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_cistatic const struct kobj_type f2fs_feature_list_ktype = { 132962306a36Sopenharmony_ci .default_groups = f2fs_sb_feat_groups, 133062306a36Sopenharmony_ci .sysfs_ops = &f2fs_feature_list_attr_ops, 133162306a36Sopenharmony_ci .release = f2fs_feature_list_kobj_release, 133262306a36Sopenharmony_ci}; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_cistatic int __maybe_unused segment_info_seq_show(struct seq_file *seq, 133562306a36Sopenharmony_ci void *offset) 133662306a36Sopenharmony_ci{ 133762306a36Sopenharmony_ci struct super_block *sb = seq->private; 133862306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 133962306a36Sopenharmony_ci unsigned int total_segs = 134062306a36Sopenharmony_ci le32_to_cpu(sbi->raw_super->segment_count_main); 134162306a36Sopenharmony_ci int i; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci seq_puts(seq, "format: segment_type|valid_blocks\n" 134462306a36Sopenharmony_ci "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n"); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci for (i = 0; i < total_segs; i++) { 134762306a36Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, i); 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci if ((i % 10) == 0) 135062306a36Sopenharmony_ci seq_printf(seq, "%-10d", i); 135162306a36Sopenharmony_ci seq_printf(seq, "%d|%-3u", se->type, se->valid_blocks); 135262306a36Sopenharmony_ci if ((i % 10) == 9 || i == (total_segs - 1)) 135362306a36Sopenharmony_ci seq_putc(seq, '\n'); 135462306a36Sopenharmony_ci else 135562306a36Sopenharmony_ci seq_putc(seq, ' '); 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci return 0; 135962306a36Sopenharmony_ci} 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_cistatic int __maybe_unused segment_bits_seq_show(struct seq_file *seq, 136262306a36Sopenharmony_ci void *offset) 136362306a36Sopenharmony_ci{ 136462306a36Sopenharmony_ci struct super_block *sb = seq->private; 136562306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 136662306a36Sopenharmony_ci unsigned int total_segs = 136762306a36Sopenharmony_ci le32_to_cpu(sbi->raw_super->segment_count_main); 136862306a36Sopenharmony_ci int i, j; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci seq_puts(seq, "format: segment_type|valid_blocks|bitmaps\n" 137162306a36Sopenharmony_ci "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n"); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci for (i = 0; i < total_segs; i++) { 137462306a36Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, i); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci seq_printf(seq, "%-10d", i); 137762306a36Sopenharmony_ci seq_printf(seq, "%d|%-3u|", se->type, se->valid_blocks); 137862306a36Sopenharmony_ci for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++) 137962306a36Sopenharmony_ci seq_printf(seq, " %.2x", se->cur_valid_map[j]); 138062306a36Sopenharmony_ci seq_putc(seq, '\n'); 138162306a36Sopenharmony_ci } 138262306a36Sopenharmony_ci return 0; 138362306a36Sopenharmony_ci} 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_cistatic int __maybe_unused victim_bits_seq_show(struct seq_file *seq, 138662306a36Sopenharmony_ci void *offset) 138762306a36Sopenharmony_ci{ 138862306a36Sopenharmony_ci struct super_block *sb = seq->private; 138962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 139062306a36Sopenharmony_ci struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 139162306a36Sopenharmony_ci int i; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci seq_puts(seq, "format: victim_secmap bitmaps\n"); 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci for (i = 0; i < MAIN_SECS(sbi); i++) { 139662306a36Sopenharmony_ci if ((i % 10) == 0) 139762306a36Sopenharmony_ci seq_printf(seq, "%-10d", i); 139862306a36Sopenharmony_ci seq_printf(seq, "%d", test_bit(i, dirty_i->victim_secmap) ? 1 : 0); 139962306a36Sopenharmony_ci if ((i % 10) == 9 || i == (MAIN_SECS(sbi) - 1)) 140062306a36Sopenharmony_ci seq_putc(seq, '\n'); 140162306a36Sopenharmony_ci else 140262306a36Sopenharmony_ci seq_putc(seq, ' '); 140362306a36Sopenharmony_ci } 140462306a36Sopenharmony_ci return 0; 140562306a36Sopenharmony_ci} 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_cistatic int __maybe_unused discard_plist_seq_show(struct seq_file *seq, 140862306a36Sopenharmony_ci void *offset) 140962306a36Sopenharmony_ci{ 141062306a36Sopenharmony_ci struct super_block *sb = seq->private; 141162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 141262306a36Sopenharmony_ci struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; 141362306a36Sopenharmony_ci int i, count; 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci seq_puts(seq, "Discard pend list(Show diacrd_cmd count on each entry, .:not exist):\n"); 141662306a36Sopenharmony_ci if (!f2fs_realtime_discard_enable(sbi)) 141762306a36Sopenharmony_ci return 0; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (dcc) { 142062306a36Sopenharmony_ci mutex_lock(&dcc->cmd_lock); 142162306a36Sopenharmony_ci for (i = 0; i < MAX_PLIST_NUM; i++) { 142262306a36Sopenharmony_ci struct list_head *pend_list; 142362306a36Sopenharmony_ci struct discard_cmd *dc, *tmp; 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci if (i % 8 == 0) 142662306a36Sopenharmony_ci seq_printf(seq, " %-3d", i); 142762306a36Sopenharmony_ci count = 0; 142862306a36Sopenharmony_ci pend_list = &dcc->pend_list[i]; 142962306a36Sopenharmony_ci list_for_each_entry_safe(dc, tmp, pend_list, list) 143062306a36Sopenharmony_ci count++; 143162306a36Sopenharmony_ci if (count) 143262306a36Sopenharmony_ci seq_printf(seq, " %7d", count); 143362306a36Sopenharmony_ci else 143462306a36Sopenharmony_ci seq_puts(seq, " ."); 143562306a36Sopenharmony_ci if (i % 8 == 7) 143662306a36Sopenharmony_ci seq_putc(seq, '\n'); 143762306a36Sopenharmony_ci } 143862306a36Sopenharmony_ci seq_putc(seq, '\n'); 143962306a36Sopenharmony_ci mutex_unlock(&dcc->cmd_lock); 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci return 0; 144362306a36Sopenharmony_ci} 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ciint __init f2fs_init_sysfs(void) 144662306a36Sopenharmony_ci{ 144762306a36Sopenharmony_ci int ret; 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci kobject_set_name(&f2fs_kset.kobj, "f2fs"); 145062306a36Sopenharmony_ci f2fs_kset.kobj.parent = fs_kobj; 145162306a36Sopenharmony_ci ret = kset_register(&f2fs_kset); 145262306a36Sopenharmony_ci if (ret) 145362306a36Sopenharmony_ci return ret; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype, 145662306a36Sopenharmony_ci NULL, "features"); 145762306a36Sopenharmony_ci if (ret) 145862306a36Sopenharmony_ci goto put_kobject; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci f2fs_proc_root = proc_mkdir("fs/f2fs", NULL); 146162306a36Sopenharmony_ci if (!f2fs_proc_root) { 146262306a36Sopenharmony_ci ret = -ENOMEM; 146362306a36Sopenharmony_ci goto put_kobject; 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci return 0; 146762306a36Sopenharmony_ciput_kobject: 146862306a36Sopenharmony_ci kobject_put(&f2fs_feat); 146962306a36Sopenharmony_ci kset_unregister(&f2fs_kset); 147062306a36Sopenharmony_ci return ret; 147162306a36Sopenharmony_ci} 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_civoid f2fs_exit_sysfs(void) 147462306a36Sopenharmony_ci{ 147562306a36Sopenharmony_ci kobject_put(&f2fs_feat); 147662306a36Sopenharmony_ci kset_unregister(&f2fs_kset); 147762306a36Sopenharmony_ci remove_proc_entry("fs/f2fs", NULL); 147862306a36Sopenharmony_ci f2fs_proc_root = NULL; 147962306a36Sopenharmony_ci} 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ciint f2fs_register_sysfs(struct f2fs_sb_info *sbi) 148262306a36Sopenharmony_ci{ 148362306a36Sopenharmony_ci struct super_block *sb = sbi->sb; 148462306a36Sopenharmony_ci int err; 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci sbi->s_kobj.kset = &f2fs_kset; 148762306a36Sopenharmony_ci init_completion(&sbi->s_kobj_unregister); 148862306a36Sopenharmony_ci err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL, 148962306a36Sopenharmony_ci "%s", sb->s_id); 149062306a36Sopenharmony_ci if (err) 149162306a36Sopenharmony_ci goto put_sb_kobj; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci sbi->s_stat_kobj.kset = &f2fs_kset; 149462306a36Sopenharmony_ci init_completion(&sbi->s_stat_kobj_unregister); 149562306a36Sopenharmony_ci err = kobject_init_and_add(&sbi->s_stat_kobj, &f2fs_stat_ktype, 149662306a36Sopenharmony_ci &sbi->s_kobj, "stat"); 149762306a36Sopenharmony_ci if (err) 149862306a36Sopenharmony_ci goto put_stat_kobj; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci sbi->s_feature_list_kobj.kset = &f2fs_kset; 150162306a36Sopenharmony_ci init_completion(&sbi->s_feature_list_kobj_unregister); 150262306a36Sopenharmony_ci err = kobject_init_and_add(&sbi->s_feature_list_kobj, 150362306a36Sopenharmony_ci &f2fs_feature_list_ktype, 150462306a36Sopenharmony_ci &sbi->s_kobj, "feature_list"); 150562306a36Sopenharmony_ci if (err) 150662306a36Sopenharmony_ci goto put_feature_list_kobj; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); 150962306a36Sopenharmony_ci if (!sbi->s_proc) { 151062306a36Sopenharmony_ci err = -ENOMEM; 151162306a36Sopenharmony_ci goto put_feature_list_kobj; 151262306a36Sopenharmony_ci } 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci proc_create_single_data("segment_info", 0444, sbi->s_proc, 151562306a36Sopenharmony_ci segment_info_seq_show, sb); 151662306a36Sopenharmony_ci proc_create_single_data("segment_bits", 0444, sbi->s_proc, 151762306a36Sopenharmony_ci segment_bits_seq_show, sb); 151862306a36Sopenharmony_ci#ifdef CONFIG_F2FS_IOSTAT 151962306a36Sopenharmony_ci proc_create_single_data("iostat_info", 0444, sbi->s_proc, 152062306a36Sopenharmony_ci iostat_info_seq_show, sb); 152162306a36Sopenharmony_ci#endif 152262306a36Sopenharmony_ci proc_create_single_data("victim_bits", 0444, sbi->s_proc, 152362306a36Sopenharmony_ci victim_bits_seq_show, sb); 152462306a36Sopenharmony_ci proc_create_single_data("discard_plist_info", 0444, sbi->s_proc, 152562306a36Sopenharmony_ci discard_plist_seq_show, sb); 152662306a36Sopenharmony_ci return 0; 152762306a36Sopenharmony_ciput_feature_list_kobj: 152862306a36Sopenharmony_ci kobject_put(&sbi->s_feature_list_kobj); 152962306a36Sopenharmony_ci wait_for_completion(&sbi->s_feature_list_kobj_unregister); 153062306a36Sopenharmony_ciput_stat_kobj: 153162306a36Sopenharmony_ci kobject_put(&sbi->s_stat_kobj); 153262306a36Sopenharmony_ci wait_for_completion(&sbi->s_stat_kobj_unregister); 153362306a36Sopenharmony_ciput_sb_kobj: 153462306a36Sopenharmony_ci kobject_put(&sbi->s_kobj); 153562306a36Sopenharmony_ci wait_for_completion(&sbi->s_kobj_unregister); 153662306a36Sopenharmony_ci return err; 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_civoid f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) 154062306a36Sopenharmony_ci{ 154162306a36Sopenharmony_ci remove_proc_subtree(sbi->sb->s_id, f2fs_proc_root); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci kobject_put(&sbi->s_stat_kobj); 154462306a36Sopenharmony_ci wait_for_completion(&sbi->s_stat_kobj_unregister); 154562306a36Sopenharmony_ci kobject_put(&sbi->s_feature_list_kobj); 154662306a36Sopenharmony_ci wait_for_completion(&sbi->s_feature_list_kobj_unregister); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci kobject_put(&sbi->s_kobj); 154962306a36Sopenharmony_ci wait_for_completion(&sbi->s_kobj_unregister); 155062306a36Sopenharmony_ci} 1551