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