xref: /dragonfly/test/stress/tuxload.c (revision f73cc8620098243df5c87cad36c5b0109372eb80)
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
mmap01(void * arg)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
mmap02(void * arg)94 mmap02(void *arg)
95 {
96           fliparg = 1;
97           mmap01(&fliparg);
98 
99           return 0;
100 }
101 
102 static void
usage(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
main(int argc,char * argv[])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
build_files(void)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
randomfill(int fd)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