| From 66e0ea531f4975fed5899a2cbbfa3986fca40680 Mon Sep 17 00:00:00 2001 |
| From: Phil Elwell <phil@raspberrypi.com> |
| Date: Tue, 5 May 2020 15:23:32 +0100 |
| Subject: [PATCH] zswap: Defer zswap initialisation |
| |
| 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: https://github.com/raspberrypi/linux/pull/3432 |
| |
| Signed-off-by: Phil Elwell <phil@raspberrypi.com> |
| --- |
| mm/zswap.c | 48 ++++++++++++++++++++++++++++-------------------- |
| 1 file changed, 28 insertions(+), 20 deletions(-) |
| |
| --- a/mm/zswap.c |
| +++ b/mm/zswap.c |
| @@ -564,8 +564,9 @@ error: |
| 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_comp(zswap_compressor, 0, 0); |
| @@ -599,9 +600,21 @@ static __init struct zswap_pool *__zswap |
| } |
| |
| if (!has_comp || !has_zpool) |
| - return NULL; |
| + return false; |
| + |
| + pool = 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_pool_create(zswap_zpool_type, zswap_compressor); |
| + return zswap_enabled; |
| } |
| |
| static void zswap_pool_destroy(struct zswap_pool *pool) |
| @@ -773,16 +786,19 @@ static int zswap_zpool_param_set(const c |
| 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; |
| } |
| |
| /********************************* |
| @@ -1297,7 +1313,6 @@ static void __exit zswap_debugfs_exit(vo |
| **********************************/ |
| static int __init init_zswap(void) |
| { |
| - struct zswap_pool *pool; |
| int ret; |
| |
| zswap_init_started = true; |
| @@ -1321,20 +1336,13 @@ 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; |
| - } |
| - |
| frontswap_register_ops(&zswap_frontswap_ops); |
| if (zswap_debugfs_init()) |
| pr_warn("debugfs initialization failed\n"); |
| + |
| + if (zswap_enabled) |
| + zswap_try_pool_create(); |
| + |
| return 0; |
| |
| hp_fail: |