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