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