mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
c432589da3
Mostly scripted like all the others, manually added tags to Makefile, nsexec.c and t_mmap_writev.c. Manually touched up open_by_handle.c and t_encrypted_d_revalidate.c post script. Notes for future reference: - src/log-writes/ code has no explicit copyright or license tags, nor does the upstream repository, hence license is unknown. Need Josef to clarify the license and send a patch adding SPDX tags to those files. - src/perf code has no explicit copyright or license tags, but it was code submitted explictly for fstests so it is assumed to be GPLv2.0 and tagged as such. If this is incorrect, Josef will need to clarify copyright and the license and send patches to correct it. Signed-off-by: Dave Chinner <dchinner@redhat.com>
437 lines
11 KiB
C
437 lines
11 KiB
C
// 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;
|
|
}
|