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