summaryrefslogtreecommitdiffstats
path: root/mm/zswap.c
diff options
context:
space:
mode:
authorDan Streetman <ddstreet@ieee.org>2017-02-27 17:26:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-27 21:43:45 -0500
commitae3d89a7e0871bc7b57ef8d3c4dd7fdda43c285c (patch)
tree21453fc7be1d56cc7c4386ed1f3ffd60af504139 /mm/zswap.c
parent01cddfe99008da87dd4f6b8fbfa31e09257b9133 (diff)
zswap: allow initialization at boot without pool
Allow zswap to initialize at boot even if it can't create its pool due to a failure to create a zpool and/or compressor. Allow those to be created later, from the sysfs module param interface. Link: http://lkml.kernel.org/r/20170124200259.16191-3-ddstreet@ieee.org Signed-off-by: Dan Streetman <dan.streetman@canonical.com> 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>
Diffstat (limited to 'mm/zswap.c')
-rw-r--r--mm/zswap.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/mm/zswap.c b/mm/zswap.c
index cabf09e0128b..77cb847938e1 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -185,6 +185,9 @@ static bool zswap_init_started;
185/* fatal error during init */ 185/* fatal error during init */
186static bool zswap_init_failed; 186static bool zswap_init_failed;
187 187
188/* init completed, but couldn't create the initial pool */
189static bool zswap_has_pool;
190
188/********************************* 191/*********************************
189* helpers and fwd declarations 192* helpers and fwd declarations
190**********************************/ 193**********************************/
@@ -424,7 +427,8 @@ static struct zswap_pool *__zswap_pool_current(void)
424 struct zswap_pool *pool; 427 struct zswap_pool *pool;
425 428
426 pool = list_first_or_null_rcu(&zswap_pools, typeof(*pool), list); 429 pool = list_first_or_null_rcu(&zswap_pools, typeof(*pool), list);
427 WARN_ON(!pool); 430 WARN_ONCE(!pool && zswap_has_pool,
431 "%s: no page storage pool!\n", __func__);
428 432
429 return pool; 433 return pool;
430} 434}
@@ -443,7 +447,7 @@ static struct zswap_pool *zswap_pool_current_get(void)
443 rcu_read_lock(); 447 rcu_read_lock();
444 448
445 pool = __zswap_pool_current(); 449 pool = __zswap_pool_current();
446 if (!pool || !zswap_pool_get(pool)) 450 if (!zswap_pool_get(pool))
447 pool = NULL; 451 pool = NULL;
448 452
449 rcu_read_unlock(); 453 rcu_read_unlock();
@@ -459,7 +463,9 @@ static struct zswap_pool *zswap_pool_last_get(void)
459 463
460 list_for_each_entry_rcu(pool, &zswap_pools, list) 464 list_for_each_entry_rcu(pool, &zswap_pools, list)
461 last = pool; 465 last = pool;
462 if (!WARN_ON(!last) && !zswap_pool_get(last)) 466 WARN_ONCE(!last && zswap_has_pool,
467 "%s: no page storage pool!\n", __func__);
468 if (!zswap_pool_get(last))
463 last = NULL; 469 last = NULL;
464 470
465 rcu_read_unlock(); 471 rcu_read_unlock();
@@ -582,6 +588,9 @@ static void zswap_pool_destroy(struct zswap_pool *pool)
582 588
583static int __must_check zswap_pool_get(struct zswap_pool *pool) 589static int __must_check zswap_pool_get(struct zswap_pool *pool)
584{ 590{
591 if (!pool)
592 return 0;
593
585 return kref_get_unless_zero(&pool->kref); 594 return kref_get_unless_zero(&pool->kref);
586} 595}
587 596
@@ -639,7 +648,7 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
639 } 648 }
640 649
641 /* no change required */ 650 /* no change required */
642 if (!strcmp(s, *(char **)kp->arg)) 651 if (!strcmp(s, *(char **)kp->arg) && zswap_has_pool)
643 return 0; 652 return 0;
644 653
645 /* if this is load-time (pre-init) param setting, 654 /* if this is load-time (pre-init) param setting,
@@ -685,6 +694,7 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
685 if (!ret) { 694 if (!ret) {
686 put_pool = zswap_pool_current(); 695 put_pool = zswap_pool_current();
687 list_add_rcu(&pool->list, &zswap_pools); 696 list_add_rcu(&pool->list, &zswap_pools);
697 zswap_has_pool = true;
688 } else if (pool) { 698 } else if (pool) {
689 /* add the possibly pre-existing pool to the end of the pools 699 /* add the possibly pre-existing pool to the end of the pools
690 * list; if it's new (and empty) then it'll be removed and 700 * list; if it's new (and empty) then it'll be removed and
@@ -692,6 +702,15 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
692 */ 702 */
693 list_add_tail_rcu(&pool->list, &zswap_pools); 703 list_add_tail_rcu(&pool->list, &zswap_pools);
694 put_pool = pool; 704 put_pool = pool;
705 } else if (!zswap_has_pool) {
706 /* if initial pool creation failed, and this pool creation also
707 * failed, maybe both compressor and zpool params were bad.
708 * Allow changing this param, so pool creation will succeed
709 * when the other param is changed. We already verified this
710 * param is ok in the zpool_has_pool() or crypto_has_comp()
711 * checks above.
712 */
713 ret = param_set_charp(s, kp);
695 } 714 }
696 715
697 spin_unlock(&zswap_pools_lock); 716 spin_unlock(&zswap_pools_lock);
@@ -724,6 +743,10 @@ static int zswap_enabled_param_set(const char *val,
724 pr_err("can't enable, initialization failed\n"); 743 pr_err("can't enable, initialization failed\n");
725 return -ENODEV; 744 return -ENODEV;
726 } 745 }
746 if (!zswap_has_pool && zswap_init_started) {
747 pr_err("can't enable, no pool configured\n");
748 return -ENODEV;
749 }
727 750
728 return param_set_bool(val, kp); 751 return param_set_bool(val, kp);
729} 752}
@@ -1205,22 +1228,21 @@ static int __init init_zswap(void)
1205 goto hp_fail; 1228 goto hp_fail;
1206 1229
1207 pool = __zswap_pool_create_fallback(); 1230 pool = __zswap_pool_create_fallback();
1208 if (!pool) { 1231 if (pool) {
1232 pr_info("loaded using pool %s/%s\n", pool->tfm_name,
1233 zpool_get_type(pool->zpool));
1234 list_add(&pool->list, &zswap_pools);
1235 zswap_has_pool = true;
1236 } else {
1209 pr_err("pool creation failed\n"); 1237 pr_err("pool creation failed\n");
1210 goto pool_fail; 1238 zswap_enabled = false;
1211 } 1239 }
1212 pr_info("loaded using pool %s/%s\n", pool->tfm_name,
1213 zpool_get_type(pool->zpool));
1214
1215 list_add(&pool->list, &zswap_pools);
1216 1240
1217 frontswap_register_ops(&zswap_frontswap_ops); 1241 frontswap_register_ops(&zswap_frontswap_ops);
1218 if (zswap_debugfs_init()) 1242 if (zswap_debugfs_init())
1219 pr_warn("debugfs initialization failed\n"); 1243 pr_warn("debugfs initialization failed\n");
1220 return 0; 1244 return 0;
1221 1245
1222pool_fail:
1223 cpuhp_remove_state_nocalls(CPUHP_MM_ZSWP_POOL_PREPARE);
1224hp_fail: 1246hp_fail:
1225 cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); 1247 cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
1226dstmem_fail: 1248dstmem_fail: