check: Remount file system if MOUNT_OPTIONS changed
[xfstests-dev.git] / src / scaleread.c
1 /*
2  * Copyright (c) 2003-2004 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 /*
19  * Test scaling of multiple processes opening/reading
20  * a number of small files simultaneously.
21  *      - create <f> files
22  *      - fork <n> processes
23  *      - wait for all processes ready
24  *      - start all proceses at the same time
25  *      - each processes opens , read, closes each file
26  *      - option to resync each process at each file
27  *
28  *      test [-c cpus] [-b bytes] [-f files] [-v] [-s] [-S]
29  *                      OR
30  *      test -i [-b bytes] [-f files] 
31  */
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/wait.h>
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <sys/ipc.h>
42 #include <sys/shm.h>
43
44 void do_initfiles(void);
45 void slave(int);
46
47 #define VPRINT(x...)    do { if(verbose) fprintf(x);} while(0)
48 #define perrorx(s) do {perror(s); exit(1);} while (0)
49
50 long bytes=8192;
51 int cpus=1;
52 int init=0;
53 int strided=0;
54 int files=1;
55 int blksize=512;
56 int syncstep=0;
57 int verbose=0;
58
59 typedef struct {
60         volatile long   go;
61         long            fill[15];
62         volatile long   rdy[512];
63 } share_t;
64
65 share_t *sharep;
66
67
68 int
69 runon(int cpu)
70 {
71 #ifdef sys_sched_setaffinity
72         unsigned long mask[8];
73         
74         if (cpu < 0 || cpu >= 512)
75                 return -1;
76         memset(mask, 0, sizeof(mask));
77         mask[cpu/64] |= 1UL<<(cpu&63);
78
79         if (syscall(sys_sched_setaffinity, 0, sizeof(mask), mask))
80                 return -1;
81 #endif
82         return 0;
83 }
84
85 long
86 scaled_atol(char *p)
87 {
88         long val;
89         char  *pe;
90
91         val = strtol(p, &pe, 0);
92         if (*pe == 'K' || *pe == 'k')
93                 val *= 1024L;
94         else if (*pe == 'M' || *pe == 'm')
95                 val *= 1024L*1024L;
96         else if (*pe == 'G' || *pe == 'g')
97                 val *= 1024L*1024L*1024L;
98         else if (*pe == 'p' || *pe == 'P')
99                 val *= getpagesize();
100         return val;
101 }
102
103
104 int
105 main(int argc, char** argv) {
106         int shmid;
107         static  char            optstr[] = "c:b:f:sSivH";
108         int                     notdone, stat, i, j, c, er=0;
109
110         opterr=1;
111         while ((c = getopt(argc, argv, optstr)) != EOF)
112                 switch (c) {
113                 case 'c':
114                         cpus = atoi(optarg);
115                         break;
116                 case 'b':
117                         bytes = scaled_atol(optarg);
118                         break;
119                 case 'f':
120                         files = atoi(optarg);
121                         break;
122                 case 'i':
123                         init++;
124                         break;
125                 case 's':
126                         syncstep++;
127                         break;
128                 case 'S':
129                         strided++;
130                         break;
131                 case 'v':
132                         verbose++;
133                         break;
134                 case '?':
135                         er = 1;
136                         break;
137                 }
138         if (er) {
139                 printf("usage: %s %s\n", argv[0], optstr);
140                 exit(1);
141         }
142
143
144         if ((shmid = shmget(IPC_PRIVATE, sizeof (share_t), IPC_CREAT|SHM_R|SHM_W))  == -1)
145                 perrorx("shmget failed");
146         sharep = (share_t*)shmat(shmid, (void*)0, SHM_R|SHM_W);
147         memset(sharep, -1, sizeof (share_t));
148
149         if (init) {
150                 do_initfiles();
151                 exit(0);
152         }
153         for (i=0; i<cpus; i++) {
154                 if (fork() == 0)
155                         slave(i);
156         }
157
158         for (i=0; i<files; i++) {
159                 VPRINT(stderr, "%d:", i);
160                 notdone = cpus;
161                 do {
162                         for (j=0; j<cpus; j++) {
163                                 if (sharep->rdy[j] == i) {
164                                         sharep->rdy[j] = -1;
165                                         VPRINT(stderr, " %d", j);
166                                         notdone--;
167                                 }
168                         }
169                 } while (notdone);
170                 VPRINT(stderr, "\n");
171                 sharep->go = i;
172                 if (!syncstep)
173                         break;
174         }
175         VPRINT(stderr, "\n");
176
177         while (wait(&stat)> 0)
178                 VPRINT(stderr, ".");
179         VPRINT(stderr, "\n");
180
181         exit(0);
182 }
183
184 void 
185 slave(int id)
186 {
187         int     i, fd, byte;
188         char    *buf, filename[32];
189
190         runon (id+1);
191         buf = malloc(blksize);
192         bzero(buf, blksize);
193         for (i=0; i<files; i++) {
194                 if (!i || syncstep) {
195                         sharep->rdy[id] = i;
196                         while(sharep->go != i);
197                 }
198                 sprintf(filename, "/tmp/tst.%d", (strided ? ((i + id) % files) : i));
199                 if ((fd = open (filename, O_RDONLY)) < 0) {
200                         perrorx(filename);
201                 }
202         
203                 for (byte=0; byte<bytes; byte+=blksize) {
204                         if (read (fd, buf, blksize) != blksize)
205                                 perrorx("read of file failed");
206                 }
207                 close(fd);
208         }
209         exit(0);
210 }
211
212 void
213 do_initfiles(void)
214 {
215         int     i, fd, byte;
216         char    *buf, filename[32];
217
218         buf = malloc(blksize);
219         bzero(buf, blksize);
220
221         for (i=0; i<files; i++) {
222                 sprintf(filename, "/tmp/tst.%d", i);
223                 unlink(filename);
224                 if ((fd = open (filename, O_RDWR|O_CREAT, 0644)) < 0)
225                         perrorx(filename);
226         
227                 for (byte=0; byte<bytes; byte+=blksize) {
228                         if (write (fd, buf, blksize) != blksize)
229                                 perrorx("write of file failed");
230                 }
231                 close(fd);
232         }
233         sync();
234 }
235
236