[f2fs-dev] [RFC PATCH v4 2/3] f2fs: add sysfs interface for inline extent management
Yongpeng Yang <[email protected]> Thu, 6 Aug 2026 21:19:04 +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). Signed-off-by: Yongpeng Yang <[email protected]> --- v4: - Remove the inline-extent code-coverage statistics output. --- fs/f2fs/sysfs.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) 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