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