summaryrefslogtreecommitdiffstats
path: root/mm/zswap.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-11-26 18:13:40 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-12-01 18:52:36 -0500
commitcab7a7e5b6c5c2638b00c72559ff9fb715583c98 (patch)
treefdea606d6c8739f33ec3444e69b40a534645caea /mm/zswap.c
parentad7ed7708db9ff388450935645816d44bf08a56d (diff)
mm/zswap: Convert pool to hotplug state machine
Install the callbacks via the state machine. Multi state is used to address the per-pool notifier. Uppon adding of the intance the callback is invoked for all online CPUs so the manual init can go. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: linux-mm@kvack.org Cc: Seth Jennings <sjenning@redhat.com> Cc: rt@linutronix.de Link: http://lkml.kernel.org/r/20161126231350.10321-13-bigeasy@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'mm/zswap.c')
-rw-r--r--mm/zswap.c99
1 files changed, 34 insertions, 65 deletions
diff --git a/mm/zswap.c b/mm/zswap.c
index b13aa5706348..067a0d62f318 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -118,7 +118,7 @@ struct zswap_pool {
118 struct kref kref; 118 struct kref kref;
119 struct list_head list; 119 struct list_head list;
120 struct work_struct work; 120 struct work_struct work;
121 struct notifier_block notifier; 121 struct hlist_node node;
122 char tfm_name[CRYPTO_MAX_ALG_NAME]; 122 char tfm_name[CRYPTO_MAX_ALG_NAME];
123}; 123};
124 124
@@ -376,77 +376,34 @@ static int zswap_dstmem_dead(unsigned int cpu)
376 return 0; 376 return 0;
377} 377}
378 378
379static int __zswap_cpu_comp_notifier(struct zswap_pool *pool, 379static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)
380 unsigned long action, unsigned long cpu)
381{ 380{
381 struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);
382 struct crypto_comp *tfm; 382 struct crypto_comp *tfm;
383 383
384 switch (action) { 384 if (WARN_ON(*per_cpu_ptr(pool->tfm, cpu)))
385 case CPU_UP_PREPARE: 385 return 0;
386 if (WARN_ON(*per_cpu_ptr(pool->tfm, cpu)))
387 break;
388 tfm = crypto_alloc_comp(pool->tfm_name, 0, 0);
389 if (IS_ERR_OR_NULL(tfm)) {
390 pr_err("could not alloc crypto comp %s : %ld\n",
391 pool->tfm_name, PTR_ERR(tfm));
392 return NOTIFY_BAD;
393 }
394 *per_cpu_ptr(pool->tfm, cpu) = tfm;
395 break;
396 case CPU_DEAD:
397 case CPU_UP_CANCELED:
398 tfm = *per_cpu_ptr(pool->tfm, cpu);
399 if (!IS_ERR_OR_NULL(tfm))
400 crypto_free_comp(tfm);
401 *per_cpu_ptr(pool->tfm, cpu) = NULL;
402 break;
403 default:
404 break;
405 }
406 return NOTIFY_OK;
407}
408
409static int zswap_cpu_comp_notifier(struct notifier_block *nb,
410 unsigned long action, void *pcpu)
411{
412 unsigned long cpu = (unsigned long)pcpu;
413 struct zswap_pool *pool = container_of(nb, typeof(*pool), notifier);
414
415 return __zswap_cpu_comp_notifier(pool, action, cpu);
416}
417 386
418static int zswap_cpu_comp_init(struct zswap_pool *pool) 387 tfm = crypto_alloc_comp(pool->tfm_name, 0, 0);
419{ 388 if (IS_ERR_OR_NULL(tfm)) {
420 unsigned long cpu; 389 pr_err("could not alloc crypto comp %s : %ld\n",
421 390 pool->tfm_name, PTR_ERR(tfm));
422 memset(&pool->notifier, 0, sizeof(pool->notifier)); 391 return -ENOMEM;
423 pool->notifier.notifier_call = zswap_cpu_comp_notifier; 392 }
424 393 *per_cpu_ptr(pool->tfm, cpu) = tfm;
425 cpu_notifier_register_begin();
426 for_each_online_cpu(cpu)
427 if (__zswap_cpu_comp_notifier(pool, CPU_UP_PREPARE, cpu) ==
428 NOTIFY_BAD)
429 goto cleanup;
430 __register_cpu_notifier(&pool->notifier);
431 cpu_notifier_register_done();
432 return 0; 394 return 0;
433
434cleanup:
435 for_each_online_cpu(cpu)
436 __zswap_cpu_comp_notifier(pool, CPU_UP_CANCELED, cpu);
437 cpu_notifier_register_done();
438 return -ENOMEM;
439} 395}
440 396
441static void zswap_cpu_comp_destroy(struct zswap_pool *pool) 397static int zswap_cpu_comp_dead(unsigned int cpu, struct hlist_node *node)
442{ 398{
443 unsigned long cpu; 399 struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);
400 struct crypto_comp *tfm;
444 401
445 cpu_notifier_register_begin(); 402 tfm = *per_cpu_ptr(pool->tfm, cpu);
446 for_each_online_cpu(cpu) 403 if (!IS_ERR_OR_NULL(tfm))
447 __zswap_cpu_comp_notifier(pool, CPU_UP_CANCELED, cpu); 404 crypto_free_comp(tfm);
448 __unregister_cpu_notifier(&pool->notifier); 405 *per_cpu_ptr(pool->tfm, cpu) = NULL;
449 cpu_notifier_register_done(); 406 return 0;
450} 407}
451 408
452/********************************* 409/*********************************
@@ -527,6 +484,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
527 struct zswap_pool *pool; 484 struct zswap_pool *pool;
528 char name[38]; /* 'zswap' + 32 char (max) num + \0 */ 485 char name[38]; /* 'zswap' + 32 char (max) num + \0 */
529 gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM; 486 gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
487 int ret;
530 488
531 pool = kzalloc(sizeof(*pool), GFP_KERNEL); 489 pool = kzalloc(sizeof(*pool), GFP_KERNEL);
532 if (!pool) { 490 if (!pool) {
@@ -551,7 +509,9 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
551 goto error; 509 goto error;
552 } 510 }
553 511
554 if (zswap_cpu_comp_init(pool)) 512 ret = cpuhp_state_add_instance(CPUHP_MM_ZSWP_POOL_PREPARE,
513 &pool->node);
514 if (ret)
555 goto error; 515 goto error;
556 pr_debug("using %s compressor\n", pool->tfm_name); 516 pr_debug("using %s compressor\n", pool->tfm_name);
557 517
@@ -605,7 +565,7 @@ static void zswap_pool_destroy(struct zswap_pool *pool)
605{ 565{
606 zswap_pool_debug("destroying", pool); 566 zswap_pool_debug("destroying", pool);
607 567
608 zswap_cpu_comp_destroy(pool); 568 cpuhp_state_remove_instance(CPUHP_MM_ZSWP_POOL_PREPARE, &pool->node);
609 free_percpu(pool->tfm); 569 free_percpu(pool->tfm);
610 zpool_destroy_pool(pool->zpool); 570 zpool_destroy_pool(pool->zpool);
611 kfree(pool); 571 kfree(pool);
@@ -1212,6 +1172,13 @@ static int __init init_zswap(void)
1212 goto dstmem_fail; 1172 goto dstmem_fail;
1213 } 1173 }
1214 1174
1175 ret = cpuhp_setup_state_multi(CPUHP_MM_ZSWP_POOL_PREPARE,
1176 "mm/zswap_pool:prepare",
1177 zswap_cpu_comp_prepare,
1178 zswap_cpu_comp_dead);
1179 if (ret)
1180 goto hp_fail;
1181
1215 pool = __zswap_pool_create_fallback(); 1182 pool = __zswap_pool_create_fallback();
1216 if (!pool) { 1183 if (!pool) {
1217 pr_err("pool creation failed\n"); 1184 pr_err("pool creation failed\n");
@@ -1228,6 +1195,8 @@ static int __init init_zswap(void)
1228 return 0; 1195 return 0;
1229 1196
1230pool_fail: 1197pool_fail:
1198 cpuhp_remove_state_nocalls(CPUHP_MM_ZSWP_POOL_PREPARE);
1199hp_fail:
1231 cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); 1200 cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
1232dstmem_fail: 1201dstmem_fail:
1233 zswap_entry_cache_destroy(); 1202 zswap_entry_cache_destroy();