Undoes mod: xfs-cmds:slinx:120772a
[xfstests-dev.git] / src / dirstress.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  * 
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32  
33  /*
34   * This is mostly a "crash & burn" test. -v turns on verbosity
35   * and -c actually fails on errors - but expected errors aren't
36   * expected...
37   */
38  
39 #include "global.h"
40
41 int verbose;
42 int pid;
43
44 int checkflag=0;
45
46 #define MKNOD_DEV 0
47
48 static int dirstress(char *dirname, int dirnum, int nfiles, int keep);
49 static int create_entries(int nfiles);
50 static int scramble_entries(int nfiles);
51 static int remove_entries(int nfiles);
52
53 int
54 main(
55         int     argc,
56         char    *argv[])
57 {
58         char    *dirname;
59         int     nprocs;
60         int     nfiles;
61         int     c;
62         int     errflg;
63         int     i;
64         long    seed;
65         int     childpid;
66         int     nprocs_per_dir;
67         int     keep;
68         int     status, istatus;
69         
70         pid=getpid();
71
72         errflg = 0;
73         dirname = NULL;
74         nprocs = 4;
75         nfiles = 100;
76         seed = time(NULL);
77         nprocs_per_dir = 1;
78         keep = 0;
79         verbose = 0;
80         while ((c = getopt(argc, argv, "d:p:f:s:n:kvc")) != EOF) {
81                 switch(c) {
82                         case 'p':
83                                 nprocs = atoi(optarg);
84                                 break;
85                         case 'f':
86                                 nfiles = atoi(optarg);
87                                 break;
88                         case 'n':
89                                 nprocs_per_dir = atoi(optarg);
90                                 break;
91                         case 'd':
92                                 dirname = optarg;
93                                 break;
94                         case 's':
95                                 seed = strtol(optarg, NULL, 0);
96                                 break;
97                         case 'k':
98                                 keep = 1;
99                                 break;
100                         case '?':
101                                 errflg++;
102                                 break;
103                         case 'v':
104                                 verbose++;
105                                 break;
106                         case 'c':
107                                 checkflag++;
108                                 break;
109                 }
110         }
111         if (errflg || (dirname == NULL)) {
112                 printf("Usage: dirstress [-d dir] [-p nprocs] [-f nfiles] [-n procs per dir]\n"
113                        "                 [-v] [-s seed] [-k] [-c]\n");
114                 exit(0); 
115         }
116
117         printf("** [%d] Using seed %ld\n", pid, seed);
118         srandom(seed);
119
120         for (i = 0; i < nprocs; i++) {
121                 if (verbose) fprintf(stderr,"** [%d] fork\n", pid);
122                 childpid = fork();
123                 if (childpid < 0) {
124                         perror("Fork failed");
125                         exit(errno);
126                 }
127                 if (childpid == 0) {
128                         int r;
129                         /* child */
130                         pid=getpid();
131                         
132                         if (verbose) fprintf(stderr,"** [%d] forked\n", pid);
133                         r=dirstress(dirname, i / nprocs_per_dir, nfiles, keep);
134                         if (verbose) fprintf(stderr,"** [%d] exit\n", pid);
135                         exit(r);
136                 }
137         }
138         if (verbose) fprintf(stderr,"** [%d] wait\n", pid);
139         istatus=0;
140         
141         /* wait & reap children, accumulating error results */
142         while (wait(&status) != -1)
143             istatus+=status/256;
144         
145         printf("INFO: Dirstress complete\n");
146         if (verbose) fprintf(stderr,"** [%d] exit %d\n", pid, istatus);
147         return istatus;
148 }
149
150
151
152 int
153 dirstress(
154         char    *dirname,
155         int     dirnum,
156         int     nfiles,
157         int     keep)
158 {
159         int             error;
160         char            buf[1024];
161         int             r;
162         
163         sprintf(buf, "%s/stressdir", dirname);
164         if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf);
165         error = mkdir(buf, 0777);
166         if (error && (errno != EEXIST)) {
167                 perror("Create stressdir directory failed");
168                 return 1;
169         }
170
171         if (verbose) fprintf(stderr,"** [%d] chdir %s\n", pid, buf);
172         error = chdir(buf);
173         if (error) {
174                 perror("Cannot chdir to main directory");
175                 return 1;
176         }
177
178         sprintf(buf, "stress.%d", dirnum);
179         if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf);
180         error = mkdir(buf, 0777);
181         if (error && (errno != EEXIST)) {
182                 perror("Create pid directory failed");
183                 return 1;
184         }
185
186         if (verbose) fprintf(stderr,"** [%d] chdir %s\n", pid, buf);
187         error = chdir(buf);
188         if (error) {
189                 perror("Cannot chdir to dirnum directory");
190                 return 1;
191         }
192
193         r=1; /* assume failure */
194         if (verbose) fprintf(stderr,"** [%d] create entries\n", pid);
195         if (create_entries(nfiles)) {
196             printf("!! [%d] create failed\n", pid);
197         } else {
198             if (verbose) fprintf(stderr,"** [%d] scramble entries\n", pid);
199             if (scramble_entries(nfiles)) {
200                 printf("!! [%d] scramble failed\n", pid);
201             } else {
202                 if (keep) {
203                     if (verbose) fprintf(stderr,"** [%d] keep entries\n", pid);
204                     r=0; /* success */
205                 } else {
206                     if (verbose) fprintf(stderr,"** [%d] remove entries\n", pid);
207                     if (remove_entries(nfiles)) {
208                         printf("!! [%d] remove failed\n", pid);
209                     } else {
210                         r=0; /* success */
211                     }
212                 }
213             }
214         }
215
216         if (verbose) fprintf(stderr,"** [%d] chdir ..\n", pid);
217         error = chdir("..");
218         if (error) {
219                 perror("Cannot chdir out of pid directory");
220                 return 1;
221         }
222
223         if (!keep) {
224                 sprintf(buf, "stress.%d", dirnum);
225                 if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf);
226                 if (rmdir(buf)) {
227                     perror("rmdir");
228                     if (checkflag) return 1;
229                 }
230         }
231         
232         if (verbose) fprintf(stderr,"** [%d] chdir ..\n", pid);
233         error = chdir("..");
234         if (error) {
235                 perror("Cannot chdir out of working directory");
236                 return 1;
237         }
238
239         if (!keep) {
240                 if (verbose) fprintf(stderr,"** [%d] rmdir stressdir\n", pid);
241                 if (rmdir("stressdir")) {
242                     perror("rmdir");
243                     if (checkflag) return 1;
244                 }
245         }
246
247         return r;
248 }
249
250 int
251 create_entries(
252        int      nfiles)
253 {
254         int     i;
255         int     fd;
256         char    buf[1024];
257
258         for (i = 0; i < nfiles; i++) {
259                 sprintf(buf, "XXXXXXXXXXXX.%d", i);
260                 switch (i % 4) {
261                 case 0:
262                         /*
263                          * Create a file
264                          */
265                         if (verbose) fprintf(stderr,"** [%d] creat %s\n", pid, buf);
266                         fd = creat(buf, 0666);
267                         if (fd > 0) {
268                                 if (verbose) fprintf(stderr,"** [%d] close %s\n", pid, buf);
269                                 close(fd);
270                         } else {
271                                 fprintf(stderr,"!! [%d] close %s failed\n", pid, buf);
272                                 perror("close");
273                                 if (checkflag) return 1;
274                         }
275                         
276                         break;
277                 case 1:
278                         /*
279                          * Make a directory.
280                          */
281                         if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf);
282                         if (mkdir(buf, 0777)) {
283                             fprintf(stderr,"!! [%d] mkdir %s 0777 failed\n", pid, buf);
284                             perror("mkdir");
285                             if (checkflag) return 1;
286                         }
287                         
288                         break;
289                 case 2:
290                         /*
291                          * Make a symlink
292                          */
293                         if (verbose) fprintf(stderr,"** [%d] symlink %s %s\n", pid, buf, buf);
294                         if (symlink(buf, buf)) {
295                             fprintf(stderr,"!! [%d] symlink %s %s failed\n", pid, buf, buf);
296                             perror("symlink");
297                             if (checkflag) return 1;
298                         }
299                         
300                         break;
301                 case 3:
302                         /*
303                          * Make a dev node
304                          */
305                         if (verbose) fprintf(stderr,"** [%d] mknod %s 0x%x\n", pid, buf, MKNOD_DEV);
306                         if (mknod(buf, S_IFCHR | 0666, MKNOD_DEV)) {
307                             fprintf(stderr,"!! [%d] mknod %s 0x%x failed\n", pid, buf, MKNOD_DEV);
308                             perror("mknod");
309                             if (checkflag) return 1;
310                         }
311                         
312                         break;
313                 default:
314                         break;
315                 }
316         }
317         return 0;
318 }
319
320
321 int
322 scramble_entries(
323         int     nfiles)
324 {
325         int             i;
326         char            buf[1024];
327         char            buf1[1024];
328         long            r;
329         int             fd;
330
331         for (i = 0; i < nfiles * 2; i++) {
332                 switch (i % 5) {
333                 case 0:
334                         /*
335                          * rename two random entries
336                          */
337                         r = random() % nfiles;
338                         sprintf(buf, "XXXXXXXXXXXX.%ld", r);
339                         r = random() % nfiles;
340                         sprintf(buf1, "XXXXXXXXXXXX.%ld", r);
341
342                         if (verbose) fprintf(stderr,"** [%d] rename %s %s\n", pid, buf, buf1);
343                         if (rename(buf, buf1)) {
344                             perror("rename");
345                             if (checkflag) return 1;
346                         }
347                         break;
348                 case 1:
349                         /*
350                          * unlink a random entry
351                          */
352                         r = random() % nfiles;
353                         sprintf(buf, "XXXXXXXXXXXX.%ld", r);
354                         if (verbose) fprintf(stderr,"** [%d] unlink %s\n", pid, buf);
355                         if (unlink(buf)) {
356                             fprintf(stderr,"!! [%d] unlink %s failed\n", pid, buf);
357                             perror("unlink");
358                             if (checkflag) return 1;
359                         }
360                         break;
361                 case 2:
362                         /*
363                          * rmdir a random entry
364                          */
365                         r = random() % nfiles;
366                         sprintf(buf, "XXXXXXXXXXXX.%ld", r);
367                         if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf);
368                         if (rmdir(buf)) {
369                             fprintf(stderr,"!! [%d] rmdir %s failed\n", pid, buf);
370                             perror("rmdir");
371                             if (checkflag) return 1;
372                         }
373                         break;
374                 case 3:
375                         /*
376                          * create a random entry
377                          */
378                         r = random() % nfiles;
379                         sprintf(buf, "XXXXXXXXXXXX.%ld", r);
380
381                         if (verbose) fprintf(stderr,"** [%d] creat %s 0666\n", pid, buf);
382                         fd = creat(buf, 0666);
383                         if (fd > 0) {
384                                 if (verbose) fprintf(stderr,"** [%d] close %s\n", pid, buf);
385                                 if (close(fd)) {
386                                     fprintf(stderr,"!! [%d] close %s failed\n", pid, buf);
387                                     perror("close");
388                                     if (checkflag) return 1;
389                                 }
390                         } else {
391                             fprintf(stderr,"!! [%d] creat %s 0666 failed\n", pid, buf);
392                             perror("creat");
393                             if (checkflag) return 1;
394                         }
395                         break;
396                 case 4:
397                         /*
398                          * mkdir a random entry
399                          */
400                         r = random() % nfiles;
401                         sprintf(buf, "XXXXXXXXXXXX.%ld", r);
402                         if (verbose) fprintf(stderr,"** [%d] mkdir %s\n", pid, buf);
403                         if (mkdir(buf, 0777)) {
404                             fprintf(stderr,"!! [%d] mkdir %s failed\n", pid, buf);
405                             perror("mkdir");
406                             if (checkflag) return 1;
407                         }
408                         break;
409                 default:
410                         break;
411                 }
412         }
413         return 0;
414 }
415                         
416 int
417 remove_entries(
418         int     nfiles)
419 {
420         int             i;
421         char            buf[1024];
422         struct stat     statb;
423         int             error;
424
425         for (i = 0; i < nfiles; i++) {
426                 sprintf(buf, "XXXXXXXXXXXX.%d", i);
427                 error = lstat(buf, &statb);
428                 if (error) {
429                         /* ignore this one */
430                         continue;
431                 }
432                 if (S_ISDIR(statb.st_mode)) {
433                         if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf);
434                         if (rmdir(buf)) {
435                             fprintf(stderr,"!! [%d] rmdir %s failed\n", pid, buf);
436                             perror("rmdir");
437                             if (checkflag) return 1;
438                         }
439                 } else {
440                         if (verbose) fprintf(stderr,"** [%d] unlink %s\n", pid, buf);
441                         if (unlink(buf)) {
442                             fprintf(stderr,"!! [%d] unlink %s failed\n", pid, buf);
443                             perror("unlink");
444                             if (checkflag) return 1;
445                         }
446                 }
447         }
448         return 0;
449 }