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