18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * f2fs sysfs interface 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 68c2ecf20Sopenharmony_ci * http://www.samsung.com/ 78c2ecf20Sopenharmony_ci * Copyright (c) 2017 Chao Yu <chao@kernel.org> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/compiler.h> 108c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 118c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h> 128c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 138c2ecf20Sopenharmony_ci#include <linux/unicode.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "f2fs.h" 168c2ecf20Sopenharmony_ci#include "segment.h" 178c2ecf20Sopenharmony_ci#include "gc.h" 188c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic struct proc_dir_entry *f2fs_proc_root; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* Sysfs support for f2fs */ 238c2ecf20Sopenharmony_cienum { 248c2ecf20Sopenharmony_ci GC_THREAD, /* struct f2fs_gc_thread */ 258c2ecf20Sopenharmony_ci SM_INFO, /* struct f2fs_sm_info */ 268c2ecf20Sopenharmony_ci DCC_INFO, /* struct discard_cmd_control */ 278c2ecf20Sopenharmony_ci NM_INFO, /* struct f2fs_nm_info */ 288c2ecf20Sopenharmony_ci F2FS_SBI, /* struct f2fs_sb_info */ 298c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 308c2ecf20Sopenharmony_ci STAT_INFO, /* struct f2fs_stat_info */ 318c2ecf20Sopenharmony_ci#endif 328c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 338c2ecf20Sopenharmony_ci FAULT_INFO_RATE, /* struct f2fs_fault_info */ 348c2ecf20Sopenharmony_ci FAULT_INFO_TYPE, /* struct f2fs_fault_info */ 358c2ecf20Sopenharmony_ci#endif 368c2ecf20Sopenharmony_ci RESERVED_BLOCKS, /* struct f2fs_sb_info */ 378c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 388c2ecf20Sopenharmony_ci F2FS_HOT_COLD_PARAMS, /* struct f2fs_hot_cold_params */ 398c2ecf20Sopenharmony_ci#endif 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct f2fs_attr { 438c2ecf20Sopenharmony_ci struct attribute attr; 448c2ecf20Sopenharmony_ci ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); 458c2ecf20Sopenharmony_ci ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, 468c2ecf20Sopenharmony_ci const char *, size_t); 478c2ecf20Sopenharmony_ci int struct_type; 488c2ecf20Sopenharmony_ci int offset; 498c2ecf20Sopenharmony_ci int id; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic ssize_t f2fs_sbi_show(struct f2fs_attr *a, 538c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci if (struct_type == GC_THREAD) 588c2ecf20Sopenharmony_ci return (unsigned char *)sbi->gc_thread; 598c2ecf20Sopenharmony_ci else if (struct_type == SM_INFO) 608c2ecf20Sopenharmony_ci return (unsigned char *)SM_I(sbi); 618c2ecf20Sopenharmony_ci else if (struct_type == DCC_INFO) 628c2ecf20Sopenharmony_ci return (unsigned char *)SM_I(sbi)->dcc_info; 638c2ecf20Sopenharmony_ci else if (struct_type == NM_INFO) 648c2ecf20Sopenharmony_ci return (unsigned char *)NM_I(sbi); 658c2ecf20Sopenharmony_ci else if (struct_type == F2FS_SBI || struct_type == RESERVED_BLOCKS) 668c2ecf20Sopenharmony_ci return (unsigned char *)sbi; 678c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 688c2ecf20Sopenharmony_ci else if (struct_type == F2FS_HOT_COLD_PARAMS) 698c2ecf20Sopenharmony_ci return (unsigned char *)&sbi->hot_cold_params; 708c2ecf20Sopenharmony_ci#endif 718c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 728c2ecf20Sopenharmony_ci else if (struct_type == FAULT_INFO_RATE || 738c2ecf20Sopenharmony_ci struct_type == FAULT_INFO_TYPE) 748c2ecf20Sopenharmony_ci return (unsigned char *)&F2FS_OPTION(sbi).fault_info; 758c2ecf20Sopenharmony_ci#endif 768c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 778c2ecf20Sopenharmony_ci else if (struct_type == STAT_INFO) 788c2ecf20Sopenharmony_ci return (unsigned char *)F2FS_STAT(sbi); 798c2ecf20Sopenharmony_ci#endif 808c2ecf20Sopenharmony_ci return NULL; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic ssize_t dirty_segments_show(struct f2fs_attr *a, 848c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", 878c2ecf20Sopenharmony_ci (unsigned long long)(dirty_segments(sbi))); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic ssize_t free_segments_show(struct f2fs_attr *a, 918c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", 948c2ecf20Sopenharmony_ci (unsigned long long)(free_segments(sbi))); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a, 988c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (!sb->s_bdev->bd_part) 1038c2ecf20Sopenharmony_ci return sprintf(buf, "0\n"); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", 1068c2ecf20Sopenharmony_ci (unsigned long long)(sbi->kbytes_written + 1078c2ecf20Sopenharmony_ci BD_PART_WRITTEN(sbi))); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic ssize_t features_show(struct f2fs_attr *a, 1118c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 1148c2ecf20Sopenharmony_ci int len = 0; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (!sb->s_bdev->bd_part) 1178c2ecf20Sopenharmony_ci return sprintf(buf, "0\n"); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (f2fs_sb_has_encrypt(sbi)) 1208c2ecf20Sopenharmony_ci len += scnprintf(buf, PAGE_SIZE - len, "%s", 1218c2ecf20Sopenharmony_ci "encryption"); 1228c2ecf20Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi)) 1238c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1248c2ecf20Sopenharmony_ci len ? ", " : "", "blkzoned"); 1258c2ecf20Sopenharmony_ci if (f2fs_sb_has_extra_attr(sbi)) 1268c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1278c2ecf20Sopenharmony_ci len ? ", " : "", "extra_attr"); 1288c2ecf20Sopenharmony_ci if (f2fs_sb_has_project_quota(sbi)) 1298c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1308c2ecf20Sopenharmony_ci len ? ", " : "", "projquota"); 1318c2ecf20Sopenharmony_ci if (f2fs_sb_has_inode_chksum(sbi)) 1328c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1338c2ecf20Sopenharmony_ci len ? ", " : "", "inode_checksum"); 1348c2ecf20Sopenharmony_ci if (f2fs_sb_has_flexible_inline_xattr(sbi)) 1358c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1368c2ecf20Sopenharmony_ci len ? ", " : "", "flexible_inline_xattr"); 1378c2ecf20Sopenharmony_ci if (f2fs_sb_has_quota_ino(sbi)) 1388c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1398c2ecf20Sopenharmony_ci len ? ", " : "", "quota_ino"); 1408c2ecf20Sopenharmony_ci if (f2fs_sb_has_inode_crtime(sbi)) 1418c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1428c2ecf20Sopenharmony_ci len ? ", " : "", "inode_crtime"); 1438c2ecf20Sopenharmony_ci if (f2fs_sb_has_lost_found(sbi)) 1448c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1458c2ecf20Sopenharmony_ci len ? ", " : "", "lost_found"); 1468c2ecf20Sopenharmony_ci if (f2fs_sb_has_verity(sbi)) 1478c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1488c2ecf20Sopenharmony_ci len ? ", " : "", "verity"); 1498c2ecf20Sopenharmony_ci if (f2fs_sb_has_sb_chksum(sbi)) 1508c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1518c2ecf20Sopenharmony_ci len ? ", " : "", "sb_checksum"); 1528c2ecf20Sopenharmony_ci if (f2fs_sb_has_casefold(sbi)) 1538c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1548c2ecf20Sopenharmony_ci len ? ", " : "", "casefold"); 1558c2ecf20Sopenharmony_ci if (f2fs_sb_has_compression(sbi)) 1568c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1578c2ecf20Sopenharmony_ci len ? ", " : "", "compression"); 1588c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", 1598c2ecf20Sopenharmony_ci len ? ", " : "", "pin_file"); 1608c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); 1618c2ecf20Sopenharmony_ci return len; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic ssize_t current_reserved_blocks_show(struct f2fs_attr *a, 1658c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sbi->current_reserved_blocks); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic ssize_t unusable_show(struct f2fs_attr *a, 1718c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci block_t unusable; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (test_opt(sbi, DISABLE_CHECKPOINT)) 1768c2ecf20Sopenharmony_ci unusable = sbi->unusable_block_count; 1778c2ecf20Sopenharmony_ci else 1788c2ecf20Sopenharmony_ci unusable = f2fs_get_unusable_blocks(sbi); 1798c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", (unsigned long long)unusable); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic ssize_t encoding_show(struct f2fs_attr *a, 1838c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 1868c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (f2fs_sb_has_casefold(sbi)) 1898c2ecf20Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "%s (%d.%d.%d)\n", 1908c2ecf20Sopenharmony_ci sb->s_encoding->charset, 1918c2ecf20Sopenharmony_ci (sb->s_encoding->version >> 16) & 0xff, 1928c2ecf20Sopenharmony_ci (sb->s_encoding->version >> 8) & 0xff, 1938c2ecf20Sopenharmony_ci sb->s_encoding->version & 0xff); 1948c2ecf20Sopenharmony_ci#endif 1958c2ecf20Sopenharmony_ci return sprintf(buf, "(none)"); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic ssize_t mounted_time_sec_show(struct f2fs_attr *a, 1998c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci return sprintf(buf, "%llu", SIT_I(sbi)->mounted_time); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 2058c2ecf20Sopenharmony_cistatic ssize_t moved_blocks_foreground_show(struct f2fs_attr *a, 2068c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct f2fs_stat_info *si = F2FS_STAT(sbi); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", 2118c2ecf20Sopenharmony_ci (unsigned long long)(si->tot_blks - 2128c2ecf20Sopenharmony_ci (si->bg_data_blks + si->bg_node_blks))); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic ssize_t moved_blocks_background_show(struct f2fs_attr *a, 2168c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct f2fs_stat_info *si = F2FS_STAT(sbi); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", 2218c2ecf20Sopenharmony_ci (unsigned long long)(si->bg_data_blks + si->bg_node_blks)); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic ssize_t avg_vblocks_show(struct f2fs_attr *a, 2258c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct f2fs_stat_info *si = F2FS_STAT(sbi); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci si->dirty_count = dirty_segments(sbi); 2308c2ecf20Sopenharmony_ci f2fs_update_sit_info(sbi); 2318c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", (unsigned long long)(si->avg_vblocks)); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci#endif 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic ssize_t main_blkaddr_show(struct f2fs_attr *a, 2368c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "%llu\n", 2398c2ecf20Sopenharmony_ci (unsigned long long)MAIN_BLKADDR(sbi)); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic ssize_t f2fs_sbi_show(struct f2fs_attr *a, 2438c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci unsigned char *ptr = NULL; 2468c2ecf20Sopenharmony_ci unsigned int *ui; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci ptr = __struct_ptr(sbi, a->struct_type); 2498c2ecf20Sopenharmony_ci if (!ptr) 2508c2ecf20Sopenharmony_ci return -EINVAL; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "extension_list")) { 2538c2ecf20Sopenharmony_ci __u8 (*extlist)[F2FS_EXTENSION_LEN] = 2548c2ecf20Sopenharmony_ci sbi->raw_super->extension_list; 2558c2ecf20Sopenharmony_ci int cold_count = le32_to_cpu(sbi->raw_super->extension_count); 2568c2ecf20Sopenharmony_ci int hot_count = sbi->raw_super->hot_ext_count; 2578c2ecf20Sopenharmony_ci int len = 0, i; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 2608c2ecf20Sopenharmony_ci "cold file extension:\n"); 2618c2ecf20Sopenharmony_ci for (i = 0; i < cold_count; i++) 2628c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", 2638c2ecf20Sopenharmony_ci extlist[i]); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 2668c2ecf20Sopenharmony_ci "hot file extension:\n"); 2678c2ecf20Sopenharmony_ci for (i = cold_count; i < cold_count + hot_count; i++) 2688c2ecf20Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", 2698c2ecf20Sopenharmony_ci extlist[i]); 2708c2ecf20Sopenharmony_ci return len; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci ui = (unsigned int *)(ptr + a->offset); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", *ui); 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic ssize_t __sbi_store(struct f2fs_attr *a, 2798c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, 2808c2ecf20Sopenharmony_ci const char *buf, size_t count) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci unsigned char *ptr; 2838c2ecf20Sopenharmony_ci unsigned long t; 2848c2ecf20Sopenharmony_ci unsigned int *ui; 2858c2ecf20Sopenharmony_ci ssize_t ret; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci ptr = __struct_ptr(sbi, a->struct_type); 2888c2ecf20Sopenharmony_ci if (!ptr) 2898c2ecf20Sopenharmony_ci return -EINVAL; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "extension_list")) { 2928c2ecf20Sopenharmony_ci const char *name = strim((char *)buf); 2938c2ecf20Sopenharmony_ci bool set = true, hot; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (!strncmp(name, "[h]", 3)) 2968c2ecf20Sopenharmony_ci hot = true; 2978c2ecf20Sopenharmony_ci else if (!strncmp(name, "[c]", 3)) 2988c2ecf20Sopenharmony_ci hot = false; 2998c2ecf20Sopenharmony_ci else 3008c2ecf20Sopenharmony_ci return -EINVAL; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci name += 3; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (*name == '!') { 3058c2ecf20Sopenharmony_ci name++; 3068c2ecf20Sopenharmony_ci set = false; 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (strlen(name) >= F2FS_EXTENSION_LEN) 3108c2ecf20Sopenharmony_ci return -EINVAL; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci down_write(&sbi->sb_lock); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci ret = f2fs_update_extension_list(sbi, name, hot, set); 3158c2ecf20Sopenharmony_ci if (ret) 3168c2ecf20Sopenharmony_ci goto out; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci ret = f2fs_commit_super(sbi, false); 3198c2ecf20Sopenharmony_ci if (ret) 3208c2ecf20Sopenharmony_ci f2fs_update_extension_list(sbi, name, hot, !set); 3218c2ecf20Sopenharmony_ciout: 3228c2ecf20Sopenharmony_ci up_write(&sbi->sb_lock); 3238c2ecf20Sopenharmony_ci return ret ? ret : count; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci ui = (unsigned int *)(ptr + a->offset); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci ret = kstrtoul(skip_spaces(buf), 0, &t); 3298c2ecf20Sopenharmony_ci if (ret < 0) 3308c2ecf20Sopenharmony_ci return ret; 3318c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 3328c2ecf20Sopenharmony_ci if (a->struct_type == FAULT_INFO_TYPE) { 3338c2ecf20Sopenharmony_ci if (f2fs_build_fault_attr(sbi, 0, t)) 3348c2ecf20Sopenharmony_ci return -EINVAL; 3358c2ecf20Sopenharmony_ci return count; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci if (a->struct_type == FAULT_INFO_RATE) { 3388c2ecf20Sopenharmony_ci if (f2fs_build_fault_attr(sbi, t, 0)) 3398c2ecf20Sopenharmony_ci return -EINVAL; 3408c2ecf20Sopenharmony_ci return count; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci#endif 3438c2ecf20Sopenharmony_ci if (a->struct_type == RESERVED_BLOCKS) { 3448c2ecf20Sopenharmony_ci spin_lock(&sbi->stat_lock); 3458c2ecf20Sopenharmony_ci if (t > (unsigned long)(sbi->user_block_count - 3468c2ecf20Sopenharmony_ci F2FS_OPTION(sbi).root_reserved_blocks - 3478c2ecf20Sopenharmony_ci sbi->blocks_per_seg * 3488c2ecf20Sopenharmony_ci SM_I(sbi)->additional_reserved_segments)) { 3498c2ecf20Sopenharmony_ci spin_unlock(&sbi->stat_lock); 3508c2ecf20Sopenharmony_ci return -EINVAL; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci *ui = t; 3538c2ecf20Sopenharmony_ci sbi->current_reserved_blocks = min(sbi->reserved_blocks, 3548c2ecf20Sopenharmony_ci sbi->user_block_count - valid_user_blocks(sbi)); 3558c2ecf20Sopenharmony_ci spin_unlock(&sbi->stat_lock); 3568c2ecf20Sopenharmony_ci return count; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "discard_granularity")) { 3608c2ecf20Sopenharmony_ci if (t == 0 || t > MAX_PLIST_NUM) 3618c2ecf20Sopenharmony_ci return -EINVAL; 3628c2ecf20Sopenharmony_ci if (t == *ui) 3638c2ecf20Sopenharmony_ci return count; 3648c2ecf20Sopenharmony_ci *ui = t; 3658c2ecf20Sopenharmony_ci return count; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "migration_granularity")) { 3698c2ecf20Sopenharmony_ci if (t == 0 || t > sbi->segs_per_sec) 3708c2ecf20Sopenharmony_ci return -EINVAL; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "trim_sections")) 3748c2ecf20Sopenharmony_ci return -EINVAL; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "gc_urgent")) { 3778c2ecf20Sopenharmony_ci if (t == 0) { 3788c2ecf20Sopenharmony_ci sbi->gc_mode = GC_NORMAL; 3798c2ecf20Sopenharmony_ci } else if (t == 1) { 3808c2ecf20Sopenharmony_ci sbi->gc_mode = GC_URGENT_HIGH; 3818c2ecf20Sopenharmony_ci if (sbi->gc_thread) { 3828c2ecf20Sopenharmony_ci sbi->gc_thread->gc_wake = 1; 3838c2ecf20Sopenharmony_ci wake_up_interruptible_all( 3848c2ecf20Sopenharmony_ci &sbi->gc_thread->gc_wait_queue_head); 3858c2ecf20Sopenharmony_ci wake_up_discard_thread(sbi, true); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci } else if (t == 2) { 3888c2ecf20Sopenharmony_ci sbi->gc_mode = GC_URGENT_LOW; 3898c2ecf20Sopenharmony_ci } else { 3908c2ecf20Sopenharmony_ci return -EINVAL; 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci return count; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "gc_idle")) { 3958c2ecf20Sopenharmony_ci if (t == GC_IDLE_CB) { 3968c2ecf20Sopenharmony_ci sbi->gc_mode = GC_IDLE_CB; 3978c2ecf20Sopenharmony_ci } else if (t == GC_IDLE_GREEDY) { 3988c2ecf20Sopenharmony_ci sbi->gc_mode = GC_IDLE_GREEDY; 3998c2ecf20Sopenharmony_ci } else if (t == GC_IDLE_AT) { 4008c2ecf20Sopenharmony_ci if (!sbi->am.atgc_enabled) 4018c2ecf20Sopenharmony_ci return -EINVAL; 4028c2ecf20Sopenharmony_ci sbi->gc_mode = GC_IDLE_AT; 4038c2ecf20Sopenharmony_ci } else { 4048c2ecf20Sopenharmony_ci sbi->gc_mode = GC_NORMAL; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci return count; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "iostat_enable")) { 4108c2ecf20Sopenharmony_ci sbi->iostat_enable = !!t; 4118c2ecf20Sopenharmony_ci if (!sbi->iostat_enable) 4128c2ecf20Sopenharmony_ci f2fs_reset_iostat(sbi); 4138c2ecf20Sopenharmony_ci return count; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci if (!strcmp(a->attr.name, "iostat_period_ms")) { 4178c2ecf20Sopenharmony_ci if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS) 4188c2ecf20Sopenharmony_ci return -EINVAL; 4198c2ecf20Sopenharmony_ci spin_lock_irq(&sbi->iostat_lock); 4208c2ecf20Sopenharmony_ci sbi->iostat_period_ms = (unsigned int)t; 4218c2ecf20Sopenharmony_ci spin_unlock_irq(&sbi->iostat_lock); 4228c2ecf20Sopenharmony_ci return count; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci *ui = (unsigned int)t; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci return count; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic ssize_t f2fs_sbi_store(struct f2fs_attr *a, 4318c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, 4328c2ecf20Sopenharmony_ci const char *buf, size_t count) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci ssize_t ret; 4358c2ecf20Sopenharmony_ci bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") || 4368c2ecf20Sopenharmony_ci a->struct_type == GC_THREAD); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (gc_entry) { 4398c2ecf20Sopenharmony_ci if (!down_read_trylock(&sbi->sb->s_umount)) 4408c2ecf20Sopenharmony_ci return -EAGAIN; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci ret = __sbi_store(a, sbi, buf, count); 4438c2ecf20Sopenharmony_ci if (gc_entry) 4448c2ecf20Sopenharmony_ci up_read(&sbi->sb->s_umount); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci return ret; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic ssize_t f2fs_attr_show(struct kobject *kobj, 4508c2ecf20Sopenharmony_ci struct attribute *attr, char *buf) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 4538c2ecf20Sopenharmony_ci s_kobj); 4548c2ecf20Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci return a->show ? a->show(a, sbi, buf) : 0; 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_cistatic ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr, 4608c2ecf20Sopenharmony_ci const char *buf, size_t len) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 4638c2ecf20Sopenharmony_ci s_kobj); 4648c2ecf20Sopenharmony_ci struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci return a->store ? a->store(a, sbi, buf, len) : 0; 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic void f2fs_sb_release(struct kobject *kobj) 4708c2ecf20Sopenharmony_ci{ 4718c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, 4728c2ecf20Sopenharmony_ci s_kobj); 4738c2ecf20Sopenharmony_ci complete(&sbi->s_kobj_unregister); 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_cienum feat_id { 4778c2ecf20Sopenharmony_ci FEAT_CRYPTO = 0, 4788c2ecf20Sopenharmony_ci FEAT_BLKZONED, 4798c2ecf20Sopenharmony_ci FEAT_ATOMIC_WRITE, 4808c2ecf20Sopenharmony_ci FEAT_EXTRA_ATTR, 4818c2ecf20Sopenharmony_ci FEAT_PROJECT_QUOTA, 4828c2ecf20Sopenharmony_ci FEAT_INODE_CHECKSUM, 4838c2ecf20Sopenharmony_ci FEAT_FLEXIBLE_INLINE_XATTR, 4848c2ecf20Sopenharmony_ci FEAT_QUOTA_INO, 4858c2ecf20Sopenharmony_ci FEAT_INODE_CRTIME, 4868c2ecf20Sopenharmony_ci FEAT_LOST_FOUND, 4878c2ecf20Sopenharmony_ci FEAT_VERITY, 4888c2ecf20Sopenharmony_ci FEAT_SB_CHECKSUM, 4898c2ecf20Sopenharmony_ci FEAT_CASEFOLD, 4908c2ecf20Sopenharmony_ci FEAT_COMPRESSION, 4918c2ecf20Sopenharmony_ci FEAT_TEST_DUMMY_ENCRYPTION_V2, 4928c2ecf20Sopenharmony_ci}; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic ssize_t f2fs_feature_show(struct f2fs_attr *a, 4958c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi, char *buf) 4968c2ecf20Sopenharmony_ci{ 4978c2ecf20Sopenharmony_ci switch (a->id) { 4988c2ecf20Sopenharmony_ci case FEAT_CRYPTO: 4998c2ecf20Sopenharmony_ci case FEAT_BLKZONED: 5008c2ecf20Sopenharmony_ci case FEAT_ATOMIC_WRITE: 5018c2ecf20Sopenharmony_ci case FEAT_EXTRA_ATTR: 5028c2ecf20Sopenharmony_ci case FEAT_PROJECT_QUOTA: 5038c2ecf20Sopenharmony_ci case FEAT_INODE_CHECKSUM: 5048c2ecf20Sopenharmony_ci case FEAT_FLEXIBLE_INLINE_XATTR: 5058c2ecf20Sopenharmony_ci case FEAT_QUOTA_INO: 5068c2ecf20Sopenharmony_ci case FEAT_INODE_CRTIME: 5078c2ecf20Sopenharmony_ci case FEAT_LOST_FOUND: 5088c2ecf20Sopenharmony_ci case FEAT_VERITY: 5098c2ecf20Sopenharmony_ci case FEAT_SB_CHECKSUM: 5108c2ecf20Sopenharmony_ci case FEAT_CASEFOLD: 5118c2ecf20Sopenharmony_ci case FEAT_COMPRESSION: 5128c2ecf20Sopenharmony_ci case FEAT_TEST_DUMMY_ENCRYPTION_V2: 5138c2ecf20Sopenharmony_ci return sprintf(buf, "supported\n"); 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci return 0; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ 5198c2ecf20Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##_name = { \ 5208c2ecf20Sopenharmony_ci .attr = {.name = __stringify(_name), .mode = _mode }, \ 5218c2ecf20Sopenharmony_ci .show = _show, \ 5228c2ecf20Sopenharmony_ci .store = _store, \ 5238c2ecf20Sopenharmony_ci .struct_type = _struct_type, \ 5248c2ecf20Sopenharmony_ci .offset = _offset \ 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci#define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ 5288c2ecf20Sopenharmony_ci F2FS_ATTR_OFFSET(struct_type, name, 0644, \ 5298c2ecf20Sopenharmony_ci f2fs_sbi_show, f2fs_sbi_store, \ 5308c2ecf20Sopenharmony_ci offsetof(struct struct_name, elname)) 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci#define F2FS_GENERAL_RO_ATTR(name) \ 5338c2ecf20Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL) 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci#define F2FS_FEATURE_RO_ATTR(_name, _id) \ 5368c2ecf20Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##_name = { \ 5378c2ecf20Sopenharmony_ci .attr = {.name = __stringify(_name), .mode = 0444 }, \ 5388c2ecf20Sopenharmony_ci .show = f2fs_feature_show, \ 5398c2ecf20Sopenharmony_ci .id = _id, \ 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci#define F2FS_STAT_ATTR(_struct_type, _struct_name, _name, _elname) \ 5438c2ecf20Sopenharmony_cistatic struct f2fs_attr f2fs_attr_##_name = { \ 5448c2ecf20Sopenharmony_ci .attr = {.name = __stringify(_name), .mode = 0444 }, \ 5458c2ecf20Sopenharmony_ci .show = f2fs_sbi_show, \ 5468c2ecf20Sopenharmony_ci .struct_type = _struct_type, \ 5478c2ecf20Sopenharmony_ci .offset = offsetof(struct _struct_name, _elname), \ 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ciF2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time, 5518c2ecf20Sopenharmony_ci urgent_sleep_time); 5528c2ecf20Sopenharmony_ciF2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time); 5538c2ecf20Sopenharmony_ciF2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); 5548c2ecf20Sopenharmony_ciF2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); 5558c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode); 5568c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode); 5578c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); 5588c2ecf20Sopenharmony_ciF2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards); 5598c2ecf20Sopenharmony_ciF2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity); 5608c2ecf20Sopenharmony_ciF2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_type, discard_type); 5618c2ecf20Sopenharmony_ciF2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, reserved_blocks, reserved_blocks); 5628c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections); 5638c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); 5648c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); 5658c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks); 5668c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_seq_blocks, min_seq_blocks); 5678c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_hot_blocks, min_hot_blocks); 5688c2ecf20Sopenharmony_ciF2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ssr_sections, min_ssr_sections); 5698c2ecf20Sopenharmony_ciF2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh); 5708c2ecf20Sopenharmony_ciF2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages); 5718c2ecf20Sopenharmony_ciF2FS_RW_ATTR(NM_INFO, f2fs_nm_info, dirty_nats_ratio, dirty_nats_ratio); 5728c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); 5738c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, migration_granularity, migration_granularity); 5748c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); 5758c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); 5768c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); 5778c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval, 5788c2ecf20Sopenharmony_ci interval_time[DISCARD_TIME]); 5798c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]); 5808c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, 5818c2ecf20Sopenharmony_ci umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]); 5828c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); 5838c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_period_ms, iostat_period_ms); 5848c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra); 5858c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold); 5868c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list); 5878c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 5888c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 5898c2ecf20Sopenharmony_ci hc_hot_data_lower_limit, hot_data_lower_limit); 5908c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 5918c2ecf20Sopenharmony_ci hc_hot_data_waterline, hot_data_waterline); 5928c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 5938c2ecf20Sopenharmony_ci hc_warm_data_lower_limit, warm_data_lower_limit); 5948c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 5958c2ecf20Sopenharmony_ci hc_warm_data_waterline, warm_data_waterline); 5968c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 5978c2ecf20Sopenharmony_ci hc_hot_node_lower_limit, hot_node_lower_limit); 5988c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 5998c2ecf20Sopenharmony_ci hc_hot_node_waterline, hot_node_waterline); 6008c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 6018c2ecf20Sopenharmony_ci hc_warm_node_lower_limit, warm_node_lower_limit); 6028c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 6038c2ecf20Sopenharmony_ci hc_warm_node_waterline, warm_node_waterline); 6048c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_HOT_COLD_PARAMS, f2fs_hot_cold_params, 6058c2ecf20Sopenharmony_ci hc_enable, enable); 6068c2ecf20Sopenharmony_ci#endif 6078c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 6088c2ecf20Sopenharmony_ciF2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate); 6098c2ecf20Sopenharmony_ciF2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type); 6108c2ecf20Sopenharmony_ci#endif 6118c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag); 6128c2ecf20Sopenharmony_ciF2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag); 6138c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(dirty_segments); 6148c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(free_segments); 6158c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(lifetime_write_kbytes); 6168c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(features); 6178c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(current_reserved_blocks); 6188c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(unusable); 6198c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(encoding); 6208c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(mounted_time_sec); 6218c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(main_blkaddr); 6228c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 6238c2ecf20Sopenharmony_ciF2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, cp_foreground_calls, cp_count); 6248c2ecf20Sopenharmony_ciF2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, cp_background_calls, bg_cp_count); 6258c2ecf20Sopenharmony_ciF2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, gc_foreground_calls, call_count); 6268c2ecf20Sopenharmony_ciF2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, gc_background_calls, bg_gc); 6278c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(moved_blocks_background); 6288c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(moved_blocks_foreground); 6298c2ecf20Sopenharmony_ciF2FS_GENERAL_RO_ATTR(avg_vblocks); 6308c2ecf20Sopenharmony_ci#endif 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 6338c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO); 6348c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2, FEAT_TEST_DUMMY_ENCRYPTION_V2); 6358c2ecf20Sopenharmony_ci#endif 6368c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 6378c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(block_zoned, FEAT_BLKZONED); 6388c2ecf20Sopenharmony_ci#endif 6398c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(atomic_write, FEAT_ATOMIC_WRITE); 6408c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(extra_attr, FEAT_EXTRA_ATTR); 6418c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA); 6428c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM); 6438c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); 6448c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); 6458c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); 6468c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); 6478c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_VERITY 6488c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY); 6498c2ecf20Sopenharmony_ci#endif 6508c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM); 6518c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 6528c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(casefold, FEAT_CASEFOLD); 6538c2ecf20Sopenharmony_ci#endif 6548c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 6558c2ecf20Sopenharmony_ciF2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION); 6568c2ecf20Sopenharmony_ci#endif 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci#define ATTR_LIST(name) (&f2fs_attr_##name.attr) 6598c2ecf20Sopenharmony_cistatic struct attribute *f2fs_attrs[] = { 6608c2ecf20Sopenharmony_ci ATTR_LIST(gc_urgent_sleep_time), 6618c2ecf20Sopenharmony_ci ATTR_LIST(gc_min_sleep_time), 6628c2ecf20Sopenharmony_ci ATTR_LIST(gc_max_sleep_time), 6638c2ecf20Sopenharmony_ci ATTR_LIST(gc_no_gc_sleep_time), 6648c2ecf20Sopenharmony_ci ATTR_LIST(gc_idle), 6658c2ecf20Sopenharmony_ci ATTR_LIST(gc_urgent), 6668c2ecf20Sopenharmony_ci ATTR_LIST(reclaim_segments), 6678c2ecf20Sopenharmony_ci ATTR_LIST(main_blkaddr), 6688c2ecf20Sopenharmony_ci ATTR_LIST(max_small_discards), 6698c2ecf20Sopenharmony_ci ATTR_LIST(discard_granularity), 6708c2ecf20Sopenharmony_ci ATTR_LIST(discard_type), 6718c2ecf20Sopenharmony_ci ATTR_LIST(batched_trim_sections), 6728c2ecf20Sopenharmony_ci ATTR_LIST(ipu_policy), 6738c2ecf20Sopenharmony_ci ATTR_LIST(min_ipu_util), 6748c2ecf20Sopenharmony_ci ATTR_LIST(min_fsync_blocks), 6758c2ecf20Sopenharmony_ci ATTR_LIST(min_seq_blocks), 6768c2ecf20Sopenharmony_ci ATTR_LIST(min_hot_blocks), 6778c2ecf20Sopenharmony_ci ATTR_LIST(min_ssr_sections), 6788c2ecf20Sopenharmony_ci ATTR_LIST(max_victim_search), 6798c2ecf20Sopenharmony_ci ATTR_LIST(migration_granularity), 6808c2ecf20Sopenharmony_ci ATTR_LIST(dir_level), 6818c2ecf20Sopenharmony_ci ATTR_LIST(ram_thresh), 6828c2ecf20Sopenharmony_ci ATTR_LIST(ra_nid_pages), 6838c2ecf20Sopenharmony_ci ATTR_LIST(dirty_nats_ratio), 6848c2ecf20Sopenharmony_ci ATTR_LIST(cp_interval), 6858c2ecf20Sopenharmony_ci ATTR_LIST(idle_interval), 6868c2ecf20Sopenharmony_ci ATTR_LIST(discard_idle_interval), 6878c2ecf20Sopenharmony_ci ATTR_LIST(gc_idle_interval), 6888c2ecf20Sopenharmony_ci ATTR_LIST(umount_discard_timeout), 6898c2ecf20Sopenharmony_ci ATTR_LIST(iostat_enable), 6908c2ecf20Sopenharmony_ci ATTR_LIST(iostat_period_ms), 6918c2ecf20Sopenharmony_ci ATTR_LIST(readdir_ra), 6928c2ecf20Sopenharmony_ci ATTR_LIST(gc_pin_file_thresh), 6938c2ecf20Sopenharmony_ci ATTR_LIST(extension_list), 6948c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FAULT_INJECTION 6958c2ecf20Sopenharmony_ci ATTR_LIST(inject_rate), 6968c2ecf20Sopenharmony_ci ATTR_LIST(inject_type), 6978c2ecf20Sopenharmony_ci#endif 6988c2ecf20Sopenharmony_ci ATTR_LIST(data_io_flag), 6998c2ecf20Sopenharmony_ci ATTR_LIST(node_io_flag), 7008c2ecf20Sopenharmony_ci ATTR_LIST(dirty_segments), 7018c2ecf20Sopenharmony_ci ATTR_LIST(free_segments), 7028c2ecf20Sopenharmony_ci ATTR_LIST(unusable), 7038c2ecf20Sopenharmony_ci ATTR_LIST(lifetime_write_kbytes), 7048c2ecf20Sopenharmony_ci ATTR_LIST(features), 7058c2ecf20Sopenharmony_ci ATTR_LIST(reserved_blocks), 7068c2ecf20Sopenharmony_ci ATTR_LIST(current_reserved_blocks), 7078c2ecf20Sopenharmony_ci ATTR_LIST(encoding), 7088c2ecf20Sopenharmony_ci ATTR_LIST(mounted_time_sec), 7098c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_STAT_FS 7108c2ecf20Sopenharmony_ci ATTR_LIST(cp_foreground_calls), 7118c2ecf20Sopenharmony_ci ATTR_LIST(cp_background_calls), 7128c2ecf20Sopenharmony_ci ATTR_LIST(gc_foreground_calls), 7138c2ecf20Sopenharmony_ci ATTR_LIST(gc_background_calls), 7148c2ecf20Sopenharmony_ci ATTR_LIST(moved_blocks_foreground), 7158c2ecf20Sopenharmony_ci ATTR_LIST(moved_blocks_background), 7168c2ecf20Sopenharmony_ci ATTR_LIST(avg_vblocks), 7178c2ecf20Sopenharmony_ci#endif 7188c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 7198c2ecf20Sopenharmony_ci ATTR_LIST(hc_hot_data_lower_limit), 7208c2ecf20Sopenharmony_ci ATTR_LIST(hc_hot_data_waterline), 7218c2ecf20Sopenharmony_ci ATTR_LIST(hc_warm_data_lower_limit), 7228c2ecf20Sopenharmony_ci ATTR_LIST(hc_warm_data_waterline), 7238c2ecf20Sopenharmony_ci ATTR_LIST(hc_hot_node_lower_limit), 7248c2ecf20Sopenharmony_ci ATTR_LIST(hc_hot_node_waterline), 7258c2ecf20Sopenharmony_ci ATTR_LIST(hc_warm_node_lower_limit), 7268c2ecf20Sopenharmony_ci ATTR_LIST(hc_warm_node_waterline), 7278c2ecf20Sopenharmony_ci ATTR_LIST(hc_enable), 7288c2ecf20Sopenharmony_ci#endif 7298c2ecf20Sopenharmony_ci NULL, 7308c2ecf20Sopenharmony_ci}; 7318c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(f2fs); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_cistatic struct attribute *f2fs_feat_attrs[] = { 7348c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 7358c2ecf20Sopenharmony_ci ATTR_LIST(encryption), 7368c2ecf20Sopenharmony_ci ATTR_LIST(test_dummy_encryption_v2), 7378c2ecf20Sopenharmony_ci#endif 7388c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 7398c2ecf20Sopenharmony_ci ATTR_LIST(block_zoned), 7408c2ecf20Sopenharmony_ci#endif 7418c2ecf20Sopenharmony_ci ATTR_LIST(atomic_write), 7428c2ecf20Sopenharmony_ci ATTR_LIST(extra_attr), 7438c2ecf20Sopenharmony_ci ATTR_LIST(project_quota), 7448c2ecf20Sopenharmony_ci ATTR_LIST(inode_checksum), 7458c2ecf20Sopenharmony_ci ATTR_LIST(flexible_inline_xattr), 7468c2ecf20Sopenharmony_ci ATTR_LIST(quota_ino), 7478c2ecf20Sopenharmony_ci ATTR_LIST(inode_crtime), 7488c2ecf20Sopenharmony_ci ATTR_LIST(lost_found), 7498c2ecf20Sopenharmony_ci#ifdef CONFIG_FS_VERITY 7508c2ecf20Sopenharmony_ci ATTR_LIST(verity), 7518c2ecf20Sopenharmony_ci#endif 7528c2ecf20Sopenharmony_ci ATTR_LIST(sb_checksum), 7538c2ecf20Sopenharmony_ci#ifdef CONFIG_UNICODE 7548c2ecf20Sopenharmony_ci ATTR_LIST(casefold), 7558c2ecf20Sopenharmony_ci#endif 7568c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 7578c2ecf20Sopenharmony_ci ATTR_LIST(compression), 7588c2ecf20Sopenharmony_ci#endif 7598c2ecf20Sopenharmony_ci NULL, 7608c2ecf20Sopenharmony_ci}; 7618c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(f2fs_feat); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_cistatic const struct sysfs_ops f2fs_attr_ops = { 7648c2ecf20Sopenharmony_ci .show = f2fs_attr_show, 7658c2ecf20Sopenharmony_ci .store = f2fs_attr_store, 7668c2ecf20Sopenharmony_ci}; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_cistatic struct kobj_type f2fs_sb_ktype = { 7698c2ecf20Sopenharmony_ci .default_groups = f2fs_groups, 7708c2ecf20Sopenharmony_ci .sysfs_ops = &f2fs_attr_ops, 7718c2ecf20Sopenharmony_ci .release = f2fs_sb_release, 7728c2ecf20Sopenharmony_ci}; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_cistatic struct kobj_type f2fs_ktype = { 7758c2ecf20Sopenharmony_ci .sysfs_ops = &f2fs_attr_ops, 7768c2ecf20Sopenharmony_ci}; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic struct kset f2fs_kset = { 7798c2ecf20Sopenharmony_ci .kobj = {.ktype = &f2fs_ktype}, 7808c2ecf20Sopenharmony_ci}; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_cistatic struct kobj_type f2fs_feat_ktype = { 7838c2ecf20Sopenharmony_ci .default_groups = f2fs_feat_groups, 7848c2ecf20Sopenharmony_ci .sysfs_ops = &f2fs_attr_ops, 7858c2ecf20Sopenharmony_ci}; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_cistatic struct kobject f2fs_feat = { 7888c2ecf20Sopenharmony_ci .kset = &f2fs_kset, 7898c2ecf20Sopenharmony_ci}; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_cistatic int __maybe_unused segment_info_seq_show(struct seq_file *seq, 7928c2ecf20Sopenharmony_ci void *offset) 7938c2ecf20Sopenharmony_ci{ 7948c2ecf20Sopenharmony_ci struct super_block *sb = seq->private; 7958c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 7968c2ecf20Sopenharmony_ci unsigned int total_segs = 7978c2ecf20Sopenharmony_ci le32_to_cpu(sbi->raw_super->segment_count_main); 7988c2ecf20Sopenharmony_ci int i; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci seq_puts(seq, "format: segment_type|valid_blocks\n" 8018c2ecf20Sopenharmony_ci "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n"); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci for (i = 0; i < total_segs; i++) { 8048c2ecf20Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, i); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci if ((i % 10) == 0) 8078c2ecf20Sopenharmony_ci seq_printf(seq, "%-10d", i); 8088c2ecf20Sopenharmony_ci seq_printf(seq, "%d|%-3u", se->type, se->valid_blocks); 8098c2ecf20Sopenharmony_ci if ((i % 10) == 9 || i == (total_segs - 1)) 8108c2ecf20Sopenharmony_ci seq_putc(seq, '\n'); 8118c2ecf20Sopenharmony_ci else 8128c2ecf20Sopenharmony_ci seq_putc(seq, ' '); 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci return 0; 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic int __maybe_unused segment_bits_seq_show(struct seq_file *seq, 8198c2ecf20Sopenharmony_ci void *offset) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci struct super_block *sb = seq->private; 8228c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 8238c2ecf20Sopenharmony_ci unsigned int total_segs = 8248c2ecf20Sopenharmony_ci le32_to_cpu(sbi->raw_super->segment_count_main); 8258c2ecf20Sopenharmony_ci int i, j; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci seq_puts(seq, "format: segment_type|valid_blocks|bitmaps\n" 8288c2ecf20Sopenharmony_ci "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n"); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci for (i = 0; i < total_segs; i++) { 8318c2ecf20Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, i); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci seq_printf(seq, "%-10d", i); 8348c2ecf20Sopenharmony_ci seq_printf(seq, "%d|%-3u|", se->type, se->valid_blocks); 8358c2ecf20Sopenharmony_ci for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++) 8368c2ecf20Sopenharmony_ci seq_printf(seq, " %.2x", se->cur_valid_map[j]); 8378c2ecf20Sopenharmony_ci seq_putc(seq, '\n'); 8388c2ecf20Sopenharmony_ci } 8398c2ecf20Sopenharmony_ci return 0; 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_civoid f2fs_record_iostat(struct f2fs_sb_info *sbi) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci unsigned long long iostat_diff[NR_IO_TYPE]; 8458c2ecf20Sopenharmony_ci int i; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci if (time_is_after_jiffies(sbi->iostat_next_period)) 8488c2ecf20Sopenharmony_ci return; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci /* Need double check under the lock */ 8518c2ecf20Sopenharmony_ci spin_lock(&sbi->iostat_lock); 8528c2ecf20Sopenharmony_ci if (time_is_after_jiffies(sbi->iostat_next_period)) { 8538c2ecf20Sopenharmony_ci spin_unlock(&sbi->iostat_lock); 8548c2ecf20Sopenharmony_ci return; 8558c2ecf20Sopenharmony_ci } 8568c2ecf20Sopenharmony_ci sbi->iostat_next_period = jiffies + 8578c2ecf20Sopenharmony_ci msecs_to_jiffies(sbi->iostat_period_ms); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci for (i = 0; i < NR_IO_TYPE; i++) { 8608c2ecf20Sopenharmony_ci iostat_diff[i] = sbi->rw_iostat[i] - 8618c2ecf20Sopenharmony_ci sbi->prev_rw_iostat[i]; 8628c2ecf20Sopenharmony_ci sbi->prev_rw_iostat[i] = sbi->rw_iostat[i]; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci spin_unlock(&sbi->iostat_lock); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci trace_f2fs_iostat(sbi, iostat_diff); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic int __maybe_unused iostat_info_seq_show(struct seq_file *seq, 8708c2ecf20Sopenharmony_ci void *offset) 8718c2ecf20Sopenharmony_ci{ 8728c2ecf20Sopenharmony_ci struct super_block *sb = seq->private; 8738c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 8748c2ecf20Sopenharmony_ci time64_t now = ktime_get_real_seconds(); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci if (!sbi->iostat_enable) 8778c2ecf20Sopenharmony_ci return 0; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci seq_printf(seq, "time: %-16llu\n", now); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* print app write IOs */ 8828c2ecf20Sopenharmony_ci seq_puts(seq, "[WRITE]\n"); 8838c2ecf20Sopenharmony_ci seq_printf(seq, "app buffered: %-16llu\n", 8848c2ecf20Sopenharmony_ci sbi->rw_iostat[APP_BUFFERED_IO]); 8858c2ecf20Sopenharmony_ci seq_printf(seq, "app direct: %-16llu\n", 8868c2ecf20Sopenharmony_ci sbi->rw_iostat[APP_DIRECT_IO]); 8878c2ecf20Sopenharmony_ci seq_printf(seq, "app mapped: %-16llu\n", 8888c2ecf20Sopenharmony_ci sbi->rw_iostat[APP_MAPPED_IO]); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* print fs write IOs */ 8918c2ecf20Sopenharmony_ci seq_printf(seq, "fs data: %-16llu\n", 8928c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_DATA_IO]); 8938c2ecf20Sopenharmony_ci seq_printf(seq, "fs node: %-16llu\n", 8948c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_NODE_IO]); 8958c2ecf20Sopenharmony_ci seq_printf(seq, "fs meta: %-16llu\n", 8968c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_META_IO]); 8978c2ecf20Sopenharmony_ci seq_printf(seq, "fs gc data: %-16llu\n", 8988c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_GC_DATA_IO]); 8998c2ecf20Sopenharmony_ci seq_printf(seq, "fs gc node: %-16llu\n", 9008c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_GC_NODE_IO]); 9018c2ecf20Sopenharmony_ci seq_printf(seq, "fs cp data: %-16llu\n", 9028c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_CP_DATA_IO]); 9038c2ecf20Sopenharmony_ci seq_printf(seq, "fs cp node: %-16llu\n", 9048c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_CP_NODE_IO]); 9058c2ecf20Sopenharmony_ci seq_printf(seq, "fs cp meta: %-16llu\n", 9068c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_CP_META_IO]); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* print app read IOs */ 9098c2ecf20Sopenharmony_ci seq_puts(seq, "[READ]\n"); 9108c2ecf20Sopenharmony_ci seq_printf(seq, "app buffered: %-16llu\n", 9118c2ecf20Sopenharmony_ci sbi->rw_iostat[APP_BUFFERED_READ_IO]); 9128c2ecf20Sopenharmony_ci seq_printf(seq, "app direct: %-16llu\n", 9138c2ecf20Sopenharmony_ci sbi->rw_iostat[APP_DIRECT_READ_IO]); 9148c2ecf20Sopenharmony_ci seq_printf(seq, "app mapped: %-16llu\n", 9158c2ecf20Sopenharmony_ci sbi->rw_iostat[APP_MAPPED_READ_IO]); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci /* print fs read IOs */ 9188c2ecf20Sopenharmony_ci seq_printf(seq, "fs data: %-16llu\n", 9198c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_DATA_READ_IO]); 9208c2ecf20Sopenharmony_ci seq_printf(seq, "fs gc data: %-16llu\n", 9218c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_GDATA_READ_IO]); 9228c2ecf20Sopenharmony_ci seq_printf(seq, "fs compr_data: %-16llu\n", 9238c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_CDATA_READ_IO]); 9248c2ecf20Sopenharmony_ci seq_printf(seq, "fs node: %-16llu\n", 9258c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_NODE_READ_IO]); 9268c2ecf20Sopenharmony_ci seq_printf(seq, "fs meta: %-16llu\n", 9278c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_META_READ_IO]); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci /* print other IOs */ 9308c2ecf20Sopenharmony_ci seq_puts(seq, "[OTHER]\n"); 9318c2ecf20Sopenharmony_ci seq_printf(seq, "fs discard: %-16llu\n", 9328c2ecf20Sopenharmony_ci sbi->rw_iostat[FS_DISCARD]); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci return 0; 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_cistatic int __maybe_unused victim_bits_seq_show(struct seq_file *seq, 9388c2ecf20Sopenharmony_ci void *offset) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci struct super_block *sb = seq->private; 9418c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 9428c2ecf20Sopenharmony_ci struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 9438c2ecf20Sopenharmony_ci int i; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci seq_puts(seq, "format: victim_secmap bitmaps\n"); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci for (i = 0; i < MAIN_SECS(sbi); i++) { 9488c2ecf20Sopenharmony_ci if ((i % 10) == 0) 9498c2ecf20Sopenharmony_ci seq_printf(seq, "%-10d", i); 9508c2ecf20Sopenharmony_ci seq_printf(seq, "%d", test_bit(i, dirty_i->victim_secmap) ? 1 : 0); 9518c2ecf20Sopenharmony_ci if ((i % 10) == 9 || i == (MAIN_SECS(sbi) - 1)) 9528c2ecf20Sopenharmony_ci seq_putc(seq, '\n'); 9538c2ecf20Sopenharmony_ci else 9548c2ecf20Sopenharmony_ci seq_putc(seq, ' '); 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci return 0; 9578c2ecf20Sopenharmony_ci} 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_cistatic int undiscard_info_seq_show(struct seq_file *seq, void *offset) 9608c2ecf20Sopenharmony_ci{ 9618c2ecf20Sopenharmony_ci struct super_block *sb = seq->private; 9628c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(sb); 9638c2ecf20Sopenharmony_ci struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 9648c2ecf20Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 9658c2ecf20Sopenharmony_ci unsigned int total_segs = le32_to_cpu(sbi->raw_super->segment_count_main); 9668c2ecf20Sopenharmony_ci unsigned int total = 0; 9678c2ecf20Sopenharmony_ci unsigned int i, j; 9688c2ecf20Sopenharmony_ci unsigned int max_blocks = sbi->blocks_per_seg; 9698c2ecf20Sopenharmony_ci unsigned long *dmap = SIT_I(sbi)->tmp_map; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci if (!f2fs_realtime_discard_enable(sbi)) 9728c2ecf20Sopenharmony_ci goto out; 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci for (i = 0; i < total_segs; i++) { 9758c2ecf20Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, i); 9768c2ecf20Sopenharmony_ci unsigned int entries = SIT_VBLOCK_MAP_SIZE / 9778c2ecf20Sopenharmony_ci sizeof(unsigned long); 9788c2ecf20Sopenharmony_ci unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; 9798c2ecf20Sopenharmony_ci unsigned long *discard_map = (unsigned long *)se->discard_map; 9808c2ecf20Sopenharmony_ci int start = 0, end = -1; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci down_write(&sit_i->sentry_lock); 9838c2ecf20Sopenharmony_ci if (se->valid_blocks == max_blocks) { 9848c2ecf20Sopenharmony_ci up_write(&sit_i->sentry_lock); 9858c2ecf20Sopenharmony_ci continue; 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci if (se->valid_blocks == 0) { 9898c2ecf20Sopenharmony_ci mutex_lock(&dirty_i->seglist_lock); 9908c2ecf20Sopenharmony_ci if (test_bit((int)i, dirty_i->dirty_segmap[PRE])) 9918c2ecf20Sopenharmony_ci total += 512; 9928c2ecf20Sopenharmony_ci mutex_unlock(&dirty_i->seglist_lock); 9938c2ecf20Sopenharmony_ci } else { 9948c2ecf20Sopenharmony_ci for (j = 0; j < entries; j++) 9958c2ecf20Sopenharmony_ci dmap[j] = ~ckpt_map[j] & ~discard_map[j]; 9968c2ecf20Sopenharmony_ci while (1) { 9978c2ecf20Sopenharmony_ci start = (int)find_rev_next_bit(dmap, 9988c2ecf20Sopenharmony_ci (unsigned long)max_blocks, 9998c2ecf20Sopenharmony_ci (unsigned long)(end + 1)); 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci if ((unsigned int)start >= max_blocks) 10028c2ecf20Sopenharmony_ci break; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci end = (int)find_rev_next_zero_bit(dmap, 10058c2ecf20Sopenharmony_ci (unsigned long)max_blocks, 10068c2ecf20Sopenharmony_ci (unsigned long)(start + 1)); 10078c2ecf20Sopenharmony_ci total += (unsigned int)(end - start); 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci up_write(&sit_i->sentry_lock); 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ciout: 10158c2ecf20Sopenharmony_ci seq_printf(seq, "total undiscard:%u K\n", total * 4); 10168c2ecf20Sopenharmony_ci return 0; 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ciint __init f2fs_init_sysfs(void) 10208c2ecf20Sopenharmony_ci{ 10218c2ecf20Sopenharmony_ci int ret; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci kobject_set_name(&f2fs_kset.kobj, "f2fs"); 10248c2ecf20Sopenharmony_ci f2fs_kset.kobj.parent = fs_kobj; 10258c2ecf20Sopenharmony_ci ret = kset_register(&f2fs_kset); 10268c2ecf20Sopenharmony_ci if (ret) 10278c2ecf20Sopenharmony_ci return ret; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype, 10308c2ecf20Sopenharmony_ci NULL, "features"); 10318c2ecf20Sopenharmony_ci if (ret) { 10328c2ecf20Sopenharmony_ci kobject_put(&f2fs_feat); 10338c2ecf20Sopenharmony_ci kset_unregister(&f2fs_kset); 10348c2ecf20Sopenharmony_ci } else { 10358c2ecf20Sopenharmony_ci f2fs_proc_root = proc_mkdir("fs/f2fs", NULL); 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci return ret; 10388c2ecf20Sopenharmony_ci} 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_civoid f2fs_exit_sysfs(void) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci kobject_put(&f2fs_feat); 10438c2ecf20Sopenharmony_ci kset_unregister(&f2fs_kset); 10448c2ecf20Sopenharmony_ci remove_proc_entry("fs/f2fs", NULL); 10458c2ecf20Sopenharmony_ci f2fs_proc_root = NULL; 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ciint f2fs_register_sysfs(struct f2fs_sb_info *sbi) 10498c2ecf20Sopenharmony_ci{ 10508c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 10518c2ecf20Sopenharmony_ci int err; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci sbi->s_kobj.kset = &f2fs_kset; 10548c2ecf20Sopenharmony_ci init_completion(&sbi->s_kobj_unregister); 10558c2ecf20Sopenharmony_ci err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL, 10568c2ecf20Sopenharmony_ci "%s", sb->s_id); 10578c2ecf20Sopenharmony_ci if (err) { 10588c2ecf20Sopenharmony_ci kobject_put(&sbi->s_kobj); 10598c2ecf20Sopenharmony_ci wait_for_completion(&sbi->s_kobj_unregister); 10608c2ecf20Sopenharmony_ci return err; 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci if (f2fs_proc_root) 10648c2ecf20Sopenharmony_ci sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci if (sbi->s_proc) { 10678c2ecf20Sopenharmony_ci proc_create_single_data("segment_info", S_IRUGO, sbi->s_proc, 10688c2ecf20Sopenharmony_ci segment_info_seq_show, sb); 10698c2ecf20Sopenharmony_ci proc_create_single_data("segment_bits", S_IRUGO, sbi->s_proc, 10708c2ecf20Sopenharmony_ci segment_bits_seq_show, sb); 10718c2ecf20Sopenharmony_ci proc_create_single_data("iostat_info", S_IRUGO, sbi->s_proc, 10728c2ecf20Sopenharmony_ci iostat_info_seq_show, sb); 10738c2ecf20Sopenharmony_ci proc_create_single_data("victim_bits", S_IRUGO, sbi->s_proc, 10748c2ecf20Sopenharmony_ci victim_bits_seq_show, sb); 10758c2ecf20Sopenharmony_ci proc_create_single_data("undiscard_info", S_IRUGO, sbi->s_proc, 10768c2ecf20Sopenharmony_ci undiscard_info_seq_show, sb); 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci return 0; 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_civoid f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) 10838c2ecf20Sopenharmony_ci{ 10848c2ecf20Sopenharmony_ci if (sbi->s_proc) { 10858c2ecf20Sopenharmony_ci remove_proc_entry("iostat_info", sbi->s_proc); 10868c2ecf20Sopenharmony_ci remove_proc_entry("segment_info", sbi->s_proc); 10878c2ecf20Sopenharmony_ci remove_proc_entry("segment_bits", sbi->s_proc); 10888c2ecf20Sopenharmony_ci remove_proc_entry("victim_bits", sbi->s_proc); 10898c2ecf20Sopenharmony_ci remove_proc_entry("undiscard_info", sbi->s_proc); 10908c2ecf20Sopenharmony_ci remove_proc_entry(sbi->sb->s_id, f2fs_proc_root); 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci kobject_del(&sbi->s_kobj); 10938c2ecf20Sopenharmony_ci kobject_put(&sbi->s_kobj); 10948c2ecf20Sopenharmony_ci wait_for_completion(&sbi->s_kobj_unregister); 10958c2ecf20Sopenharmony_ci} 1096