Since some users may not use zswap, the zswap_pool is wasted. Save memory by delaying the initialization of zswap until enabled. Signed-off-by: Liu Shixin <liushixin2@xxxxxxxxxx> --- mm/zswap.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/mm/zswap.c b/mm/zswap.c index 9eda48c8b8dc..af98bd8d4b79 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -81,6 +81,8 @@ static bool zswap_pool_reached_full; #define ZSWAP_PARAM_UNSET "" +static int zswap_setup(void); + /* Enable/disable zswap */ static bool zswap_enabled = IS_ENABLED(CONFIG_ZSWAP_DEFAULT_ON); static int zswap_enabled_param_set(const char *, @@ -220,6 +222,9 @@ static atomic_t zswap_pools_count = ATOMIC_INIT(0); static int zswap_init_state; +/* used to ensure the integrity of initialization */ +static DEFINE_MUTEX(zswap_init_lock); + /* init completed, but couldn't create the initial pool */ static bool zswap_has_pool; @@ -652,7 +657,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor) return NULL; } -static __init struct zswap_pool *__zswap_pool_create_fallback(void) +static struct zswap_pool *__zswap_pool_create_fallback(void) { bool has_comp, has_zpool; @@ -765,16 +770,22 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp, if (!strcmp(s, *(char **)kp->arg) && zswap_has_pool) return 0; + mutex_lock(&zswap_init_lock); if (zswap_init_state == ZSWAP_INIT_FAILED) { pr_err("can't set param, initialization failed\n"); + mutex_unlock(&zswap_init_lock); return -ENODEV; } /* if this is load-time (pre-init) param setting, * don't create a pool; that's done during init. */ - if (zswap_init_state == ZSWAP_UNINIT) - return param_set_charp(s, kp); + if (zswap_init_state == ZSWAP_UNINIT) { + ret = param_set_charp(s, kp); + mutex_unlock(&zswap_init_lock); + return ret; + } + mutex_unlock(&zswap_init_lock); if (!type) { if (!zpool_has_pool(s)) { @@ -873,14 +884,23 @@ static int zswap_enabled_param_set(const char *val, if (res == *(bool *)kp->arg) return 0; + mutex_lock(&zswap_init_lock); + if (system_state == SYSTEM_RUNNING && zswap_setup()) { + mutex_unlock(&zswap_init_lock); + return -ENODEV; + } + if (zswap_init_state == ZSWAP_INIT_FAILED) { pr_err("can't enable, initialization failed\n"); + mutex_unlock(&zswap_init_lock); return -ENODEV; } if (!zswap_has_pool && (zswap_init_state == ZSWAP_INIT_SUCCEED)) { pr_err("can't enable, no pool configured\n"); + mutex_unlock(&zswap_init_lock); return -ENODEV; } + mutex_unlock(&zswap_init_lock); return param_set_bool(val, kp); } @@ -1440,7 +1460,7 @@ static const struct frontswap_ops zswap_frontswap_ops = { static struct dentry *zswap_debugfs_root; -static int __init zswap_debugfs_init(void) +static int zswap_debugfs_init(void) { if (!debugfs_initialized()) return -ENODEV; @@ -1471,7 +1491,7 @@ static int __init zswap_debugfs_init(void) return 0; } #else -static int __init zswap_debugfs_init(void) +static int zswap_debugfs_init(void) { return 0; } @@ -1480,11 +1500,14 @@ static int __init zswap_debugfs_init(void) /********************************* * module init and exit **********************************/ -static int __init init_zswap(void) +static int zswap_setup(void) { struct zswap_pool *pool; int ret; + if (zswap_init_state != ZSWAP_UNINIT) + return 0; + zswap_entry_cache = KMEM_CACHE(zswap_entry, 0); if (!zswap_entry_cache) { pr_err("entry cache creation failed\n"); @@ -1543,8 +1566,15 @@ static int __init init_zswap(void) zswap_enabled = false; return -ENOMEM; } + +static int __init zswap_init(void) +{ + if (!zswap_enabled) + return 0; + return zswap_setup(); +} /* must be late so crypto has time to come up */ -late_initcall(init_zswap); +late_initcall(zswap_init); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Seth Jennings <sjennings@xxxxxxxxxxxxxx>"); -- 2.25.1