Home | History | Annotate | Download | only in zram
      1 /*
      2  * zram: generic RAM based compressed R/W block devices
      3  * http://lkml.org/lkml/2010/8/9/227
      4  *
      5  * Copyright (C) 2010  Red Hat, Inc.
      6  * This program is free software; you can redistribute it and/or
      7  * modify it under the terms of version 2 of the GNU General Public
      8  * License as published by the Free Software Foundation.
      9  *
     10  * This program is distributed in the hope that it would be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     13  *
     14  * Further, this software is distributed without any warranty that it
     15  * is free of the rightful claim of any third person regarding
     16  * infringement or the like.  Any license provided herein, whether
     17  * implied or otherwise, applies only to this software file.  Patent
     18  * licenses, if any, provided herein do not apply to combinations of
     19  * this program with other software, or any other product whatsoever.
     20  *
     21  * You should have received a copy of the GNU General Public License
     22  * along with this program; if not, write the Free Software
     23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     24  * 02110-1301, USA.
     25  */
     26 
     27 #include <sys/types.h>
     28 #include <sys/stat.h>
     29 #include <sys/mman.h>
     30 #include <errno.h>
     31 #include <fcntl.h>
     32 #include <stdio.h>
     33 #include <string.h>
     34 #include <unistd.h>
     35 
     36 #include "test.h"
     37 #include "safe_macros.h"
     38 
     39 char *TCID = "zram03";
     40 int TST_TOTAL = 1;
     41 
     42 #define PATH_ZRAM	"/sys/block/zram0"
     43 #define OBSOLETE_ZRAM_FILE	"/sys/block/zram0/num_reads"
     44 #define PATH_ZRAM_STAT	"/sys/block/zram0/stat"
     45 #define PATH_ZRAM_MM_STAT	"/sys/block/zram0/mm_stat"
     46 #define SIZE		(512 * 1024 * 1024L)
     47 #define DEVICE		"/dev/zram0"
     48 
     49 static int modprobe;
     50 
     51 static void set_disksize(void);
     52 static void write_device(void);
     53 static void verify_device(void);
     54 static void reset(void);
     55 static void setup(void);
     56 static void cleanup(void);
     57 static void print(char *string);
     58 static void dump_info(void);
     59 
     60 int main(int argc, char *argv[])
     61 {
     62 	int lc;
     63 
     64 	tst_parse_opts(argc, argv, NULL, NULL);
     65 
     66 	setup();
     67 
     68 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     69 		tst_count = 0;
     70 
     71 		set_disksize();
     72 
     73 		write_device();
     74 		dump_info();
     75 		verify_device();
     76 
     77 		reset();
     78 		dump_info();
     79 	}
     80 	cleanup();
     81 	tst_exit();
     82 }
     83 
     84 static void set_disksize(void)
     85 {
     86 	tst_resm(TINFO, "create a zram device with %ld bytes in size.", SIZE);
     87 	SAFE_FILE_PRINTF(cleanup, PATH_ZRAM "/disksize", "%ld", SIZE);
     88 }
     89 
     90 static void write_device(void)
     91 {
     92 	int fd;
     93 	char *s;
     94 
     95 	tst_resm(TINFO, "map this zram device into memory.");
     96 	fd = SAFE_OPEN(cleanup, DEVICE, O_RDWR);
     97 	s = SAFE_MMAP(cleanup, NULL, SIZE, PROT_READ | PROT_WRITE,
     98 		      MAP_SHARED, fd, 0);
     99 
    100 	tst_resm(TINFO, "write all the memory.");
    101 	memset(s, 'a', SIZE - 1);
    102 	s[SIZE - 1] = '\0';
    103 
    104 	SAFE_MUNMAP(cleanup, s, SIZE);
    105 	SAFE_CLOSE(cleanup, fd);
    106 }
    107 
    108 static void verify_device(void)
    109 {
    110 	int fd;
    111 	long i = 0, fail = 0;
    112 	char *s;
    113 
    114 	tst_resm(TINFO, "verify contents from device.");
    115 	fd = SAFE_OPEN(cleanup, DEVICE, O_RDONLY);
    116 	s = SAFE_MMAP(cleanup, NULL, SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
    117 
    118 	while (s[i] && i < SIZE - 1) {
    119 		if (s[i] != 'a')
    120 			fail++;
    121 		i++;
    122 	}
    123 	if (i != SIZE - 1) {
    124 		tst_resm(TFAIL, "expect size: %ld, actual size: %ld.",
    125 			 SIZE - 1, i);
    126 	} else if (s[i] != '\0') {
    127 		tst_resm(TFAIL, "zram device seems not null terminated");
    128 	} else if (fail) {
    129 		tst_resm(TFAIL, "%ld failed bytes found.", fail);
    130 	} else {
    131 		tst_resm(TPASS, "data read from zram device is consistent "
    132 			 "with those are written");
    133 	}
    134 
    135 	SAFE_MUNMAP(cleanup, s, SIZE);
    136 	SAFE_CLOSE(cleanup, fd);
    137 }
    138 
    139 static void reset(void)
    140 {
    141 	tst_resm(TINFO, "reset it.");
    142 	SAFE_FILE_PRINTF(cleanup, PATH_ZRAM "/reset", "1");
    143 }
    144 
    145 static void setup(void)
    146 {
    147 	int retried = 0;
    148 
    149 	tst_require_root();
    150 
    151 retry:
    152 	if (access(PATH_ZRAM, F_OK) == -1) {
    153 		if (errno == ENOENT) {
    154 			if (retried) {
    155 				tst_brkm(TCONF, NULL,
    156 					 "system has no zram device.");
    157 			}
    158 			if (system("modprobe zram") == -1) {
    159 				tst_brkm(TBROK | TERRNO, cleanup,
    160 					 "system(modprobe zram) failed");
    161 			}
    162 			modprobe = 1;
    163 			retried = 1;
    164 			goto retry;
    165 		} else
    166 			tst_brkm(TBROK | TERRNO, NULL, "access");
    167 	}
    168 
    169 	tst_sig(FORK, DEF_HANDLER, cleanup);
    170 	TEST_PAUSE;
    171 }
    172 
    173 static void cleanup(void)
    174 {
    175 	if (modprobe == 1 && system("rmmod zram") == -1)
    176 		tst_resm(TWARN | TERRNO, "system(rmmod zram) failed");
    177 }
    178 
    179 static void print(char *string)
    180 {
    181 	char filename[BUFSIZ], value[BUFSIZ];
    182 
    183 	sprintf(filename, "%s/%s", PATH_ZRAM, string);
    184 	SAFE_FILE_SCANF(cleanup, filename, "%s", value);
    185 	tst_resm(TINFO, "%s is %s", filename, value);
    186 }
    187 
    188 static void print_stat(char *nread, char *nwrite)
    189 {
    190 	char nread_val[BUFSIZ], nwrite_val[BUFSIZ];
    191 
    192 	SAFE_FILE_SCANF(cleanup, PATH_ZRAM_STAT, "%s %*s %*s %*s %s",
    193 			nread_val, nwrite_val);
    194 	tst_resm(TINFO, "%s from %s is %s", nread, PATH_ZRAM_STAT,
    195 		 nread_val);
    196 	tst_resm(TINFO, "%s from %s is %s", nwrite, PATH_ZRAM_STAT,
    197 		 nwrite_val);
    198 }
    199 
    200 static void print_mm_stat(char *orig, char *compr, char *mem, char *zero)
    201 {
    202 	char orig_val[BUFSIZ], compr_val[BUFSIZ];
    203 	char mem_val[BUFSIZ], zero_val[BUFSIZ];
    204 
    205 	SAFE_FILE_SCANF(cleanup, PATH_ZRAM_MM_STAT, "%s %s %s %*s %*s %s",
    206 			orig_val, compr_val, mem_val, zero_val);
    207 	tst_resm(TINFO, "%s from %s is %s", orig, PATH_ZRAM_MM_STAT,
    208 		 orig_val);
    209 	tst_resm(TINFO, "%s from %s is %s", compr, PATH_ZRAM_MM_STAT,
    210 		compr_val);
    211 	tst_resm(TINFO, "%s from %s is %s", mem, PATH_ZRAM_MM_STAT,
    212 		 mem_val);
    213 	tst_resm(TINFO, "%s from %s is %s", zero, PATH_ZRAM_MM_STAT,
    214 		 zero_val);
    215 }
    216 
    217 static void dump_info(void)
    218 {
    219 	print("initstate");
    220 	print("disksize");
    221 	if (!access(OBSOLETE_ZRAM_FILE, F_OK)) {
    222 		print("orig_data_size");
    223 		print("compr_data_size");
    224 		print("mem_used_total");
    225 		print("zero_pages");
    226 		print("num_reads");
    227 		print("num_writes");
    228 	} else {
    229 		print_mm_stat("orig_data_size", "compr_data_size",
    230 			      "mem_used_total", "zero/same_pages");
    231 		print_stat("num_reads", "num_writes");
    232 	}
    233 }
    234