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