From: Gao Xiang hsiangkao@linux.alibaba.com
anolis inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT
Reference: https://gitee.com/anolis/cloud-kernel/commit/35a08cf3d012
--------------------------------
ANBZ: #1666
commit c6be2bd0a5dd91f98d6b5d2df2c79bc32993352c upstream.
A new fscache based mode is going to be introduced for erofs, in which case on-demand read semantics is implemented through fscache.
As the first step, register fscache volume for each erofs filesystem. That means, data blobs can not be shared among erofs filesystems. In the following iteration, we are going to introduce the domain semantics, in which case several erofs filesystems can belong to one domain, and data blobs can be shared among these erofs filesystems of one domain.
Signed-off-by: Jeffle Xu jefflexu@linux.alibaba.com Reviewed-by: Gao Xiang hsiangkao@linux.alibaba.com Link: https://lore.kernel.org/r/20220425122143.56815-12-jefflexu@linux.alibaba.com Acked-by: Chao Yu chao@kernel.org Signed-off-by: Gao Xiang hsiangkao@linux.alibaba.com Signed-off-by: Huang Jianan jnhuang@linux.alibaba.com Reviewed-by: Jeffle Xu jefflexu@linux.alibaba.com Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/erofs/Kconfig | 10 ++++++++ fs/erofs/Makefile | 2 +- fs/erofs/fscache.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/internal.h | 23 ++++++++++++++++++ fs/erofs/super.c | 12 ++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 fs/erofs/fscache.c
diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 4dc00a2320e4..f7222cba2a67 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -95,3 +95,13 @@ config EROFS_FS_CLUSTER_PAGE_LIMIT into 8k-unit, hard limit should not be configured less than 2. Otherwise, the image will be refused to mount on this kernel. + +config EROFS_FS_ONDEMAND + bool "EROFS fscache-based on-demand read support" + depends on CACHEFILES_ONDEMAND && (EROFS_FS=m && FSCACHE || EROFS_FS=y && FSCACHE=y) + default n + help + This permits EROFS to use fscache-backed data blobs with on-demand + read support. + + If unsure, say N. \ No newline at end of file diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 46f2aa4ba46c..b75be64ffc0b 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_EROFS_FS) += erofs.o erofs-objs := super.o inode.o data.o namei.o dir.o utils.o erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o - +erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o \ No newline at end of file diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c new file mode 100644 index 000000000000..dbf3f1bb7588 --- /dev/null +++ b/fs/erofs/fscache.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022, Alibaba Cloud + */ +#include <linux/fscache.h> +#include "internal.h" + +struct fscache_netfs erofs_fscache_netfs = { + .name = "erofs", + .version = 0, +}; + +int erofs_fscache_register(void) +{ + return fscache_register_netfs(&erofs_fscache_netfs); +} + +void erofs_fscache_unregister(void) +{ + fscache_unregister_netfs(&erofs_fscache_netfs); +} + +const struct fscache_cookie_def erofs_fscache_super_index_def = { + .name = "EROFS.super", + .type = FSCACHE_COOKIE_TYPE_INDEX, + .check_aux = NULL, +}; + +int erofs_fscache_register_fs(struct super_block *sb) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + struct fscache_cookie *volume; + char *name; + int ret = 0; + + name = kasprintf(GFP_KERNEL, "erofs,%s", sbi->opt.fsid); + if (!name) + return -ENOMEM; + + volume = fscache_acquire_cookie(erofs_fscache_netfs.primary_index, + &erofs_fscache_super_index_def, name, strlen(name), + NULL, 0, NULL, 0, true); + if (IS_ERR_OR_NULL(volume)) { + erofs_err(sb, "failed to register volume for %s", name); + ret = volume ? PTR_ERR(volume) : -EOPNOTSUPP; + volume = NULL; + } + sbi->volume = volume; + kfree(name); + return ret; +} + +void erofs_fscache_unregister_fs(struct super_block *sb) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + + fscache_relinquish_cookie(sbi->volume, NULL, false); + sbi->volume = NULL; +} diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 713f120ac49d..a70f80f3b79c 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -64,6 +64,7 @@ struct erofs_mount_opts { unsigned int max_sync_decompress_pages; #endif unsigned int mount_opt; + char *fsid; };
struct erofs_dev_context { @@ -118,6 +119,9 @@ struct erofs_sb_info { u8 volume_name[16]; /* volume name */ u32 feature_compat; u32 feature_incompat; + + /* fscache support */ + struct fscache_cookie *volume; };
#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) @@ -468,6 +472,25 @@ static inline int z_erofs_init_zip_subsystem(void) { return 0; } static inline void z_erofs_exit_zip_subsystem(void) {} #endif /* !CONFIG_EROFS_FS_ZIP */
+/* fscache.c */ +#ifdef CONFIG_EROFS_FS_ONDEMAND +int erofs_fscache_register(void); +void erofs_fscache_unregister(void); +int erofs_fscache_register_fs(struct super_block *sb); +void erofs_fscache_unregister_fs(struct super_block *sb); +#else +static inline int erofs_fscache_register(void) +{ + return 0; +} +static inline void erofs_fscache_unregister(void) {} +static inline int erofs_fscache_register_fs(struct super_block *sb) +{ + return 0; +} +static inline void erofs_fscache_unregister_fs(struct super_block *sb) {} +#endif + #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#endif /* __EROFS_INTERNAL_H */ diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 5a891211c3f8..2b21c5efaff3 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -440,6 +440,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) if (erofs_is_fscache_mode(sb)) { sb->s_blocksize = EROFS_BLKSIZ; sb->s_blocksize_bits = LOG_BLOCK_SIZE; + + err = erofs_fscache_register_fs(sb); + if (err) + return err; } else { if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) { erofs_err(sb, "failed to set erofs blksize"); @@ -588,6 +592,7 @@ static void erofs_kill_sb(struct super_block *sb) if (!sbi) return; erofs_free_dev_context(sbi->devs); + erofs_fscache_unregister_fs(sb); kfree(sbi); sb->s_fs_info = NULL; } @@ -638,6 +643,10 @@ static int __init erofs_module_init(void) if (err) goto zip_err;
+ err = erofs_fscache_register(); + if (err) + goto fscache_err; + err = register_filesystem(&erofs_fs_type); if (err) goto fs_err; @@ -645,6 +654,8 @@ static int __init erofs_module_init(void) return 0;
fs_err: + erofs_fscache_unregister(); +fscache_err: z_erofs_exit_zip_subsystem(); zip_err: erofs_exit_shrinker(); @@ -657,6 +668,7 @@ static int __init erofs_module_init(void) static void __exit erofs_module_exit(void) { unregister_filesystem(&erofs_fs_type); + erofs_fscache_unregister(); z_erofs_exit_zip_subsystem(); erofs_exit_shrinker();