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