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