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"
31 #define SWAP_ZRAM_DISK_SIZE SWAP_ZRAM_SYSFILE"disksize"
32 #define SWAP_ZRAM_MAX_COMP_STREAMS SWAP_ZRAM_SYSFILE"max_comp_streams"
33 #define SWAP_ZRAM_COMP_ALGORITHM SWAP_ZRAM_SYSFILE"comp_algorithm"
34 #define SWAP_ZRAM_COMPACT SWAP_ZRAM_SYSFILE"compact"
35 #define SWAP_ZRAM_MEM_USED_TOTAL SWAP_ZRAM_SYSFILE"mem_used_total"
37 #define DEFAULT_ZRAM_COMPRESSOR "lz4"
38 #define DEFAULT_ZRAM_RATIO ((double) 0.25)
39 #define ZRAM_FULLNESS_RATIO 0.8
40 #define SWAPCG_CHECK_RATIO 5 /* 5 % of total swap */
42 struct swap_zram_control {
44 char comp_algorithm[MAX_TYPE_LENGTH];
46 unsigned long zram_reclaim_bytes;
49 static struct swap_zram_control zram_control = {
50 .max_comp_streams = -1,
51 .comp_algorithm = DEFAULT_ZRAM_COMPRESSOR,
52 .ratio = DEFAULT_ZRAM_RATIO,
53 .zram_reclaim_bytes = 0,
56 static int swap_zram_compact(void)
59 static unsigned int last_total;
62 _D("call zram compact");
63 r = fread_uint(SWAP_ZRAM_MEM_USED_TOTAL, &total);
65 _E("fail to read %s", SWAP_ZRAM_MEM_USED_TOTAL);
70 * Until zram size not increased of at least 1 MB from last compaction
71 * then it not makes any sense to compact it again.
73 if ((total - last_total) < MBYTE_TO_BYTE(1))
77 r = fwrite_int(SWAP_ZRAM_COMPACT, 1);
79 _E("fail to write %s", SWAP_ZRAM_COMPACT);
83 r = fread_uint(SWAP_ZRAM_MEM_USED_TOTAL, &total);
85 _E("fail to read %s", SWAP_ZRAM_MEM_USED_TOTAL);
92 static int swap_zram_activate(void *data)
94 struct swap_module_ops *swap = (struct swap_module_ops *)data;
95 unsigned int swap_size_bytes, read_size_bytes;
98 swap_size_bytes = KBYTE_TO_BYTE(swap->k_size);
99 zram_control.zram_reclaim_bytes =
100 swap_size_bytes - (swap_size_bytes * ZRAM_FULLNESS_RATIO);
102 if (swap_is_on(swap->path))
105 r = fwrite_int(SWAP_ZRAM_MAX_COMP_STREAMS,
106 zram_control.max_comp_streams);
108 _E("fail to write max_comp_streams");
112 r = fwrite_str(SWAP_ZRAM_COMP_ALGORITHM,
113 zram_control.comp_algorithm);
116 * if it fails to set compressor described in .conf file,
117 * then try again with default compressor.
119 _I("failed to write comp_algorithm: %s, try default: %s",
120 zram_control.comp_algorithm,
121 DEFAULT_ZRAM_COMPRESSOR);
122 r = fwrite_str(SWAP_ZRAM_COMP_ALGORITHM,
123 DEFAULT_ZRAM_COMPRESSOR);
125 _E("fail to write comp_algrithm");
130 r = fread_uint(SWAP_ZRAM_DISK_SIZE, &read_size_bytes);
132 _E("fail to read zram disk_size");
136 /* disksize can be pre-fixed by other means, do not set size in that case */
137 if (read_size_bytes == 0) {
138 r = fwrite_uint(SWAP_ZRAM_DISK_SIZE, swap_size_bytes);
140 _E("fail to write disk_size");
144 r = fread_uint(SWAP_ZRAM_DISK_SIZE, &read_size_bytes);
146 _E("fail to read zram disk_size");
150 /* Check if zram was sucessfully initialized (zcomp rollback case) */
151 if (read_size_bytes < swap_size_bytes) {
152 _E("swap size (%d) less than expected swap size (%d)",
153 read_size_bytes, swap_size_bytes);
154 return RESOURCED_ERROR_OUT_OF_MEMORY;
158 r = do_mkswap(swap->path);
160 _E("Failed to make swap device(%s), exit code: %d", swap->path, r);
163 _E("Failed to make swap device(%s): %m", swap->path);
170 static int swap_zram_reclaim(void *data)
173 static unsigned int swap_total = 0;
174 static bool zram_compact;
175 unsigned long swap_available;
176 unsigned int swap_usage;
177 float swapcg_usage_ratio;
178 unsigned int ram_available;
180 swap_available = KBYTE_TO_BYTE(proc_get_swap_free());
182 _D("swap available %lu, reclaimg byte %lu", swap_available, zram_control.zram_reclaim_bytes);
185 * Most kernel doesn't support migration and compaction of zmalloc.
186 * So, if zmalloc uses much kernel memory,
187 * there is no high order buddy due to memory fragmentation.
188 * It causes system sluggish or lockup problems.
189 * In case of no high order buddy, trigger LMK.
191 if (lowmem_fragmentated()) {
193 lowmem_trigger_swap_reclaim(CGROUP_ROOT, zram_control.zram_reclaim_bytes);
194 zram_compact = false;
202 if (swap_available >= zram_control.zram_reclaim_bytes)
206 r = swap_zram_compact();
213 ram_available = proc_get_mem_available();
214 if (ram_available > lowmem_get_proactive_thres())
218 * In this case, swap is almost full but can't comapt zram any longer.
219 * It means that there are many background processes or
220 * some process makes memory leak.
221 * So, it requires to trigger proactive oom killer.
222 * At first, check usage of swap cgroup.
223 * If swap usage of this cgroup is higher, run LMK about background applications.
224 * Otherwise, need to check all processes in order to find mallicious process.
227 swap_total = proc_get_swap_total();
229 r = memcg_get_swap_usage(MEMCG_LOW_GROUP_PATH, &swap_usage);
232 swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100);
233 if (swapcg_usage_ratio > SWAPCG_CHECK_RATIO)
238 lowmem_trigger_swap_reclaim(type, zram_control.zram_reclaim_bytes);
239 zram_compact = false;
243 /*static int swap_zram_parse_config_file(void)
245 ConfigTableItem items[] = {
246 { "ZRAM", "COMP_ALGORITHM", config_parse_string, 0, NULL },
247 { "ZRAM", "RATIO", config_parse_float, 0, NULL },
248 { NULL, NULL, NULL, 0, NULL }
252 _cleanup_free_ char *algorithm = NULL;
254 items[0].data = &algorithm;
255 items[1].data = &zram_control.ratio;
257 r = config_parse_new(SWAP_CONF_FILE, (void*) items);
259 _E("Failed to parse configuration file: %m");
264 strncpy(zram_control.comp_algorithm, algorithm, MAX_TYPE_LENGTH - 1);
266 _I("algorithm=%s, ratio=%f", algorithm, zram_control.ratio);
271 static int swap_zram_init(void *data)
273 struct swap_module_ops *swap = (struct swap_module_ops *)data;
275 if (access(swap->path, R_OK) != 0)
278 /* r = swap_zram_parse_config_file();
280 _E("Failed to parse SwapFile config: %m");
284 swap->k_size = lowmem_get_ktotalram() * zram_control.ratio;
286 if (zram_control.max_comp_streams < 0) {
287 int cpu = proc_get_cpu_number();
289 zram_control.max_comp_streams =
291 * On big.LITTLE we can have 8 cores visible
292 * but there can be used 4. Let's limit it to
293 * 4 if there is no specified value in .conf
303 static int swap_zram_conf(void *data)
305 struct zram_conf *zram_conf = (struct zram_conf *)data;
307 _E("Zram configuration should not be NULL");
308 return RESOURCED_ERROR_FAIL;
311 if (!is_empty(zram_conf->algorithm))
312 strncpy(zram_control.comp_algorithm, zram_conf->algorithm, MAX_TYPE_LENGTH - 1);
314 if (zram_conf->ratio > 0.0)
315 zram_control.ratio = zram_conf->ratio;
317 _I("[DEBUG] zram algorithm = %s", zram_control.comp_algorithm);
318 _I("[DEBUG] zram ratio = %f", zram_control.ratio);
320 return RESOURCED_ERROR_NONE;
323 static struct swap_module_ops swap_zram_ops = {
325 .type = SWAP_TYPE_ZRAM,
326 .path = "/dev/zram0",
327 .priority = SWAP_PRI_DEFAULT,
329 .init = swap_zram_init,
330 .activate = swap_zram_activate,
331 .reclaim = swap_zram_reclaim,
332 .conf = swap_zram_conf,
334 SWAP_MODULE_REGISTER(&swap_zram_ops)