Skip to content

Commit 7aeb95c

Browse files
ddstreetgregkh
authored andcommitted
zswap: disable changing params if init fails
commit d7b028f56a971a2e4d8d7887540a144eeefcd4ab upstream. Add zswap_init_failed bool that prevents changing any of the module params, if init_zswap() fails, and set zswap_enabled to false. Change 'enabled' param to a callback, and check zswap_init_failed before allowing any change to 'enabled', 'zpool', or 'compressor' params. Any driver that is built-in to the kernel will not be unloaded if its init function returns error, and its module params remain accessible for users to change via sysfs. Since zswap uses param callbacks, which assume that zswap has been initialized, changing the zswap params after a failed initialization will result in WARNING due to the param callbacks expecting a pool to already exist. This prevents that by immediately exiting any of the param callbacks if initialization failed. This was reported here: https://marc.info/?l=linux-mm&m=147004228125528&w=4 And fixes this WARNING: [ 429.723476] WARNING: CPU: 0 PID: 5140 at mm/zswap.c:503 __zswap_pool_current+0x56/0x60 The warning is just noise, and not serious. However, when init fails, zswap frees all its percpu dstmem pages and its kmem cache. The kmem cache might be serious, if kmem_cache_alloc(NULL, gfp) has problems; but the percpu dstmem pages are definitely a problem, as they're used as temporary buffer for compressed pages before copying into place in the zpool. If the user does get zswap enabled after an init failure, then zswap will likely Oops on the first page it tries to compress (or worse, start corrupting memory). Fixes: 90b0fc2 ("zswap: change zpool/compressor at runtime") Link: http://lkml.kernel.org/r/20170124200259.16191-2-ddstreet@ieee.org Signed-off-by: Dan Streetman <dan.streetman@canonical.com> Reported-by: Marcin Miroslaw <marcin@mejor.pl> Cc: Seth Jennings <sjenning@redhat.com> Cc: Michal Hocko <mhocko@kernel.org> Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> Cc: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5dadebc commit 7aeb95c

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

mm/zswap.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,13 @@ static u64 zswap_duplicate_entry;
7878

7979
/* Enable/disable zswap (disabled by default) */
8080
static bool zswap_enabled;
81-
module_param_named(enabled, zswap_enabled, bool, 0644);
81+
static int zswap_enabled_param_set(const char *,
82+
const struct kernel_param *);
83+
static struct kernel_param_ops zswap_enabled_param_ops = {
84+
.set = zswap_enabled_param_set,
85+
.get = param_get_bool,
86+
};
87+
module_param_cb(enabled, &zswap_enabled_param_ops, &zswap_enabled, 0644);
8288

8389
/* Crypto compressor to use */
8490
#define ZSWAP_COMPRESSOR_DEFAULT "lzo"
@@ -176,6 +182,9 @@ static atomic_t zswap_pools_count = ATOMIC_INIT(0);
176182
/* used by param callback function */
177183
static bool zswap_init_started;
178184

185+
/* fatal error during init */
186+
static bool zswap_init_failed;
187+
179188
/*********************************
180189
* helpers and fwd declarations
181190
**********************************/
@@ -702,6 +711,11 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
702711
char *s = strstrip((char *)val);
703712
int ret;
704713

714+
if (zswap_init_failed) {
715+
pr_err("can't set param, initialization failed\n");
716+
return -ENODEV;
717+
}
718+
705719
/* no change required */
706720
if (!strcmp(s, *(char **)kp->arg))
707721
return 0;
@@ -781,6 +795,17 @@ static int zswap_zpool_param_set(const char *val,
781795
return __zswap_param_set(val, kp, NULL, zswap_compressor);
782796
}
783797

798+
static int zswap_enabled_param_set(const char *val,
799+
const struct kernel_param *kp)
800+
{
801+
if (zswap_init_failed) {
802+
pr_err("can't enable, initialization failed\n");
803+
return -ENODEV;
804+
}
805+
806+
return param_set_bool(val, kp);
807+
}
808+
784809
/*********************************
785810
* writeback code
786811
**********************************/
@@ -1267,6 +1292,9 @@ static int __init init_zswap(void)
12671292
dstmem_fail:
12681293
zswap_entry_cache_destroy();
12691294
cache_fail:
1295+
/* if built-in, we aren't unloaded on failure; don't allow use */
1296+
zswap_init_failed = true;
1297+
zswap_enabled = false;
12701298
return -ENOMEM;
12711299
}
12721300
/* must be late so crypto has time to come up */

0 commit comments

Comments
 (0)