[f2fs-dev] [RFC PATCH v3 2/3] f2fs: add sysfs interface for inline extent management
Yongpeng Yang <[email protected]> Fri, 24 Jul 2026 20:58:22 +0800
| Newsgroups | net.sourceforge.lists.linux-f2fs-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Yongpeng Yang <[email protected]> Add sysfs interfaces for runtime management of the inline extent feature: - inline_extent_extension_list: read/write the file extension list that triggers inline extent allocation. Format for writing: "ext" or "ext:capacity" to add (with optional per-extension capacity), "!ext" to remove. Reading shows all extensions with their capacity settings. - inline_extent_enable: toggle inline extent allocation on/off at runtime (0 or 1). - Export inline extent debug statistics (code coverage counters for merge, split, insert, evict operations) via /sys/kernel/debug/f2fs/status when CONFIG_F2FS_INLINE_EXTENT_DEBUG is enabled. Signed-off-by: Yongpeng Yang <[email protected]> --- v3: - Config per-inode capacity via sysfs. --- fs/f2fs/debug.c | 4 +++ fs/f2fs/iextent.c | 38 ++++++++++++++++++++ fs/f2fs/iextent.h | 3 ++ fs/f2fs/sysfs.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index ff379aff4472..c441ef3fdcbc 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -19,6 +19,7 @@ #include "node.h" #include "segment.h" #include "gc.h" +#include "iextent.h" static LIST_HEAD(f2fs_stat_list); static DEFINE_SPINLOCK(f2fs_stat_lock); @@ -758,6 +759,9 @@ static int stat_show(struct seq_file *s, void *v) si->ext_mem[EX_BLOCK_AGE] >> 10); seq_printf(s, " - paged : %llu KB\n", si->page_mem >> 10); +#ifdef CONFIG_F2FS_INLINE_EXTENT_DEBUG + f2fs_iext_show_stat(sbi, s); +#endif } spin_unlock(&f2fs_stat_lock); return 0; diff --git a/fs/f2fs/iextent.c b/fs/f2fs/iextent.c index 533aaa4089bd..dd1d1782598f 100644 --- a/fs/f2fs/iextent.c +++ b/fs/f2fs/iextent.c @@ -6,6 +6,7 @@ * http://www.mi.com/ */ #include <linux/f2fs_fs.h> +#include <linux/seq_file.h> #include "f2fs.h" #include "iextent.h" @@ -710,3 +711,40 @@ int f2fs_iext_update_extension_list(struct f2fs_sb_info *sbi, const char *name, spin_unlock_irqrestore(&iext_info->iext_ext_lock, flag); return ret; } + +#ifdef CONFIG_F2FS_INLINE_EXTENT_DEBUG +void f2fs_iext_show_stat(struct f2fs_sb_info *sbi, struct seq_file *s) +{ + struct f2fs_iext_info *iext_info = sbi->iext_info; + + seq_printf(s, "Inline extent code coverage statistics:\n" + " - left_merge_count: %llu\n" + " - right_merge_count: %llu\n" + " - fast_right_merge_count: %llu\n" + " - lr_merge_count: %llu\n" + " - split_left_count: %llu\n" + " - split_right_count: %llu\n" + " - split_mid_count: %llu\n" + " - insert_new_ext_count: %llu\n" + " - overwrite_ext_count: %llu\n" + " - add_ext_count: %llu\n" + " - del_ext_count: %llu\n" + " - evict_last_ext_cnt: %llu\n" + " - truncate_last_ext_cnt: %llu\n" + " - drop_insert_new_ext_cnt: %llu\n", + atomic64_read(&iext_info->left_merge_count), + atomic64_read(&iext_info->right_merge_count), + atomic64_read(&iext_info->fast_right_merge_count), + atomic64_read(&iext_info->lr_merge_count), + atomic64_read(&iext_info->split_left_count), + atomic64_read(&iext_info->split_right_count), + atomic64_read(&iext_info->split_mid_count), + atomic64_read(&iext_info->insert_new_ext_count), + atomic64_read(&iext_info->overwrite_ext_count), + atomic64_read(&iext_info->add_ext_count), + atomic64_read(&iext_info->del_ext_count), + atomic64_read(&iext_info->evict_last_ext_cnt), + atomic64_read(&iext_info->truncate_last_ext_cnt), + atomic64_read(&iext_info->drop_insert_new_ext_cnt)); +} +#endif \ No newline at end of file diff --git a/fs/f2fs/iextent.h b/fs/f2fs/iextent.h index 722c84ce1800..66782296bbd5 100644 --- a/fs/f2fs/iextent.h +++ b/fs/f2fs/iextent.h @@ -160,4 +160,7 @@ int f2fs_iext_update_extension_list(struct f2fs_sb_info *sbi, const char *name, bool set, unsigned int capacity); int f2fs_iext_info_init(struct f2fs_sb_info *sbi); void f2fs_iext_info_destroy(struct f2fs_sb_info *sbi); +#ifdef CONFIG_F2FS_INLINE_EXTENT_DEBUG +void f2fs_iext_show_stat(struct f2fs_sb_info *sbi, struct seq_file *s); +#endif #endif diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index be92c05a5420..53d83f66f074 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -18,6 +18,7 @@ #include "segment.h" #include "gc.h" #include "iostat.h" +#include "iextent.h" #include <trace/events/f2fs.h> static struct proc_dir_entry *f2fs_proc_root; @@ -40,6 +41,9 @@ enum { RESERVED_BLOCKS, /* struct f2fs_sb_info */ CPRC_INFO, /* struct ckpt_req_control */ ATGC_INFO, /* struct atgc_management */ +#ifdef CONFIG_F2FS_INLINE_EXTENT + INLINE_EXTENT, /* struct f2fs_iext_info */ +#endif }; static const char *gc_mode_names[MAX_GC_MODE] = { @@ -98,6 +102,10 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) return (unsigned char *)&sbi->cprc_info; else if (struct_type == ATGC_INFO) return (unsigned char *)&sbi->am; +#ifdef CONFIG_F2FS_INLINE_EXTENT + else if (struct_type == INLINE_EXTENT) + return (unsigned char *)sbi->iext_info; +#endif return NULL; } @@ -405,6 +413,30 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a, return len; } +#ifdef CONFIG_F2FS_INLINE_EXTENT + if (!strcmp(a->attr.name, "inline_extent_extension_list")) { + struct f2fs_iext_info *iext_info = sbi->iext_info; + __u8 (*extlist)[F2FS_EXTENSION_LEN] = iext_info->extensions; + int len = 0, i; + unsigned long flag; + + spin_lock_irqsave(&iext_info->iext_ext_lock, flag); + for (i = 0; i < iext_info->iext_ext_cnt; i++) { + unsigned int cap = iext_info->ext_capacity[i]; + + if (cap) + len += sysfs_emit_at(buf, len, "%s:%u\n", + extlist[i], cap); + else + len += sysfs_emit_at(buf, len, "%s\n", + extlist[i]); + } + spin_unlock_irqrestore(&iext_info->iext_ext_lock, flag); + + return len; + } +#endif + if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { struct ckpt_req_control *cprc = &sbi->cprc_info; int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio); @@ -535,6 +567,48 @@ static ssize_t __sbi_store(struct f2fs_attr *a, return ret ? ret : count; } +#ifdef CONFIG_F2FS_INLINE_EXTENT + if (!strcmp(a->attr.name, "inline_extent_extension_list")) { + const char *name = strim((char *)buf); + bool set = true; + unsigned int capacity = 0; + char ext_name[F2FS_EXTENSION_LEN]; + const char *sep; + + if (*name == '!') { + name++; + set = false; + } + + if (!strlen(name) || strlen(name) >= F2FS_EXTENSION_LEN) + return -EINVAL; + + /* Parse optional capacity: "ext:capacity" format. */ + sep = strchr(name, ':'); + if (sep) { + int name_len = sep - name; + + if (name_len <= 0 || name_len >= F2FS_EXTENSION_LEN) + return -EINVAL; + memcpy(ext_name, name, name_len); + ext_name[name_len] = '\0'; + if (set) { + ret = kstrtouint(sep + 1, 10, &capacity); + if (ret) + return ret; + if (!capacity) + return -EINVAL; + } + name = ext_name; + } + + ret = f2fs_iext_update_extension_list(sbi, name, set, + capacity); + + return ret ? ret : count; + } +#endif + if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { const char *name = strim((char *)buf); struct ckpt_req_control *cprc = &sbi->cprc_info; @@ -604,6 +678,14 @@ static ssize_t __sbi_store(struct f2fs_attr *a, return count; } +#ifdef CONFIG_F2FS_INLINE_EXTENT + if (!strcmp(a->attr.name, "inline_extent_enable")) { + if (t > 1) + return -EINVAL; + f2fs_iext_set_enable(sbi, !!t); + return count; + } +#endif if (!strcmp(a->attr.name, "discard_io_aware_gran")) { if (t > MAX_PLIST_NUM) return -EINVAL; @@ -1257,6 +1339,11 @@ NM_INFO_GENERAL_RW_ATTR(dirty_nats_ratio); /* F2FS_SBI ATTR */ F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list); +#ifdef CONFIG_F2FS_INLINE_EXTENT +F2FS_RW_ATTR(INLINE_EXTENT, f2fs_iext_info, inline_extent_extension_list, + extensions); +F2FS_RW_ATTR(INLINE_EXTENT, f2fs_iext_info, inline_extent_enable, iext_enable); +#endif F2FS_SBI_RW_ATTR(gc_idle, gc_mode); F2FS_SBI_RW_ATTR(gc_urgent, gc_mode); F2FS_SBI_RW_ATTR(cp_interval, interval_time[CP_TIME]); @@ -1457,6 +1544,10 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(max_io_bytes), ATTR_LIST(gc_pin_file_thresh), ATTR_LIST(extension_list), +#ifdef CONFIG_F2FS_INLINE_EXTENT + ATTR_LIST(inline_extent_extension_list), + ATTR_LIST(inline_extent_enable), +#endif #ifdef CONFIG_F2FS_FAULT_INJECTION ATTR_LIST(inject_rate), ATTR_LIST(inject_type), -- 2.43.0 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel