Remove useless source code
[platform/core/system/resourced.git] / src / resource-optimizer / memory / swap / zramswap.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include "macro.h"
20 #include "module.h"
21 #include "module-data.h"
22 #include "trace.h"
23 #include "util.h"
24 #include "file-helper.h"
25 #include "procfs.h"
26 #include "swap-common.h"
27 #include "memory-cgroup.h"
28 #include "config-parser.h"
29 #include "lowmem-handler.h"
30
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"
36
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 */
41
42 struct swap_zram_control {
43         int max_comp_streams;
44         char comp_algorithm[MAX_TYPE_LENGTH];
45         float ratio;
46         unsigned long zram_reclaim_bytes;
47 };
48
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,
54 };
55
56 static int swap_zram_compact(void)
57 {
58         unsigned int total;
59         static unsigned int last_total;
60         int r;
61
62         _D("call zram compact");
63         r = fread_uint(SWAP_ZRAM_MEM_USED_TOTAL, &total);
64         if (r < 0) {
65                 _E("fail to read %s", SWAP_ZRAM_MEM_USED_TOTAL);
66                 return r;
67         }
68
69         /*
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.
72          */
73         if ((total - last_total) < MBYTE_TO_BYTE(1))
74                 return -ENOMEM;
75
76         last_total = total;
77         r = fwrite_int(SWAP_ZRAM_COMPACT, 1);
78         if (r < 0) {
79                 _E("fail to write %s", SWAP_ZRAM_COMPACT);
80                 return r;
81         }
82
83         r = fread_uint(SWAP_ZRAM_MEM_USED_TOTAL, &total);
84         if (r < 0) {
85                 _E("fail to read %s", SWAP_ZRAM_MEM_USED_TOTAL);
86                 return r;
87         }
88
89         return 0;
90 }
91
92 static int swap_zram_activate(void *data)
93 {
94         struct swap_module_ops *swap = (struct swap_module_ops *)data;
95         unsigned int swap_size_bytes, read_size_bytes;
96         int r;
97
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);
101
102         if (swap_is_on(swap->path))
103                 return -EEXIST;
104
105         r = fwrite_int(SWAP_ZRAM_MAX_COMP_STREAMS,
106                                 zram_control.max_comp_streams);
107         if (r < 0) {
108                 _E("fail to write max_comp_streams");
109                 return r;
110         }
111
112         r = fwrite_str(SWAP_ZRAM_COMP_ALGORITHM,
113                                 zram_control.comp_algorithm);
114         if (r < 0) {
115                 /*
116                  * if it fails to set compressor described in .conf file,
117                  * then try again with default compressor.
118                  */
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);
124                 if (r < 0) {
125                         _E("fail to write comp_algrithm");
126                         return r;
127                 }
128         }
129
130         r = fread_uint(SWAP_ZRAM_DISK_SIZE, &read_size_bytes);
131         if (r < 0) {
132                 _E("fail to read zram disk_size");
133                 return r;
134         }
135
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);
139                 if (r < 0) {
140                         _E("fail to write disk_size");
141                         return r;
142                 }
143
144                 r = fread_uint(SWAP_ZRAM_DISK_SIZE, &read_size_bytes);
145                 if (r < 0) {
146                         _E("fail to read zram disk_size");
147                         return r;
148                 }
149
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;
155                 }
156         }
157
158         r = do_mkswap(swap->path);
159         if (r > 0) {
160                 _E("Failed to make swap device(%s), exit code: %d", swap->path, r);
161                 return -EBUSY;
162         } else if (r < 0) {
163                 _E("Failed to make swap device(%s): %m", swap->path);
164                 return r;
165         }
166
167         return 0;
168 }
169
170 static int swap_zram_reclaim(void *data)
171 {
172         int r, type;
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;
179
180         swap_available = KBYTE_TO_BYTE(proc_get_swap_free());
181
182         _D("swap available %lu, reclaimg byte %lu", swap_available, zram_control.zram_reclaim_bytes);
183
184         /*
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.
190          */
191         if (lowmem_fragmentated()) {
192                 if (zram_compact) {
193                         lowmem_trigger_swap_reclaim(CGROUP_ROOT, zram_control.zram_reclaim_bytes);
194                         zram_compact = false;
195                 } else {
196                         swap_zram_compact();
197                         zram_compact = true;
198                 }
199                 return -ENOSPC;
200         }
201
202         if (swap_available >= zram_control.zram_reclaim_bytes)
203                 return 0;
204
205         if (!zram_compact) {
206                 r = swap_zram_compact();
207                 if (r != -ENOMEM) {
208                         zram_compact = true;
209                         return r;
210                 }
211         }
212
213         ram_available = proc_get_mem_available();
214         if (ram_available > lowmem_get_proactive_thres())
215                 return 0;
216
217         /*
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.
225          */
226         if (!swap_total)
227                 swap_total = proc_get_swap_total();
228
229         r = memcg_get_swap_usage(MEMCG_LOW_GROUP_PATH, &swap_usage);
230         if (r)
231                 return r;
232         swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100);
233         if (swapcg_usage_ratio > SWAPCG_CHECK_RATIO)
234                 type = CGROUP_LOW;
235         else
236                 type = CGROUP_ROOT;
237
238         lowmem_trigger_swap_reclaim(type, zram_control.zram_reclaim_bytes);
239         zram_compact = false;
240         return -ENOSPC;
241 }
242
243 static int swap_zram_init(void *data)
244 {
245         struct swap_module_ops *swap = (struct swap_module_ops *)data;
246
247         if (access(swap->path, R_OK) != 0)
248                 return -ENOENT;
249
250         swap->k_size = lowmem_get_ktotalram() * zram_control.ratio;
251
252         if (zram_control.max_comp_streams < 0) {
253                 int cpu = proc_get_cpu_number();
254
255                 zram_control.max_comp_streams =
256                         /*
257                          * On big.LITTLE we can have 8 cores visible
258                          * but there can be used 4. Let's limit it to
259                          * 4 if there is no specified value in .conf
260                          * file.
261                          */
262                         cpu >= 4 ? 4 :
263                         cpu > 0 ? cpu : 1;
264         }
265
266         return 0;
267 }
268
269 static int swap_zram_conf(void *data)
270 {
271         struct zram_conf *zram_conf = (struct zram_conf *)data;
272         if (!zram_conf) {
273                 _E("Zram configuration should not be NULL");
274                 return RESOURCED_ERROR_FAIL;
275         }
276
277         if (!is_empty(zram_conf->algorithm))
278                 strncpy(zram_control.comp_algorithm, zram_conf->algorithm, MAX_TYPE_LENGTH - 1);
279
280         if (zram_conf->ratio > 0.0)
281                 zram_control.ratio = zram_conf->ratio;
282
283         _I("[DEBUG] zram algorithm = %s", zram_control.comp_algorithm);
284         _I("[DEBUG] zram ratio = %f", zram_control.ratio);
285
286         return RESOURCED_ERROR_NONE;
287 }
288
289 static struct swap_module_ops swap_zram_ops = {
290         .name = "ZRAM",
291         .type = SWAP_TYPE_ZRAM,
292         .path = "/dev/zram0",
293         .priority = SWAP_PRI_DEFAULT,
294         .k_size = 0,
295         .init = swap_zram_init,
296         .activate = swap_zram_activate,
297         .reclaim = swap_zram_reclaim,
298         .conf = swap_zram_conf,
299 };
300 SWAP_MODULE_REGISTER(&swap_zram_ops)