1 /*
2 *
3 * Copyright (c) 2003 The Regents of the University of California. All
4 * rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31
32 /*
33
34 torturetest.c
35
36 tests device creation and open, to test for memory leaks and locking
37 problems
38
39 */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <string.h>
47 #include <sys/time.h>
48 #include <sys/wait.h>
49 #include <signal.h>
50
51 #include "fusd.h"
52
53 /* open call fails every 100th time. */
54 int _open(struct fusd_file_info *file)
55 {
56 static int counter = 0;
57 if (counter++ % 100) return 0;
58 return -81;
59 }
60
61
62 int _close(struct fusd_file_info *file)
63 {
64 return 0;
65 }
66
67
68 #define HANDLEERROR(fd) \
69 if (((fd) < 0) && (errno != 81)) \
70 {fprintf(stderr, "%s: open error: %s\n", name, strerror(errno));exit(1);}
71
72 #define CLOSE(fd) \
73 if ((fd) >= 0) \
74 if (close(fd)<0) \
75 {fprintf(stderr, "%s: close error: %s\n", name, strerror(errno));exit(1);}
76
77 int main(int argc, char *argv[])
78 {
79 int i, j;
80 int num;
81 int retval;
82 char **devs;
83 pid_t *pids;
84
85 // init function table
86 fusd_file_operations_t
87 fops = {_open,
88 _close,
89 NULL,
90 NULL,
91 NULL,
92 NULL,
93 NULL};
94
95 if (argc != 2) {
96 fprintf(stderr, "usage: %s <number-devices-to-create>\n", argv[0]);
97 exit(0);
98 }
99
100 num = atoi(argv[1]);
101
102 devs = (char**)malloc(sizeof(char *)*num);
103 pids = (pid_t *)malloc(sizeof(pid_t)*num);
104
105
106 // create device names
107 for (i=0; i<num; i++) {
108 char dev[30];
109 sprintf(dev,"/dev/fusd-test/test%d",i);
110 devs[i] = strdup(dev);
111 }
112
113 /* create devices; 2 devices handled per process */
114 for (i=0; i<num; i+=2) {
115 int fork2 = fork();
116
117 if (fork2 == 0) {
118
119 if (fusd_register(devs[i], 0666, 0, &fops) < 0) {
120 perror("Register failed");
121 exit(1);
122 } else {
123 printf("pid %d: serving %s\n", getpid(), devs[i]);
124 }
125
126 i++;
127
128 if (i < num) {
129 if (fusd_register(devs[i], 0666, 0, &fops) < 0) {
130 perror("Register failed");
131 exit(1);
132 } else {
133 printf("pid %d: serving %s\n", getpid(), devs[i]);
134 }
135 }
136
137 /* run the devices */
138 fusd_run();
139 }
140
141 }
142
143
144 /* clients */
145 for (i=0; i<num; i++) {
146 int fork2 = fork();
147
148 if (fork2 > 0) {
149 pids[i] = fork2;
150 } else if (fork2 == 0) {
151 int fd, *fds;
152 struct timeval tv;
153 char name[50];
154
155
156 if ((fds = (int*)malloc(sizeof(int)*num)) == NULL) {
157 fprintf(stderr, "malloc failure");
158 exit(1);
159 }
160
161 // sleep((1+num/10) * (2+i/5));
162 sleep(10);
163 printf("pid %d: client starting...\n", getpid());
164 sprintf(name, "client (pid %d)", getpid());
165
166 // randomize
167 gettimeofday(&tv, NULL);
168 srandom(tv.tv_usec);
169 for (i=0; i<num*5; i++) {
170 int j = random() % num;
171 char *tmp = devs[j];
172 devs[j] = devs[0];
173 devs[0] = tmp;
174 }
175
176
177 for (j=0; j<num; j++) {
178 printf("loop (%d) %d\n", getpid(), j);
179
180 /* open and close each device */
181 for (i=0; i<num; i++) {
182 //printf("opening %s\n", sdevs[i]);
183 fd = open(devs[i], O_RDWR);
184 HANDLEERROR(fd);
185 CLOSE(fd);
186 if (random() % 2) usleep(20000);
187 }
188
189 /* open random device num x */
190 for (i=0; i<num; i++) {
191 fds[i] = open(devs[0], O_RDWR);
192 HANDLEERROR(fds[i]);
193 if (random() % 2) usleep(20000);
194 }
195
196 /* CLOSE that device, open a new one */
197 for (i=0; i<num; i++) {
198 CLOSE(fds[i]);
199 fds[i] = open(devs[i], O_RDWR);
200 HANDLEERROR(fds[i]);
201 if (random() % 2) usleep(20000);
202 }
203
204 /* open and close each device */
205 for (i=num-1; i>=0; i--) {
206 fd = open(devs[i], O_RDWR);
207 HANDLEERROR(fd);
208 CLOSE(fd);
209 CLOSE(fds[i]);
210 if (random() % 2) usleep(20000);
211 }
212
213 }
214
215 // leave some stuff open..
216 /* open random device num x */
217 for (i=0; i<num; i++) {
218 fd = open(devs[i], O_RDWR);
219 HANDLEERROR(fd);
220 fd = open(devs[0], O_RDWR);
221 HANDLEERROR(fd);
222 }
223
224 printf("done (%d) well, we finished..\n", getpid());
225 exit(0);
226 }
227
228 }
229
230 /* now wait for all the clients to finish */
231 retval = 1;
232
233 for (;;) {
234 int pid, status;
235 int i, j;
236
237 for (i = 0; i < num; i++) {
238 pid = wait(&status);
239
240 for (j = 0; j < num; j++) {
241 if (pids[j] == pid) {
242 pids[j] = -1;
243 fprintf(stderr, "master: pid %d finished\n", pid);
244 break;
245 }
246 }
247
248 if (j >= num) {
249 fprintf(stderr, "master: nonclient pid %d exited\n", pid);
250 goto done;
251 }
252
253 if (WEXITSTATUS(status)) {
254 fprintf(stderr, "master: uh oh, client %d reported retval %d\n",
255 pid, WEXITSTATUS(status));
256 goto done;
257 }
258
259 }
260
261 fprintf(stderr, "master: all clients exited successfully\n");
262 retval = 0;
263 goto done;
264 }
265
266 done:
267 signal(SIGINT, SIG_IGN);
268 kill(0, SIGINT);
269 exit(retval);
270 }
271
272
273
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.