Home | History | Annotate | Download | only in contrib
      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.,
     21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #define NO_XFS
     34 #define HAVE_SYS_PRCTL_H
     35 #define _LARGEFILE64_SOURCE
     36 
     37 #define MAXNAMELEN 1024
     38 struct dioattr {
     39 	int d_miniosz, d_maxiosz, d_mem;
     40 };
     41 
     42 #define MIN(a,b) ((a)<(b) ? (a):(b))
     43 #define MAX(a,b) ((a)>(b) ? (a):(b))
     44 
     45 #include <sys/stat.h>
     46 #include <sys/statvfs.h>
     47 #include <sys/time.h>
     48 #include <sys/ioctl.h>
     49 #include <sys/wait.h>
     50 #include <sys/types.h>
     51 #include <fcntl.h>
     52 #include <stdlib.h>
     53 #include <dirent.h>
     54 #include <errno.h>
     55 #include <string.h>
     56 #include <stdlib.h>
     57 #include <stdio.h>
     58 #include <unistd.h>
     59 
     60 #ifndef O_DIRECT
     61 #define O_DIRECT 040000
     62 #endif
     63 
     64 #ifdef HAVE_SYS_PRCTL_H
     65 # include <sys/prctl.h>
     66 #endif
     67 
     68 #define XFS_ERRTAG_MAX		17
     69 
     70 typedef enum {
     71 #ifndef NO_XFS
     72 	OP_ALLOCSP,
     73 	OP_ATTR_REMOVE,
     74 	OP_ATTR_SET,
     75 	OP_BULKSTAT,
     76 	OP_BULKSTAT1,
     77 #endif
     78 	OP_CHOWN,
     79 	OP_CREAT,
     80 	OP_DREAD,
     81 	OP_DWRITE,
     82 	OP_FDATASYNC,
     83 #ifndef NO_XFS
     84 	OP_FREESP,
     85 #endif
     86 	OP_FSYNC,
     87 	OP_GETDENTS,
     88 	OP_LINK,
     89 	OP_MKDIR,
     90 	OP_MKNOD,
     91 	OP_READ,
     92 	OP_READLINK,
     93 	OP_RENAME,
     94 #ifndef NO_XFS
     95 	OP_RESVSP,
     96 #endif
     97 	OP_RMDIR,
     98 	OP_STAT,
     99 	OP_SYMLINK,
    100 	OP_SYNC,
    101 	OP_TRUNCATE,
    102 	OP_UNLINK,
    103 #ifndef NO_XFS
    104 	OP_UNRESVSP,
    105 #endif
    106 	OP_WRITE,
    107 	OP_LAST
    108 } opty_t;
    109 
    110 typedef void (*opfnc_t) (int, long);
    111 
    112 typedef struct opdesc {
    113 	opty_t op;
    114 	char *name;
    115 	opfnc_t func;
    116 	int freq;
    117 	int iswrite;
    118 	int isxfs;
    119 } opdesc_t;
    120 
    121 typedef struct fent {
    122 	int id;
    123 	int parent;
    124 } fent_t;
    125 
    126 typedef struct flist {
    127 	int nfiles;
    128 	int nslots;
    129 	int tag;
    130 	fent_t *fents;
    131 } flist_t;
    132 
    133 typedef struct pathname {
    134 	int len;
    135 	char *path;
    136 } pathname_t;
    137 
    138 #define	FT_DIR	0
    139 #define	FT_DIRm	(1 << FT_DIR)
    140 #define	FT_REG	1
    141 #define	FT_REGm	(1 << FT_REG)
    142 #define	FT_SYM	2
    143 #define	FT_SYMm	(1 << FT_SYM)
    144 #define	FT_DEV	3
    145 #define	FT_DEVm	(1 << FT_DEV)
    146 #define	FT_RTF	4
    147 #define	FT_RTFm	(1 << FT_RTF)
    148 #define	FT_nft	5
    149 #define	FT_ANYm	((1 << FT_nft) - 1)
    150 #define	FT_REGFILE	(FT_REGm | FT_RTFm)
    151 #define	FT_NOTDIR	(FT_ANYm & ~FT_DIRm)
    152 
    153 #define	FLIST_SLOT_INCR	16
    154 #define	NDCACHE	64
    155 
    156 #define	MAXFSIZE	((1ULL << 63) - 1ULL)
    157 #define	MAXFSIZE32	((1ULL << 40) - 1ULL)
    158 
    159 void allocsp_f(int, long);
    160 void attr_remove_f(int, long);
    161 void attr_set_f(int, long);
    162 void bulkstat_f(int, long);
    163 void bulkstat1_f(int, long);
    164 void chown_f(int, long);
    165 void creat_f(int, long);
    166 void dread_f(int, long);
    167 void dwrite_f(int, long);
    168 void fdatasync_f(int, long);
    169 void freesp_f(int, long);
    170 void fsync_f(int, long);
    171 void getdents_f(int, long);
    172 void link_f(int, long);
    173 void mkdir_f(int, long);
    174 void mknod_f(int, long);
    175 void read_f(int, long);
    176 void readlink_f(int, long);
    177 void rename_f(int, long);
    178 void resvsp_f(int, long);
    179 void rmdir_f(int, long);
    180 void stat_f(int, long);
    181 void symlink_f(int, long);
    182 void sync_f(int, long);
    183 void truncate_f(int, long);
    184 void unlink_f(int, long);
    185 void unresvsp_f(int, long);
    186 void write_f(int, long);
    187 
    188 opdesc_t ops[] = {
    189 #ifndef NO_XFS
    190 	{OP_ALLOCSP, "allocsp", allocsp_f, 1, 1, 1},
    191 	{OP_ATTR_REMOVE, "attr_remove", attr_remove_f, /* 1 */ 0, 1, 1},
    192 	{OP_ATTR_SET, "attr_set", attr_set_f, /* 2 */ 0, 1, 1},
    193 	{OP_BULKSTAT, "bulkstat", bulkstat_f, 1, 0, 1},
    194 	{OP_BULKSTAT1, "bulkstat1", bulkstat1_f, 1, 0, 1},
    195 #endif
    196 	{OP_CHOWN, "chown", chown_f, 3, 1, 0},
    197 	{OP_CREAT, "creat", creat_f, 4, 1, 0},
    198 	{OP_DREAD, "dread", dread_f, 4, 0, 0},
    199 	{OP_DWRITE, "dwrite", dwrite_f, 4, 1, 0},
    200 	{OP_FDATASYNC, "fdatasync", fdatasync_f, 1, 1, 0},
    201 #ifndef NO_XFS
    202 	{OP_FREESP, "freesp", freesp_f, 1, 1, 1},
    203 #endif
    204 	{OP_FSYNC, "fsync", fsync_f, 1, 1, 0},
    205 	{OP_GETDENTS, "getdents", getdents_f, 1, 0, 0},
    206 	{OP_LINK, "link", link_f, 1, 1, 0},
    207 	{OP_MKDIR, "mkdir", mkdir_f, 2, 1, 0},
    208 	{OP_MKNOD, "mknod", mknod_f, 2, 1, 0},
    209 	{OP_READ, "read", read_f, 1, 0, 0},
    210 	{OP_READLINK, "readlink", readlink_f, 1, 0, 0},
    211 	{OP_RENAME, "rename", rename_f, 2, 1, 0},
    212 #ifndef NO_XFS
    213 	{OP_RESVSP, "resvsp", resvsp_f, 1, 1, 1},
    214 #endif
    215 	{OP_RMDIR, "rmdir", rmdir_f, 1, 1, 0},
    216 	{OP_STAT, "stat", stat_f, 1, 0, 0},
    217 	{OP_SYMLINK, "symlink", symlink_f, 2, 1, 0},
    218 	{OP_SYNC, "sync", sync_f, 1, 0, 0},
    219 	{OP_TRUNCATE, "truncate", truncate_f, 2, 1, 0},
    220 	{OP_UNLINK, "unlink", unlink_f, 1, 1, 0},
    221 #ifndef NO_XFS
    222 	{OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1, 1},
    223 #endif
    224 	{OP_WRITE, "write", write_f, 4, 1, 0},
    225 }, *ops_end;
    226 
    227 flist_t flist[FT_nft] = {
    228 	{0, 0, 'd', NULL},
    229 	{0, 0, 'f', NULL},
    230 	{0, 0, 'l', NULL},
    231 	{0, 0, 'c', NULL},
    232 	{0, 0, 'r', NULL},
    233 };
    234 
    235 int dcache[NDCACHE];
    236 int errrange;
    237 int errtag;
    238 opty_t *freq_table;
    239 int freq_table_size;
    240 #ifndef NO_XFS
    241 xfs_fsop_geom_t geom;
    242 #endif
    243 char *homedir;
    244 int *ilist;
    245 int ilistlen;
    246 off64_t maxfsize;
    247 char *myprog;
    248 int namerand;
    249 int nameseq;
    250 int nops;
    251 int nproc = 1;
    252 int operations = 1;
    253 int procid;
    254 int rtpct;
    255 unsigned long seed = 0;
    256 ino_t top_ino;
    257 int verbose = 0;
    258 #ifndef NO_XFS
    259 int no_xfs = 0;
    260 #else
    261 int no_xfs = 1;
    262 #endif
    263 sig_atomic_t should_stop = 0;
    264 
    265 void add_to_flist(int, int, int);
    266 void append_pathname(pathname_t *, char *);
    267 #ifndef NO_XFS
    268 int attr_list_path(pathname_t *, char *, const int, int, attrlist_cursor_t *);
    269 int attr_remove_path(pathname_t *, const char *, int);
    270 int attr_set_path(pathname_t *, const char *, const char *, const int, int);
    271 #endif
    272 void check_cwd(void);
    273 int creat_path(pathname_t *, mode_t);
    274 void dcache_enter(int, int);
    275 void dcache_init(void);
    276 fent_t *dcache_lookup(int);
    277 void dcache_purge(int);
    278 void del_from_flist(int, int);
    279 int dirid_to_name(char *, int);
    280 void doproc(void);
    281 void fent_to_name(pathname_t *, flist_t *, fent_t *);
    282 void fix_parent(int, int);
    283 void free_pathname(pathname_t *);
    284 int generate_fname(fent_t *, int, pathname_t *, int *, int *);
    285 int get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *);
    286 void init_pathname(pathname_t *);
    287 int lchown_path(pathname_t *, uid_t, gid_t);
    288 int link_path(pathname_t *, pathname_t *);
    289 int lstat64_path(pathname_t *, struct stat64 *);
    290 void make_freq_table(void);
    291 int mkdir_path(pathname_t *, mode_t);
    292 int mknod_path(pathname_t *, mode_t, dev_t);
    293 void namerandpad(int, char *, int);
    294 int open_path(pathname_t *, int);
    295 DIR *opendir_path(pathname_t *);
    296 void process_freq(char *);
    297 int readlink_path(pathname_t *, char *, size_t);
    298 int rename_path(pathname_t *, pathname_t *);
    299 int rmdir_path(pathname_t *);
    300 void separate_pathname(pathname_t *, char *, pathname_t *);
    301 void show_ops(int, char *);
    302 int stat64_path(pathname_t *, struct stat64 *);
    303 int symlink_path(const char *, pathname_t *);
    304 int truncate64_path(pathname_t *, off64_t);
    305 int unlink_path(pathname_t *);
    306 void usage(void);
    307 void write_freq(void);
    308 void zero_freq(void);
    309 
    310 void sg_handler(int signum)
    311 {
    312 	should_stop = 1;
    313 }
    314 
    315 int main(int argc, char **argv)
    316 {
    317 	char buf[10];
    318 	int c;
    319 	char *dirname = NULL;
    320 	int fd;
    321 	int i;
    322 	int cleanup = 0;
    323 	int loops = 1;
    324 	int loopcntr = 1;
    325 	char cmd[256];
    326 #ifndef NO_XFS
    327 	int j;
    328 #endif
    329 	char *p;
    330 	int stat;
    331 	struct timeval t;
    332 #ifndef NO_XFS
    333 	ptrdiff_t srval;
    334 #endif
    335 	int nousage = 0;
    336 #ifndef NO_XFS
    337 	xfs_error_injection_t err_inj;
    338 #endif
    339 	struct sigaction action;
    340 
    341 	errrange = errtag = 0;
    342 	umask(0);
    343 	nops = sizeof(ops) / sizeof(ops[0]);
    344 	ops_end = &ops[nops];
    345 	myprog = argv[0];
    346 	while ((c = getopt(argc, argv, "cd:e:f:i:l:n:p:rs:vwzHSX")) != -1) {
    347 		switch (c) {
    348 		case 'c':
    349 			/*Don't cleanup */
    350 			cleanup = 1;
    351 			break;
    352 		case 'd':
    353 			dirname = optarg;
    354 			break;
    355 		case 'e':
    356 			sscanf(optarg, "%d", &errtag);
    357 			if (errtag < 0) {
    358 				errtag = -errtag;
    359 				errrange = 1;
    360 			} else if (errtag == 0)
    361 				errtag = -1;
    362 			if (errtag >= XFS_ERRTAG_MAX) {
    363 				fprintf(stderr,
    364 					"error tag %d too large (max %d)\n",
    365 					errtag, XFS_ERRTAG_MAX - 1);
    366 				exit(1);
    367 			}
    368 			break;
    369 		case 'f':
    370 			process_freq(optarg);
    371 			break;
    372 		case 'i':
    373 			ilist = realloc(ilist, ++ilistlen * sizeof(*ilist));
    374 			ilist[ilistlen - 1] = strtol(optarg, &p, 16);
    375 			break;
    376 		case 'l':
    377 			loops = atoi(optarg);
    378 			break;
    379 		case 'n':
    380 			operations = atoi(optarg);
    381 			break;
    382 		case 'p':
    383 			nproc = atoi(optarg);
    384 			break;
    385 		case 'r':
    386 			namerand = 1;
    387 			break;
    388 		case 's':
    389 			seed = strtoul(optarg, NULL, 0);
    390 			break;
    391 		case 'v':
    392 			verbose = 1;
    393 			break;
    394 		case 'w':
    395 			write_freq();
    396 			break;
    397 		case 'z':
    398 			zero_freq();
    399 			break;
    400 		case 'S':
    401 			show_ops(0, NULL);
    402 			printf("\n");
    403 			nousage = 1;
    404 			break;
    405 		case '?':
    406 			fprintf(stderr, "%s - invalid parameters\n", myprog);
    407 			/* fall through */
    408 		case 'H':
    409 			usage();
    410 			exit(1);
    411 		case 'X':
    412 			no_xfs = 1;
    413 			break;
    414 		}
    415 	}
    416 
    417 	if (no_xfs && errtag) {
    418 		fprintf(stderr, "error injection only works on XFS\n");
    419 		exit(1);
    420 	}
    421 
    422 	if (no_xfs) {
    423 		int i;
    424 		for (i = 0; ops + i < ops_end; ++i) {
    425 			if (ops[i].isxfs)
    426 				ops[i].freq = 0;
    427 		}
    428 	}
    429 
    430 	make_freq_table();
    431 
    432 	while (((loopcntr <= loops) || (loops == 0)) && !should_stop) {
    433 		if (!dirname) {
    434 			/* no directory specified */
    435 			if (!nousage)
    436 				usage();
    437 			exit(1);
    438 		}
    439 
    440 		(void)mkdir(dirname, 0777);
    441 		if (chdir(dirname) < 0) {
    442 			perror(dirname);
    443 			exit(1);
    444 		}
    445 		sprintf(buf, "fss%x", getpid());
    446 		fd = creat(buf, 0666);
    447 		if (lseek64(fd, (off64_t) (MAXFSIZE32 + 1ULL), SEEK_SET) < 0)
    448 			maxfsize = (off64_t) MAXFSIZE32;
    449 		else
    450 			maxfsize = (off64_t) MAXFSIZE;
    451 		dcache_init();
    452 		setlinebuf(stdout);
    453 		if (!seed) {
    454 			gettimeofday(&t, NULL);
    455 			seed = (int)t.tv_sec ^ (int)t.tv_usec;
    456 			printf("seed = %ld\n", seed);
    457 		}
    458 #ifndef NO_XFS
    459 		if (!no_xfs) {
    460 			memset(&geom, 0, sizeof(geom));
    461 			i = ioctl(fd, XFS_IOC_FSGEOMETRY, &geom);
    462 			if (i >= 0 && geom.rtblocks)
    463 				rtpct = MIN(MAX(geom.rtblocks * 100 /
    464 						(geom.rtblocks +
    465 						 geom.datablocks), 1), 99);
    466 			else
    467 				rtpct = 0;
    468 		}
    469 		if (errtag != 0) {
    470 			if (errrange == 0) {
    471 				if (errtag <= 0) {
    472 					srandom(seed);
    473 					j = random() % 100;
    474 
    475 					for (i = 0; i < j; i++)
    476 						(void)random();
    477 
    478 					errtag =
    479 					    (random() % (XFS_ERRTAG_MAX - 1)) +
    480 					    1;
    481 				}
    482 			} else {
    483 				srandom(seed);
    484 				j = random() % 100;
    485 
    486 				for (i = 0; i < j; i++)
    487 					(void)random();
    488 
    489 				errtag +=
    490 				    (random() % (XFS_ERRTAG_MAX - errtag));
    491 			}
    492 			printf("Injecting failure on tag #%d\n", errtag);
    493 			memset(&err_inj, 0, sizeof(err_inj));
    494 			err_inj.errtag = errtag;
    495 			err_inj.fd = fd;
    496 			srval = ioctl(fd, XFS_IOC_ERROR_INJECTION, &err_inj);
    497 			if (srval < -1) {
    498 				perror
    499 				    ("fsstress - XFS_SYSSGI error injection call");
    500 				close(fd);
    501 				unlink(buf);
    502 				exit(1);
    503 			}
    504 		} else
    505 #endif
    506 			close(fd);
    507 		unlink(buf);
    508 
    509 
    510 		if (nproc == 1) {
    511 			procid = 0;
    512 			doproc();
    513 		} else {
    514 			setpgid(0, 0);
    515 			action.sa_handler = sg_handler;
    516 			sigemptyset(&action.sa_mask);
    517 			action.sa_flags = 0;
    518 			if (sigaction(SIGTERM, &action, 0)) {
    519 				perror("sigaction failed");
    520 				exit(1);
    521 			}
    522 
    523 			for (i = 0; i < nproc; i++) {
    524 				if (fork() == 0) {
    525 
    526 					action.sa_handler = SIG_DFL;
    527 					sigemptyset(&action.sa_mask);
    528 					if (sigaction(SIGTERM, &action, 0))
    529 						return 1;
    530 #ifdef HAVE_SYS_PRCTL_H
    531 					prctl(PR_SET_PDEATHSIG, SIGKILL);
    532 					if (getppid() == 1) /* parent died already? */
    533 						return 0;
    534 #endif
    535 					procid = i;
    536 					doproc();
    537 					return 0;
    538 				}
    539 			}
    540 			while (wait(&stat) > 0 && !should_stop) {
    541 				continue;
    542 			}
    543 			if (should_stop) {
    544 				action.sa_flags = SA_RESTART;
    545 				sigaction(SIGTERM, &action, 0);
    546 				kill(-getpid(), SIGTERM);
    547 				while (wait(&stat) > 0)
    548 					continue;
    549 			}
    550 		}
    551 #ifndef NO_XFS
    552 		if (errtag != 0) {
    553 			memset(&err_inj, 0, sizeof(err_inj));
    554 			err_inj.errtag = 0;
    555 			err_inj.fd = fd;
    556 			if ((srval =
    557 			     ioctl(fd, XFS_IOC_ERROR_CLEARALL,
    558 				   &err_inj)) != 0) {
    559 				fprintf(stderr, "Bad ej clear on %d (%d).\n",
    560 					fd, errno);
    561 				perror
    562 				    ("fsstress - XFS_SYSSGI clear error injection call");
    563 				close(fd);
    564 				exit(1);
    565 			}
    566 			close(fd);
    567 		}
    568 #endif
    569 		if (cleanup == 0) {
    570 			sprintf(cmd, "rm -rf %s/*", dirname);
    571 			system(cmd);
    572 			for (i = 0; i < FT_nft; i++) {
    573 				flist[i].nslots = 0;
    574 				flist[i].nfiles = 0;
    575 				free(flist[i].fents);
    576 				flist[i].fents = NULL;
    577 			}
    578 		}
    579 		loopcntr++;
    580 	}
    581 	return 0;
    582 }
    583 
    584 void add_to_flist(int ft, int id, int parent)
    585 {
    586 	fent_t *fep;
    587 	flist_t *ftp;
    588 
    589 	ftp = &flist[ft];
    590 	if (ftp->nfiles == ftp->nslots) {
    591 		ftp->nslots += FLIST_SLOT_INCR;
    592 		ftp->fents = realloc(ftp->fents, ftp->nslots * sizeof(fent_t));
    593 	}
    594 	fep = &ftp->fents[ftp->nfiles++];
    595 	fep->id = id;
    596 	fep->parent = parent;
    597 }
    598 
    599 void append_pathname(pathname_t * name, char *str)
    600 {
    601 	int len;
    602 
    603 	len = strlen(str);
    604 #ifdef DEBUG
    605 	if (len && *str == '/' && name->len == 0) {
    606 		fprintf(stderr, "fsstress: append_pathname failure\n");
    607 		chdir(homedir);
    608 		abort();
    609 
    610 	}
    611 #endif
    612 	name->path = realloc(name->path, name->len + 1 + len);
    613 	strcpy(&name->path[name->len], str);
    614 	name->len += len;
    615 }
    616 
    617 #ifndef NO_XFS
    618 int
    619 attr_list_path(pathname_t * name, char *buffer, const int buffersize, int flags,
    620 	       attrlist_cursor_t * cursor)
    621 {
    622 	char buf[MAXNAMELEN];
    623 	pathname_t newname;
    624 	int rval;
    625 
    626 	rval = attr_list(name->path, buffer, buffersize, flags, cursor);
    627 	if (rval >= 0 || errno != ENAMETOOLONG)
    628 		return rval;
    629 	separate_pathname(name, buf, &newname);
    630 	if (chdir(buf) == 0) {
    631 		rval = attr_list_path(&newname, buffer, buffersize, flags,
    632 				      cursor);
    633 		chdir("..");
    634 	}
    635 	free_pathname(&newname);
    636 	return rval;
    637 }
    638 
    639 int attr_remove_path(pathname_t * name, const char *attrname, int flags)
    640 {
    641 	char buf[MAXNAMELEN];
    642 	pathname_t newname;
    643 	int rval;
    644 
    645 	rval = attr_remove(name->path, attrname, flags);
    646 	if (rval >= 0 || errno != ENAMETOOLONG)
    647 		return rval;
    648 	separate_pathname(name, buf, &newname);
    649 	if (chdir(buf) == 0) {
    650 		rval = attr_remove_path(&newname, attrname, flags);
    651 		chdir("..");
    652 	}
    653 	free_pathname(&newname);
    654 	return rval;
    655 }
    656 
    657 int
    658 attr_set_path(pathname_t * name, const char *attrname, const char *attrvalue,
    659 	      const int valuelength, int flags)
    660 {
    661 	char buf[MAXNAMELEN];
    662 	pathname_t newname;
    663 	int rval;
    664 
    665 	rval = attr_set(name->path, attrname, attrvalue, valuelength, flags);
    666 	if (rval >= 0 || errno != ENAMETOOLONG)
    667 		return rval;
    668 	separate_pathname(name, buf, &newname);
    669 	if (chdir(buf) == 0) {
    670 		rval = attr_set_path(&newname, attrname, attrvalue, valuelength,
    671 				     flags);
    672 		chdir("..");
    673 	}
    674 	free_pathname(&newname);
    675 	return rval;
    676 }
    677 #endif
    678 
    679 void check_cwd(void)
    680 {
    681 #ifdef DEBUG
    682 	struct stat64 statbuf;
    683 
    684 	if (stat64(".", &statbuf) == 0 && statbuf.st_ino == top_ino)
    685 		return;
    686 	chdir(homedir);
    687 	fprintf(stderr, "fsstress: check_cwd failure\n");
    688 	abort();
    689 
    690 #endif
    691 }
    692 
    693 int creat_path(pathname_t * name, mode_t mode)
    694 {
    695 	char buf[MAXNAMELEN];
    696 	pathname_t newname;
    697 	int rval;
    698 
    699 	rval = creat(name->path, mode);
    700 	if (rval >= 0 || errno != ENAMETOOLONG)
    701 		return rval;
    702 	separate_pathname(name, buf, &newname);
    703 	if (chdir(buf) == 0) {
    704 		rval = creat_path(&newname, mode);
    705 		chdir("..");
    706 	}
    707 	free_pathname(&newname);
    708 	return rval;
    709 }
    710 
    711 void dcache_enter(int dirid, int slot)
    712 {
    713 	dcache[dirid % NDCACHE] = slot;
    714 }
    715 
    716 void dcache_init(void)
    717 {
    718 	int i;
    719 
    720 	for (i = 0; i < NDCACHE; i++)
    721 		dcache[i] = -1;
    722 }
    723 
    724 fent_t *dcache_lookup(int dirid)
    725 {
    726 	fent_t *fep;
    727 	int i;
    728 
    729 	i = dcache[dirid % NDCACHE];
    730 	if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
    731 		return fep;
    732 	return NULL;
    733 }
    734 
    735 void dcache_purge(int dirid)
    736 {
    737 	int *dcp;
    738 
    739 	dcp = &dcache[dirid % NDCACHE];
    740 	if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
    741 		*dcp = -1;
    742 }
    743 
    744 void del_from_flist(int ft, int slot)
    745 {
    746 	flist_t *ftp;
    747 
    748 	ftp = &flist[ft];
    749 	if (ft == FT_DIR)
    750 		dcache_purge(ftp->fents[slot].id);
    751 	if (slot != ftp->nfiles - 1) {
    752 		if (ft == FT_DIR)
    753 			dcache_purge(ftp->fents[ftp->nfiles - 1].id);
    754 		ftp->fents[slot] = ftp->fents[--ftp->nfiles];
    755 	} else
    756 		ftp->nfiles--;
    757 }
    758 
    759 fent_t *dirid_to_fent(int dirid)
    760 {
    761 	fent_t *efep;
    762 	fent_t *fep;
    763 	flist_t *flp;
    764 
    765 	if ((fep = dcache_lookup(dirid)))
    766 		return fep;
    767 	flp = &flist[FT_DIR];
    768 	for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
    769 		if (fep->id == dirid) {
    770 			dcache_enter(dirid, fep - flp->fents);
    771 			return fep;
    772 		}
    773 	}
    774 	return NULL;
    775 }
    776 
    777 void doproc(void)
    778 {
    779 	struct stat64 statbuf;
    780 	char buf[10];
    781 	int opno;
    782 	int rval;
    783 	opdesc_t *p;
    784 
    785 	sprintf(buf, "p%x", procid);
    786 	(void)mkdir(buf, 0777);
    787 	if (chdir(buf) < 0 || stat64(".", &statbuf) < 0) {
    788 		perror(buf);
    789 		_exit(1);
    790 	}
    791 	top_ino = statbuf.st_ino;
    792 	homedir = getcwd(NULL, -1);
    793 	seed += procid;
    794 	srandom(seed);
    795 	if (namerand)
    796 		namerand = random();
    797 	for (opno = 0; opno < operations; opno++) {
    798 		p = &ops[freq_table[random() % freq_table_size]];
    799 		if ((unsigned long)p->func < 4096)
    800 			abort();
    801 
    802 		p->func(opno, random());
    803 		/*
    804 		 * test for forced shutdown by stat'ing the test
    805 		 * directory.  If this stat returns EIO, assume
    806 		 * the forced shutdown happened.
    807 		 */
    808 		if (errtag != 0 && opno % 100 == 0) {
    809 			rval = stat64(".", &statbuf);
    810 			if (rval == EIO) {
    811 				fprintf(stderr, "Detected EIO\n");
    812 				return;
    813 			}
    814 		}
    815 	}
    816 }
    817 
    818 void fent_to_name(pathname_t * name, flist_t * flp, fent_t * fep)
    819 {
    820 	char buf[MAXNAMELEN];
    821 	int i;
    822 	fent_t *pfep;
    823 
    824 	if (fep == NULL)
    825 		return;
    826 	if (fep->parent != -1) {
    827 		pfep = dirid_to_fent(fep->parent);
    828 		fent_to_name(name, &flist[FT_DIR], pfep);
    829 		append_pathname(name, "/");
    830 	}
    831 	i = sprintf(buf, "%c%x", flp->tag, fep->id);
    832 	namerandpad(fep->id, buf, i);
    833 	append_pathname(name, buf);
    834 }
    835 
    836 void fix_parent(int oldid, int newid)
    837 {
    838 	fent_t *fep;
    839 	flist_t *flp;
    840 	int i;
    841 	int j;
    842 
    843 	for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
    844 		for (j = 0, fep = flp->fents; j < flp->nfiles; j++, fep++) {
    845 			if (fep->parent == oldid)
    846 				fep->parent = newid;
    847 		}
    848 	}
    849 }
    850 
    851 void free_pathname(pathname_t * name)
    852 {
    853 	if (name->path) {
    854 		free(name->path);
    855 		name->path = NULL;
    856 		name->len = 0;
    857 	}
    858 }
    859 
    860 int generate_fname(fent_t * fep, int ft, pathname_t * name, int *idp, int *v)
    861 {
    862 	char buf[MAXNAMELEN];
    863 	flist_t *flp;
    864 	int id;
    865 	int j;
    866 	int len;
    867 
    868 	flp = &flist[ft];
    869 	len = sprintf(buf, "%c%x", flp->tag, id = nameseq++);
    870 	namerandpad(id, buf, len);
    871 	if (fep) {
    872 		fent_to_name(name, &flist[FT_DIR], fep);
    873 		append_pathname(name, "/");
    874 	}
    875 	append_pathname(name, buf);
    876 	*idp = id;
    877 	*v = verbose;
    878 	for (j = 0; !*v && j < ilistlen; j++) {
    879 		if (ilist[j] == id) {
    880 			*v = 1;
    881 			break;
    882 		}
    883 	}
    884 	return 1;
    885 }
    886 
    887 int
    888 get_fname(int which, long r, pathname_t * name, flist_t ** flpp, fent_t ** fepp,
    889 	  int *v)
    890 {
    891 	int c;
    892 	fent_t *fep;
    893 	flist_t *flp;
    894 	int i;
    895 	int j;
    896 	int x;
    897 
    898 	for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) {
    899 		if (which & (1 << i))
    900 			c += flp->nfiles;
    901 	}
    902 	if (c == 0) {
    903 		if (flpp)
    904 			*flpp = NULL;
    905 		if (fepp)
    906 			*fepp = NULL;
    907 		*v = verbose;
    908 		return 0;
    909 	}
    910 	x = (int)(r % c);
    911 	for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) {
    912 		if (which & (1 << i)) {
    913 			if (x < c + flp->nfiles) {
    914 				fep = &flp->fents[x - c];
    915 				if (name)
    916 					fent_to_name(name, flp, fep);
    917 				if (flpp)
    918 					*flpp = flp;
    919 				if (fepp)
    920 					*fepp = fep;
    921 				*v = verbose;
    922 				for (j = 0; !*v && j < ilistlen; j++) {
    923 					if (ilist[j] == fep->id) {
    924 						*v = 1;
    925 						break;
    926 					}
    927 				}
    928 				return 1;
    929 			}
    930 			c += flp->nfiles;
    931 		}
    932 	}
    933 #ifdef DEBUG
    934 	fprintf(stderr, "fsstress: get_fname failure\n");
    935 	abort();
    936 #endif
    937 	return -1;
    938 
    939 }
    940 
    941 void init_pathname(pathname_t * name)
    942 {
    943 	name->len = 0;
    944 	name->path = NULL;
    945 }
    946 
    947 int lchown_path(pathname_t * name, uid_t owner, gid_t group)
    948 {
    949 	char buf[MAXNAMELEN];
    950 	pathname_t newname;
    951 	int rval;
    952 
    953 	rval = lchown(name->path, owner, group);
    954 	if (rval >= 0 || errno != ENAMETOOLONG)
    955 		return rval;
    956 	separate_pathname(name, buf, &newname);
    957 	if (chdir(buf) == 0) {
    958 		rval = lchown_path(&newname, owner, group);
    959 		chdir("..");
    960 	}
    961 	free_pathname(&newname);
    962 	return rval;
    963 }
    964 
    965 int link_path(pathname_t * name1, pathname_t * name2)
    966 {
    967 	char buf1[MAXNAMELEN];
    968 	char buf2[MAXNAMELEN];
    969 	int down1;
    970 	pathname_t newname1;
    971 	pathname_t newname2;
    972 	int rval;
    973 
    974 	rval = link(name1->path, name2->path);
    975 	if (rval >= 0 || errno != ENAMETOOLONG)
    976 		return rval;
    977 	separate_pathname(name1, buf1, &newname1);
    978 	separate_pathname(name2, buf2, &newname2);
    979 	if (strcmp(buf1, buf2) == 0) {
    980 		if (chdir(buf1) == 0) {
    981 			rval = link_path(&newname1, &newname2);
    982 			chdir("..");
    983 		}
    984 	} else {
    985 		if (strcmp(buf1, "..") == 0)
    986 			down1 = 0;
    987 		else if (strcmp(buf2, "..") == 0)
    988 			down1 = 1;
    989 		else if (strlen(buf1) == 0)
    990 			down1 = 0;
    991 		else if (strlen(buf2) == 0)
    992 			down1 = 1;
    993 		else
    994 			down1 = MAX(newname1.len, 3 + name2->len) <=
    995 			    MAX(3 + name1->len, newname2.len);
    996 		if (down1) {
    997 			free_pathname(&newname2);
    998 			append_pathname(&newname2, "../");
    999 			append_pathname(&newname2, name2->path);
   1000 			if (chdir(buf1) == 0) {
   1001 				rval = link_path(&newname1, &newname2);
   1002 				chdir("..");
   1003 			}
   1004 		} else {
   1005 			free_pathname(&newname1);
   1006 			append_pathname(&newname1, "../");
   1007 			append_pathname(&newname1, name1->path);
   1008 			if (chdir(buf2) == 0) {
   1009 				rval = link_path(&newname1, &newname2);
   1010 				chdir("..");
   1011 			}
   1012 		}
   1013 	}
   1014 	free_pathname(&newname1);
   1015 	free_pathname(&newname2);
   1016 	return rval;
   1017 }
   1018 
   1019 int lstat64_path(pathname_t * name, struct stat64 *sbuf)
   1020 {
   1021 	char buf[MAXNAMELEN];
   1022 	pathname_t newname;
   1023 	int rval;
   1024 
   1025 	rval = lstat64(name->path, sbuf);
   1026 	if (rval >= 0 || errno != ENAMETOOLONG)
   1027 		return rval;
   1028 	separate_pathname(name, buf, &newname);
   1029 	if (chdir(buf) == 0) {
   1030 		rval = lstat64_path(&newname, sbuf);
   1031 		chdir("..");
   1032 	}
   1033 	free_pathname(&newname);
   1034 	return rval;
   1035 }
   1036 
   1037 void make_freq_table(void)
   1038 {
   1039 	int f;
   1040 	int i;
   1041 	opdesc_t *p;
   1042 
   1043 	for (p = ops, f = 0; p < ops_end; p++)
   1044 		f += p->freq;
   1045 	freq_table = malloc(f * sizeof(*freq_table));
   1046 	freq_table_size = f;
   1047 	for (p = ops, i = 0; p < ops_end; p++) {
   1048 		for (f = 0; f < p->freq; f++, i++)
   1049 			freq_table[i] = p->op;
   1050 	}
   1051 }
   1052 
   1053 int mkdir_path(pathname_t * name, mode_t mode)
   1054 {
   1055 	char buf[MAXNAMELEN];
   1056 	pathname_t newname;
   1057 	int rval;
   1058 
   1059 	rval = mkdir(name->path, mode);
   1060 	if (rval >= 0 || errno != ENAMETOOLONG)
   1061 		return rval;
   1062 	separate_pathname(name, buf, &newname);
   1063 	if (chdir(buf) == 0) {
   1064 		rval = mkdir_path(&newname, mode);
   1065 		chdir("..");
   1066 	}
   1067 	free_pathname(&newname);
   1068 	return rval;
   1069 }
   1070 
   1071 int mknod_path(pathname_t * name, mode_t mode, dev_t dev)
   1072 {
   1073 	char buf[MAXNAMELEN];
   1074 	pathname_t newname;
   1075 	int rval;
   1076 
   1077 	rval = mknod(name->path, mode, dev);
   1078 	if (rval >= 0 || errno != ENAMETOOLONG)
   1079 		return rval;
   1080 	separate_pathname(name, buf, &newname);
   1081 	if (chdir(buf) == 0) {
   1082 		rval = mknod_path(&newname, mode, dev);
   1083 		chdir("..");
   1084 	}
   1085 	free_pathname(&newname);
   1086 	return rval;
   1087 }
   1088 
   1089 void namerandpad(int id, char *buf, int i)
   1090 {
   1091 	int bucket;
   1092 	static int buckets[] = { 2, 4, 8, 16, 32, 64, 128, MAXNAMELEN - 1 };
   1093 	int padlen;
   1094 	int padmod;
   1095 
   1096 	if (namerand == 0)
   1097 		return;
   1098 	bucket = (id ^ namerand) % (sizeof(buckets) / sizeof(buckets[0]));
   1099 	padmod = buckets[bucket] + 1 - i;
   1100 	if (padmod <= 0)
   1101 		return;
   1102 	padlen = (id ^ namerand) % padmod;
   1103 	if (padlen) {
   1104 		memset(&buf[i], 'X', padlen);
   1105 		buf[i + padlen] = '\0';
   1106 	}
   1107 }
   1108 
   1109 int open_path(pathname_t * name, int oflag)
   1110 {
   1111 	char buf[MAXNAMELEN];
   1112 	pathname_t newname;
   1113 	int rval;
   1114 
   1115 	rval = open(name->path, oflag);
   1116 	if (rval >= 0 || errno != ENAMETOOLONG)
   1117 		return rval;
   1118 	separate_pathname(name, buf, &newname);
   1119 	if (chdir(buf) == 0) {
   1120 		rval = open_path(&newname, oflag);
   1121 		chdir("..");
   1122 	}
   1123 	free_pathname(&newname);
   1124 	return rval;
   1125 }
   1126 
   1127 DIR *opendir_path(pathname_t * name)
   1128 {
   1129 	char buf[MAXNAMELEN];
   1130 	pathname_t newname;
   1131 	DIR *rval;
   1132 
   1133 	rval = opendir(name->path);
   1134 	if (rval || errno != ENAMETOOLONG)
   1135 		return rval;
   1136 	separate_pathname(name, buf, &newname);
   1137 	if (chdir(buf) == 0) {
   1138 		rval = opendir_path(&newname);
   1139 		chdir("..");
   1140 	}
   1141 	free_pathname(&newname);
   1142 	return rval;
   1143 }
   1144 
   1145 void process_freq(char *arg)
   1146 {
   1147 	opdesc_t *p;
   1148 	char *s;
   1149 
   1150 	s = strchr(arg, '=');
   1151 	if (s == NULL) {
   1152 		fprintf(stderr, "bad argument '%s'\n", arg);
   1153 		exit(1);
   1154 	}
   1155 	*s++ = '\0';
   1156 	for (p = ops; p < ops_end; p++) {
   1157 		if (strcmp(arg, p->name) == 0) {
   1158 			p->freq = atoi(s);
   1159 			return;
   1160 		}
   1161 	}
   1162 	fprintf(stderr, "can't find op type %s for -f\n", arg);
   1163 	exit(1);
   1164 }
   1165 
   1166 int readlink_path(pathname_t * name, char *lbuf, size_t lbufsiz)
   1167 {
   1168 	char buf[MAXNAMELEN];
   1169 	pathname_t newname;
   1170 	int rval;
   1171 
   1172 	rval = readlink(name->path, lbuf, lbufsiz);
   1173 	if (rval >= 0 || errno != ENAMETOOLONG)
   1174 		return rval;
   1175 	separate_pathname(name, buf, &newname);
   1176 	if (chdir(buf) == 0) {
   1177 		rval = readlink_path(&newname, lbuf, lbufsiz);
   1178 		chdir("..");
   1179 	}
   1180 	free_pathname(&newname);
   1181 	return rval;
   1182 }
   1183 
   1184 int rename_path(pathname_t * name1, pathname_t * name2)
   1185 {
   1186 	char buf1[MAXNAMELEN];
   1187 	char buf2[MAXNAMELEN];
   1188 	int down1;
   1189 	pathname_t newname1;
   1190 	pathname_t newname2;
   1191 	int rval;
   1192 
   1193 	rval = rename(name1->path, name2->path);
   1194 	if (rval >= 0 || errno != ENAMETOOLONG)
   1195 		return rval;
   1196 	separate_pathname(name1, buf1, &newname1);
   1197 	separate_pathname(name2, buf2, &newname2);
   1198 	if (strcmp(buf1, buf2) == 0) {
   1199 		if (chdir(buf1) == 0) {
   1200 			rval = rename_path(&newname1, &newname2);
   1201 			chdir("..");
   1202 		}
   1203 	} else {
   1204 		if (strcmp(buf1, "..") == 0)
   1205 			down1 = 0;
   1206 		else if (strcmp(buf2, "..") == 0)
   1207 			down1 = 1;
   1208 		else if (strlen(buf1) == 0)
   1209 			down1 = 0;
   1210 		else if (strlen(buf2) == 0)
   1211 			down1 = 1;
   1212 		else
   1213 			down1 = MAX(newname1.len, 3 + name2->len) <=
   1214 			    MAX(3 + name1->len, newname2.len);
   1215 		if (down1) {
   1216 			free_pathname(&newname2);
   1217 			append_pathname(&newname2, "../");
   1218 			append_pathname(&newname2, name2->path);
   1219 			if (chdir(buf1) == 0) {
   1220 				rval = rename_path(&newname1, &newname2);
   1221 				chdir("..");
   1222 			}
   1223 		} else {
   1224 			free_pathname(&newname1);
   1225 			append_pathname(&newname1, "../");
   1226 			append_pathname(&newname1, name1->path);
   1227 			if (chdir(buf2) == 0) {
   1228 				rval = rename_path(&newname1, &newname2);
   1229 				chdir("..");
   1230 			}
   1231 		}
   1232 	}
   1233 	free_pathname(&newname1);
   1234 	free_pathname(&newname2);
   1235 	return rval;
   1236 }
   1237 
   1238 int rmdir_path(pathname_t * name)
   1239 {
   1240 	char buf[MAXNAMELEN];
   1241 	pathname_t newname;
   1242 	int rval;
   1243 
   1244 	rval = rmdir(name->path);
   1245 	if (rval >= 0 || errno != ENAMETOOLONG)
   1246 		return rval;
   1247 	separate_pathname(name, buf, &newname);
   1248 	if (chdir(buf) == 0) {
   1249 		rval = rmdir_path(&newname);
   1250 		chdir("..");
   1251 	}
   1252 	free_pathname(&newname);
   1253 	return rval;
   1254 }
   1255 
   1256 void separate_pathname(pathname_t * name, char *buf, pathname_t * newname)
   1257 {
   1258 	char *slash;
   1259 
   1260 	init_pathname(newname);
   1261 	slash = strchr(name->path, '/');
   1262 	if (slash == NULL) {
   1263 		buf[0] = '\0';
   1264 		return;
   1265 	}
   1266 	*slash = '\0';
   1267 	strcpy(buf, name->path);
   1268 	*slash = '/';
   1269 	append_pathname(newname, slash + 1);
   1270 }
   1271 
   1272 #define WIDTH 80
   1273 
   1274 void show_ops(int flag, char *lead_str)
   1275 {
   1276 	opdesc_t *p;
   1277 
   1278 	if (flag < 0) {
   1279 		/* print in list form */
   1280 		int x = WIDTH;
   1281 
   1282 		for (p = ops; p < ops_end; p++) {
   1283 			if (lead_str != NULL
   1284 			    && x + strlen(p->name) >= WIDTH - 5)
   1285 				x = printf("%s%s", (p == ops) ? "" : "\n",
   1286 					   lead_str);
   1287 			x += printf("%s ", p->name);
   1288 		}
   1289 		printf("\n");
   1290 	} else {
   1291 		int f;
   1292 		for (f = 0, p = ops; p < ops_end; p++)
   1293 			f += p->freq;
   1294 
   1295 		if (f == 0)
   1296 			flag = 1;
   1297 
   1298 		for (p = ops; p < ops_end; p++) {
   1299 			if (flag != 0 || p->freq > 0) {
   1300 				if (lead_str != NULL)
   1301 					printf("%s", lead_str);
   1302 				printf("%20s %d/%d %s\n",
   1303 				       p->name, p->freq, f,
   1304 				       (p->iswrite == 0) ? " " : "write op");
   1305 			}
   1306 		}
   1307 	}
   1308 }
   1309 
   1310 int stat64_path(pathname_t * name, struct stat64 *sbuf)
   1311 {
   1312 	char buf[MAXNAMELEN];
   1313 	pathname_t newname;
   1314 	int rval;
   1315 
   1316 	rval = stat64(name->path, sbuf);
   1317 	if (rval >= 0 || errno != ENAMETOOLONG)
   1318 		return rval;
   1319 	separate_pathname(name, buf, &newname);
   1320 	if (chdir(buf) == 0) {
   1321 		rval = stat64_path(&newname, sbuf);
   1322 		chdir("..");
   1323 	}
   1324 	free_pathname(&newname);
   1325 	return rval;
   1326 }
   1327 
   1328 int symlink_path(const char *name1, pathname_t * name)
   1329 {
   1330 	char buf[MAXNAMELEN];
   1331 	pathname_t newname;
   1332 	int rval;
   1333 
   1334 	if (!strcmp(name1, name->path)) {
   1335 		printf("yikes! %s %s\n", name1, name->path);
   1336 		return 0;
   1337 	}
   1338 
   1339 	rval = symlink(name1, name->path);
   1340 	if (rval >= 0 || errno != ENAMETOOLONG)
   1341 		return rval;
   1342 	separate_pathname(name, buf, &newname);
   1343 	if (chdir(buf) == 0) {
   1344 		rval = symlink_path(name1, &newname);
   1345 		chdir("..");
   1346 	}
   1347 	free_pathname(&newname);
   1348 	return rval;
   1349 }
   1350 
   1351 int truncate64_path(pathname_t * name, off64_t length)
   1352 {
   1353 	char buf[MAXNAMELEN];
   1354 	pathname_t newname;
   1355 	int rval;
   1356 
   1357 	rval = truncate64(name->path, length);
   1358 	if (rval >= 0 || errno != ENAMETOOLONG)
   1359 		return rval;
   1360 	separate_pathname(name, buf, &newname);
   1361 	if (chdir(buf) == 0) {
   1362 		rval = truncate64_path(&newname, length);
   1363 		chdir("..");
   1364 	}
   1365 	free_pathname(&newname);
   1366 	return rval;
   1367 }
   1368 
   1369 int unlink_path(pathname_t * name)
   1370 {
   1371 	char buf[MAXNAMELEN];
   1372 	pathname_t newname;
   1373 	int rval;
   1374 
   1375 	rval = unlink(name->path);
   1376 	if (rval >= 0 || errno != ENAMETOOLONG)
   1377 		return rval;
   1378 	separate_pathname(name, buf, &newname);
   1379 	if (chdir(buf) == 0) {
   1380 		rval = unlink_path(&newname);
   1381 		chdir("..");
   1382 	}
   1383 	free_pathname(&newname);
   1384 	return rval;
   1385 }
   1386 
   1387 void usage(void)
   1388 {
   1389 	printf("Usage: %s -H   or\n", myprog);
   1390 	printf
   1391 	    ("       %s [-c][-d dir][-e errtg][-f op_name=freq][-l loops][-n nops]\n",
   1392 	     myprog);
   1393 	printf("          [-p nproc][-r len][-s seed][-v][-w][-z][-S]\n");
   1394 	printf("where\n");
   1395 	printf
   1396 	    ("   -c               specifies not to remove files(cleanup) after execution\n");
   1397 	printf
   1398 	    ("   -d dir           specifies the base directory for operations\n");
   1399 	printf("   -e errtg         specifies error injection stuff\n");
   1400 	printf
   1401 	    ("   -f op_name=freq  changes the frequency of option name to freq\n");
   1402 	printf("                    the valid operation names are:\n");
   1403 	show_ops(-1, "                        ");
   1404 	printf
   1405 	    ("   -l loops         specifies the no. of times the testrun should loop.\n");
   1406 	printf("                     *use 0 for infinite (default 1)\n");
   1407 	printf
   1408 	    ("   -n nops          specifies the no. of operations per process (default 1)\n");
   1409 	printf
   1410 	    ("   -p nproc         specifies the no. of processes (default 1)\n");
   1411 	printf("   -r               specifies random name padding\n");
   1412 	printf
   1413 	    ("   -s seed          specifies the seed for the random generator (default random)\n");
   1414 	printf("   -v               specifies verbose mode\n");
   1415 	printf
   1416 	    ("   -w               zeros frequencies of non-write operations\n");
   1417 	printf("   -z               zeros frequencies of all operations\n");
   1418 	printf
   1419 	    ("   -S               prints the table of operations (omitting zero frequency)\n");
   1420 	printf("   -H               prints usage and exits\n");
   1421 	printf
   1422 	    ("   -X               don't do anything XFS specific (default with -DNO_XFS)\n");
   1423 }
   1424 
   1425 void write_freq(void)
   1426 {
   1427 	opdesc_t *p;
   1428 
   1429 	for (p = ops; p < ops_end; p++) {
   1430 		if (!p->iswrite)
   1431 			p->freq = 0;
   1432 	}
   1433 }
   1434 
   1435 void zero_freq(void)
   1436 {
   1437 	opdesc_t *p;
   1438 
   1439 	for (p = ops; p < ops_end; p++)
   1440 		p->freq = 0;
   1441 }
   1442 
   1443 #ifndef NO_XFS
   1444 
   1445 void allocsp_f(int opno, long r)
   1446 {
   1447 	int e;
   1448 	pathname_t f;
   1449 	int fd;
   1450 	struct xfs_flock64 fl;
   1451 	__s64 lr;
   1452 	__s64 off;
   1453 	struct stat64 stb;
   1454 	int v;
   1455 
   1456 	init_pathname(&f);
   1457 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   1458 		if (v)
   1459 			printf("%d/%d: allocsp - no filename\n", procid, opno);
   1460 		free_pathname(&f);
   1461 		return;
   1462 	}
   1463 	fd = open_path(&f, O_RDWR);
   1464 	e = fd < 0 ? errno : 0;
   1465 	check_cwd();
   1466 	if (fd < 0) {
   1467 		if (v)
   1468 			printf("%d/%d: allocsp - open %s failed %d\n",
   1469 			       procid, opno, f.path, e);
   1470 		free_pathname(&f);
   1471 		return;
   1472 	}
   1473 	if (fstat64(fd, &stb) < 0) {
   1474 		if (v)
   1475 			printf("%d/%d: allocsp - fstat64 %s failed %d\n",
   1476 			       procid, opno, f.path, errno);
   1477 		free_pathname(&f);
   1478 		close(fd);
   1479 		return;
   1480 	}
   1481 	lr = ((__s64) random() << 32) + random();
   1482 	off = lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE);
   1483 	off %= maxfsize;
   1484 	memset(&fl, 0, sizeof(fl));
   1485 	fl.l_whence = SEEK_SET;
   1486 	fl.l_start = off;
   1487 	fl.l_len = 0;
   1488 	e = ioctl(fd, XFS_IOC_ALLOCSP64, &fl) < 0 ? errno : 0;
   1489 	if (v)
   1490 		printf("%d/%d: ioctl(XFS_IOC_ALLOCSP64) %s %lld 0 %d\n",
   1491 		       procid, opno, f.path, (long long)off, e);
   1492 	free_pathname(&f);
   1493 	close(fd);
   1494 }
   1495 
   1496 void attr_remove_f(int opno, long r)
   1497 {
   1498 	attrlist_ent_t *aep;
   1499 	attrlist_t *alist;
   1500 	char *aname;
   1501 	char buf[4096];
   1502 	attrlist_cursor_t cursor;
   1503 	int e;
   1504 	int ent;
   1505 	pathname_t f;
   1506 	int total;
   1507 	int v;
   1508 	int which;
   1509 
   1510 	init_pathname(&f);
   1511 	if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
   1512 		append_pathname(&f, ".");
   1513 	total = 0;
   1514 	memset(&cursor, 0x00, sizeof(cursor));
   1515 	do {
   1516 		e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW,
   1517 				   &cursor);
   1518 		check_cwd();
   1519 		if (e)
   1520 			break;
   1521 		alist = (attrlist_t *) buf;
   1522 		total += alist->al_count;
   1523 	} while (alist->al_more);
   1524 	if (total == 0) {
   1525 		if (v)
   1526 			printf("%d/%d: attr_remove - no attrs for %s\n",
   1527 			       procid, opno, f.path);
   1528 		free_pathname(&f);
   1529 		return;
   1530 	}
   1531 	which = (int)(random() % total);
   1532 	memset(&cursor, 0x00, sizeof(cursor));
   1533 	ent = 0;
   1534 	aname = NULL;
   1535 	do {
   1536 		e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW,
   1537 				   &cursor);
   1538 		check_cwd();
   1539 		if (e)
   1540 			break;
   1541 		alist = (attrlist_t *) buf;
   1542 		if (which < ent + alist->al_count) {
   1543 			aep = (attrlist_ent_t *)
   1544 			    & buf[alist->al_offset[which - ent]];
   1545 			aname = aep->a_name;
   1546 			break;
   1547 		}
   1548 		ent += alist->al_count;
   1549 	} while (alist->al_more);
   1550 	if (aname == NULL) {
   1551 		if (v)
   1552 			printf("%d/%d: attr_remove - name %d not found at %s\n",
   1553 			       procid, opno, which, f.path);
   1554 		free_pathname(&f);
   1555 		return;
   1556 	}
   1557 	e = attr_remove_path(&f, aname, ATTR_DONTFOLLOW) < 0 ? errno : 0;
   1558 	check_cwd();
   1559 	if (v)
   1560 		printf("%d/%d: attr_remove %s %s %d\n",
   1561 		       procid, opno, f.path, aname, e);
   1562 	free_pathname(&f);
   1563 }
   1564 
   1565 void attr_set_f(int opno, long r)
   1566 {
   1567 	char aname[10];
   1568 	char *aval;
   1569 	int e;
   1570 	pathname_t f;
   1571 	int len;
   1572 	static int lengths[] = { 10, 100, 1000, 10000 };
   1573 	int li;
   1574 	int v;
   1575 
   1576 	init_pathname(&f);
   1577 	if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
   1578 		append_pathname(&f, ".");
   1579 	sprintf(aname, "a%x", nameseq++);
   1580 	li = (int)(random() % (sizeof(lengths) / sizeof(lengths[0])));
   1581 	len = (int)(random() % lengths[li]);
   1582 	if (len == 0)
   1583 		len = 1;
   1584 	aval = malloc(len);
   1585 	memset(aval, nameseq & 0xff, len);
   1586 	e = attr_set_path(&f, aname, aval, len, ATTR_DONTFOLLOW) < 0 ?
   1587 	    errno : 0;
   1588 	check_cwd();
   1589 	free(aval);
   1590 	if (v)
   1591 		printf("%d/%d: attr_set %s %s %d\n", procid, opno, f.path,
   1592 		       aname, e);
   1593 	free_pathname(&f);
   1594 }
   1595 
   1596 void bulkstat_f(int opno, long r)
   1597 {
   1598 	__s32 count;
   1599 	int fd;
   1600 	__u64 last;
   1601 	__s32 nent;
   1602 	xfs_bstat_t *t;
   1603 	__int64_t total;
   1604 	xfs_fsop_bulkreq_t bsr;
   1605 
   1606 	last = 0;
   1607 	nent = (r % 999) + 2;
   1608 	t = malloc(nent * sizeof(*t));
   1609 	fd = open(".", O_RDONLY);
   1610 	total = 0;
   1611 
   1612 	memset(&bsr, 0, sizeof(bsr));
   1613 	bsr.lastip = &last;
   1614 	bsr.icount = nent;
   1615 	bsr.ubuffer = t;
   1616 	bsr.ocount = &count;
   1617 
   1618 	while (ioctl(fd, XFS_IOC_FSBULKSTAT, &bsr) == 0 && count > 0)
   1619 		total += count;
   1620 	free(t);
   1621 	if (verbose)
   1622 		printf("%d/%d: bulkstat nent %d total %lld\n",
   1623 		       procid, opno, (int)nent, (long long)total);
   1624 	close(fd);
   1625 }
   1626 
   1627 void bulkstat1_f(int opno, long r)
   1628 {
   1629 	int e;
   1630 	pathname_t f;
   1631 	int fd;
   1632 	int good;
   1633 	__u64 ino;
   1634 	struct stat64 s;
   1635 	xfs_bstat_t t;
   1636 	int v;
   1637 	xfs_fsop_bulkreq_t bsr;
   1638 
   1639 	good = random() & 1;
   1640 	if (good) {
   1641 		/* use an inode we know exists */
   1642 		init_pathname(&f);
   1643 		if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
   1644 			append_pathname(&f, ".");
   1645 		ino = stat64_path(&f, &s) < 0 ? (ino64_t) r : s.st_ino;
   1646 		check_cwd();
   1647 		free_pathname(&f);
   1648 	} else {
   1649 		/*
   1650 		 * pick a random inode
   1651 		 *
   1652 		 * note this can generate kernel warning messages
   1653 		 * since bulkstat_one will read the disk block that
   1654 		 * would contain a given inode even if that disk
   1655 		 * block doesn't contain inodes.
   1656 		 *
   1657 		 * this is detected later, but not until after the
   1658 		 * warning is displayed.
   1659 		 *
   1660 		 * "XFS: device 0x825- bad inode magic/vsn daddr 0x0 #0"
   1661 		 *
   1662 		 */
   1663 		ino = (ino64_t) r;
   1664 		v = verbose;
   1665 	}
   1666 	fd = open(".", O_RDONLY);
   1667 
   1668 	memset(&bsr, 0, sizeof(bsr));
   1669 	bsr.lastip = &ino;
   1670 	bsr.icount = 1;
   1671 	bsr.ubuffer = &t;
   1672 	bsr.ocount = NULL;
   1673 
   1674 	e = ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bsr) < 0 ? errno : 0;
   1675 	if (v)
   1676 		printf("%d/%d: bulkstat1 %s ino %lld %d\n",
   1677 		       procid, opno, good ? "real" : "random",
   1678 		       (long long)ino, e);
   1679 	close(fd);
   1680 }
   1681 
   1682 #endif
   1683 
   1684 void chown_f(int opno, long r)
   1685 {
   1686 	int e;
   1687 	pathname_t f;
   1688 	int nbits;
   1689 	uid_t u;
   1690 	int v;
   1691 
   1692 	init_pathname(&f);
   1693 	if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
   1694 		append_pathname(&f, ".");
   1695 	u = (uid_t) random();
   1696 	nbits = (int)(random() % 32);
   1697 	u &= (1 << nbits) - 1;
   1698 	e = lchown_path(&f, u, -1) < 0 ? errno : 0;
   1699 	check_cwd();
   1700 	if (v)
   1701 		printf("%d/%d: chown %s %d %d\n", procid, opno, f.path, u, e);
   1702 	free_pathname(&f);
   1703 }
   1704 
   1705 void creat_f(int opno, long r)
   1706 {
   1707 	int e;
   1708 	int e1;
   1709 	int extsize;
   1710 	pathname_t f;
   1711 	int fd;
   1712 	fent_t *fep;
   1713 	int id;
   1714 	int parid;
   1715 	int type;
   1716 	int v;
   1717 	int v1;
   1718 	int esz = 0;
   1719 
   1720 	if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
   1721 		parid = -1;
   1722 	else
   1723 		parid = fep->id;
   1724 	init_pathname(&f);
   1725 	type = rtpct ? ((random() % 100) > rtpct ? FT_REG : FT_RTF) : FT_REG;
   1726 	if (type == FT_RTF)
   1727 		extsize = (random() % 10) + 1;
   1728 	else
   1729 		extsize = 0;
   1730 	e = generate_fname(fep, type, &f, &id, &v);
   1731 	v |= v1;
   1732 	if (!e) {
   1733 		if (v) {
   1734 			fent_to_name(&f, &flist[FT_DIR], fep);
   1735 			printf("%d/%d: creat - no filename from %s\n",
   1736 			       procid, opno, f.path);
   1737 		}
   1738 		free_pathname(&f);
   1739 		return;
   1740 	}
   1741 	fd = creat_path(&f, 0666);
   1742 	e = fd < 0 ? errno : 0;
   1743 	e1 = 0;
   1744 	check_cwd();
   1745 	esz = 0;
   1746 	if (fd >= 0) {
   1747 #ifndef NO_XFS
   1748 		struct fsxattr a;
   1749 		memset(&a, 0, sizeof(a));
   1750 		if (extsize && ioctl(fd, XFS_IOC_FSGETXATTR, &a) >= 0) {
   1751 			a.fsx_xflags |= XFS_XFLAG_REALTIME;
   1752 			a.fsx_extsize =
   1753 			    geom.rtextsize * geom.blocksize * extsize;
   1754 			if (ioctl(fd, XFS_IOC_FSSETXATTR, &a) < 0)
   1755 				e1 = errno;
   1756 			esz = a.fsx_extsize;
   1757 
   1758 		}
   1759 #endif
   1760 		add_to_flist(type, id, parid);
   1761 		close(fd);
   1762 	}
   1763 	if (v)
   1764 		printf("%d/%d: creat %s x:%d %d %d\n", procid, opno, f.path,
   1765 		       esz, e, e1);
   1766 	free_pathname(&f);
   1767 }
   1768 
   1769 int setdirect(int fd)
   1770 {
   1771 	static int no_direct;
   1772 	int flags;
   1773 
   1774 	if (no_direct)
   1775 		return 0;
   1776 
   1777 	flags = fcntl(fd, F_GETFL, 0);
   1778 	if (flags < 0)
   1779 		return 0;
   1780 
   1781 	if (fcntl(fd, F_SETFL, flags | O_DIRECT) < 0) {
   1782 		if (no_xfs) {
   1783 			no_direct = 1;
   1784 			return 0;
   1785 		}
   1786 		printf("cannot set O_DIRECT: %s\n", strerror(errno));
   1787 		return 0;
   1788 	}
   1789 
   1790 	return 1;
   1791 }
   1792 
   1793 void dread_f(int opno, long r)
   1794 {
   1795 	__int64_t align;
   1796 	char *buf = NULL;
   1797 	struct dioattr diob;
   1798 	int e;
   1799 	pathname_t f;
   1800 	int fd;
   1801 	size_t len;
   1802 	__int64_t lr;
   1803 	off64_t off;
   1804 	struct stat64 stb;
   1805 	int v;
   1806 
   1807 	init_pathname(&f);
   1808 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   1809 		if (v)
   1810 			printf("%d/%d: dread - no filename\n", procid, opno);
   1811 		free_pathname(&f);
   1812 		return;
   1813 	}
   1814 	fd = open_path(&f, O_RDONLY);
   1815 
   1816 	e = fd < 0 ? errno : 0;
   1817 	check_cwd();
   1818 	if (fd < 0) {
   1819 		if (v)
   1820 			printf("%d/%d: dread - open %s failed %d\n",
   1821 			       procid, opno, f.path, e);
   1822 		free_pathname(&f);
   1823 		return;
   1824 	}
   1825 
   1826 	if (!setdirect(fd)) {
   1827 		close(fd);
   1828 		free_pathname(&f);
   1829 		return;
   1830 	}
   1831 
   1832 	if (fstat64(fd, &stb) < 0) {
   1833 		if (v)
   1834 			printf("%d/%d: dread - fstat64 %s failed %d\n",
   1835 			       procid, opno, f.path, errno);
   1836 		free_pathname(&f);
   1837 		close(fd);
   1838 		return;
   1839 	}
   1840 	if (stb.st_size == 0) {
   1841 		if (v)
   1842 			printf("%d/%d: dread - %s zero size\n", procid, opno,
   1843 			       f.path);
   1844 		free_pathname(&f);
   1845 		close(fd);
   1846 		return;
   1847 	}
   1848 
   1849 	memset(&diob, 0, sizeof(diob));
   1850 	if (no_xfs) {
   1851 		diob.d_miniosz = stb.st_blksize;
   1852 		diob.d_maxiosz = stb.st_blksize * 256;	/* good number ? */
   1853 		diob.d_mem = stb.st_blksize;
   1854 	}
   1855 #ifndef NO_XFS
   1856 	else if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
   1857 		if (v)
   1858 			printf
   1859 			    ("%d/%d: dread - ioctl(fd, XFS_IOC_DIOINFO) %s failed %d\n",
   1860 			     procid, opno, f.path, errno);
   1861 		free_pathname(&f);
   1862 		close(fd);
   1863 		return;
   1864 	}
   1865 #endif
   1866 	align = (__int64_t) diob.d_miniosz;
   1867 	lr = ((__int64_t) random() << 32) + random();
   1868 	off = (off64_t) (lr % stb.st_size);
   1869 	off -= (off % align);
   1870 	lseek64(fd, off, SEEK_SET);
   1871 	len = (random() % (getpagesize() * 32)) + 1;
   1872 	len -= (len % align);
   1873 	if (len <= 0)
   1874 		len = align;
   1875 	else if (len > diob.d_maxiosz)
   1876 		len = diob.d_maxiosz;
   1877 	if ((e = posix_memalign((void **)&buf, diob.d_mem, len)) != 0) {
   1878 		fprintf(stderr, "posix_memalign: %s\n", strerror(e));
   1879 		exit(1);
   1880 	}
   1881 	if (buf == NULL) {
   1882 		fprintf(stderr, "posix_memalign: buf is NULL\n");
   1883 		exit(1);
   1884 	}
   1885 	e = read(fd, buf, len) < 0 ? errno : 0;
   1886 	free(buf);
   1887 	if (v)
   1888 		printf("%d/%d: dread %s [%lld,%ld] %d\n",
   1889 		       procid, opno, f.path, (long long int)off, (long)len, e);
   1890 	free_pathname(&f);
   1891 	close(fd);
   1892 }
   1893 
   1894 void dwrite_f(int opno, long r)
   1895 {
   1896 	__int64_t align;
   1897 	char *buf = NULL;
   1898 	struct dioattr diob;
   1899 	int e;
   1900 	pathname_t f;
   1901 	int fd;
   1902 	size_t len;
   1903 	__int64_t lr;
   1904 	off64_t off;
   1905 	struct stat64 stb;
   1906 	int v;
   1907 
   1908 	init_pathname(&f);
   1909 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   1910 		if (v)
   1911 			printf("%d/%d: dwrite - no filename\n", procid, opno);
   1912 		free_pathname(&f);
   1913 		return;
   1914 	}
   1915 	fd = open_path(&f, O_WRONLY);
   1916 	e = fd < 0 ? errno : 0;
   1917 	check_cwd();
   1918 	if (fd < 0) {
   1919 		if (v)
   1920 			printf("%d/%d: dwrite - open %s failed %d\n",
   1921 			       procid, opno, f.path, e);
   1922 		free_pathname(&f);
   1923 		return;
   1924 	}
   1925 
   1926 	if (!setdirect(fd)) {
   1927 		close(fd);
   1928 		free_pathname(&f);
   1929 		return;
   1930 	}
   1931 	if (fstat64(fd, &stb) < 0) {
   1932 		if (v)
   1933 			printf("%d/%d: dwrite - fstat64 %s failed %d\n",
   1934 			       procid, opno, f.path, errno);
   1935 		free_pathname(&f);
   1936 		close(fd);
   1937 		return;
   1938 	}
   1939 	memset(&diob, 0, sizeof(diob));
   1940 	if (no_xfs) {
   1941 		diob.d_miniosz = stb.st_blksize;
   1942 		diob.d_maxiosz = stb.st_blksize * 256;	/* good number ? */
   1943 		diob.d_mem = stb.st_blksize;
   1944 	}
   1945 #ifndef NO_XFS
   1946 	else if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
   1947 		if (v)
   1948 			printf
   1949 			    ("%d/%d: dwrite - ioctl(fd, XFS_IOC_DIOINFO) %s failed %d\n",
   1950 			     procid, opno, f.path, errno);
   1951 		free_pathname(&f);
   1952 		close(fd);
   1953 		return;
   1954 	}
   1955 #endif
   1956 	align = (__int64_t) diob.d_miniosz;
   1957 	lr = ((__int64_t) random() << 32) + random();
   1958 	off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
   1959 	off -= (off % align);
   1960 	lseek64(fd, off, SEEK_SET);
   1961 	len = (random() % (getpagesize() * 32)) + 1;
   1962 	len -= (len % align);
   1963 	if (len <= 0)
   1964 		len = align;
   1965 	else if (len > diob.d_maxiosz)
   1966 		len = diob.d_maxiosz;
   1967 	if ((e = posix_memalign((void **)&buf, diob.d_mem, len)) != 0) {
   1968 		fprintf(stderr, "posix_memalign: %s\n", strerror(e));
   1969 		exit(1);
   1970 	}
   1971 	if (buf == NULL) {
   1972 		fprintf(stderr, "posix_memalign: buf is NULL\n");
   1973 		exit(1);
   1974 	}
   1975 	off %= maxfsize;
   1976 	lseek64(fd, off, SEEK_SET);
   1977 	memset(buf, nameseq & 0xff, len);
   1978 	e = write(fd, buf, len) < 0 ? errno : 0;
   1979 	free(buf);
   1980 	if (v)
   1981 		printf("%d/%d: dwrite %s [%lld,%ld] %d\n",
   1982 		       procid, opno, f.path, (long long)off, (long int)len, e);
   1983 	free_pathname(&f);
   1984 	close(fd);
   1985 }
   1986 
   1987 void fdatasync_f(int opno, long r)
   1988 {
   1989 	int e;
   1990 	pathname_t f;
   1991 	int fd;
   1992 	int v;
   1993 
   1994 	init_pathname(&f);
   1995 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   1996 		if (v)
   1997 			printf("%d/%d: fdatasync - no filename\n",
   1998 			       procid, opno);
   1999 		free_pathname(&f);
   2000 		return;
   2001 	}
   2002 	fd = open_path(&f, O_WRONLY);
   2003 	e = fd < 0 ? errno : 0;
   2004 	check_cwd();
   2005 	if (fd < 0) {
   2006 		if (v)
   2007 			printf("%d/%d: fdatasync - open %s failed %d\n",
   2008 			       procid, opno, f.path, e);
   2009 		free_pathname(&f);
   2010 		return;
   2011 	}
   2012 	e = fdatasync(fd) < 0 ? errno : 0;
   2013 	if (v)
   2014 		printf("%d/%d: fdatasync %s %d\n", procid, opno, f.path, e);
   2015 	free_pathname(&f);
   2016 	close(fd);
   2017 }
   2018 
   2019 #ifndef NO_XFS
   2020 void freesp_f(int opno, long r)
   2021 {
   2022 	int e;
   2023 	pathname_t f;
   2024 	int fd;
   2025 	struct xfs_flock64 fl;
   2026 	__s64 lr;
   2027 	__s64 off;
   2028 	struct stat64 stb;
   2029 	int v;
   2030 
   2031 	init_pathname(&f);
   2032 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   2033 		if (v)
   2034 			printf("%d/%d: freesp - no filename\n", procid, opno);
   2035 		free_pathname(&f);
   2036 		return;
   2037 	}
   2038 	fd = open_path(&f, O_RDWR);
   2039 	e = fd < 0 ? errno : 0;
   2040 	check_cwd();
   2041 	if (fd < 0) {
   2042 		if (v)
   2043 			printf("%d/%d: freesp - open %s failed %d\n",
   2044 			       procid, opno, f.path, e);
   2045 		free_pathname(&f);
   2046 		return;
   2047 	}
   2048 	if (fstat64(fd, &stb) < 0) {
   2049 		if (v)
   2050 			printf("%d/%d: freesp - fstat64 %s failed %d\n",
   2051 			       procid, opno, f.path, errno);
   2052 		free_pathname(&f);
   2053 		close(fd);
   2054 		return;
   2055 	}
   2056 	lr = ((__s64) random() << 32) + random();
   2057 	off = lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE);
   2058 	off %= maxfsize;
   2059 	memset(&fl, 0, sizeof(fl));
   2060 	fl.l_whence = SEEK_SET;
   2061 	fl.l_start = off;
   2062 	fl.l_len = 0;
   2063 	e = ioctl(fd, XFS_IOC_FREESP64, &fl) < 0 ? errno : 0;
   2064 	if (v)
   2065 		printf("%d/%d: ioctl(XFS_IOC_FREESP64) %s %lld 0 %d\n",
   2066 		       procid, opno, f.path, (long long)off, e);
   2067 	free_pathname(&f);
   2068 	close(fd);
   2069 }
   2070 
   2071 #endif
   2072 
   2073 void fsync_f(int opno, long r)
   2074 {
   2075 	int e;
   2076 	pathname_t f;
   2077 	int fd;
   2078 	int v;
   2079 
   2080 	init_pathname(&f);
   2081 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   2082 		if (v)
   2083 			printf("%d/%d: fsync - no filename\n", procid, opno);
   2084 		free_pathname(&f);
   2085 		return;
   2086 	}
   2087 	fd = open_path(&f, O_WRONLY);
   2088 	e = fd < 0 ? errno : 0;
   2089 	check_cwd();
   2090 	if (fd < 0) {
   2091 		if (v)
   2092 			printf("%d/%d: fsync - open %s failed %d\n",
   2093 			       procid, opno, f.path, e);
   2094 		free_pathname(&f);
   2095 		return;
   2096 	}
   2097 	e = fsync(fd) < 0 ? errno : 0;
   2098 	if (v)
   2099 		printf("%d/%d: fsync %s %d\n", procid, opno, f.path, e);
   2100 	free_pathname(&f);
   2101 	close(fd);
   2102 }
   2103 
   2104 void getdents_f(int opno, long r)
   2105 {
   2106 	DIR *dir;
   2107 	pathname_t f;
   2108 	int v;
   2109 
   2110 	init_pathname(&f);
   2111 	if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
   2112 		append_pathname(&f, ".");
   2113 	dir = opendir_path(&f);
   2114 	check_cwd();
   2115 	if (dir == NULL) {
   2116 		if (v)
   2117 			printf("%d/%d: getdents - can't open %s\n",
   2118 			       procid, opno, f.path);
   2119 		free_pathname(&f);
   2120 		return;
   2121 	}
   2122 	while (readdir64(dir) != NULL)
   2123 		continue;
   2124 	if (v)
   2125 		printf("%d/%d: getdents %s 0\n", procid, opno, f.path);
   2126 	free_pathname(&f);
   2127 	closedir(dir);
   2128 }
   2129 
   2130 void link_f(int opno, long r)
   2131 {
   2132 	int e;
   2133 	pathname_t f;
   2134 	fent_t *fep;
   2135 	flist_t *flp;
   2136 	int id;
   2137 	pathname_t l;
   2138 	int parid;
   2139 	int v;
   2140 	int v1;
   2141 
   2142 	init_pathname(&f);
   2143 	if (!get_fname(FT_NOTDIR, r, &f, &flp, NULL, &v1)) {
   2144 		if (v1)
   2145 			printf("%d/%d: link - no file\n", procid, opno);
   2146 		free_pathname(&f);
   2147 		return;
   2148 	}
   2149 	if (!get_fname(FT_DIRm, random(), NULL, NULL, &fep, &v))
   2150 		parid = -1;
   2151 	else
   2152 		parid = fep->id;
   2153 	v |= v1;
   2154 	init_pathname(&l);
   2155 	e = generate_fname(fep, flp - flist, &l, &id, &v1);
   2156 	v |= v1;
   2157 	if (!e) {
   2158 		if (v) {
   2159 			fent_to_name(&l, &flist[FT_DIR], fep);
   2160 			printf("%d/%d: link - no filename from %s\n",
   2161 			       procid, opno, l.path);
   2162 		}
   2163 		free_pathname(&l);
   2164 		free_pathname(&f);
   2165 		return;
   2166 	}
   2167 	e = link_path(&f, &l) < 0 ? errno : 0;
   2168 	check_cwd();
   2169 	if (e == 0)
   2170 		add_to_flist(flp - flist, id, parid);
   2171 	if (v)
   2172 		printf("%d/%d: link %s %s %d\n", procid, opno, f.path, l.path,
   2173 		       e);
   2174 	free_pathname(&l);
   2175 	free_pathname(&f);
   2176 }
   2177 
   2178 void mkdir_f(int opno, long r)
   2179 {
   2180 	int e;
   2181 	pathname_t f;
   2182 	fent_t *fep;
   2183 	int id;
   2184 	int parid;
   2185 	int v;
   2186 	int v1;
   2187 
   2188 	if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
   2189 		parid = -1;
   2190 	else
   2191 		parid = fep->id;
   2192 	init_pathname(&f);
   2193 	e = generate_fname(fep, FT_DIR, &f, &id, &v1);
   2194 	v |= v1;
   2195 	if (!e) {
   2196 		if (v) {
   2197 			fent_to_name(&f, &flist[FT_DIR], fep);
   2198 			printf("%d/%d: mkdir - no filename from %s\n",
   2199 			       procid, opno, f.path);
   2200 		}
   2201 		free_pathname(&f);
   2202 		return;
   2203 	}
   2204 	e = mkdir_path(&f, 0777) < 0 ? errno : 0;
   2205 	check_cwd();
   2206 	if (e == 0)
   2207 		add_to_flist(FT_DIR, id, parid);
   2208 	if (v)
   2209 		printf("%d/%d: mkdir %s %d\n", procid, opno, f.path, e);
   2210 	free_pathname(&f);
   2211 }
   2212 
   2213 void mknod_f(int opno, long r)
   2214 {
   2215 	int e;
   2216 	pathname_t f;
   2217 	fent_t *fep;
   2218 	int id;
   2219 	int parid;
   2220 	int v;
   2221 	int v1;
   2222 
   2223 	if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
   2224 		parid = -1;
   2225 	else
   2226 		parid = fep->id;
   2227 	init_pathname(&f);
   2228 	e = generate_fname(fep, FT_DEV, &f, &id, &v1);
   2229 	v |= v1;
   2230 	if (!e) {
   2231 		if (v) {
   2232 			fent_to_name(&f, &flist[FT_DIR], fep);
   2233 			printf("%d/%d: mknod - no filename from %s\n",
   2234 			       procid, opno, f.path);
   2235 		}
   2236 		free_pathname(&f);
   2237 		return;
   2238 	}
   2239 	e = mknod_path(&f, S_IFCHR | 0444, 0) < 0 ? errno : 0;
   2240 	check_cwd();
   2241 	if (e == 0)
   2242 		add_to_flist(FT_DEV, id, parid);
   2243 	if (v)
   2244 		printf("%d/%d: mknod %s %d\n", procid, opno, f.path, e);
   2245 	free_pathname(&f);
   2246 }
   2247 
   2248 void read_f(int opno, long r)
   2249 {
   2250 	char *buf;
   2251 	int e;
   2252 	pathname_t f;
   2253 	int fd;
   2254 	size_t len;
   2255 	__int64_t lr;
   2256 	off64_t off;
   2257 	struct stat64 stb;
   2258 	int v;
   2259 
   2260 	init_pathname(&f);
   2261 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   2262 		if (v)
   2263 			printf("%d/%d: read - no filename\n", procid, opno);
   2264 		free_pathname(&f);
   2265 		return;
   2266 	}
   2267 	fd = open_path(&f, O_RDONLY);
   2268 	e = fd < 0 ? errno : 0;
   2269 	check_cwd();
   2270 	if (fd < 0) {
   2271 		if (v)
   2272 			printf("%d/%d: read - open %s failed %d\n",
   2273 			       procid, opno, f.path, e);
   2274 		free_pathname(&f);
   2275 		return;
   2276 	}
   2277 	if (fstat64(fd, &stb) < 0) {
   2278 		if (v)
   2279 			printf("%d/%d: read - fstat64 %s failed %d\n",
   2280 			       procid, opno, f.path, errno);
   2281 		free_pathname(&f);
   2282 		close(fd);
   2283 		return;
   2284 	}
   2285 	if (stb.st_size == 0) {
   2286 		if (v)
   2287 			printf("%d/%d: read - %s zero size\n", procid, opno,
   2288 			       f.path);
   2289 		free_pathname(&f);
   2290 		close(fd);
   2291 		return;
   2292 	}
   2293 	lr = ((__int64_t) random() << 32) + random();
   2294 	off = (off64_t) (lr % stb.st_size);
   2295 	lseek64(fd, off, SEEK_SET);
   2296 	len = (random() % (getpagesize() * 32)) + 1;
   2297 	buf = malloc(len);
   2298 	e = read(fd, buf, len) < 0 ? errno : 0;
   2299 	free(buf);
   2300 	if (v)
   2301 		printf("%d/%d: read %s [%lld,%ld] %d\n",
   2302 		       procid, opno, f.path, (long long)off, (long int)len, e);
   2303 	free_pathname(&f);
   2304 	close(fd);
   2305 }
   2306 
   2307 void readlink_f(int opno, long r)
   2308 {
   2309 	char buf[PATH_MAX];
   2310 	int e;
   2311 	pathname_t f;
   2312 	int v;
   2313 
   2314 	init_pathname(&f);
   2315 	if (!get_fname(FT_SYMm, r, &f, NULL, NULL, &v)) {
   2316 		if (v)
   2317 			printf("%d/%d: readlink - no filename\n", procid, opno);
   2318 		free_pathname(&f);
   2319 		return;
   2320 	}
   2321 	e = readlink_path(&f, buf, PATH_MAX) < 0 ? errno : 0;
   2322 	check_cwd();
   2323 	if (v)
   2324 		printf("%d/%d: readlink %s %d\n", procid, opno, f.path, e);
   2325 	free_pathname(&f);
   2326 }
   2327 
   2328 void rename_f(int opno, long r)
   2329 {
   2330 	fent_t *dfep;
   2331 	int e;
   2332 	pathname_t f;
   2333 	fent_t *fep;
   2334 	flist_t *flp;
   2335 	int id;
   2336 	pathname_t newf;
   2337 	int oldid;
   2338 	int parid;
   2339 	int v;
   2340 	int v1;
   2341 
   2342 	init_pathname(&f);
   2343 	if (!get_fname(FT_ANYm, r, &f, &flp, &fep, &v1)) {
   2344 		if (v1)
   2345 			printf("%d/%d: rename - no filename\n", procid, opno);
   2346 		free_pathname(&f);
   2347 		return;
   2348 	}
   2349 	if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
   2350 		parid = -1;
   2351 	else
   2352 		parid = dfep->id;
   2353 	v |= v1;
   2354 	init_pathname(&newf);
   2355 	e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
   2356 	v |= v1;
   2357 	if (!e) {
   2358 		if (v) {
   2359 			fent_to_name(&f, &flist[FT_DIR], dfep);
   2360 			printf("%d/%d: rename - no filename from %s\n",
   2361 			       procid, opno, f.path);
   2362 		}
   2363 		free_pathname(&newf);
   2364 		free_pathname(&f);
   2365 		return;
   2366 	}
   2367 	e = rename_path(&f, &newf) < 0 ? errno : 0;
   2368 	check_cwd();
   2369 	if (e == 0) {
   2370 		if (flp - flist == FT_DIR) {
   2371 			oldid = fep->id;
   2372 			fix_parent(oldid, id);
   2373 		}
   2374 		del_from_flist(flp - flist, fep - flp->fents);
   2375 		add_to_flist(flp - flist, id, parid);
   2376 	}
   2377 	if (v)
   2378 		printf("%d/%d: rename %s to %s %d\n", procid, opno, f.path,
   2379 		       newf.path, e);
   2380 	free_pathname(&newf);
   2381 	free_pathname(&f);
   2382 }
   2383 
   2384 #ifndef NO_XFS
   2385 void resvsp_f(int opno, long r)
   2386 {
   2387 	int e;
   2388 	pathname_t f;
   2389 	int fd;
   2390 	struct xfs_flock64 fl;
   2391 	__s64 lr;
   2392 	__s64 off;
   2393 	struct stat64 stb;
   2394 	int v;
   2395 
   2396 	init_pathname(&f);
   2397 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   2398 		if (v)
   2399 			printf("%d/%d: resvsp - no filename\n", procid, opno);
   2400 		free_pathname(&f);
   2401 		return;
   2402 	}
   2403 	fd = open_path(&f, O_RDWR);
   2404 	e = fd < 0 ? errno : 0;
   2405 	check_cwd();
   2406 	if (fd < 0) {
   2407 		if (v)
   2408 			printf("%d/%d: resvsp - open %s failed %d\n",
   2409 			       procid, opno, f.path, e);
   2410 		free_pathname(&f);
   2411 		return;
   2412 	}
   2413 	if (fstat64(fd, &stb) < 0) {
   2414 		if (v)
   2415 			printf("%d/%d: resvsp - fstat64 %s failed %d\n",
   2416 			       procid, opno, f.path, errno);
   2417 		free_pathname(&f);
   2418 		close(fd);
   2419 		return;
   2420 	}
   2421 	lr = ((__s64) random() << 32) + random();
   2422 	off = lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE);
   2423 	off %= maxfsize;
   2424 	memset(&fl, 0, sizeof(fl));
   2425 	fl.l_whence = SEEK_SET;
   2426 	fl.l_start = off;
   2427 	fl.l_len = (__s64) (random() % (1024 * 1024));
   2428 	e = ioctl(fd, XFS_IOC_RESVSP64, &fl) < 0 ? errno : 0;
   2429 	if (v)
   2430 		printf("%d/%d: ioctl(XFS_IOC_RESVSP64) %s %lld %lld %d\n",
   2431 		       procid, opno, f.path, (long long)off,
   2432 		       (long long)fl.l_len, e);
   2433 	free_pathname(&f);
   2434 	close(fd);
   2435 }
   2436 #endif
   2437 
   2438 void rmdir_f(int opno, long r)
   2439 {
   2440 	int e;
   2441 	pathname_t f;
   2442 	fent_t *fep;
   2443 	int v;
   2444 
   2445 	init_pathname(&f);
   2446 	if (!get_fname(FT_DIRm, r, &f, NULL, &fep, &v)) {
   2447 		if (v)
   2448 			printf("%d/%d: rmdir - no directory\n", procid, opno);
   2449 		free_pathname(&f);
   2450 		return;
   2451 	}
   2452 	e = rmdir_path(&f) < 0 ? errno : 0;
   2453 	check_cwd();
   2454 	if (e == 0)
   2455 		del_from_flist(FT_DIR, fep - flist[FT_DIR].fents);
   2456 	if (v)
   2457 		printf("%d/%d: rmdir %s %d\n", procid, opno, f.path, e);
   2458 	free_pathname(&f);
   2459 }
   2460 
   2461 void stat_f(int opno, long r)
   2462 {
   2463 	int e;
   2464 	pathname_t f;
   2465 	struct stat64 stb;
   2466 	int v;
   2467 
   2468 	init_pathname(&f);
   2469 	if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v)) {
   2470 		if (v)
   2471 			printf("%d/%d: stat - no entries\n", procid, opno);
   2472 		free_pathname(&f);
   2473 		return;
   2474 	}
   2475 	e = lstat64_path(&f, &stb) < 0 ? errno : 0;
   2476 	check_cwd();
   2477 	if (v)
   2478 		printf("%d/%d: stat %s %d\n", procid, opno, f.path, e);
   2479 	free_pathname(&f);
   2480 }
   2481 
   2482 void symlink_f(int opno, long r)
   2483 {
   2484 	int e;
   2485 	pathname_t f;
   2486 	fent_t *fep;
   2487 	int i;
   2488 	int id;
   2489 	int len;
   2490 	int parid;
   2491 	int v;
   2492 	int v1;
   2493 	char *val;
   2494 
   2495 	if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
   2496 		parid = -1;
   2497 	else
   2498 		parid = fep->id;
   2499 	init_pathname(&f);
   2500 	e = generate_fname(fep, FT_SYM, &f, &id, &v1);
   2501 	v |= v1;
   2502 	if (!e) {
   2503 		if (v) {
   2504 			fent_to_name(&f, &flist[FT_DIR], fep);
   2505 			printf("%d/%d: symlink - no filename from %s\n",
   2506 			       procid, opno, f.path);
   2507 		}
   2508 		free_pathname(&f);
   2509 		return;
   2510 	}
   2511 	len = (int)(random() % PATH_MAX);
   2512 	val = malloc(len + 1);
   2513 	if (len)
   2514 		memset(val, 'x', len);
   2515 	val[len] = '\0';
   2516 	for (i = 10; i < len - 1; i += 10)
   2517 		val[i] = '/';
   2518 	e = symlink_path(val, &f) < 0 ? errno : 0;
   2519 	check_cwd();
   2520 	if (e == 0)
   2521 		add_to_flist(FT_SYM, id, parid);
   2522 	free(val);
   2523 	if (v)
   2524 		printf("%d/%d: symlink %s %d\n", procid, opno, f.path, e);
   2525 	free_pathname(&f);
   2526 }
   2527 
   2528 /* ARGSUSED */
   2529 void sync_f(int opno, long r)
   2530 {
   2531 	sync();
   2532 	if (verbose)
   2533 		printf("%d/%d: sync\n", procid, opno);
   2534 }
   2535 
   2536 void truncate_f(int opno, long r)
   2537 {
   2538 	int e;
   2539 	pathname_t f;
   2540 	__int64_t lr;
   2541 	off64_t off;
   2542 	struct stat64 stb;
   2543 	int v;
   2544 
   2545 	init_pathname(&f);
   2546 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   2547 		if (v)
   2548 			printf("%d/%d: truncate - no filename\n", procid, opno);
   2549 		free_pathname(&f);
   2550 		return;
   2551 	}
   2552 	e = stat64_path(&f, &stb) < 0 ? errno : 0;
   2553 	check_cwd();
   2554 	if (e > 0) {
   2555 		if (v)
   2556 			printf("%d/%d: truncate - stat64 %s failed %d\n",
   2557 			       procid, opno, f.path, e);
   2558 		free_pathname(&f);
   2559 		return;
   2560 	}
   2561 	lr = ((__int64_t) random() << 32) + random();
   2562 	off = lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE);
   2563 	off %= maxfsize;
   2564 	e = truncate64_path(&f, off) < 0 ? errno : 0;
   2565 	check_cwd();
   2566 	if (v)
   2567 		printf("%d/%d: truncate %s %lld %d\n", procid, opno, f.path,
   2568 		       (long long)off, e);
   2569 	free_pathname(&f);
   2570 }
   2571 
   2572 void unlink_f(int opno, long r)
   2573 {
   2574 	int e;
   2575 	pathname_t f;
   2576 	fent_t *fep;
   2577 	flist_t *flp;
   2578 	int v;
   2579 
   2580 	init_pathname(&f);
   2581 	if (!get_fname(FT_NOTDIR, r, &f, &flp, &fep, &v)) {
   2582 		if (v)
   2583 			printf("%d/%d: unlink - no file\n", procid, opno);
   2584 		free_pathname(&f);
   2585 		return;
   2586 	}
   2587 	e = unlink_path(&f) < 0 ? errno : 0;
   2588 	check_cwd();
   2589 	if (e == 0)
   2590 		del_from_flist(flp - flist, fep - flp->fents);
   2591 	if (v)
   2592 		printf("%d/%d: unlink %s %d\n", procid, opno, f.path, e);
   2593 	free_pathname(&f);
   2594 }
   2595 
   2596 #ifndef NO_XFS
   2597 void unresvsp_f(int opno, long r)
   2598 {
   2599 	int e;
   2600 	pathname_t f;
   2601 	int fd;
   2602 	struct xfs_flock64 fl;
   2603 	__s64 lr;
   2604 	__s64 off;
   2605 	struct stat64 stb;
   2606 	int v;
   2607 
   2608 	init_pathname(&f);
   2609 	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
   2610 		if (v)
   2611 			printf("%d/%d: unresvsp - no filename\n", procid, opno);
   2612 		free_pathname(&f);
   2613 		return;
   2614 	}
   2615 	fd = open_path(&f, O_RDWR);
   2616 	e = fd < 0 ? errno : 0;
   2617 	check_cwd();
   2618 	if (fd < 0) {
   2619 		if (v)
   2620 			printf("%d/%d: unresvsp - open %s failed %d\n",
   2621 			       procid, opno, f.path, e);
   2622 		free_pathname(&f);
   2623 		return;
   2624 	}
   2625 	if (fstat64(fd, &stb) < 0) {
   2626 		if (v)
   2627 			printf("%d/%d: unresvsp - fstat64 %s failed %d\n",
   2628 			       procid, opno, f.path, errno);
   2629 		free_pathname(&f);
   2630 		close(fd);
   2631 		return;
   2632 	}
   2633 	lr = ((__s64) random() << 32) + random();
   2634 	off = lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE);
   2635 	off %= maxfsize;
   2636 	memset(&fl, 0, sizeof(fl));
   2637 	fl.l_whence = SEEK_SET;
   2638 	fl.l_start = off;
   2639 	fl.l_len = (__s64) (random() % (1 << 20));
   2640 	e = ioctl(fd, XFS_IOC_UNRESVSP64, &fl) < 0 ? errno : 0;
   2641 	if (v)
   2642 		printf("%d/%d: ioctl(XFS_IOC_UNRESVSP64) %s %lld %lld %d\n",
   2643 		       procid, opno, f.path, (long long)off,
   2644 		       (long long)fl.l_len, e);
   2645 	free_pathname(&f);
   2646 	close(fd);
   2647 }
   2648 #endif
   2649 
   2650 void write_f(int opno, long r)
   2651 {
   2652 	char *buf;
   2653 	int e;
   2654 	pathname_t f;
   2655 	int fd;
   2656 	size_t len;
   2657 	__int64_t lr;
   2658 	off64_t off;
   2659 	struct stat64 stb;
   2660 	int v;
   2661 
   2662 	init_pathname(&f);
   2663 	if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) {
   2664 		if (v)
   2665 			printf("%d/%d: write - no filename\n", procid, opno);
   2666 		free_pathname(&f);
   2667 		return;
   2668 	}
   2669 	fd = open_path(&f, O_WRONLY);
   2670 	e = fd < 0 ? errno : 0;
   2671 	check_cwd();
   2672 	if (fd < 0) {
   2673 		if (v)
   2674 			printf("%d/%d: write - open %s failed %d\n",
   2675 			       procid, opno, f.path, e);
   2676 		free_pathname(&f);
   2677 		return;
   2678 	}
   2679 	if (fstat64(fd, &stb) < 0) {
   2680 		if (v)
   2681 			printf("%d/%d: write - fstat64 %s failed %d\n",
   2682 			       procid, opno, f.path, errno);
   2683 		free_pathname(&f);
   2684 		close(fd);
   2685 		return;
   2686 	}
   2687 	lr = ((__int64_t) random() << 32) + random();
   2688 	off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
   2689 	off %= maxfsize;
   2690 	lseek64(fd, off, SEEK_SET);
   2691 	len = (random() % (getpagesize() * 32)) + 1;
   2692 	buf = malloc(len);
   2693 	memset(buf, nameseq & 0xff, len);
   2694 	e = write(fd, buf, len) < 0 ? errno : 0;
   2695 	free(buf);
   2696 	if (v)
   2697 		printf("%d/%d: write %s [%lld,%ld] %d\n",
   2698 		       procid, opno, f.path, (long long)off, (long int)len, e);
   2699 	free_pathname(&f);
   2700 	close(fd);
   2701 }
   2702