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
38struct 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
70typedef 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
110typedef void (*opfnc_t) (int, long);
111
112typedef 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
121typedef struct fent {
122	int id;
123	int parent;
124} fent_t;
125
126typedef struct flist {
127	int nfiles;
128	int nslots;
129	int tag;
130	fent_t *fents;
131} flist_t;
132
133typedef 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
159void allocsp_f(int, long);
160void attr_remove_f(int, long);
161void attr_set_f(int, long);
162void bulkstat_f(int, long);
163void bulkstat1_f(int, long);
164void chown_f(int, long);
165void creat_f(int, long);
166void dread_f(int, long);
167void dwrite_f(int, long);
168void fdatasync_f(int, long);
169void freesp_f(int, long);
170void fsync_f(int, long);
171void getdents_f(int, long);
172void link_f(int, long);
173void mkdir_f(int, long);
174void mknod_f(int, long);
175void read_f(int, long);
176void readlink_f(int, long);
177void rename_f(int, long);
178void resvsp_f(int, long);
179void rmdir_f(int, long);
180void stat_f(int, long);
181void symlink_f(int, long);
182void sync_f(int, long);
183void truncate_f(int, long);
184void unlink_f(int, long);
185void unresvsp_f(int, long);
186void write_f(int, long);
187
188opdesc_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
227flist_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
235int dcache[NDCACHE];
236int errrange;
237int errtag;
238opty_t *freq_table;
239int freq_table_size;
240#ifndef NO_XFS
241xfs_fsop_geom_t geom;
242#endif
243char *homedir;
244int *ilist;
245int ilistlen;
246off64_t maxfsize;
247char *myprog;
248int namerand;
249int nameseq;
250int nops;
251int nproc = 1;
252int operations = 1;
253int procid;
254int rtpct;
255unsigned long seed = 0;
256ino_t top_ino;
257int verbose = 0;
258#ifndef NO_XFS
259int no_xfs = 0;
260#else
261int no_xfs = 1;
262#endif
263sig_atomic_t should_stop = 0;
264
265void add_to_flist(int, int, int);
266void append_pathname(pathname_t *, char *);
267#ifndef NO_XFS
268int attr_list_path(pathname_t *, char *, const int, int, attrlist_cursor_t *);
269int attr_remove_path(pathname_t *, const char *, int);
270int attr_set_path(pathname_t *, const char *, const char *, const int, int);
271#endif
272void check_cwd(void);
273int creat_path(pathname_t *, mode_t);
274void dcache_enter(int, int);
275void dcache_init(void);
276fent_t *dcache_lookup(int);
277void dcache_purge(int);
278void del_from_flist(int, int);
279int dirid_to_name(char *, int);
280void doproc(void);
281void fent_to_name(pathname_t *, flist_t *, fent_t *);
282void fix_parent(int, int);
283void free_pathname(pathname_t *);
284int generate_fname(fent_t *, int, pathname_t *, int *, int *);
285int get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *);
286void init_pathname(pathname_t *);
287int lchown_path(pathname_t *, uid_t, gid_t);
288int link_path(pathname_t *, pathname_t *);
289int lstat64_path(pathname_t *, struct stat64 *);
290void make_freq_table(void);
291int mkdir_path(pathname_t *, mode_t);
292int mknod_path(pathname_t *, mode_t, dev_t);
293void namerandpad(int, char *, int);
294int open_path(pathname_t *, int);
295DIR *opendir_path(pathname_t *);
296void process_freq(char *);
297int readlink_path(pathname_t *, char *, size_t);
298int rename_path(pathname_t *, pathname_t *);
299int rmdir_path(pathname_t *);
300void separate_pathname(pathname_t *, char *, pathname_t *);
301void show_ops(int, char *);
302int stat64_path(pathname_t *, struct stat64 *);
303int symlink_path(const char *, pathname_t *);
304int truncate64_path(pathname_t *, off64_t);
305int unlink_path(pathname_t *);
306void usage(void);
307void write_freq(void);
308void zero_freq(void);
309
310void sg_handler(int signum)
311{
312	should_stop = 1;
313}
314
315int 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
584void 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
599void 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
618int
619attr_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
639int 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
657int
658attr_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
679void 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
693int 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
711void dcache_enter(int dirid, int slot)
712{
713	dcache[dirid % NDCACHE] = slot;
714}
715
716void dcache_init(void)
717{
718	int i;
719
720	for (i = 0; i < NDCACHE; i++)
721		dcache[i] = -1;
722}
723
724fent_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
735void 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
744void 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
759fent_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
777void 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
818void 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
836void 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
851void 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
860int 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
887int
888get_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
941void init_pathname(pathname_t * name)
942{
943	name->len = 0;
944	name->path = NULL;
945}
946
947int 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
965int 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
1019int 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
1037void 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
1053int 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
1071int 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
1089void 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
1109int 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
1127DIR *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
1145void 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
1166int 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
1184int 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
1238int 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
1256void 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
1274void 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
1310int 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
1328int 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
1351int 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
1369int 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
1387void 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
1425void 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
1435void 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
1445void 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
1496void 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
1565void 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
1596void 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
1627void 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
1684void 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
1705void 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
1769int 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
1793void 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
1894void 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
1987void 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
2020void 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
2073void 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
2104void 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
2130void 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
2178void 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
2213void 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
2248void 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
2307void 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
2328void 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
2385void 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
2438void 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
2461void 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
2482void 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 */
2529void sync_f(int opno, long r)
2530{
2531	sync();
2532	if (verbose)
2533		printf("%d/%d: sync\n", procid, opno);
2534}
2535
2536void 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
2572void 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
2597void 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
2650void 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