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 SIZE (512 * 1024 * 1024L) 44 #define DEVICE "/dev/zram0" 45 46 static int modprobe; 47 48 static void set_disksize(void); 49 static void write_device(void); 50 static void verify_device(void); 51 static void reset(void); 52 static void setup(void); 53 static void cleanup(void); 54 static void print(char *string); 55 static void dump_info(void); 56 57 int main(int argc, char *argv[]) 58 { 59 int lc; 60 61 tst_parse_opts(argc, argv, NULL, NULL); 62 63 setup(); 64 65 for (lc = 0; TEST_LOOPING(lc); lc++) { 66 tst_count = 0; 67 68 set_disksize(); 69 70 write_device(); 71 dump_info(); 72 verify_device(); 73 74 reset(); 75 dump_info(); 76 } 77 cleanup(); 78 tst_exit(); 79 } 80 81 static void set_disksize(void) 82 { 83 tst_resm(TINFO, "create a zram device with %ld bytes in size.", SIZE); 84 SAFE_FILE_PRINTF(cleanup, PATH_ZRAM "/disksize", "%ld", SIZE); 85 } 86 87 static void write_device(void) 88 { 89 int fd; 90 char *s; 91 92 tst_resm(TINFO, "map this zram device into memory."); 93 fd = SAFE_OPEN(cleanup, DEVICE, O_RDWR); 94 s = SAFE_MMAP(cleanup, NULL, SIZE, PROT_READ | PROT_WRITE, 95 MAP_SHARED, fd, 0); 96 97 tst_resm(TINFO, "write all the memory."); 98 memset(s, 'a', SIZE - 1); 99 s[SIZE - 1] = '\0'; 100 101 SAFE_MUNMAP(cleanup, s, SIZE); 102 SAFE_CLOSE(cleanup, fd); 103 } 104 105 static void verify_device(void) 106 { 107 int fd; 108 long i = 0, fail = 0; 109 char *s; 110 111 tst_resm(TINFO, "verify contents from device."); 112 fd = SAFE_OPEN(cleanup, DEVICE, O_RDONLY); 113 s = SAFE_MMAP(cleanup, NULL, SIZE, PROT_READ, MAP_PRIVATE, fd, 0); 114 115 while (s[i] && i < SIZE - 1) { 116 if (s[i] != 'a') 117 fail++; 118 i++; 119 } 120 if (i != SIZE - 1) { 121 tst_resm(TFAIL, "expect size: %ld, actual size: %ld.", 122 SIZE - 1, i); 123 } else if (s[i] != '\0') { 124 tst_resm(TFAIL, "zram device seems not null terminated"); 125 } else if (fail) { 126 tst_resm(TFAIL, "%ld failed bytes found.", fail); 127 } else { 128 tst_resm(TPASS, "data read from zram device is consistent " 129 "with those are written"); 130 } 131 132 SAFE_MUNMAP(cleanup, s, SIZE); 133 SAFE_CLOSE(cleanup, fd); 134 } 135 136 static void reset(void) 137 { 138 tst_resm(TINFO, "reset it."); 139 SAFE_FILE_PRINTF(cleanup, PATH_ZRAM "/reset", "1"); 140 } 141 142 static void setup(void) 143 { 144 int retried = 0; 145 146 tst_require_root(); 147 148 retry: 149 if (access(PATH_ZRAM, F_OK) == -1) { 150 if (errno == ENOENT) { 151 if (retried) { 152 tst_brkm(TCONF, NULL, 153 "system has no zram device."); 154 } 155 if (system("modprobe zram") == -1) { 156 tst_brkm(TBROK | TERRNO, cleanup, 157 "system(modprobe zram) failed"); 158 } 159 modprobe = 1; 160 retried = 1; 161 goto retry; 162 } else 163 tst_brkm(TBROK | TERRNO, NULL, "access"); 164 } 165 166 tst_sig(FORK, DEF_HANDLER, cleanup); 167 TEST_PAUSE; 168 } 169 170 static void cleanup(void) 171 { 172 if (modprobe == 1 && system("rmmod zram") == -1) 173 tst_resm(TWARN | TERRNO, "system(rmmod zram) failed"); 174 } 175 176 static void print(char *string) 177 { 178 char filename[BUFSIZ], value[BUFSIZ]; 179 180 sprintf(filename, "%s/%s", PATH_ZRAM, string); 181 SAFE_FILE_SCANF(cleanup, filename, "%s", value); 182 tst_resm(TINFO, "%s is %s", filename, value); 183 } 184 185 static void dump_info(void) 186 { 187 print("initstate"); 188 print("compr_data_size"); 189 print("orig_data_size"); 190 print("disksize"); 191 print("mem_used_total"); 192 print("num_reads"); 193 print("num_writes"); 194 print("zero_pages"); 195 } 196