
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/IBK2MJ -------------------------------- Add CONFIG_EROFS_TRIO to control the trio feature. For reading data, we first check the data in trio. When the users want to use TrIO in erofs, they should mount with @trio_meta and @trio_data options. The target options is the valid path where the TrIO info stored. Erofs will parse the TrIO info and build the runtime buffer for reading. Signed-off-by: Hongbo Li <lihongbo22@huawei.com> --- fs/erofs/Kconfig | 11 +++++++++ fs/erofs/Makefile | 1 + fs/erofs/data.c | 17 ++++++++++++++ fs/erofs/fscache.c | 22 +++++++++++++++++- fs/erofs/internal.h | 50 +++++++++++++++++++++++++++++++++++++++++ fs/erofs/super.c | 47 +++++++++++++++++++++++++++++++++++++- fs/erofs/trio_manager.c | 15 +++++++++++-- 7 files changed, 159 insertions(+), 4 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index f6dc961e6c2b..c36bcaeffc14 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -125,6 +125,17 @@ config EROFS_FS_ONDEMAND If unsure, say N. +config EROFS_TRIO + bool "EROFS TrIO support" + depends on EROFS_FS_ONDEMAND + default n + help + If this config option is enabled then erofs trio will be enable. + This is used for container cases to boost on-demand loading for + container's images. + + If unsure, say N. + config EROFS_FS_PCPU_KTHREAD bool "EROFS per-cpu decompression kthread workers" depends on EROFS_FS_ZIP diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 994d0b9deddf..d7aeef9d50a4 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -7,3 +7,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o pcpubuf.o erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) += decompressor_lzma.o erofs-$(CONFIG_EROFS_FS_ZIP_DEFLATE) += decompressor_deflate.o erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o +erofs-$(CONFIG_EROFS_TRIO) += trio_manager.o diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 19ab9bb3a9a0..8a8f9dc5198f 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -445,10 +445,27 @@ static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma) #define erofs_file_mmap generic_file_readonly_mmap #endif +#ifdef CONFIG_EROFS_TRIO +static int erofs_file_open(struct inode *inode, struct file *file) +{ + if (!erofs_is_fscache_mode(inode->i_sb)) + return 0; + + if (!inode->i_private) { + inode->i_private = erofs_get_trio_object(inode); + } + + return 0; +} +#else +#define erofs_file_open generic_file_open +#endif + const struct file_operations erofs_file_fops = { .llseek = generic_file_llseek, .read_iter = erofs_file_read_iter, .mmap = erofs_file_mmap, .get_unmapped_area = thp_get_unmapped_area, .splice_read = filemap_splice_read, + .open = erofs_file_open, }; diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 7bcd1d261e7d..096384ea2a85 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -198,6 +198,21 @@ static int erofs_fscache_meta_read_folio(struct file *data, struct folio *folio) return ret; } +static bool erofs_fscache_read_trio(struct erofs_fscache_request *primary) +{ + struct address_space *mapping = primary->mapping; + loff_t pos = primary->start + primary->submitted; + + ssize_t ret = erofs_read_from_trio(mapping, pos, + primary->len - primary->submitted); + if (ret > 0) { + primary->submitted += ret; + return true; + } + + return false; +} + static int erofs_fscache_data_read_slice(struct erofs_fscache_request *primary) { struct address_space *mapping = primary->mapping; @@ -207,10 +222,15 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_request *primary) struct erofs_map_blocks map; struct erofs_map_dev mdev; struct iov_iter iter; - loff_t pos = primary->start + primary->submitted; + loff_t pos; size_t count; int ret; + /* first try mapping in trio */ + if (erofs_fscache_read_trio(primary)) + return 0; + + pos = primary->start + primary->submitted; map.m_la = pos; ret = erofs_map_blocks(inode, &map); if (ret) diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index a53152693ae2..00205df66e53 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/iomap.h> +#include <linux/hashtable.h> #include "erofs_fs.h" /* redefine pr_fmt "erofs: " */ @@ -177,6 +178,15 @@ struct erofs_sb_info { char *fsid; char *domain_id; bool ondemand_enabled; + +#ifdef CONFIG_EROFS_TRIO +#define TRIO_HT_BITS 10 + /* trio support */ + char *trio_meta; + char *trio_data; + void *buffer; + DECLARE_HASHTABLE(meta_ht, TRIO_HT_BITS); +#endif }; #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) @@ -525,6 +535,46 @@ static inline void erofs_fscache_unregister_cookie(struct erofs_fscache *fscache } #endif +#ifdef CONFIG_EROFS_TRIO +static inline bool erofs_trio_is_enable(struct super_block *sb) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + + return sbi->trio_meta && sbi->trio_data; +} +void *erofs_get_trio_object(struct inode *inode); +ssize_t erofs_read_from_trio(struct address_space *mapping, + loff_t pos, size_t len); +int erofs_register_trio(struct super_block *sb); +void erofs_unregister_trio(struct super_block *sb); +int trio_manager_init(void); +void trio_manager_exit(void); +#else +static inline bool erofs_trio_is_enable(struct super_block *sb) +{ + return false; +} +static inline ssize_t erofs_read_from_trio(struct address_space *mapping, + loff_t pos, size_t len) +{ + return 0; +} + +static inline int erofs_register_trio(struct super_block *sb) +{ + return 0; +} + +static inline void erofs_unregister_trio(struct super_block *sb) {} + +static inline int trio_manager_init(void) +{ + return 0; +} + +static inline void trio_manager_exit(void) {} +#endif + #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ #endif /* __EROFS_INTERNAL_H */ diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 43e3a8322a6c..acb5eb44ed73 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -13,6 +13,7 @@ #include <linux/fs_parser.h> #include <linux/dax.h> #include <linux/exportfs.h> +#include <linux/backing-dev-defs.h> #include "xattr.h" #define CREATE_TRACE_POINTS @@ -388,6 +389,8 @@ enum { Opt_device, Opt_fsid, Opt_domain_id, + Opt_trio_meta, + Opt_trio_data, Opt_err }; @@ -414,6 +417,8 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = { fsparam_string("device", Opt_device), fsparam_string("fsid", Opt_fsid), fsparam_string("domain_id", Opt_domain_id), + fsparam_string("trio_meta", Opt_trio_meta), + fsparam_string("trio_data", Opt_trio_data), {} }; @@ -530,6 +535,25 @@ static int erofs_fc_parse_param(struct fs_context *fc, if (!sbi->domain_id) return -ENOMEM; break; +#ifdef CONFIG_EROFS_TRIO + case Opt_trio_meta: + kfree(sbi->trio_meta); + sbi->trio_meta = kstrdup(param->string, GFP_KERNEL); + if (!sbi->trio_meta) + return -ENOMEM; + break; + case Opt_trio_data: + kfree(sbi->trio_data); + sbi->trio_data = kstrdup(param->string, GFP_KERNEL); + if (!sbi->trio_data) + return -ENOMEM; + break; +#else + case Opt_trio_meta: + case Opt_trio_data: + errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name); + break; +#endif #else case Opt_fsid: case Opt_domain_id: @@ -596,6 +620,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; + err = erofs_register_trio(sb); + if (err) + return err; + err = erofs_fscache_register_fs(sb); if (err) return err; @@ -603,6 +631,11 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) err = super_setup_bdi(sb); if (err) return err; + + if (erofs_trio_is_enable(sb)) { + sb->s_bdi->ra_pages = 0; + sb->s_bdi->io_pages = 0; + } } else { if (!sb_set_blocksize(sb, PAGE_SIZE)) { errorfc(fc, "failed to set initial blksize"); @@ -809,7 +842,12 @@ static void erofs_kill_sb(struct super_block *sb) erofs_free_dev_context(sbi->devs); fs_put_dax(sbi->dax_dev, NULL); + erofs_unregister_trio(sb); erofs_fscache_unregister_fs(sb); +#ifdef CONFIG_EROFS_TRIO + kfree(sbi->trio_meta); + kfree(sbi->trio_data); +#endif kfree(sbi->fsid); kfree(sbi->domain_id); kfree(sbi); @@ -833,6 +871,7 @@ static void erofs_put_super(struct super_block *sb) sbi->packed_inode = NULL; erofs_free_dev_context(sbi->devs); sbi->devs = NULL; + erofs_unregister_trio(sb); erofs_fscache_unregister_fs(sb); } @@ -883,8 +922,13 @@ static int __init erofs_module_init(void) if (err) goto fs_err; - return 0; + err = trio_manager_init(); + if (err) + goto trio_err; + return 0; +trio_err: + unregister_filesystem(&erofs_fs_type); fs_err: erofs_exit_sysfs(); sysfs_err: @@ -902,6 +946,7 @@ static int __init erofs_module_init(void) static void __exit erofs_module_exit(void) { + trio_manager_exit(); unregister_filesystem(&erofs_fs_type); /* Ensure all RCU free inodes / pclusters are safe to be destroyed. */ diff --git a/fs/erofs/trio_manager.c b/fs/erofs/trio_manager.c index 6f5ab0b85227..c594bec21c06 100644 --- a/fs/erofs/trio_manager.c +++ b/fs/erofs/trio_manager.c @@ -169,6 +169,14 @@ static void *_read_data_inner(struct super_block *sb, const char *path) return data; } +void *erofs_get_trio_object(struct inode *inode) +{ + struct trace_object *obj; + + obj = find_trace_object(inode); + return obj; +} + ssize_t erofs_read_from_trio(struct address_space *mapping, loff_t pos, size_t len) { @@ -181,10 +189,10 @@ ssize_t erofs_read_from_trio(struct address_space *mapping, size_t hit_len; ssize_t ret; - obj = find_trace_object(inode); - if (!obj) + if (!inode->i_private) return 0; + obj = (struct trace_object *)inode->i_private; target_io = get_io_from_object(obj, pos, len, &hit_len); if (!target_io || !hit_len) return 0; @@ -209,6 +217,9 @@ int erofs_register_trio(struct super_block *sb) LIST_HEAD(head); int ret = -EINVAL; + if (!sbi->trio_meta && !sbi->trio_data) + return 0; + if (!sbi->trio_meta || !sbi->trio_data) { erofs_err(sb, "trio_meta and trio_data must be set together"); return ret; -- 2.34.1