@@ -81,6 +81,8 @@ static bool zswap_pool_reached_full;
8181
8282#define ZSWAP_PARAM_UNSET ""
8383
84+ static int zswap_setup (void );
85+
8486/* Enable/disable zswap */
8587static bool zswap_enabled = IS_ENABLED (CONFIG_ZSWAP_DEFAULT_ON );
8688static int zswap_enabled_param_set (const char * ,
@@ -222,6 +224,9 @@ enum zswap_init_type {
222224
223225static enum zswap_init_type zswap_init_state ;
224226
227+ /* used to ensure the integrity of initialization */
228+ static DEFINE_MUTEX (zswap_init_lock );
229+
225230/* init completed, but couldn't create the initial pool */
226231static bool zswap_has_pool ;
227232
@@ -654,7 +659,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
654659 return NULL ;
655660}
656661
657- static __init struct zswap_pool * __zswap_pool_create_fallback (void )
662+ static struct zswap_pool * __zswap_pool_create_fallback (void )
658663{
659664 bool has_comp , has_zpool ;
660665
@@ -755,29 +760,43 @@ static void zswap_pool_put(struct zswap_pool *pool)
755760* param callbacks
756761**********************************/
757762
763+ static bool zswap_pool_changed (const char * s , const struct kernel_param * kp )
764+ {
765+ /* no change required */
766+ if (!strcmp (s , * (char * * )kp -> arg ) && zswap_has_pool )
767+ return false;
768+ return true;
769+ }
770+
758771/* val must be a null-terminated string */
759772static int __zswap_param_set (const char * val , const struct kernel_param * kp ,
760773 char * type , char * compressor )
761774{
762775 struct zswap_pool * pool , * put_pool = NULL ;
763776 char * s = strstrip ((char * )val );
764- int ret ;
777+ int ret = 0 ;
778+ bool new_pool = false;
765779
780+ mutex_lock (& zswap_init_lock );
766781 switch (zswap_init_state ) {
767782 case ZSWAP_UNINIT :
768783 /* if this is load-time (pre-init) param setting,
769784 * don't create a pool; that's done during init.
770785 */
771- return param_set_charp (s , kp );
786+ ret = param_set_charp (s , kp );
787+ break ;
772788 case ZSWAP_INIT_SUCCEED :
773- /* no change required */
774- if (!strcmp (s , * (char * * )kp -> arg ) && zswap_has_pool )
775- return 0 ;
789+ new_pool = zswap_pool_changed (s , kp );
776790 break ;
777791 case ZSWAP_INIT_FAILED :
778792 pr_err ("can't set param, initialization failed\n" );
779- return - ENODEV ;
793+ ret = - ENODEV ;
780794 }
795+ mutex_unlock (& zswap_init_lock );
796+
797+ /* no need to create a new pool, return directly */
798+ if (!new_pool )
799+ return ret ;
781800
782801 if (!type ) {
783802 if (!zpool_has_pool (s )) {
@@ -867,19 +886,30 @@ static int zswap_zpool_param_set(const char *val,
867886static int zswap_enabled_param_set (const char * val ,
868887 const struct kernel_param * kp )
869888{
889+ int ret = - ENODEV ;
890+
891+ /* if this is load-time (pre-init) param setting, only set param. */
892+ if (system_state != SYSTEM_RUNNING )
893+ return param_set_bool (val , kp );
894+
895+ mutex_lock (& zswap_init_lock );
870896 switch (zswap_init_state ) {
871897 case ZSWAP_UNINIT :
872- return param_set_bool (val , kp );
898+ if (zswap_setup ())
899+ break ;
900+ fallthrough ;
873901 case ZSWAP_INIT_SUCCEED :
874- if (!zswap_has_pool ) {
902+ if (!zswap_has_pool )
875903 pr_err ("can't enable, no pool configured\n" );
876- return - ENODEV ;
877- } else
878- return param_set_bool ( val , kp ) ;
904+ else
905+ ret = param_set_bool ( val , kp );
906+ break ;
879907 case ZSWAP_INIT_FAILED :
880908 pr_err ("can't enable, initialization failed\n" );
881- return - ENODEV ;
882909 }
910+ mutex_unlock (& zswap_init_lock );
911+
912+ return ret ;
883913}
884914
885915/*********************************
@@ -1437,7 +1467,7 @@ static const struct frontswap_ops zswap_frontswap_ops = {
14371467
14381468static struct dentry * zswap_debugfs_root ;
14391469
1440- static int __init zswap_debugfs_init (void )
1470+ static int zswap_debugfs_init (void )
14411471{
14421472 if (!debugfs_initialized ())
14431473 return - ENODEV ;
@@ -1468,7 +1498,7 @@ static int __init zswap_debugfs_init(void)
14681498 return 0 ;
14691499}
14701500#else
1471- static int __init zswap_debugfs_init (void )
1501+ static int zswap_debugfs_init (void )
14721502{
14731503 return 0 ;
14741504}
@@ -1477,7 +1507,7 @@ static int __init zswap_debugfs_init(void)
14771507/*********************************
14781508* module init and exit
14791509**********************************/
1480- static int __init init_zswap (void )
1510+ static int zswap_setup (void )
14811511{
14821512 struct zswap_pool * pool ;
14831513 int ret ;
@@ -1540,8 +1570,15 @@ static int __init init_zswap(void)
15401570 zswap_enabled = false;
15411571 return - ENOMEM ;
15421572}
1573+
1574+ static int __init zswap_init (void )
1575+ {
1576+ if (!zswap_enabled )
1577+ return 0 ;
1578+ return zswap_setup ();
1579+ }
15431580/* must be late so crypto has time to come up */
1544- late_initcall (init_zswap );
1581+ late_initcall (zswap_init );
15451582
15461583MODULE_LICENSE ("GPL" );
15471584MODULE_AUTHOR ("Seth Jennings <sjennings@variantweb.net>" );
0 commit comments