Skip to content

Commit

Permalink
zswap: Defer zswap initialisation
Browse files Browse the repository at this point in the history
Enabling zswap support in the kernel configuration costs about 1.5MB
of RAM, even when zswap is not enabled at runtime. This cost can be
reduced significantly by deferring initialisation (including pool
creation) until the "enabled" parameter is set to true. There is a
small cost to this in that some initialisation code has to remain in
memory after the init phase, just in case they are needed later,
but the total size increase is negligible.

See: #3432

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
  • Loading branch information
pelwell authored and popcornmix committed Jul 14, 2023
1 parent 324504e commit 980b610
Showing 1 changed file with 29 additions and 24 deletions.
53 changes: 29 additions & 24 deletions mm/zswap.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,9 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
return NULL;
}

static __init struct zswap_pool *__zswap_pool_create_fallback(void)
static bool zswap_try_pool_create(void)
{
struct zswap_pool *pool;
bool has_comp, has_zpool;

has_comp = crypto_has_acomp(zswap_compressor, 0, 0);
Expand Down Expand Up @@ -700,9 +701,21 @@ static __init struct zswap_pool *__zswap_pool_create_fallback(void)
}

if (!has_comp || !has_zpool)
return NULL;
return false;

pool = zswap_pool_create(zswap_zpool_type, zswap_compressor);

return zswap_pool_create(zswap_zpool_type, zswap_compressor);
if (pool) {
pr_info("loaded using pool %s/%s\n", pool->tfm_name,
zpool_get_type(pool->zpool));
list_add(&pool->list, &zswap_pools);
zswap_has_pool = true;
} else {
pr_err("pool creation failed\n");
zswap_enabled = false;
}

return zswap_enabled;
}

static void zswap_pool_destroy(struct zswap_pool *pool)
Expand Down Expand Up @@ -875,16 +888,19 @@ static int zswap_zpool_param_set(const char *val,
static int zswap_enabled_param_set(const char *val,
const struct kernel_param *kp)
{
int ret;

if (zswap_init_failed) {
pr_err("can't enable, initialization failed\n");
return -ENODEV;
}
if (!zswap_has_pool && zswap_init_started) {
pr_err("can't enable, no pool configured\n");
return -ENODEV;
}

return param_set_bool(val, kp);
ret = param_set_bool(val, kp);
if (!ret && zswap_enabled && zswap_init_started && !zswap_has_pool)
if (!zswap_try_pool_create())
ret = -ENODEV;

return ret;
}

/*********************************
Expand Down Expand Up @@ -1499,7 +1515,6 @@ static int __init zswap_debugfs_init(void)
**********************************/
static int __init init_zswap(void)
{
struct zswap_pool *pool;
int ret;

zswap_init_started = true;
Expand All @@ -1523,33 +1538,23 @@ static int __init init_zswap(void)
if (ret)
goto hp_fail;

pool = __zswap_pool_create_fallback();
if (pool) {
pr_info("loaded using pool %s/%s\n", pool->tfm_name,
zpool_get_type(pool->zpool));
list_add(&pool->list, &zswap_pools);
zswap_has_pool = true;
} else {
pr_err("pool creation failed\n");
zswap_enabled = false;
}

shrink_wq = create_workqueue("zswap-shrink");
if (!shrink_wq)
goto fallback_fail;
goto hp_fail;

ret = frontswap_register_ops(&zswap_frontswap_ops);
if (ret)
goto destroy_wq;
if (zswap_debugfs_init())
pr_warn("debugfs initialization failed\n");

if (zswap_enabled)
zswap_try_pool_create();

return 0;

destroy_wq:
destroy_workqueue(shrink_wq);
fallback_fail:
if (pool)
zswap_pool_destroy(pool);
hp_fail:
cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
dstmem_fail:
Expand Down

0 comments on commit 980b610

Please sign in to comment.