| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000-2001 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| /* |
| * This is mostly a "crash & burn" test. -v turns on verbosity |
| * and -c actually fails on errors - but expected errors aren't |
| * expected... |
| */ |
| |
| #include "global.h" |
| |
| int verbose; |
| int pid; |
| |
| int checkflag=0; |
| |
| #define MKNOD_DEV 0 |
| |
| static int dirstress(char *dirname, int dirnum, int nfiles, int keep, int nprocs_per_dir); |
| static int create_entries(int nfiles); |
| static int scramble_entries(int nfiles); |
| static int remove_entries(int nfiles); |
| |
| int |
| main( |
| int argc, |
| char *argv[]) |
| { |
| char *dirname; |
| int nprocs; |
| int nfiles; |
| int c; |
| int errflg; |
| int i; |
| long seed; |
| int childpid; |
| int nprocs_per_dir; |
| int keep; |
| int status, istatus; |
| |
| pid=getpid(); |
| |
| errflg = 0; |
| dirname = NULL; |
| nprocs = 4; |
| nfiles = 100; |
| seed = time(NULL); |
| nprocs_per_dir = 1; |
| keep = 0; |
| verbose = 0; |
| while ((c = getopt(argc, argv, "d:p:f:s:n:kvc")) != EOF) { |
| switch(c) { |
| case 'p': |
| nprocs = atoi(optarg); |
| break; |
| case 'f': |
| nfiles = atoi(optarg); |
| break; |
| case 'n': |
| nprocs_per_dir = atoi(optarg); |
| break; |
| case 'd': |
| dirname = optarg; |
| break; |
| case 's': |
| seed = strtol(optarg, NULL, 0); |
| break; |
| case 'k': |
| keep = 1; |
| break; |
| case '?': |
| errflg++; |
| break; |
| case 'v': |
| verbose++; |
| break; |
| case 'c': |
| checkflag++; |
| break; |
| } |
| } |
| if (errflg || (dirname == NULL)) { |
| printf("Usage: dirstress [-d dir] [-p nprocs] [-f nfiles] [-n procs per dir]\n" |
| " [-v] [-s seed] [-k] [-c]\n"); |
| exit(0); |
| } |
| |
| printf("** [%d] Using seed %ld\n", pid, seed); |
| srandom(seed); |
| |
| for (i = 0; i < nprocs; i++) { |
| if (verbose) fprintf(stderr,"** [%d] fork\n", pid); |
| childpid = fork(); |
| if (childpid < 0) { |
| perror("Fork failed"); |
| exit(errno); |
| } |
| if (childpid == 0) { |
| int r; |
| /* child */ |
| pid=getpid(); |
| |
| if (verbose) fprintf(stderr,"** [%d] forked\n", pid); |
| r=dirstress(dirname, i / nprocs_per_dir, nfiles, keep, nprocs_per_dir); |
| if (verbose) fprintf(stderr,"** [%d] exit %d\n", pid, r); |
| exit(r); |
| } |
| } |
| if (verbose) fprintf(stderr,"** [%d] wait\n", pid); |
| istatus=0; |
| |
| /* wait & reap children, accumulating error results */ |
| while (wait(&status) != -1) |
| istatus+=status/256; |
| |
| printf("INFO: Dirstress complete\n"); |
| if (verbose) fprintf(stderr,"** [%d] parent exit %d\n", pid, istatus); |
| return istatus; |
| } |
| |
| |
| |
| int |
| dirstress( |
| char *dirname, |
| int dirnum, |
| int nfiles, |
| int keep, |
| int nprocs_per_dir) |
| { |
| int error; |
| char buf[1024]; |
| int r; |
| |
| sprintf(buf, "%s/stressdir", dirname); |
| if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf); |
| error = mkdir(buf, 0777); |
| if (error && (errno != EEXIST)) { |
| perror("Create stressdir directory failed"); |
| return 1; |
| } |
| |
| if (verbose) fprintf(stderr,"** [%d] chdir %s\n", pid, buf); |
| error = chdir(buf); |
| if (error) { |
| perror("Cannot chdir to main directory"); |
| return 1; |
| } |
| |
| sprintf(buf, "stress.%d", dirnum); |
| if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf); |
| error = mkdir(buf, 0777); |
| if (error && (errno != EEXIST)) { |
| perror("Create pid directory failed"); |
| return 1; |
| } |
| |
| if (verbose) fprintf(stderr,"** [%d] chdir %s\n", pid, buf); |
| error = chdir(buf); |
| if (error) { |
| perror("Cannot chdir to dirnum directory"); |
| return 1; |
| } |
| |
| r=1; /* assume failure */ |
| if (verbose) fprintf(stderr,"** [%d] create entries\n", pid); |
| if (create_entries(nfiles)) { |
| printf("!! [%d] create failed\n", pid); |
| } else { |
| if (verbose) fprintf(stderr,"** [%d] scramble entries\n", pid); |
| if (scramble_entries(nfiles)) { |
| printf("!! [%d] scramble failed\n", pid); |
| } else { |
| if (keep) { |
| if (verbose) fprintf(stderr,"** [%d] keep entries\n", pid); |
| r=0; /* success */ |
| } else { |
| if (verbose) fprintf(stderr,"** [%d] remove entries\n", pid); |
| if (remove_entries(nfiles)) { |
| printf("!! [%d] remove failed\n", pid); |
| } else { |
| r=0; /* success */ |
| } |
| } |
| } |
| } |
| |
| if (verbose) fprintf(stderr,"** [%d] chdir ..\n", pid); |
| error = chdir(".."); |
| if (error) { |
| /* If this is multithreaded, then expecting a ENOENT here is fine, |
| * and ESTALE is normal in the NFS case. */ |
| if (nprocs_per_dir > 1 && (errno == ENOENT || errno == ESTALE)) { |
| return 0; |
| } |
| |
| perror("Cannot chdir out of pid directory"); |
| return 1; |
| } |
| |
| if (!keep) { |
| sprintf(buf, "stress.%d", dirnum); |
| if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf); |
| if (rmdir(buf)) { |
| perror("rmdir"); |
| if (checkflag) return 1; |
| } |
| } |
| |
| if (verbose) fprintf(stderr,"** [%d] chdir ..\n", pid); |
| error = chdir(".."); |
| if (error) { |
| /* If this is multithreaded, then expecting a ENOENT here is fine, |
| * and ESTALE is normal in the NFS case. */ |
| if (nprocs_per_dir > 1 && (errno == ENOENT || errno == ESTALE)) { |
| return 0; |
| } |
| |
| perror("Cannot chdir out of working directory"); |
| return 1; |
| } |
| |
| if (!keep) { |
| if (verbose) fprintf(stderr,"** [%d] rmdir stressdir\n", pid); |
| if (rmdir("stressdir")) { |
| perror("rmdir"); |
| if (checkflag) return 1; |
| } |
| } |
| |
| return r; |
| } |
| |
| int |
| create_entries( |
| int nfiles) |
| { |
| int i; |
| int fd; |
| char buf[1024]; |
| |
| for (i = 0; i < nfiles; i++) { |
| sprintf(buf, "XXXXXXXXXXXX.%d", i); |
| switch (i % 4) { |
| case 0: |
| /* |
| * Create a file |
| */ |
| if (verbose) fprintf(stderr,"** [%d] creat %s\n", pid, buf); |
| fd = creat(buf, 0666); |
| if (fd > 0) { |
| if (verbose) fprintf(stderr,"** [%d] close %s\n", pid, buf); |
| close(fd); |
| } else { |
| fprintf(stderr,"!! [%d] close %s failed\n", pid, buf); |
| perror("close"); |
| if (checkflag) return 1; |
| } |
| |
| break; |
| case 1: |
| /* |
| * Make a directory. |
| */ |
| if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf); |
| if (mkdir(buf, 0777)) { |
| fprintf(stderr,"!! [%d] mkdir %s 0777 failed\n", pid, buf); |
| perror("mkdir"); |
| if (checkflag) return 1; |
| } |
| |
| break; |
| case 2: |
| /* |
| * Make a symlink |
| */ |
| if (verbose) fprintf(stderr,"** [%d] symlink %s %s\n", pid, buf, buf); |
| if (symlink(buf, buf)) { |
| fprintf(stderr,"!! [%d] symlink %s %s failed\n", pid, buf, buf); |
| perror("symlink"); |
| if (checkflag) return 1; |
| } |
| |
| break; |
| case 3: |
| /* |
| * Make a dev node |
| */ |
| if (verbose) fprintf(stderr,"** [%d] mknod %s 0x%x\n", pid, buf, MKNOD_DEV); |
| if (mknod(buf, S_IFCHR | 0666, MKNOD_DEV)) { |
| fprintf(stderr,"!! [%d] mknod %s 0x%x failed\n", pid, buf, MKNOD_DEV); |
| perror("mknod"); |
| if (checkflag) return 1; |
| } |
| |
| break; |
| default: |
| break; |
| } |
| } |
| return 0; |
| } |
| |
| |
| int |
| scramble_entries( |
| int nfiles) |
| { |
| int i; |
| char buf[1024]; |
| char buf1[1024]; |
| long r; |
| int fd; |
| |
| for (i = 0; i < nfiles * 2; i++) { |
| switch (i % 5) { |
| case 0: |
| /* |
| * rename two random entries |
| */ |
| r = random() % nfiles; |
| sprintf(buf, "XXXXXXXXXXXX.%ld", r); |
| r = random() % nfiles; |
| sprintf(buf1, "XXXXXXXXXXXX.%ld", r); |
| |
| if (verbose) fprintf(stderr,"** [%d] rename %s %s\n", pid, buf, buf1); |
| if (rename(buf, buf1)) { |
| perror("rename"); |
| if (checkflag) return 1; |
| } |
| break; |
| case 1: |
| /* |
| * unlink a random entry |
| */ |
| r = random() % nfiles; |
| sprintf(buf, "XXXXXXXXXXXX.%ld", r); |
| if (verbose) fprintf(stderr,"** [%d] unlink %s\n", pid, buf); |
| if (unlink(buf)) { |
| fprintf(stderr,"!! [%d] unlink %s failed\n", pid, buf); |
| perror("unlink"); |
| if (checkflag) return 1; |
| } |
| break; |
| case 2: |
| /* |
| * rmdir a random entry |
| */ |
| r = random() % nfiles; |
| sprintf(buf, "XXXXXXXXXXXX.%ld", r); |
| if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf); |
| if (rmdir(buf)) { |
| fprintf(stderr,"!! [%d] rmdir %s failed\n", pid, buf); |
| perror("rmdir"); |
| if (checkflag) return 1; |
| } |
| break; |
| case 3: |
| /* |
| * create a random entry |
| */ |
| r = random() % nfiles; |
| sprintf(buf, "XXXXXXXXXXXX.%ld", r); |
| |
| if (verbose) fprintf(stderr,"** [%d] creat %s 0666\n", pid, buf); |
| fd = creat(buf, 0666); |
| if (fd > 0) { |
| if (verbose) fprintf(stderr,"** [%d] close %s\n", pid, buf); |
| if (close(fd)) { |
| fprintf(stderr,"!! [%d] close %s failed\n", pid, buf); |
| perror("close"); |
| if (checkflag) return 1; |
| } |
| } else { |
| fprintf(stderr,"!! [%d] creat %s 0666 failed\n", pid, buf); |
| perror("creat"); |
| if (checkflag) return 1; |
| } |
| break; |
| case 4: |
| /* |
| * mkdir a random entry |
| */ |
| r = random() % nfiles; |
| sprintf(buf, "XXXXXXXXXXXX.%ld", r); |
| if (verbose) fprintf(stderr,"** [%d] mkdir %s\n", pid, buf); |
| if (mkdir(buf, 0777)) { |
| fprintf(stderr,"!! [%d] mkdir %s failed\n", pid, buf); |
| perror("mkdir"); |
| if (checkflag) return 1; |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| return 0; |
| } |
| |
| int |
| remove_entries( |
| int nfiles) |
| { |
| int i; |
| char buf[1024]; |
| struct stat statb; |
| int error; |
| |
| for (i = 0; i < nfiles; i++) { |
| sprintf(buf, "XXXXXXXXXXXX.%d", i); |
| error = lstat(buf, &statb); |
| if (error) { |
| /* ignore this one */ |
| continue; |
| } |
| if (S_ISDIR(statb.st_mode)) { |
| if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf); |
| if (rmdir(buf)) { |
| fprintf(stderr,"!! [%d] rmdir %s failed\n", pid, buf); |
| perror("rmdir"); |
| if (checkflag) return 1; |
| } |
| } else { |
| if (verbose) fprintf(stderr,"** [%d] unlink %s\n", pid, buf); |
| if (unlink(buf)) { |
| fprintf(stderr,"!! [%d] unlink %s failed\n", pid, buf); |
| perror("unlink"); |
| if (checkflag) return 1; |
| } |
| } |
| } |
| return 0; |
| } |