1 /* 2 * TUXLOAD.C 3 * 4 * (c)Copyright 2012 Antonio Huete Jimenez <tuxillo@quantumachine.net>, 5 * this code is hereby placed in the public domain. 6 * 7 * As a safety the directory 'tmpfiles/' must exist. This program will 8 * create 500 x 8MB files in tmpfiles/*, memory map the files MAP_SHARED, 9 * R+W, make random modifications, and msync() in a loop. 10 * 11 * The purpose is to stress the VM system. 12 * 13 */ 14 #include <stdio.h> 15 #include <unistd.h> 16 #include <fcntl.h> 17 #include <stdlib.h> 18 #include <sys/mman.h> 19 #include <sys/stat.h> 20 #include <err.h> 21 #include <errno.h> 22 23 static void randomfill(int fd); 24 static int mmap01(void *); 25 static int mmap02(void *); 26 static int build_files(void); 27 28 int opt_verbose; 29 int opt_testno; 30 int opt_nofiles; 31 int opt_mbfile; 32 int opt_count; 33 int fliparg; 34 35 int *fd; 36 struct stat *st; 37 char **pp; 38 39 static const struct test { 40 char testdesc[128]; 41 int (*testfn)(void *); 42 } testlist[] = { 43 { "mmap01 - Massive mmap / msync (flushing all pages)", mmap01 }, 44 { "mmap02 - Massive mmap / msync (flushing only specified pages)", mmap02 }, 45 { "", NULL } 46 }; 47 48 static int 49 mmap01(void *arg) 50 { 51 int i; 52 int *bug = arg; 53 long jump; 54 size_t size, len; 55 56 if ((build_files()) != 0) 57 err(1, "Failed to create the files"); 58 59 if (opt_verbose) 60 printf("\n"); 61 62 for (i = 0; i < opt_nofiles; i++) { 63 64 if (opt_verbose) { 65 fflush(stdout); 66 fprintf(stdout, "\rDoing mmap() + msync() [%d/%d] ", i+1, opt_nofiles); 67 } 68 size = st[i].st_size; 69 pp[i] = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0); 70 if (pp[i] == MAP_FAILED) 71 err(1, "mmap"); 72 73 for (jump = 0; jump < size; jump += 65535) { 74 pp[i][jump] = jump + i; 75 } 76 77 if (fliparg) 78 len = MS_SYNC; 79 else 80 len = 0; 81 82 if ((msync(pp[i], len, MS_SYNC)) == -1) { 83 printf("fd %d %p\n", fd[i], pp[i]); 84 err(1, "msync"); 85 86 } 87 } 88 printf("\n"); 89 90 return 0; 91 } 92 93 static int 94 mmap02(void *arg) 95 { 96 fliparg = 1; 97 mmap01(&fliparg); 98 99 return 0; 100 } 101 102 static void 103 usage(void) 104 { 105 int i; 106 const struct test *tp; 107 108 printf("tuxload: [-v] [-c count] [-m megs_per_file] [-n no_of_files] [-t test_to_run] \n" 109 "Available tests: \n"); 110 111 for (tp = testlist; tp->testfn != NULL; tp++) 112 printf("\t%s\n", tp->testdesc); 113 exit(1); 114 } 115 116 int 117 main(int argc, char *argv[]) 118 { 119 int forever; 120 char c; 121 122 opt_verbose = opt_testno = 0; 123 opt_nofiles = 500; 124 opt_mbfile = 8; 125 opt_count = 1; 126 fliparg = 0; 127 forever = 0; 128 129 while ((c = getopt(argc, argv, "n:t:m:c:v")) != -1) { 130 switch(c) { 131 case 'v': 132 opt_verbose++; 133 break; 134 case 'n': 135 opt_nofiles = (int)strtol(optarg, NULL, 0); 136 break; 137 case 't': 138 opt_testno = (int)strtol(optarg, NULL, 0); 139 opt_testno--; 140 break; 141 case 'm': 142 opt_mbfile = (int)strtol(optarg, NULL, 0); 143 break; 144 case 'c': 145 opt_count = (int)strtol(optarg, NULL, 0); 146 if (opt_count == 0) 147 forever++; 148 break; 149 default: 150 usage(); 151 ; 152 } 153 } 154 argc -= optind; 155 argv += optind; 156 157 if (argc != 0) 158 usage(); 159 160 st = malloc(opt_nofiles * sizeof(*st)); 161 fd = malloc(opt_nofiles * sizeof(*fd)); 162 pp = malloc(opt_nofiles * sizeof(*pp)); 163 164 while (opt_count-- || forever) 165 testlist[opt_testno].testfn(0); 166 167 return 0; 168 } 169 170 static int 171 build_files(void) 172 { 173 char name[128]; 174 int i; 175 int error; 176 177 for (i = 0, error = 0; i < opt_nofiles; i++) { 178 snprintf(name, 128, "tmpfiles/file%d", i); 179 if ((fd[i] = open(name, O_RDWR)) < 1) { 180 if ((fd[i] = open(name, O_RDWR | O_CREAT, 0644)) < 1) { 181 error = errno; 182 break; 183 } 184 randomfill(fd[i]); 185 } 186 if ((fstat(fd[i], &st[i])) == -1) { 187 error = errno; 188 break; 189 } 190 if (opt_verbose) { 191 fprintf(stdout, "\rFile creation, random data filled [%d/%d] ", i+1, opt_nofiles); 192 fflush(stdout); 193 } 194 } 195 196 return error; 197 } 198 199 static void 200 randomfill(int fd) 201 { 202 char buf[32768]; 203 long tot; 204 int i; 205 206 srandomdev(); 207 tot = opt_mbfile * 1024L; 208 for (i = 0; i < 32768; ++i) 209 buf[i] = random(); 210 for (i = 0; i < tot; i += 32) /* 8MB by default */ 211 write(fd, buf, 32768); 212 fsync(fd); 213 lseek(fd, 0L, 0); 214 } 215