aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorDan Streetman <ddstreet@ieee.org>2015-09-09 18:35:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:29:01 -0400
commit90b0fc26d5dbe21c7a21668320b276af9b2281d7 (patch)
tree309a8470f6b1e6e36b4810e33b2a4b3e2603b88f /mm
parentf1c54846ee4504d89b59b04d870831db4046b478 (diff)
zswap: change zpool/compressor at runtime
Update the zpool and compressor parameters to be changeable at runtime. When changed, a new pool is created with the requested zpool/compressor, and added as the current pool at the front of the pool list. Previous pools remain in the list only to remove existing compressed pages from. The old pool(s) are removed once they become empty. Signed-off-by: Dan Streetman <ddstreet@ieee.org> Acked-by: Seth Jennings <sjennings@variantweb.net> Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/zswap.c142
1 files changed, 129 insertions, 13 deletions
diff --git a/mm/zswap.c b/mm/zswap.c
index f9ba9bb1c1b8..4043df7c672f 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -80,23 +80,39 @@ static u64 zswap_duplicate_entry;
80static bool zswap_enabled; 80static bool zswap_enabled;
81module_param_named(enabled, zswap_enabled, bool, 0644); 81module_param_named(enabled, zswap_enabled, bool, 0644);
82 82
83/* Compressor to be used by zswap (fixed at boot for now) */ 83/* Crypto compressor to use */
84#define ZSWAP_COMPRESSOR_DEFAULT "lzo" 84#define ZSWAP_COMPRESSOR_DEFAULT "lzo"
85static char *zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT; 85static char zswap_compressor[CRYPTO_MAX_ALG_NAME] = ZSWAP_COMPRESSOR_DEFAULT;
86module_param_named(compressor, zswap_compressor, charp, 0444); 86static struct kparam_string zswap_compressor_kparam = {
87 87 .string = zswap_compressor,
88/* The maximum percentage of memory that the compressed pool can occupy */ 88 .maxlen = sizeof(zswap_compressor),
89static unsigned int zswap_max_pool_percent = 20; 89};
90module_param_named(max_pool_percent, 90static int zswap_compressor_param_set(const char *,
91 zswap_max_pool_percent, uint, 0644); 91 const struct kernel_param *);
92static struct kernel_param_ops zswap_compressor_param_ops = {
93 .set = zswap_compressor_param_set,
94 .get = param_get_string,
95};
96module_param_cb(compressor, &zswap_compressor_param_ops,
97 &zswap_compressor_kparam, 0644);
92 98
93/* Compressed storage to use */ 99/* Compressed storage zpool to use */
94#define ZSWAP_ZPOOL_DEFAULT "zbud" 100#define ZSWAP_ZPOOL_DEFAULT "zbud"
95static char *zswap_zpool_type = ZSWAP_ZPOOL_DEFAULT; 101static char zswap_zpool_type[32 /* arbitrary */] = ZSWAP_ZPOOL_DEFAULT;
96module_param_named(zpool, zswap_zpool_type, charp, 0444); 102static struct kparam_string zswap_zpool_kparam = {
103 .string = zswap_zpool_type,
104 .maxlen = sizeof(zswap_zpool_type),
105};
106static int zswap_zpool_param_set(const char *, const struct kernel_param *);
107static struct kernel_param_ops zswap_zpool_param_ops = {
108 .set = zswap_zpool_param_set,
109 .get = param_get_string,
110};
111module_param_cb(zpool, &zswap_zpool_param_ops, &zswap_zpool_kparam, 0644);
97 112
98/* zpool is shared by all of zswap backend */ 113/* The maximum percentage of memory that the compressed pool can occupy */
99static struct zpool *zswap_pool; 114static unsigned int zswap_max_pool_percent = 20;
115module_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644);
100 116
101/********************************* 117/*********************************
102* data structures 118* data structures
@@ -161,6 +177,9 @@ static LIST_HEAD(zswap_pools);
161/* protects zswap_pools list modification */ 177/* protects zswap_pools list modification */
162static DEFINE_SPINLOCK(zswap_pools_lock); 178static DEFINE_SPINLOCK(zswap_pools_lock);
163 179
180/* used by param callback function */
181static bool zswap_init_started;
182
164/********************************* 183/*********************************
165* helpers and fwd declarations 184* helpers and fwd declarations
166**********************************/ 185**********************************/
@@ -662,6 +681,101 @@ static void zswap_pool_put(struct zswap_pool *pool)
662} 681}
663 682
664/********************************* 683/*********************************
684* param callbacks
685**********************************/
686
687static int __zswap_param_set(const char *val, const struct kernel_param *kp,
688 char *type, char *compressor)
689{
690 struct zswap_pool *pool, *put_pool = NULL;
691 char str[kp->str->maxlen], *s;
692 int ret;
693
694 /*
695 * kp is either zswap_zpool_kparam or zswap_compressor_kparam, defined
696 * at the top of this file, so maxlen is CRYPTO_MAX_ALG_NAME (64) or
697 * 32 (arbitrary).
698 */
699 strlcpy(str, val, kp->str->maxlen);
700 s = strim(str);
701
702 /* if this is load-time (pre-init) param setting,
703 * don't create a pool; that's done during init.
704 */
705 if (!zswap_init_started)
706 return param_set_copystring(s, kp);
707
708 /* no change required */
709 if (!strncmp(kp->str->string, s, kp->str->maxlen))
710 return 0;
711
712 if (!type) {
713 type = s;
714 if (!zpool_has_pool(type)) {
715 pr_err("zpool %s not available\n", type);
716 return -ENOENT;
717 }
718 } else if (!compressor) {
719 compressor = s;
720 if (!crypto_has_comp(compressor, 0, 0)) {
721 pr_err("compressor %s not available\n", compressor);
722 return -ENOENT;
723 }
724 }
725
726 spin_lock(&zswap_pools_lock);
727
728 pool = zswap_pool_find_get(type, compressor);
729 if (pool) {
730 zswap_pool_debug("using existing", pool);
731 list_del_rcu(&pool->list);
732 } else {
733 spin_unlock(&zswap_pools_lock);
734 pool = zswap_pool_create(type, compressor);
735 spin_lock(&zswap_pools_lock);
736 }
737
738 if (pool)
739 ret = param_set_copystring(s, kp);
740 else
741 ret = -EINVAL;
742
743 if (!ret) {
744 put_pool = zswap_pool_current();
745 list_add_rcu(&pool->list, &zswap_pools);
746 } else if (pool) {
747 /* add the possibly pre-existing pool to the end of the pools
748 * list; if it's new (and empty) then it'll be removed and
749 * destroyed by the put after we drop the lock
750 */
751 list_add_tail_rcu(&pool->list, &zswap_pools);
752 put_pool = pool;
753 }
754
755 spin_unlock(&zswap_pools_lock);
756
757 /* drop the ref from either the old current pool,
758 * or the new pool we failed to add
759 */
760 if (put_pool)
761 zswap_pool_put(put_pool);
762
763 return ret;
764}
765
766static int zswap_compressor_param_set(const char *val,
767 const struct kernel_param *kp)
768{
769 return __zswap_param_set(val, kp, zswap_zpool_type, NULL);
770}
771
772static int zswap_zpool_param_set(const char *val,
773 const struct kernel_param *kp)
774{
775 return __zswap_param_set(val, kp, NULL, zswap_compressor);
776}
777
778/*********************************
665* writeback code 779* writeback code
666**********************************/ 780**********************************/
667/* return enum for zswap_get_swap_cache_page */ 781/* return enum for zswap_get_swap_cache_page */
@@ -1114,6 +1228,8 @@ static int __init init_zswap(void)
1114{ 1228{
1115 struct zswap_pool *pool; 1229 struct zswap_pool *pool;
1116 1230
1231 zswap_init_started = true;
1232
1117 if (zswap_entry_cache_create()) { 1233 if (zswap_entry_cache_create()) {
1118 pr_err("entry cache creation failed\n"); 1234 pr_err("entry cache creation failed\n");
1119 goto cache_fail; 1235 goto cache_fail;