xref: /linux/tools/testing/selftests/cgroup/test_zswap.c (revision a52a93358ac2bef65f15e0069cd410a2b59ae03b)
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 
4 #include <linux/limits.h>
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <signal.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <sys/sysinfo.h>
11 #include <string.h>
12 #include <sys/wait.h>
13 #include <sys/mman.h>
14 #include <sys/random.h>
15 
16 #include "kselftest.h"
17 #include "cgroup_util.h"
18 
19 static int page_size;
20 
21 #define PATH_ZSWAP "/sys/module/zswap"
22 #define PATH_ZSWAP_ENABLED "/sys/module/zswap/parameters/enabled"
23 #define PATH_ZSWAP_SHRINKER_ENABLED "/sys/module/zswap/parameters/shrinker_enabled"
24 #define PATH_ZSWAP_STORED_PAGES "/sys/kernel/debug/zswap/stored_pages"
25 
read_int(const char * path,size_t * value)26 static int read_int(const char *path, size_t *value)
27 {
28 	FILE *file;
29 	int ret = 0;
30 
31 	file = fopen(path, "r");
32 	if (!file)
33 		return -1;
34 	if (fscanf(file, "%ld", value) != 1)
35 		ret = -1;
36 	fclose(file);
37 	return ret;
38 }
39 
set_min_free_kb(size_t value)40 static int set_min_free_kb(size_t value)
41 {
42 	FILE *file;
43 	int ret;
44 
45 	file = fopen("/proc/sys/vm/min_free_kbytes", "w");
46 	if (!file)
47 		return -1;
48 	ret = fprintf(file, "%ld\n", value);
49 	fclose(file);
50 	return ret;
51 }
52 
read_min_free_kb(size_t * value)53 static int read_min_free_kb(size_t *value)
54 {
55 	return read_int("/proc/sys/vm/min_free_kbytes", value);
56 }
57 
get_zswap_stored_pages(size_t * value)58 static int get_zswap_stored_pages(size_t *value)
59 {
60 	return read_int(PATH_ZSWAP_STORED_PAGES, value);
61 }
62 
get_cg_wb_count(const char * cg)63 static long get_cg_wb_count(const char *cg)
64 {
65 	return cg_read_key_long(cg, "memory.stat", "zswpwb");
66 }
67 
get_zswpout(const char * cgroup)68 static long get_zswpout(const char *cgroup)
69 {
70 	return cg_read_key_long(cgroup, "memory.stat", "zswpout ");
71 }
72 
allocate_and_read_bytes(const char * cgroup,void * arg)73 static int allocate_and_read_bytes(const char *cgroup, void *arg)
74 {
75 	size_t size = (size_t)arg;
76 	char *mem = (char *)malloc(size);
77 	int ret = 0;
78 
79 	if (!mem)
80 		return -1;
81 	for (int i = 0; i < size; i += page_size)
82 		mem[i] = 'a';
83 
84 	/* Go through the allocated memory to (z)swap in and out pages */
85 	for (int i = 0; i < size; i += page_size) {
86 		if (mem[i] != 'a')
87 			ret = -1;
88 	}
89 
90 	free(mem);
91 	return ret;
92 }
93 
allocate_bytes(const char * cgroup,void * arg)94 static int allocate_bytes(const char *cgroup, void *arg)
95 {
96 	size_t size = (size_t)arg;
97 	char *mem = (char *)malloc(size);
98 
99 	if (!mem)
100 		return -1;
101 	for (int i = 0; i < size; i += page_size)
102 		mem[i] = 'a';
103 	free(mem);
104 	return 0;
105 }
106 
setup_test_group_1M(const char * root,const char * name)107 static char *setup_test_group_1M(const char *root, const char *name)
108 {
109 	char *group_name = cg_name(root, name);
110 
111 	if (!group_name)
112 		return NULL;
113 	if (cg_create(group_name))
114 		goto fail;
115 	if (cg_write(group_name, "memory.max", "1M")) {
116 		cg_destroy(group_name);
117 		goto fail;
118 	}
119 	return group_name;
120 fail:
121 	free(group_name);
122 	return NULL;
123 }
124 
125 /*
126  * Writeback is asynchronous; poll until at least one writeback has
127  * been recorded for @cg, or until @timeout_ms has elapsed.
128  */
wait_for_writeback(const char * cg,int timeout_ms)129 static long wait_for_writeback(const char *cg, int timeout_ms)
130 {
131 	long elapsed, count;
132 	for (elapsed = 0; elapsed < timeout_ms; elapsed += 100) {
133 		count = get_cg_wb_count(cg);
134 
135 		if (count < 0)
136 			return -1;
137 		if (count > 0)
138 			return count;
139 
140 		usleep(100000);
141 	}
142 
143 	return 0;
144 }
145 
146 /*
147  * Sanity test to check that pages are written into zswap.
148  */
test_zswap_usage(const char * root)149 static int test_zswap_usage(const char *root)
150 {
151 	long zswpout_before, zswpout_after;
152 	int ret = KSFT_FAIL;
153 	char *test_group;
154 
155 	test_group = cg_name(root, "no_shrink_test");
156 	if (!test_group)
157 		goto out;
158 	if (cg_create(test_group))
159 		goto out;
160 	if (cg_write(test_group, "memory.max", "1M"))
161 		goto out;
162 
163 	zswpout_before = get_zswpout(test_group);
164 	if (zswpout_before < 0) {
165 		ksft_print_msg("Failed to get zswpout\n");
166 		goto out;
167 	}
168 
169 	/* Allocate more than memory.max to push memory into zswap */
170 	if (cg_run(test_group, allocate_bytes, (void *)MB(4)))
171 		goto out;
172 
173 	/* Verify that pages come into zswap */
174 	zswpout_after = get_zswpout(test_group);
175 	if (zswpout_after <= zswpout_before) {
176 		ksft_print_msg("zswpout does not increase after test program\n");
177 		goto out;
178 	}
179 	ret = KSFT_PASS;
180 
181 out:
182 	cg_destroy(test_group);
183 	free(test_group);
184 	return ret;
185 }
186 
187 /*
188  * Check that when memory.zswap.max = 0, no pages can go to the zswap pool for
189  * the cgroup.
190  */
test_swapin_nozswap(const char * root)191 static int test_swapin_nozswap(const char *root)
192 {
193 	int ret = KSFT_FAIL;
194 	char *test_group, mem_max_buf[32];
195 	long swap_peak, zswpout, min_swap;
196 	size_t allocation_size = page_size * 512;
197 
198 	min_swap = allocation_size / 4;
199 	snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", allocation_size * 3/4);
200 
201 	test_group = cg_name(root, "no_zswap_test");
202 	if (!test_group)
203 		goto out;
204 	if (cg_create(test_group))
205 		goto out;
206 	if (cg_write(test_group, "memory.max", mem_max_buf))
207 		goto out;
208 	if (cg_write(test_group, "memory.zswap.max", "0"))
209 		goto out;
210 
211 	/* Allocate and read more than memory.max to trigger swapin */
212 	if (cg_run(test_group, allocate_and_read_bytes, (void *)allocation_size))
213 		goto out;
214 
215 	/* Verify that pages are swapped out, but no zswap happened */
216 	swap_peak = cg_read_long(test_group, "memory.swap.peak");
217 	if (swap_peak < 0) {
218 		ksft_print_msg("failed to get cgroup's swap_peak\n");
219 		goto out;
220 	}
221 
222 	if (swap_peak < min_swap) {
223 		ksft_print_msg("at least %ldKB of memory should be swapped out\n",
224 				min_swap / 1024);
225 		goto out;
226 	}
227 
228 	zswpout = get_zswpout(test_group);
229 	if (zswpout < 0) {
230 		ksft_print_msg("failed to get zswpout\n");
231 		goto out;
232 	}
233 
234 	if (zswpout > 0) {
235 		ksft_print_msg("zswapout > 0 when memory.zswap.max = 0\n");
236 		goto out;
237 	}
238 
239 	ret = KSFT_PASS;
240 
241 out:
242 	cg_destroy(test_group);
243 	free(test_group);
244 	return ret;
245 }
246 
247 /* Simple test to verify the (z)swapin code paths */
test_zswapin(const char * root)248 static int test_zswapin(const char *root)
249 {
250 	int ret = KSFT_FAIL;
251 	char *test_group;
252 	long zswpin;
253 
254 	test_group = cg_name(root, "zswapin_test");
255 	if (!test_group)
256 		goto out;
257 	if (cg_create(test_group))
258 		goto out;
259 	if (cg_write(test_group, "memory.max", "8M"))
260 		goto out;
261 	if (cg_write(test_group, "memory.zswap.max", "max"))
262 		goto out;
263 
264 	/* Allocate and read more than memory.max to trigger (z)swap in */
265 	if (cg_run(test_group, allocate_and_read_bytes, (void *)MB(32)))
266 		goto out;
267 
268 	zswpin = cg_read_key_long(test_group, "memory.stat", "zswpin ");
269 	if (zswpin < 0) {
270 		ksft_print_msg("failed to get zswpin\n");
271 		goto out;
272 	}
273 
274 	if (zswpin < MB(24) / page_size) {
275 		ksft_print_msg("at least 24MB should be brought back from zswap\n");
276 		goto out;
277 	}
278 
279 	ret = KSFT_PASS;
280 
281 out:
282 	cg_destroy(test_group);
283 	free(test_group);
284 	return ret;
285 }
286 
287 /*
288  * Attempt writeback with the following steps:
289  * 1. Allocate memory.
290  * 2. Reclaim memory equal to the amount that was allocated in step 1.
291       This will move it into zswap.
292  * 3. Save current zswap usage.
293  * 4. Move the memory allocated in step 1 back in from zswap.
294  * 5. Set zswap.max to 1/4 of the amount that was recorded in step 3.
295  * 6. Attempt to reclaim memory equal to the amount that was allocated,
296       this will either trigger writeback if it's enabled, or reclamation
297       will fail if writeback is disabled as there isn't enough zswap space.
298  */
attempt_writeback(const char * cgroup,void * arg)299 static int attempt_writeback(const char *cgroup, void *arg)
300 {
301 	size_t memsize = page_size * 1024;
302 	char buf[page_size];
303 	long zswap_usage;
304 	bool wb_enabled = *(bool *) arg;
305 	int ret = -1;
306 	char *mem;
307 
308 	mem = (char *)malloc(memsize);
309 	if (!mem)
310 		return ret;
311 
312 	/*
313 	 * Fill half of each page with increasing data, and keep other
314 	 * half empty, this will result in data that is still compressible
315 	 * and ends up in zswap, with material zswap usage.
316 	 */
317 	for (int i = 0; i < page_size; i++)
318 		buf[i] = i < page_size/2 ? (char) i : 0;
319 
320 	for (int i = 0; i < memsize; i += page_size)
321 		memcpy(&mem[i], buf, page_size);
322 
323 	/* Try and reclaim allocated memory */
324 	if (cg_write_numeric(cgroup, "memory.reclaim", memsize)) {
325 		ksft_print_msg("Failed to reclaim all of the requested memory\n");
326 		goto out;
327 	}
328 
329 	zswap_usage = cg_read_long(cgroup, "memory.zswap.current");
330 
331 	/* zswpin */
332 	for (int i = 0; i < memsize; i += page_size) {
333 		if (memcmp(&mem[i], buf, page_size)) {
334 			ksft_print_msg("invalid memory\n");
335 			goto out;
336 		}
337 	}
338 
339 	if (cg_write_numeric(cgroup, "memory.zswap.max", zswap_usage/4))
340 		goto out;
341 
342 	/*
343 	 * If writeback is enabled, trying to reclaim memory now will trigger a
344 	 * writeback as zswap.max is 1/4 of what was needed when reclaim ran the first time.
345 	 * If writeback is disabled, memory reclaim will fail as zswap is limited and
346 	 * it can't writeback to swap.
347 	 */
348 	ret = cg_write_numeric(cgroup, "memory.reclaim", memsize);
349 	if (!wb_enabled)
350 		ret = (ret == -EAGAIN) ? 0 : -1;
351 
352 out:
353 	free(mem);
354 	return ret;
355 }
356 
test_zswap_writeback_one(const char * cgroup,bool wb)357 static int test_zswap_writeback_one(const char *cgroup, bool wb)
358 {
359 	long zswpwb_before, zswpwb_after;
360 
361 	zswpwb_before = get_cg_wb_count(cgroup);
362 	if (zswpwb_before != 0) {
363 		ksft_print_msg("zswpwb_before = %ld instead of 0\n", zswpwb_before);
364 		return -1;
365 	}
366 
367 	if (cg_run(cgroup, attempt_writeback, (void *) &wb))
368 		return -1;
369 
370 	/* Verify that zswap writeback occurred only if writeback was enabled */
371 	if (wb)
372 		zswpwb_after = wait_for_writeback(cgroup, 5000);
373 	else
374 		zswpwb_after = get_cg_wb_count(cgroup);
375 	if (zswpwb_after < 0)
376 		return -1;
377 
378 	if (wb != !!zswpwb_after) {
379 		ksft_print_msg("zswpwb_after is %ld while wb is %s\n",
380 				zswpwb_after, wb ? "enabled" : "disabled");
381 		return -1;
382 	}
383 
384 	return 0;
385 }
386 
387 /* Test to verify the zswap writeback path */
test_zswap_writeback(const char * root,bool wb)388 static int test_zswap_writeback(const char *root, bool wb)
389 {
390 	int ret = KSFT_FAIL;
391 	char *test_group, *test_group_child = NULL;
392 
393 	if (cg_read_strcmp(root, "memory.zswap.writeback", "1"))
394 		return KSFT_SKIP;
395 
396 	test_group = cg_name(root, "zswap_writeback_test");
397 	if (!test_group)
398 		goto out;
399 	if (cg_create(test_group))
400 		goto out;
401 	if (cg_write(test_group, "memory.zswap.writeback", wb ? "1" : "0"))
402 		goto out;
403 
404 	if (test_zswap_writeback_one(test_group, wb))
405 		goto out;
406 
407 	/* Reset memory.zswap.max to max (modified by attempt_writeback), and
408 	 * set up child cgroup, whose memory.zswap.writeback is hardcoded to 1.
409 	 * Thus, the parent's setting shall be what's in effect. */
410 	if (cg_write(test_group, "memory.zswap.max", "max"))
411 		goto out;
412 	if (cg_write(test_group, "cgroup.subtree_control", "+memory"))
413 		goto out;
414 
415 	test_group_child = cg_name(test_group, "zswap_writeback_test_child");
416 	if (!test_group_child)
417 		goto out;
418 	if (cg_create(test_group_child))
419 		goto out;
420 	if (cg_write(test_group_child, "memory.zswap.writeback", "1"))
421 		goto out;
422 
423 	if (test_zswap_writeback_one(test_group_child, wb))
424 		goto out;
425 
426 	ret = KSFT_PASS;
427 
428 out:
429 	if (test_group_child) {
430 		cg_destroy(test_group_child);
431 		free(test_group_child);
432 	}
433 	cg_destroy(test_group);
434 	free(test_group);
435 	return ret;
436 }
437 
test_zswap_writeback_enabled(const char * root)438 static int test_zswap_writeback_enabled(const char *root)
439 {
440 	return test_zswap_writeback(root, true);
441 }
442 
test_zswap_writeback_disabled(const char * root)443 static int test_zswap_writeback_disabled(const char *root)
444 {
445 	return test_zswap_writeback(root, false);
446 }
447 
zswap_shrinker_enabled(void)448 static bool zswap_shrinker_enabled(void)
449 {
450 	char value[2];
451 
452 	if (read_text(PATH_ZSWAP_SHRINKER_ENABLED, value, sizeof(value)) <= 0)
453 		return 0;
454 
455 	return value[0] == 'Y';
456 }
457 
458 /*
459  * When trying to store a memcg page in zswap, if the memcg hits its memory
460  * limit in zswap, writeback should affect only the zswapped pages of that
461  * memcg.
462  */
test_no_invasive_cgroup_shrink(const char * root)463 static int test_no_invasive_cgroup_shrink(const char *root)
464 {
465 	int ret = KSFT_FAIL;
466 	unsigned int off;
467 	long zswpwb_before, zswpwb_after, zswpwb_target;
468 	size_t allocation_size = page_size * 1024;
469 	unsigned int nr_pages = allocation_size / page_size;
470 	char zswap_max_buf[32], mem_max_buf[32];
471 	char *zw_allocation = NULL, *wb_allocation = NULL;
472 	char *zw_group = NULL, *wb_group = NULL;
473 
474 	snprintf(zswap_max_buf, sizeof(zswap_max_buf), "%d", page_size);
475 	snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", allocation_size / 2);
476 
477 	wb_group = setup_test_group_1M(root, "per_memcg_wb_test1");
478 	if (!wb_group)
479 		return KSFT_FAIL;
480 	if (cg_write(wb_group, "memory.zswap.max", zswap_max_buf))
481 		goto out;
482 	if (cg_write(wb_group, "memory.max", mem_max_buf))
483 		goto out;
484 
485 	zw_group = setup_test_group_1M(root, "per_memcg_wb_test2");
486 	if (!zw_group)
487 		goto out;
488 	if (cg_write(zw_group, "memory.max", mem_max_buf))
489 		goto out;
490 
491 	/* Push some zw_group memory into zswap (simple data, easy to compress) */
492 	if (cg_enter_current(zw_group))
493 		goto out;
494 	zw_allocation = malloc(allocation_size);
495 	for (int i = 0; i < nr_pages; i++) {
496 		off = (unsigned long)i * page_size;
497 		memset(&zw_allocation[off], 0, page_size);
498 		memset(&zw_allocation[off], 'a', page_size/4);
499 	}
500 	if (cg_read_key_long(zw_group, "memory.stat", "zswapped") < 1)
501 		goto out;
502 
503 	/* If the shrinker is enabled, try to let the writebacks finish first */
504 	if (zswap_shrinker_enabled())
505 		sleep(5);
506 
507 	zswpwb_before = get_cg_wb_count(zw_group);
508 	if (zswpwb_before < 0)
509 		goto out;
510 
511 	/* Push wb_group memory into zswap with hard-to-compress data to trigger wb */
512 	if (cg_enter_current(wb_group))
513 		goto out;
514 	wb_allocation = malloc(allocation_size);
515 	if (!wb_allocation)
516 		goto out;
517 	for (int i = 0; i < nr_pages; i++) {
518 		off = (unsigned long)i * page_size;
519 		memset(&wb_allocation[off], 0, page_size);
520 		getrandom(&wb_allocation[off], page_size/4, 0);
521 	}
522 
523 	/* Verify that only zswapped memory from wb_group has been written back */
524 	zswpwb_target = wait_for_writeback(wb_group, 5000);
525 	zswpwb_after = get_cg_wb_count(zw_group);
526 
527 	if (zswpwb_target > 0 && zswpwb_before == zswpwb_after)
528 		ret = KSFT_PASS;
529 
530 out:
531 	cg_enter_current(root);
532 	if (zw_group) {
533 		cg_destroy(zw_group);
534 		free(zw_group);
535 	}
536 	if (wb_group) {
537 		cg_destroy(wb_group);
538 		free(wb_group);
539 	}
540 	if (zw_allocation)
541 		free(zw_allocation);
542 	if (wb_allocation)
543 		free(wb_allocation);
544 	return ret;
545 }
546 
547 struct no_kmem_bypass_child_args {
548 	size_t target_alloc_bytes;
549 	size_t child_allocated;
550 };
551 
no_kmem_bypass_child(const char * cgroup,void * arg)552 static int no_kmem_bypass_child(const char *cgroup, void *arg)
553 {
554 	struct no_kmem_bypass_child_args *values = arg;
555 	void *allocation;
556 
557 	allocation = malloc(values->target_alloc_bytes);
558 	if (!allocation) {
559 		values->child_allocated = true;
560 		return -1;
561 	}
562 	for (long i = 0; i < values->target_alloc_bytes; i += page_size)
563 		((char *)allocation)[i] = 'a';
564 	values->child_allocated = true;
565 	pause();
566 	free(allocation);
567 	return 0;
568 }
569 
570 /*
571  * When pages owned by a memcg are pushed to zswap by kswapd, they should be
572  * charged to that cgroup. This wasn't the case before commit
573  * cd08d80ecdac("mm: correctly charge compressed memory to its memcg").
574  *
575  * The test first allocates memory in a memcg, then raises min_free_kbytes to
576  * a very high value so that the allocation falls below low wm, then makes
577  * another allocation to trigger kswapd that should push the memcg-owned pages
578  * to zswap and verifies that the zswap pages are correctly charged.
579  *
580  * To be run on a VM with at most 4G of memory.
581  */
test_no_kmem_bypass(const char * root)582 static int test_no_kmem_bypass(const char *root)
583 {
584 	size_t min_free_kb_high, min_free_kb_low, min_free_kb_original;
585 	struct no_kmem_bypass_child_args *values;
586 	size_t trigger_allocation_size;
587 	int wait_child_iteration = 0;
588 	long stored_pages_threshold;
589 	struct sysinfo sys_info;
590 	int ret = KSFT_FAIL;
591 	int child_status;
592 	char *test_group = NULL;
593 	pid_t child_pid;
594 
595 	/* Read sys info and compute test values accordingly */
596 	if (sysinfo(&sys_info) != 0)
597 		return KSFT_FAIL;
598 	if (sys_info.totalram > GB(4)) {
599 		ksft_print_msg(
600 			"requires less than 4GB total ram, sys_info.totalram: %.1fGB\n",
601 			(double)sys_info.totalram / GB(1));
602 		return KSFT_SKIP;
603 	}
604 	if (access(PATH_ZSWAP_STORED_PAGES, R_OK)) {
605 		ksft_print_msg("debugfs not mounted at /sys/kernel/debug\n");
606 		return KSFT_SKIP;
607 	}
608 	values = mmap(0, sizeof(struct no_kmem_bypass_child_args), PROT_READ |
609 			PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
610 	if (values == MAP_FAILED)
611 		return KSFT_FAIL;
612 	if (read_min_free_kb(&min_free_kb_original))
613 		return KSFT_FAIL;
614 	min_free_kb_high = sys_info.totalram / 2000;
615 	min_free_kb_low = sys_info.totalram / 500000;
616 	values->target_alloc_bytes = (sys_info.totalram - min_free_kb_high * 1000) +
617 		sys_info.totalram * 5 / 100;
618 	stored_pages_threshold = sys_info.totalram / 5 / page_size;
619 	trigger_allocation_size = sys_info.totalram / 20;
620 
621 	/* Set up test memcg */
622 	test_group = cg_name(root, "kmem_bypass_test");
623 	if (!test_group)
624 		goto out;
625 
626 	/* Spawn memcg child and wait for it to allocate */
627 	set_min_free_kb(min_free_kb_low);
628 	if (cg_create(test_group))
629 		goto out;
630 	values->child_allocated = false;
631 	child_pid = cg_run_nowait(test_group, no_kmem_bypass_child, values);
632 	if (child_pid < 0)
633 		goto out;
634 	while (!values->child_allocated && wait_child_iteration++ < 10000)
635 		usleep(1000);
636 
637 	/* Try to wakeup kswapd and let it push child memory to zswap */
638 	set_min_free_kb(min_free_kb_high);
639 	for (int i = 0; i < 20; i++) {
640 		size_t stored_pages;
641 		char *trigger_allocation = malloc(trigger_allocation_size);
642 
643 		if (!trigger_allocation)
644 			break;
645 		for (int i = 0; i < trigger_allocation_size; i += page_size)
646 			trigger_allocation[i] = 'b';
647 		usleep(100000);
648 		free(trigger_allocation);
649 		if (get_zswap_stored_pages(&stored_pages))
650 			break;
651 		if (stored_pages < 0)
652 			break;
653 		/* If memory was pushed to zswap, verify it belongs to memcg */
654 		if (stored_pages > stored_pages_threshold) {
655 			int zswapped = cg_read_key_long(test_group, "memory.stat", "zswapped ");
656 			int delta = stored_pages * page_size - zswapped;
657 			int result_ok = delta < stored_pages * page_size / 4;
658 
659 			ret = result_ok ? KSFT_PASS : KSFT_FAIL;
660 			break;
661 		}
662 	}
663 
664 	kill(child_pid, SIGTERM);
665 	waitpid(child_pid, &child_status, 0);
666 out:
667 	set_min_free_kb(min_free_kb_original);
668 	cg_destroy(test_group);
669 	free(test_group);
670 	return ret;
671 }
672 
673 struct incomp_child_args {
674 	size_t size;
675 	int pipefd[2];
676 	int madvise_ret;
677 	int madvise_errno;
678 };
679 
allocate_random_and_wait(const char * cgroup,void * arg)680 static int allocate_random_and_wait(const char *cgroup, void *arg)
681 {
682 	struct incomp_child_args *values = arg;
683 	size_t size = values->size;
684 	char *mem;
685 	int fd;
686 	ssize_t n;
687 
688 	close(values->pipefd[0]);
689 
690 	mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
691 		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
692 	if (mem == MAP_FAILED)
693 		return -1;
694 
695 	/* Fill with random data from /dev/urandom - incompressible */
696 	fd = open("/dev/urandom", O_RDONLY);
697 	if (fd < 0) {
698 		munmap(mem, size);
699 		return -1;
700 	}
701 
702 	for (size_t i = 0; i < size; ) {
703 		n = read(fd, mem + i, size - i);
704 		if (n <= 0)
705 			break;
706 		i += n;
707 	}
708 	close(fd);
709 
710 	/* Touch all pages to ensure they're faulted in */
711 	for (size_t i = 0; i < size; i += page_size)
712 		mem[i] = mem[i];
713 
714 	/* Use MADV_PAGEOUT to push pages into zswap */
715 	values->madvise_ret = madvise(mem, size, MADV_PAGEOUT);
716 	values->madvise_errno = errno;
717 
718 	/* Notify parent that allocation and pageout are done */
719 	write(values->pipefd[1], "x", 1);
720 	close(values->pipefd[1]);
721 
722 	/* Keep memory alive for parent to check stats */
723 	pause();
724 	munmap(mem, size);
725 	return 0;
726 }
727 
get_zswap_incomp(const char * cgroup)728 static long get_zswap_incomp(const char *cgroup)
729 {
730 	return cg_read_key_long(cgroup, "memory.stat", "zswap_incomp ");
731 }
732 
733 /*
734  * Test that incompressible pages (random data) are tracked by zswap_incomp.
735  *
736  * The child process allocates random data within memory.max, then uses
737  * MADV_PAGEOUT to push pages into zswap. The parent waits on a pipe for
738  * the child to finish, then checks the zswap_incomp stat before the child
739  * exits (zswap_incomp is a gauge that decreases on free).
740  */
test_zswap_incompressible(const char * root)741 static int test_zswap_incompressible(const char *root)
742 {
743 	int ret = KSFT_FAIL;
744 	struct incomp_child_args *values;
745 	char *test_group;
746 	long zswap_incomp;
747 	pid_t child_pid;
748 	int child_status;
749 	char buf;
750 
751 	values = mmap(0, sizeof(struct incomp_child_args), PROT_READ |
752 			PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
753 	if (values == MAP_FAILED)
754 		return KSFT_FAIL;
755 
756 	if (pipe(values->pipefd)) {
757 		munmap(values, sizeof(struct incomp_child_args));
758 		return KSFT_FAIL;
759 	}
760 
761 	test_group = cg_name(root, "zswap_incompressible_test");
762 	if (!test_group)
763 		goto out;
764 	if (cg_create(test_group))
765 		goto out;
766 	if (cg_write(test_group, "memory.max", "32M"))
767 		goto out;
768 
769 	values->size = MB(4);
770 	child_pid = cg_run_nowait(test_group, allocate_random_and_wait, values);
771 	if (child_pid < 0)
772 		goto out;
773 
774 	close(values->pipefd[1]);
775 
776 	/* Wait for child to finish allocating and pageout */
777 	read(values->pipefd[0], &buf, 1);
778 	close(values->pipefd[0]);
779 
780 	zswap_incomp = get_zswap_incomp(test_group);
781 	if (zswap_incomp <= 0) {
782 		long zswpout = get_zswpout(test_group);
783 		long zswapped = cg_read_key_long(test_group, "memory.stat", "zswapped ");
784 		long zswap_b = cg_read_key_long(test_group, "memory.stat", "zswap ");
785 
786 		ksft_print_msg("zswap_incomp not increased: %ld\n", zswap_incomp);
787 		ksft_print_msg("debug: zswpout=%ld zswapped=%ld zswap_b=%ld\n",
788 			       zswpout, zswapped, zswap_b);
789 		ksft_print_msg("debug: madvise ret=%d errno=%d\n",
790 			       values->madvise_ret, values->madvise_errno);
791 		goto out_kill;
792 	}
793 
794 	ret = KSFT_PASS;
795 
796 out_kill:
797 	kill(child_pid, SIGTERM);
798 	waitpid(child_pid, &child_status, 0);
799 out:
800 	cg_destroy(test_group);
801 	free(test_group);
802 	munmap(values, sizeof(struct incomp_child_args));
803 	return ret;
804 }
805 
806 #define T(x) { x, #x }
807 struct zswap_test {
808 	int (*fn)(const char *root);
809 	const char *name;
810 } tests[] = {
811 	T(test_zswap_usage),
812 	T(test_swapin_nozswap),
813 	T(test_zswapin),
814 	T(test_zswap_writeback_enabled),
815 	T(test_zswap_writeback_disabled),
816 	T(test_no_kmem_bypass),
817 	T(test_no_invasive_cgroup_shrink),
818 	T(test_zswap_incompressible),
819 };
820 #undef T
821 
check_zswap_enabled(void)822 static void check_zswap_enabled(void)
823 {
824 	char value[2];
825 
826 	if (access(PATH_ZSWAP, F_OK))
827 		ksft_exit_skip("zswap isn't configured\n");
828 
829 	if (read_text(PATH_ZSWAP_ENABLED, value, sizeof(value)) <= 0)
830 		ksft_exit_fail_msg("Failed to read " PATH_ZSWAP_ENABLED "\n");
831 
832 	if (value[0] == 'N')
833 		ksft_exit_skip("zswap is disabled (hint: echo 1 > " PATH_ZSWAP_ENABLED ")\n");
834 }
835 
main(int argc,char ** argv)836 int main(int argc, char **argv)
837 {
838 	char root[PATH_MAX];
839 	int i;
840 
841 	page_size = sysconf(_SC_PAGE_SIZE);
842 	if (page_size <= 0)
843 		page_size = BUF_SIZE;
844 
845 	ksft_print_header();
846 	if (cg_find_unified_root(root, sizeof(root), NULL))
847 		ksft_exit_skip("cgroup v2 isn't mounted\n");
848 
849 	check_zswap_enabled();
850 
851 	/*
852 	 * Check that memory controller is available:
853 	 * memory is listed in cgroup.controllers
854 	 */
855 	if (cg_read_strstr(root, "cgroup.controllers", "memory"))
856 		ksft_exit_skip("memory controller isn't available\n");
857 
858 	if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
859 		if (cg_write(root, "cgroup.subtree_control", "+memory"))
860 			ksft_exit_skip("Failed to set memory controller\n");
861 
862 	ksft_set_plan(ARRAY_SIZE(tests));
863 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
864 		switch (tests[i].fn(root)) {
865 		case KSFT_PASS:
866 			ksft_test_result_pass("%s\n", tests[i].name);
867 			break;
868 		case KSFT_SKIP:
869 			ksft_test_result_skip("%s\n", tests[i].name);
870 			break;
871 		default:
872 			ksft_test_result_fail("%s\n", tests[i].name);
873 			break;
874 		}
875 	}
876 
877 	ksft_finished();
878 }
879