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