Defer initialization of per-CPU workers and registration for CPU hotplug events until the first mount. Similarly, unregister from hotplug events and destroy per-CPU workers when the last mount is unmounted.
Signed-off-by: Sandeep Dhavale <dhav...@google.com> --- fs/erofs/internal.h | 5 +++++ fs/erofs/super.c | 27 +++++++++++++++++++++++++++ fs/erofs/zdata.c | 35 +++++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 4ac188d5d894..c88cba4da3eb 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -450,6 +450,8 @@ int z_erofs_gbuf_growsize(unsigned int nrpages); int __init z_erofs_gbuf_init(void); void z_erofs_gbuf_exit(void); int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb); +int z_erofs_init_workers(void); +void z_erofs_destroy_workers(void); #else static inline void erofs_shrinker_register(struct super_block *sb) {} static inline void erofs_shrinker_unregister(struct super_block *sb) {} @@ -458,6 +460,9 @@ static inline void erofs_exit_shrinker(void) {} static inline int z_erofs_init_subsystem(void) { return 0; } static inline void z_erofs_exit_subsystem(void) {} static inline int z_erofs_init_super(struct super_block *sb) { return 0; } +static inline int z_erofs_init_workers(void) { return 0; }; +static inline z_erofs_exit_workers(void); + #endif /* !CONFIG_EROFS_FS_ZIP */ #ifdef CONFIG_EROFS_FS_BACKED_BY_FILE diff --git a/fs/erofs/super.c b/fs/erofs/super.c index cadec6b1b554..8e8d3a7c8dba 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -17,6 +17,7 @@ #include <trace/events/erofs.h> static struct kmem_cache *erofs_inode_cachep __read_mostly; +static atomic_t erofs_mount_count = ATOMIC_INIT(0); void _erofs_printk(struct super_block *sb, const char *fmt, ...) { @@ -777,9 +778,28 @@ static const struct fs_context_operations erofs_context_ops = { .free = erofs_fc_free, }; +static inline int erofs_init_zip_workers_if_needed(void) +{ + int ret; + + if (atomic_inc_return(&erofs_mount_count) == 1) { + ret = z_erofs_init_workers(); + if (ret) + return ret; + } + return 0; +} + +static inline void erofs_destroy_zip_workers_if_last(void) +{ + if (atomic_dec_and_test(&erofs_mount_count)) + z_erofs_destroy_workers(); +} + static int erofs_init_fs_context(struct fs_context *fc) { struct erofs_sb_info *sbi; + int err; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) @@ -790,6 +810,12 @@ static int erofs_init_fs_context(struct fs_context *fc) kfree(sbi); return -ENOMEM; } + err = erofs_init_zip_workers_if_needed(); + if (err) { + kfree(sbi->devs); + kfree(sbi); + return err; + } fc->s_fs_info = sbi; idr_init(&sbi->devs->tree); @@ -823,6 +849,7 @@ static void erofs_kill_sb(struct super_block *sb) erofs_fscache_unregister_fs(sb); erofs_sb_free(sbi); sb->s_fs_info = NULL; + erofs_destroy_zip_workers_if_last(); } static void erofs_put_super(struct super_block *sb) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 0671184d9cf1..4cd91b798716 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -403,10 +403,32 @@ static inline int erofs_cpu_hotplug_init(void) { return 0; } static inline void erofs_cpu_hotplug_destroy(void) {} #endif -void z_erofs_exit_subsystem(void) +int z_erofs_init_workers(void) +{ + int err; + + err = erofs_init_percpu_workers(); + if (err) + return err; + + err = erofs_cpu_hotplug_init(); + if (err < 0) + goto err_cpuhp_init; + return err; + +err_cpuhp_init: + erofs_destroy_percpu_workers(); + return err; +} + +void z_erofs_destroy_workers(void) { erofs_cpu_hotplug_destroy(); erofs_destroy_percpu_workers(); +} + +void z_erofs_exit_subsystem(void) +{ destroy_workqueue(z_erofs_workqueue); z_erofs_destroy_pcluster_pool(); z_erofs_exit_decompressor(); @@ -430,19 +452,8 @@ int __init z_erofs_init_subsystem(void) goto err_workqueue_init; } - err = erofs_init_percpu_workers(); - if (err) - goto err_pcpu_worker; - - err = erofs_cpu_hotplug_init(); - if (err < 0) - goto err_cpuhp_init; return err; -err_cpuhp_init: - erofs_destroy_percpu_workers(); -err_pcpu_worker: - destroy_workqueue(z_erofs_workqueue); err_workqueue_init: z_erofs_destroy_pcluster_pool(); err_pcluster_pool: -- 2.49.0.472.ge94155a9ec-goog