2023-06-08 17:49:36 +00:00
|
|
|
From cfe4cda49168a35df7a278e567542c2b7fa096c3 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 | 53 +++++++++++++++++++++++++++++------------------------
|
|
|
|
1 file changed, 29 insertions(+), 24 deletions(-)
|
|
|
|
|
|
|
|
--- a/mm/zswap.c
|
|
|
|
+++ b/mm/zswap.c
|
|
|
|
@@ -663,8 +663,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_acomp(zswap_compressor, 0, 0);
|
|
|
|
@@ -700,9 +701,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);
|
|
|
|
|
|
|
|
- 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)
|
|
|
|
@@ -875,16 +888,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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************
|
2024-03-01 21:08:40 +00:00
|
|
|
@@ -1498,7 +1514,6 @@ static int __init zswap_debugfs_init(voi
|
2023-06-08 17:49:36 +00:00
|
|
|
**********************************/
|
|
|
|
static int __init init_zswap(void)
|
|
|
|
{
|
|
|
|
- struct zswap_pool *pool;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
zswap_init_started = true;
|
2024-03-01 21:08:40 +00:00
|
|
|
@@ -1522,33 +1537,23 @@ static int __init init_zswap(void)
|
2023-06-08 17:49:36 +00:00
|
|
|
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:
|