Skip to content

Commit 90b0fc2

Browse files
ddstreettorvalds
authored andcommitted
zswap: change zpool/compressor at runtime
Update the zpool and compressor parameters to be changeable at runtime. When changed, a new pool is created with the requested zpool/compressor, and added as the current pool at the front of the pool list. Previous pools remain in the list only to remove existing compressed pages from. The old pool(s) are removed once they become empty. Signed-off-by: Dan Streetman <[email protected]> Acked-by: Seth Jennings <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f1c5484 commit 90b0fc2

File tree

1 file changed

+129
-13
lines changed

1 file changed

+129
-13
lines changed

mm/zswap.c

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,39 @@ static u64 zswap_duplicate_entry;
8080
static bool zswap_enabled;
8181
module_param_named(enabled, zswap_enabled, bool, 0644);
8282

83-
/* Compressor to be used by zswap (fixed at boot for now) */
83+
/* Crypto compressor to use */
8484
#define ZSWAP_COMPRESSOR_DEFAULT "lzo"
85-
static char *zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT;
86-
module_param_named(compressor, zswap_compressor, charp, 0444);
87-
88-
/* The maximum percentage of memory that the compressed pool can occupy */
89-
static unsigned int zswap_max_pool_percent = 20;
90-
module_param_named(max_pool_percent,
91-
zswap_max_pool_percent, uint, 0644);
85+
static char zswap_compressor[CRYPTO_MAX_ALG_NAME] = ZSWAP_COMPRESSOR_DEFAULT;
86+
static struct kparam_string zswap_compressor_kparam = {
87+
.string = zswap_compressor,
88+
.maxlen = sizeof(zswap_compressor),
89+
};
90+
static int zswap_compressor_param_set(const char *,
91+
const struct kernel_param *);
92+
static struct kernel_param_ops zswap_compressor_param_ops = {
93+
.set = zswap_compressor_param_set,
94+
.get = param_get_string,
95+
};
96+
module_param_cb(compressor, &zswap_compressor_param_ops,
97+
&zswap_compressor_kparam, 0644);
9298

93-
/* Compressed storage to use */
99+
/* Compressed storage zpool to use */
94100
#define ZSWAP_ZPOOL_DEFAULT "zbud"
95-
static char *zswap_zpool_type = ZSWAP_ZPOOL_DEFAULT;
96-
module_param_named(zpool, zswap_zpool_type, charp, 0444);
101+
static char zswap_zpool_type[32 /* arbitrary */] = ZSWAP_ZPOOL_DEFAULT;
102+
static struct kparam_string zswap_zpool_kparam = {
103+
.string = zswap_zpool_type,
104+
.maxlen = sizeof(zswap_zpool_type),
105+
};
106+
static int zswap_zpool_param_set(const char *, const struct kernel_param *);
107+
static struct kernel_param_ops zswap_zpool_param_ops = {
108+
.set = zswap_zpool_param_set,
109+
.get = param_get_string,
110+
};
111+
module_param_cb(zpool, &zswap_zpool_param_ops, &zswap_zpool_kparam, 0644);
97112

98-
/* zpool is shared by all of zswap backend */
99-
static struct zpool *zswap_pool;
113+
/* The maximum percentage of memory that the compressed pool can occupy */
114+
static unsigned int zswap_max_pool_percent = 20;
115+
module_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644);
100116

101117
/*********************************
102118
* data structures
@@ -161,6 +177,9 @@ static LIST_HEAD(zswap_pools);
161177
/* protects zswap_pools list modification */
162178
static DEFINE_SPINLOCK(zswap_pools_lock);
163179

180+
/* used by param callback function */
181+
static bool zswap_init_started;
182+
164183
/*********************************
165184
* helpers and fwd declarations
166185
**********************************/
@@ -661,6 +680,101 @@ static void zswap_pool_put(struct zswap_pool *pool)
661680
kref_put(&pool->kref, __zswap_pool_empty);
662681
}
663682

683+
/*********************************
684+
* param callbacks
685+
**********************************/
686+
687+
static int __zswap_param_set(const char *val, const struct kernel_param *kp,
688+
char *type, char *compressor)
689+
{
690+
struct zswap_pool *pool, *put_pool = NULL;
691+
char str[kp->str->maxlen], *s;
692+
int ret;
693+
694+
/*
695+
* kp is either zswap_zpool_kparam or zswap_compressor_kparam, defined
696+
* at the top of this file, so maxlen is CRYPTO_MAX_ALG_NAME (64) or
697+
* 32 (arbitrary).
698+
*/
699+
strlcpy(str, val, kp->str->maxlen);
700+
s = strim(str);
701+
702+
/* if this is load-time (pre-init) param setting,
703+
* don't create a pool; that's done during init.
704+
*/
705+
if (!zswap_init_started)
706+
return param_set_copystring(s, kp);
707+
708+
/* no change required */
709+
if (!strncmp(kp->str->string, s, kp->str->maxlen))
710+
return 0;
711+
712+
if (!type) {
713+
type = s;
714+
if (!zpool_has_pool(type)) {
715+
pr_err("zpool %s not available\n", type);
716+
return -ENOENT;
717+
}
718+
} else if (!compressor) {
719+
compressor = s;
720+
if (!crypto_has_comp(compressor, 0, 0)) {
721+
pr_err("compressor %s not available\n", compressor);
722+
return -ENOENT;
723+
}
724+
}
725+
726+
spin_lock(&zswap_pools_lock);
727+
728+
pool = zswap_pool_find_get(type, compressor);
729+
if (pool) {
730+
zswap_pool_debug("using existing", pool);
731+
list_del_rcu(&pool->list);
732+
} else {
733+
spin_unlock(&zswap_pools_lock);
734+
pool = zswap_pool_create(type, compressor);
735+
spin_lock(&zswap_pools_lock);
736+
}
737+
738+
if (pool)
739+
ret = param_set_copystring(s, kp);
740+
else
741+
ret = -EINVAL;
742+
743+
if (!ret) {
744+
put_pool = zswap_pool_current();
745+
list_add_rcu(&pool->list, &zswap_pools);
746+
} else if (pool) {
747+
/* add the possibly pre-existing pool to the end of the pools
748+
* list; if it's new (and empty) then it'll be removed and
749+
* destroyed by the put after we drop the lock
750+
*/
751+
list_add_tail_rcu(&pool->list, &zswap_pools);
752+
put_pool = pool;
753+
}
754+
755+
spin_unlock(&zswap_pools_lock);
756+
757+
/* drop the ref from either the old current pool,
758+
* or the new pool we failed to add
759+
*/
760+
if (put_pool)
761+
zswap_pool_put(put_pool);
762+
763+
return ret;
764+
}
765+
766+
static int zswap_compressor_param_set(const char *val,
767+
const struct kernel_param *kp)
768+
{
769+
return __zswap_param_set(val, kp, zswap_zpool_type, NULL);
770+
}
771+
772+
static int zswap_zpool_param_set(const char *val,
773+
const struct kernel_param *kp)
774+
{
775+
return __zswap_param_set(val, kp, NULL, zswap_compressor);
776+
}
777+
664778
/*********************************
665779
* writeback code
666780
**********************************/
@@ -1114,6 +1228,8 @@ static int __init init_zswap(void)
11141228
{
11151229
struct zswap_pool *pool;
11161230

1231+
zswap_init_started = true;
1232+
11171233
if (zswap_entry_cache_create()) {
11181234
pr_err("entry cache creation failed\n");
11191235
goto cache_fail;

0 commit comments

Comments
 (0)