@ -118,7 +118,7 @@ struct zswap_pool {
struct kref kref ;
struct list_head list ;
struct work_struct work ;
struct notifier_block notifier ;
struct hlist_node node ;
char tfm_name [ CRYPTO_MAX_ALG_NAME ] ;
} ;
@ -376,77 +376,34 @@ static int zswap_dstmem_dead(unsigned int cpu)
return 0 ;
}
static int __zswap_cpu_comp_notifier ( struct zswap_pool * pool ,
unsigned long action , unsigned long cpu )
static int zswap_cpu_comp_prepare ( unsigned int cpu , struct hlist_node * node )
{
struct zswap_pool * pool = hlist_entry ( node , struct zswap_pool , node ) ;
struct crypto_comp * tfm ;
switch ( action ) {
case CPU_UP_PREPARE :
if ( WARN_ON ( * per_cpu_ptr ( pool - > tfm , cpu ) ) )
break ;
tfm = crypto_alloc_comp ( pool - > tfm_name , 0 , 0 ) ;
if ( IS_ERR_OR_NULL ( tfm ) ) {
pr_err ( " could not alloc crypto comp %s : %ld \n " ,
pool - > tfm_name , PTR_ERR ( tfm ) ) ;
return NOTIFY_BAD ;
}
* per_cpu_ptr ( pool - > tfm , cpu ) = tfm ;
break ;
case CPU_DEAD :
case CPU_UP_CANCELED :
tfm = * per_cpu_ptr ( pool - > tfm , cpu ) ;
if ( ! IS_ERR_OR_NULL ( tfm ) )
crypto_free_comp ( tfm ) ;
* per_cpu_ptr ( pool - > tfm , cpu ) = NULL ;
break ;
default :
break ;
}
return NOTIFY_OK ;
}
static int zswap_cpu_comp_notifier ( struct notifier_block * nb ,
unsigned long action , void * pcpu )
{
unsigned long cpu = ( unsigned long ) pcpu ;
struct zswap_pool * pool = container_of ( nb , typeof ( * pool ) , notifier ) ;
return __zswap_cpu_comp_notifier ( pool , action , cpu ) ;
}
if ( WARN_ON ( * per_cpu_ptr ( pool - > tfm , cpu ) ) )
return 0 ;
static int zswap_cpu_comp_init ( struct zswap_pool * pool )
{
unsigned long cpu ;
memset ( & pool - > notifier , 0 , sizeof ( pool - > notifier ) ) ;
pool - > notifier . notifier_call = zswap_cpu_comp_notifier ;
cpu_notifier_register_begin ( ) ;
for_each_online_cpu ( cpu )
if ( __zswap_cpu_comp_notifier ( pool , CPU_UP_PREPARE , cpu ) = =
NOTIFY_BAD )
goto cleanup ;
__register_cpu_notifier ( & pool - > notifier ) ;
cpu_notifier_register_done ( ) ;
tfm = crypto_alloc_comp ( pool - > tfm_name , 0 , 0 ) ;
if ( IS_ERR_OR_NULL ( tfm ) ) {
pr_err ( " could not alloc crypto comp %s : %ld \n " ,
pool - > tfm_name , PTR_ERR ( tfm ) ) ;
return - ENOMEM ;
}
* per_cpu_ptr ( pool - > tfm , cpu ) = tfm ;
return 0 ;
cleanup :
for_each_online_cpu ( cpu )
__zswap_cpu_comp_notifier ( pool , CPU_UP_CANCELED , cpu ) ;
cpu_notifier_register_done ( ) ;
return - ENOMEM ;
}
static void zswap_cpu_comp_destroy ( struct zswap_pool * pool )
static int zswap_cpu_comp_dead ( unsigned int cpu , struct hlist_node * node )
{
unsigned long cpu ;
struct zswap_pool * pool = hlist_entry ( node , struct zswap_pool , node ) ;
struct crypto_comp * tfm ;
cpu_notifier_register_begin ( ) ;
for_each_online_cpu ( cpu )
__zswap_cpu_comp_notifier ( pool , CPU_UP_CANCELED , cpu ) ;
__unregister_cpu_notifier ( & pool - > notifier ) ;
cpu_notifier_register_done ( ) ;
tfm = * per_cpu_ptr ( pool - > tfm , cpu ) ;
if ( ! IS_ERR_OR_NULL ( tfm ) )
crypto_free_comp ( tfm ) ;
* per_cpu_ptr ( pool - > tfm , cpu ) = NULL ;
return 0 ;
}
/*********************************
@ -527,6 +484,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
struct zswap_pool * pool ;
char name [ 38 ] ; /* 'zswap' + 32 char (max) num + \0 */
gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM ;
int ret ;
pool = kzalloc ( sizeof ( * pool ) , GFP_KERNEL ) ;
if ( ! pool ) {
@ -551,7 +509,9 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
goto error ;
}
if ( zswap_cpu_comp_init ( pool ) )
ret = cpuhp_state_add_instance ( CPUHP_MM_ZSWP_POOL_PREPARE ,
& pool - > node ) ;
if ( ret )
goto error ;
pr_debug ( " using %s compressor \n " , pool - > tfm_name ) ;
@ -605,7 +565,7 @@ static void zswap_pool_destroy(struct zswap_pool *pool)
{
zswap_pool_debug ( " destroying " , pool ) ;
zswap_cpu_comp_destroy ( pool ) ;
cpuhp_state_remove_instance ( CPUHP_MM_ZSWP_POOL_PREPARE , & pool - > node ) ;
free_percpu ( pool - > tfm ) ;
zpool_destroy_pool ( pool - > zpool ) ;
kfree ( pool ) ;
@ -1212,6 +1172,13 @@ static int __init init_zswap(void)
goto dstmem_fail ;
}
ret = cpuhp_setup_state_multi ( CPUHP_MM_ZSWP_POOL_PREPARE ,
" mm/zswap_pool:prepare " ,
zswap_cpu_comp_prepare ,
zswap_cpu_comp_dead ) ;
if ( ret )
goto hp_fail ;
pool = __zswap_pool_create_fallback ( ) ;
if ( ! pool ) {
pr_err ( " pool creation failed \n " ) ;
@ -1228,6 +1195,8 @@ static int __init init_zswap(void)
return 0 ;
pool_fail :
cpuhp_remove_state_nocalls ( CPUHP_MM_ZSWP_POOL_PREPARE ) ;
hp_fail :
cpuhp_remove_state ( CPUHP_MM_ZSWP_MEM_PREPARE ) ;
dstmem_fail :
zswap_entry_cache_destroy ( ) ;