From: Yongpeng Yang <[email protected]> Add sysfs attributes to manage the inline extent feature at runtime:
- inline_extent_extension_list: read/write interface to manage file extension list that determines which files should use inline extent format. Writing an extension name adds it to the list; writing "!extension" removes it. - inline_extent_enable: toggle to dynamically enable or disable the inline extent feature without remounting. Also add inline extent code coverage statistics output under /sys/kernel/debug/f2fs/ when CONFIG_F2FS_INLINE_EXTENT_DEBUG is enabled, showing counters for various extent operations (merges, splits, inserts, evictions, etc.). Signed-off-by: Yongpeng Yang <[email protected]> --- fs/f2fs/debug.c | 4 ++++ fs/f2fs/iextent.c | 39 +++++++++++++++++++++++++++++++++++ fs/f2fs/iextent.h | 3 +++ fs/f2fs/sysfs.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index af88db8fdb71..b77246b6dbfc 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); @@ -762,6 +763,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 d919448ef740..63a3433aa9bc 100644 --- a/fs/f2fs/iextent.c +++ b/fs/f2fs/iextent.c @@ -821,3 +821,42 @@ 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" + " - trigger_ext_format_convert: %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), + atomic64_read(&iext_info->trigger_ext_format_convert)); +} +#endif diff --git a/fs/f2fs/iextent.h b/fs/f2fs/iextent.h index e5fb028612ad..785eed312bf1 100644 --- a/fs/f2fs/iextent.h +++ b/fs/f2fs/iextent.h @@ -181,4 +181,7 @@ int f2fs_iext_update_extension_list(struct f2fs_sb_info *sbi, const char *name, bool set); 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 665687244c93..c3a35e033df3 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,22 @@ 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++) + 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 +559,25 @@ 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; + + if (*name == '!') { + name++; + set = false; + } + + if (!strlen(name) || strlen(name) >= F2FS_EXTENSION_LEN) + return -EINVAL; + + ret = f2fs_iext_update_extension_list(sbi, name, set); + + 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; @@ -1257,6 +1300,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 +1505,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
