xref: /aosp_15_r20/external/ltp/testcases/kernel/device-drivers/zram/zram03.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2010  Red Hat, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker  */
5*49cdfc7eSAndroid Build Coastguard Worker 
6*49cdfc7eSAndroid Build Coastguard Worker /*\
7*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
8*49cdfc7eSAndroid Build Coastguard Worker  *
9*49cdfc7eSAndroid Build Coastguard Worker  * zram: generic RAM based compressed R/W block devices
10*49cdfc7eSAndroid Build Coastguard Worker  * http://lkml.org/lkml/2010/8/9/227
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * This case check whether data read from zram device is consistent with
13*49cdfc7eSAndroid Build Coastguard Worker  * thoese are written.
14*49cdfc7eSAndroid Build Coastguard Worker  */
15*49cdfc7eSAndroid Build Coastguard Worker 
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_stdio.h"
25*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker #define ZRAM_CONTROL_PATH	"/sys/class/zram-control"
28*49cdfc7eSAndroid Build Coastguard Worker #define HOT_ADD_PATH		ZRAM_CONTROL_PATH"/hot_add"
29*49cdfc7eSAndroid Build Coastguard Worker #define HOT_REMOVE_PATH		ZRAM_CONTROL_PATH"/hot_remove"
30*49cdfc7eSAndroid Build Coastguard Worker #define SIZE			(512 * 1024 * 1024L)
31*49cdfc7eSAndroid Build Coastguard Worker 
32*49cdfc7eSAndroid Build Coastguard Worker static char zram_block_path[100], zram_dev_path[100];
33*49cdfc7eSAndroid Build Coastguard Worker static int modprobe, dev_num, hot_add_flag;
34*49cdfc7eSAndroid Build Coastguard Worker static const char *const cmd_rmmod[] = {"rmmod", "zram", NULL};
35*49cdfc7eSAndroid Build Coastguard Worker 
set_disksize(void)36*49cdfc7eSAndroid Build Coastguard Worker static void set_disksize(void)
37*49cdfc7eSAndroid Build Coastguard Worker {
38*49cdfc7eSAndroid Build Coastguard Worker 	char disksize_path[200];
39*49cdfc7eSAndroid Build Coastguard Worker 
40*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "create a zram device with %ld bytes in size", SIZE);
41*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(disksize_path, "%s/disksize", zram_block_path);
42*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_PRINTF(disksize_path, "%ld", SIZE);
43*49cdfc7eSAndroid Build Coastguard Worker }
44*49cdfc7eSAndroid Build Coastguard Worker 
write_device(void)45*49cdfc7eSAndroid Build Coastguard Worker static void write_device(void)
46*49cdfc7eSAndroid Build Coastguard Worker {
47*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
48*49cdfc7eSAndroid Build Coastguard Worker 	char *s;
49*49cdfc7eSAndroid Build Coastguard Worker 
50*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "map this zram device into memory");
51*49cdfc7eSAndroid Build Coastguard Worker 	fd = SAFE_OPEN(zram_dev_path, O_RDWR);
52*49cdfc7eSAndroid Build Coastguard Worker 	s = SAFE_MMAP(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "write all the memory");
55*49cdfc7eSAndroid Build Coastguard Worker 	memset(s, 'a', SIZE - 1);
56*49cdfc7eSAndroid Build Coastguard Worker 	s[SIZE - 1] = '\0';
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_MUNMAP(s, SIZE);
59*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(fd);
60*49cdfc7eSAndroid Build Coastguard Worker }
61*49cdfc7eSAndroid Build Coastguard Worker 
verify_device(void)62*49cdfc7eSAndroid Build Coastguard Worker static void verify_device(void)
63*49cdfc7eSAndroid Build Coastguard Worker {
64*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
65*49cdfc7eSAndroid Build Coastguard Worker 	long i = 0, fail = 0;
66*49cdfc7eSAndroid Build Coastguard Worker 	char *s;
67*49cdfc7eSAndroid Build Coastguard Worker 
68*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "verify contents from device");
69*49cdfc7eSAndroid Build Coastguard Worker 	fd = SAFE_OPEN(zram_dev_path, O_RDONLY);
70*49cdfc7eSAndroid Build Coastguard Worker 	s = SAFE_MMAP(NULL, SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker 	while (s[i] && i < SIZE - 1) {
73*49cdfc7eSAndroid Build Coastguard Worker 		if (s[i] != 'a')
74*49cdfc7eSAndroid Build Coastguard Worker 			fail++;
75*49cdfc7eSAndroid Build Coastguard Worker 		i++;
76*49cdfc7eSAndroid Build Coastguard Worker 	}
77*49cdfc7eSAndroid Build Coastguard Worker 	if (i != SIZE - 1) {
78*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "expect size: %ld, actual size: %ld.",
79*49cdfc7eSAndroid Build Coastguard Worker 			 SIZE - 1, i);
80*49cdfc7eSAndroid Build Coastguard Worker 	} else if (s[i] != '\0') {
81*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "zram device seems not null terminated");
82*49cdfc7eSAndroid Build Coastguard Worker 	} else if (fail) {
83*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "%ld failed bytes found", fail);
84*49cdfc7eSAndroid Build Coastguard Worker 	} else {
85*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "data read from zram device is consistent with those are written");
86*49cdfc7eSAndroid Build Coastguard Worker 	}
87*49cdfc7eSAndroid Build Coastguard Worker 
88*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_MUNMAP(s, SIZE);
89*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(fd);
90*49cdfc7eSAndroid Build Coastguard Worker }
91*49cdfc7eSAndroid Build Coastguard Worker 
reset_zram(void)92*49cdfc7eSAndroid Build Coastguard Worker static void reset_zram(void)
93*49cdfc7eSAndroid Build Coastguard Worker {
94*49cdfc7eSAndroid Build Coastguard Worker 	char reset_path[200];
95*49cdfc7eSAndroid Build Coastguard Worker 
96*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Reset zram");
97*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(reset_path, "%s/reset", zram_block_path);
98*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_PRINTF(reset_path, "1");
99*49cdfc7eSAndroid Build Coastguard Worker }
100*49cdfc7eSAndroid Build Coastguard Worker 
print(char * string)101*49cdfc7eSAndroid Build Coastguard Worker static void print(char *string)
102*49cdfc7eSAndroid Build Coastguard Worker {
103*49cdfc7eSAndroid Build Coastguard Worker 	char filename[BUFSIZ], value[BUFSIZ];
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s",  zram_block_path);
106*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(filename, "%s/%s", zram_block_path, string);
107*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_SCANF(filename, "%s", value);
108*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s is %s", filename, value);
109*49cdfc7eSAndroid Build Coastguard Worker }
110*49cdfc7eSAndroid Build Coastguard Worker 
print_stat(char * nread,char * nwrite)111*49cdfc7eSAndroid Build Coastguard Worker static void print_stat(char *nread, char *nwrite)
112*49cdfc7eSAndroid Build Coastguard Worker {
113*49cdfc7eSAndroid Build Coastguard Worker 	char nread_val[BUFSIZ], nwrite_val[BUFSIZ];
114*49cdfc7eSAndroid Build Coastguard Worker 	char zram_stat_path[100];
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(zram_stat_path, "/sys/block/zram%d/stat", dev_num);
117*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_SCANF(zram_stat_path, "%s %*s %*s %*s %s", nread_val, nwrite_val);
118*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s from %s is %s", nread, zram_stat_path, nread_val);
119*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s from %s is %s", nwrite, zram_stat_path, nwrite_val);
120*49cdfc7eSAndroid Build Coastguard Worker }
121*49cdfc7eSAndroid Build Coastguard Worker 
print_mm_stat(char * orig,char * compr,char * mem,char * zero)122*49cdfc7eSAndroid Build Coastguard Worker static void print_mm_stat(char *orig, char *compr, char *mem, char *zero)
123*49cdfc7eSAndroid Build Coastguard Worker {
124*49cdfc7eSAndroid Build Coastguard Worker 	char orig_val[BUFSIZ], compr_val[BUFSIZ];
125*49cdfc7eSAndroid Build Coastguard Worker 	char mem_val[BUFSIZ], zero_val[BUFSIZ];
126*49cdfc7eSAndroid Build Coastguard Worker 	char zram_mm_stat_path[100];
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(zram_mm_stat_path, "/sys/block/zram%d/mm_stat", dev_num);
129*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_SCANF(zram_mm_stat_path, "%s %s %s %*s %*s %s",
130*49cdfc7eSAndroid Build Coastguard Worker 			orig_val, compr_val, mem_val, zero_val);
131*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s from %s is %s", orig, zram_mm_stat_path, orig_val);
132*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s from %s is %s", compr, zram_mm_stat_path, compr_val);
133*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s from %s is %s", mem, zram_mm_stat_path, mem_val);
134*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s from %s is %s", zero, zram_mm_stat_path, zero_val);
135*49cdfc7eSAndroid Build Coastguard Worker }
136*49cdfc7eSAndroid Build Coastguard Worker 
dump_info(void)137*49cdfc7eSAndroid Build Coastguard Worker static void dump_info(void)
138*49cdfc7eSAndroid Build Coastguard Worker {
139*49cdfc7eSAndroid Build Coastguard Worker 	char zram_obsolete_file_path[100];
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(zram_obsolete_file_path, "/sys/block/zram%d/num_reads", dev_num);
142*49cdfc7eSAndroid Build Coastguard Worker 	print("initstate");
143*49cdfc7eSAndroid Build Coastguard Worker 	print("disksize");
144*49cdfc7eSAndroid Build Coastguard Worker 	if (!access(zram_obsolete_file_path, F_OK)) {
145*49cdfc7eSAndroid Build Coastguard Worker 		print("orig_data_size");
146*49cdfc7eSAndroid Build Coastguard Worker 		print("compr_data_size");
147*49cdfc7eSAndroid Build Coastguard Worker 		print("mem_used_total");
148*49cdfc7eSAndroid Build Coastguard Worker 		print("zero_pages");
149*49cdfc7eSAndroid Build Coastguard Worker 		print("num_reads");
150*49cdfc7eSAndroid Build Coastguard Worker 		print("num_writes");
151*49cdfc7eSAndroid Build Coastguard Worker 	} else {
152*49cdfc7eSAndroid Build Coastguard Worker 		print_mm_stat("orig_data_size", "compr_data_size",
153*49cdfc7eSAndroid Build Coastguard Worker 			      "mem_used_total", "zero/same_pages");
154*49cdfc7eSAndroid Build Coastguard Worker 		print_stat("num_reads", "num_writes");
155*49cdfc7eSAndroid Build Coastguard Worker 	}
156*49cdfc7eSAndroid Build Coastguard Worker }
157*49cdfc7eSAndroid Build Coastguard Worker 
run(void)158*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
159*49cdfc7eSAndroid Build Coastguard Worker {
160*49cdfc7eSAndroid Build Coastguard Worker 	set_disksize();
161*49cdfc7eSAndroid Build Coastguard Worker 
162*49cdfc7eSAndroid Build Coastguard Worker 	write_device();
163*49cdfc7eSAndroid Build Coastguard Worker 	dump_info();
164*49cdfc7eSAndroid Build Coastguard Worker 	verify_device();
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	reset_zram();
167*49cdfc7eSAndroid Build Coastguard Worker 	dump_info();
168*49cdfc7eSAndroid Build Coastguard Worker }
169*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)170*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
171*49cdfc7eSAndroid Build Coastguard Worker {
172*49cdfc7eSAndroid Build Coastguard Worker 	const char *const cmd_modprobe[] = {"modprobe", "zram", NULL};
173*49cdfc7eSAndroid Build Coastguard Worker 	const char *const cmd_zramctl[] = {"zramctl", "-f", NULL};
174*49cdfc7eSAndroid Build Coastguard Worker 	const char *zramctl_log_path = "zramctl.log";
175*49cdfc7eSAndroid Build Coastguard Worker 	FILE *file;
176*49cdfc7eSAndroid Build Coastguard Worker 	char line[PATH_MAX];
177*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
178*49cdfc7eSAndroid Build Coastguard Worker 
179*49cdfc7eSAndroid Build Coastguard Worker 	/* zram module was built in or loaded on new kernel */
180*49cdfc7eSAndroid Build Coastguard Worker 	if (!access(ZRAM_CONTROL_PATH, F_OK)) {
181*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO,
182*49cdfc7eSAndroid Build Coastguard Worker 			"zram module already loaded, kernel supports zram-control interface");
183*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FILE_SCANF(HOT_ADD_PATH, "%d", &dev_num);
184*49cdfc7eSAndroid Build Coastguard Worker 		hot_add_flag = 1;
185*49cdfc7eSAndroid Build Coastguard Worker 		goto fill_path;
186*49cdfc7eSAndroid Build Coastguard Worker 	}
187*49cdfc7eSAndroid Build Coastguard Worker 
188*49cdfc7eSAndroid Build Coastguard Worker 	 /* zram module was built in or being used on old kernel */
189*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CMD(cmd_modprobe, NULL, NULL);
190*49cdfc7eSAndroid Build Coastguard Worker 	file = SAFE_FOPEN("/proc/modules", "r");
191*49cdfc7eSAndroid Build Coastguard Worker 	while (fgets(line, sizeof(line), file)) {
192*49cdfc7eSAndroid Build Coastguard Worker 		if (strstr(line, "zram")) {
193*49cdfc7eSAndroid Build Coastguard Worker 			modprobe = 1;
194*49cdfc7eSAndroid Build Coastguard Worker 			break;
195*49cdfc7eSAndroid Build Coastguard Worker 		}
196*49cdfc7eSAndroid Build Coastguard Worker 	}
197*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FCLOSE(file);
198*49cdfc7eSAndroid Build Coastguard Worker 	if (access(ZRAM_CONTROL_PATH, F_OK)) {
199*49cdfc7eSAndroid Build Coastguard Worker 		if (modprobe) {
200*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO,
201*49cdfc7eSAndroid Build Coastguard Worker 				"rmmod zram before test on old kernel without zram-control interface");
202*49cdfc7eSAndroid Build Coastguard Worker 			if (!tst_cmd(cmd_rmmod, NULL, NULL, TST_CMD_PASS_RETVAL)) {
203*49cdfc7eSAndroid Build Coastguard Worker 				SAFE_CMD(cmd_modprobe, NULL, NULL);
204*49cdfc7eSAndroid Build Coastguard Worker 				goto fill_path;
205*49cdfc7eSAndroid Build Coastguard Worker 			}
206*49cdfc7eSAndroid Build Coastguard Worker 		} else {
207*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO,
208*49cdfc7eSAndroid Build Coastguard Worker 				"zram module is built in old kernel without zram-control interface");
209*49cdfc7eSAndroid Build Coastguard Worker 		}
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 		modprobe = 0;
212*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "use zramctl -f to find free zram device");
213*49cdfc7eSAndroid Build Coastguard Worker 		fd = SAFE_OPEN(zramctl_log_path, O_CREAT | O_RDWR, 0644);
214*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd);
215*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_cmd(cmd_zramctl, zramctl_log_path, NULL, TST_CMD_PASS_RETVAL))
216*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TCONF | TERRNO, "zramctl -f failed");
217*49cdfc7eSAndroid Build Coastguard Worker 		else
218*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_FILE_SCANF(zramctl_log_path, "/dev/zram%d", &dev_num);
219*49cdfc7eSAndroid Build Coastguard Worker 	}
220*49cdfc7eSAndroid Build Coastguard Worker 
221*49cdfc7eSAndroid Build Coastguard Worker fill_path:
222*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(zram_block_path, "/sys/block/zram%d", dev_num);
223*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(zram_dev_path, "/dev/zram%d", dev_num);
224*49cdfc7eSAndroid Build Coastguard Worker }
225*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)226*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
227*49cdfc7eSAndroid Build Coastguard Worker {
228*49cdfc7eSAndroid Build Coastguard Worker 	if (hot_add_flag)
229*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FILE_PRINTF(HOT_REMOVE_PATH, "%d", dev_num);
230*49cdfc7eSAndroid Build Coastguard Worker 
231*49cdfc7eSAndroid Build Coastguard Worker 	if (modprobe)
232*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CMD(cmd_rmmod, NULL, NULL);
233*49cdfc7eSAndroid Build Coastguard Worker }
234*49cdfc7eSAndroid Build Coastguard Worker 
235*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
236*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
237*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
238*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
239*49cdfc7eSAndroid Build Coastguard Worker 	.needs_root = 1,
240*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
241*49cdfc7eSAndroid Build Coastguard Worker 	.needs_drivers = (const char *const []) {
242*49cdfc7eSAndroid Build Coastguard Worker 		"zram",
243*49cdfc7eSAndroid Build Coastguard Worker 		NULL
244*49cdfc7eSAndroid Build Coastguard Worker 	},
245*49cdfc7eSAndroid Build Coastguard Worker 	.needs_cmds = (const char *[]) {
246*49cdfc7eSAndroid Build Coastguard Worker 		"modprobe",
247*49cdfc7eSAndroid Build Coastguard Worker 		"rmmod",
248*49cdfc7eSAndroid Build Coastguard Worker 		NULL
249*49cdfc7eSAndroid Build Coastguard Worker 	}
250*49cdfc7eSAndroid Build Coastguard Worker };
251