4 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include "module-data.h"
24 #include "file-helper.h"
26 #include "swap-common.h"
27 #include "memory-cgroup.h"
28 #include "config-parser.h"
29 #include "lowmem-handler.h"
32 #define DEFAULT_ZSWAP_POOL_RATIO (25)
33 #define ZSWAP_FULLNESS_RATIO 0.8
34 #define DEFAULT_ZSWAP_FILE_SIZE MBYTE_TO_BYTE(30)
36 #define ZSWAP_POOL_PERCENT "/sys/module/zswap/parameters/max_pool_percent"
37 #define ZSWAP_POOL_TYPE "/sys/module/zswap/parameters/zpool"
38 #define ZSWAP_WRITTEN_SIZE "/sys/kernel/debug/zswap/written_back_pages"
39 #define ZSWAP_ENABLED "/sys/module/zswap/parameters/enabled"
41 struct swap_zswap_control {
42 char crypt_type[MAX_TYPE_LENGTH];
46 unsigned long zswap_reclaim_bytes;
47 char zpool_type[MAX_TYPE_LENGTH];
50 static struct swap_zswap_control zswap_control = {
52 .swapfile = SWAP_FILE_NAME,
53 .zpool_ratio = DEFAULT_ZSWAP_POOL_RATIO,
54 .zswap_file_size = DEFAULT_ZSWAP_FILE_SIZE,
55 .zswap_reclaim_bytes = 0,
59 static int swap_zswap_activate(void *data)
61 struct swap_module_ops *swap = (struct swap_module_ops *)data;
64 zswap_control.zswap_reclaim_bytes =
65 zswap_control.zswap_file_size * ZSWAP_FULLNESS_RATIO;
67 r = swap_set_file(zswap_control.swapfile, swap, zswap_control.crypt_type);
71 r = fwrite_int(ZSWAP_POOL_PERCENT, zswap_control.zpool_ratio);
73 _E("fail to write max_pool_percent: %.2f", zswap_control.zpool_ratio);
77 r = fwrite_str(ZSWAP_POOL_TYPE, zswap_control.zpool_type);
79 _E("fail to change zpool : %s use default", ZSWAP_POOL_TYPE);
81 r = fwrite_int(ZSWAP_ENABLED, true);
83 _E("fail to enable zswap");
88 static int swap_zswap_reclaim(void *data)
91 unsigned int swap_size;
93 r = fread_uint(ZSWAP_WRITTEN_SIZE, &swap_size);
95 _E("fail to read written swap size");
99 swap_size <<= PAGE_SHIFT;
100 if (swap_size <= zswap_control.zswap_reclaim_bytes)
104 * In this case, swap storage is almost full.
105 * It means that there are many background processes or
106 * some process makes memory leak.
107 * So, it requires to trigger proactive oom killer.
110 lowmem_trigger_swap_reclaim(CGROUP_ROOT, swap_size);
114 /*static int swap_zswap_parse_config_file(void)
116 ConfigTableItem items[] = {
117 { "FILE", "CryptType", config_parse_string, 0, NULL },
118 { "FILE", "FileSize", config_parse_bytes, 0, NULL },
119 { "ZSWAP", "PoolRatio", config_parse_float, 0, NULL },
120 { "ZSWAP", "PoolType", config_parse_string, 0, NULL },
121 { NULL, NULL, NULL, 0, NULL }
125 _cleanup_free_ char *crypt_type = NULL;
126 _cleanup_free_ char *zpool_type = NULL;
128 items[0].data = &crypt_type;
129 items[1].data = &zswap_control.zswap_file_size;
130 items[2].data = &zswap_control.zpool_ratio;
131 items[3].data = &zpool_type;
133 r = config_parse_new(SWAP_CONF_FILE, (void*) items);
135 _E("Failed to parse configuration file: %d", r);
139 if (check_valid_compressor(crypt_type) == RESOURCED_ERROR_NONE)
140 strncpy(zswap_control.crypt_type, crypt_type, MAX_TYPE_LENGTH-1);
142 memset(zswap_control.crypt_type, 0, MAX_TYPE_LENGTH);
145 strncpy(zswap_control.zpool_type, zpool_type, MAX_TYPE_LENGTH-1);
147 memset(zswap_control.zpool_type, 0, MAX_TYPE_LENGTH);
152 static int swap_zswap_init(void *data)
154 struct swap_module_ops *swap = (struct swap_module_ops *)data;
156 if (access(ZSWAP_POOL_PERCENT, R_OK) != 0)
159 /* r = swap_zswap_parse_config_file();
161 _E("Failed to parse SwapFile config: %d", r);
165 swap->k_size = BYTE_TO_KBYTE(zswap_control.zswap_file_size);
169 static int swap_zswap_conf(void *data)
171 struct zswap_conf *zswap_conf = (struct zswap_conf *)data;
173 _E("[DEBUG] Zswap configuration should not be NULL");
174 return RESOURCED_ERROR_FAIL;
177 if (check_valid_compressor(zswap_conf->type) == RESOURCED_ERROR_NONE)
178 strncpy(zswap_control.crypt_type, zswap_conf->type, MAX_TYPE_LENGTH-1);
180 if (zswap_conf->filesize > 0)
181 zswap_control.zswap_file_size = zswap_conf->filesize;
183 if (zswap_conf->pool_ratio > 0.0)
184 zswap_control.zpool_ratio = zswap_conf->pool_ratio;
186 if (!is_empty(zswap_conf->pool_type))
187 strncpy(zswap_control.zpool_type, zswap_conf->pool_type, MAX_TYPE_LENGTH-1);
189 memset(zswap_control.zpool_type, 0, MAX_TYPE_LENGTH);
191 _I("[DEBUG] zswap type = %s", zswap_control.crypt_type);
192 _I("[DEBUG] zswap filesize = %ld", zswap_control.zswap_file_size);
193 _I("[DEBUG] zswap pool ratio = %f", zswap_control.zpool_ratio);
194 _I("[DEBUG] zswap pool type = %s", zswap_control.zpool_type);
196 return RESOURCED_ERROR_NONE;
200 static struct swap_module_ops swap_zswap_ops = {
202 .type = SWAP_TYPE_ZSWAP,
204 .priority = SWAP_PRI_DISABLE,
206 .init = swap_zswap_init,
207 .activate = swap_zswap_activate,
208 .reclaim = swap_zswap_reclaim,
209 .conf = swap_zswap_conf,
211 SWAP_MODULE_REGISTER(&swap_zswap_ops)