63c2eb4b17267fa221bb252dc929368f56898710
[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 <linux/fs.h>
20 #include <setjmp.h>
21 #include <sys/uio.h>
22 #include <stddef.h>
23 #include "global.h"
24
25 #ifdef HAVE_ATTR_XATTR_H
26 #include <attr/xattr.h>
27 #endif
28 #ifdef HAVE_ATTR_ATTRIBUTES_H
29 #include <attr/attributes.h>
30 #endif
31 #ifdef HAVE_LINUX_FIEMAP_H
32 #include <linux/fiemap.h>
33 #endif
34 #ifndef HAVE_ATTR_LIST
35 #define attr_list(path, buf, size, flags, cursor) (errno = -ENOSYS, -1)
36 #endif
37 #ifdef HAVE_SYS_PRCTL_H
38 #include <sys/prctl.h>
39 #endif
40 #ifdef AIO
41 #include <libaio.h>
42 io_context_t    io_ctx;
43 #endif
44
45 #ifndef FS_IOC_GETFLAGS
46 #define FS_IOC_GETFLAGS                 _IOR('f', 1, long)
47 #endif
48 #ifndef FS_IOC_SETFLAGS
49 #define FS_IOC_SETFLAGS                 _IOW('f', 2, long)
50 #endif
51
52 #include <math.h>
53 #define XFS_ERRTAG_MAX          17
54 #define XFS_IDMODULO_MAX        31      /* user/group IDs (1 << x)  */
55 #define XFS_PROJIDMODULO_MAX    16      /* project IDs (1 << x)     */
56 #ifndef IOV_MAX
57 #define IOV_MAX 1024
58 #endif
59
60 #define FILELEN_MAX             (32*4096)
61
62 typedef enum {
63         OP_AFSYNC,
64         OP_ALLOCSP,
65         OP_AREAD,
66         OP_ATTR_REMOVE,
67         OP_ATTR_SET,
68         OP_AWRITE,
69         OP_BULKSTAT,
70         OP_BULKSTAT1,
71         OP_CHOWN,
72         OP_CLONERANGE,
73         OP_CREAT,
74         OP_DEDUPERANGE,
75         OP_DREAD,
76         OP_DWRITE,
77         OP_FALLOCATE,
78         OP_FDATASYNC,
79         OP_FIEMAP,
80         OP_FREESP,
81         OP_FSYNC,
82         OP_GETATTR,
83         OP_GETDENTS,
84         OP_LINK,
85         OP_MKDIR,
86         OP_MKNOD,
87         OP_MREAD,
88         OP_MWRITE,
89         OP_PUNCH,
90         OP_ZERO,
91         OP_COLLAPSE,
92         OP_INSERT,
93         OP_READ,
94         OP_READLINK,
95         OP_READV,
96         OP_RENAME,
97         OP_RESVSP,
98         OP_RMDIR,
99         OP_SETATTR,
100         OP_SETXATTR,
101         OP_STAT,
102         OP_SYMLINK,
103         OP_SYNC,
104         OP_TRUNCATE,
105         OP_UNLINK,
106         OP_UNRESVSP,
107         OP_WRITE,
108         OP_WRITEV,
109         OP_LAST
110 } opty_t;
111
112 typedef void (*opfnc_t)(int, long);
113
114 typedef struct opdesc {
115         opty_t  op;
116         char    *name;
117         opfnc_t func;
118         int     freq;
119         int     iswrite;
120 } opdesc_t;
121
122 typedef struct fent {
123         int     id;
124         int     parent;
125 } fent_t;
126
127 typedef struct flist {
128         int     nfiles;
129         int     nslots;
130         int     tag;
131         fent_t  *fents;
132 } flist_t;
133
134 typedef struct pathname {
135         int     len;
136         char    *path;
137 } pathname_t;
138
139 struct print_flags {
140         unsigned long mask;
141         const char *name;
142 };
143
144 struct print_string {
145         char *buffer;
146         int len;
147         int max;
148 };
149
150 #define FT_DIR  0
151 #define FT_DIRm (1 << FT_DIR)
152 #define FT_REG  1
153 #define FT_REGm (1 << FT_REG)
154 #define FT_SYM  2
155 #define FT_SYMm (1 << FT_SYM)
156 #define FT_DEV  3
157 #define FT_DEVm (1 << FT_DEV)
158 #define FT_RTF  4
159 #define FT_RTFm (1 << FT_RTF)
160 #define FT_nft  5
161 #define FT_ANYm ((1 << FT_nft) - 1)
162 #define FT_REGFILE      (FT_REGm | FT_RTFm)
163 #define FT_NOTDIR       (FT_ANYm & ~FT_DIRm)
164
165 #define FLIST_SLOT_INCR 16
166 #define NDCACHE 64
167
168 #define MAXFSIZE        ((1ULL << 63) - 1ULL)
169 #define MAXFSIZE32      ((1ULL << 40) - 1ULL)
170
171 void    afsync_f(int, long);
172 void    allocsp_f(int, long);
173 void    aread_f(int, long);
174 void    attr_remove_f(int, long);
175 void    attr_set_f(int, long);
176 void    awrite_f(int, long);
177 void    bulkstat_f(int, long);
178 void    bulkstat1_f(int, long);
179 void    chown_f(int, long);
180 void    clonerange_f(int, long);
181 void    creat_f(int, long);
182 void    deduperange_f(int, long);
183 void    dread_f(int, long);
184 void    dwrite_f(int, long);
185 void    fallocate_f(int, long);
186 void    fdatasync_f(int, long);
187 void    fiemap_f(int, long);
188 void    freesp_f(int, long);
189 void    fsync_f(int, long);
190 void    getattr_f(int, long);
191 void    getdents_f(int, long);
192 void    link_f(int, long);
193 void    mkdir_f(int, long);
194 void    mknod_f(int, long);
195 void    mread_f(int, long);
196 void    mwrite_f(int, long);
197 void    punch_f(int, long);
198 void    zero_f(int, long);
199 void    collapse_f(int, long);
200 void    insert_f(int, long);
201 void    read_f(int, long);
202 void    readlink_f(int, long);
203 void    readv_f(int, long);
204 void    rename_f(int, long);
205 void    resvsp_f(int, long);
206 void    rmdir_f(int, long);
207 void    setattr_f(int, long);
208 void    setxattr_f(int, long);
209 void    stat_f(int, long);
210 void    symlink_f(int, long);
211 void    sync_f(int, long);
212 void    truncate_f(int, long);
213 void    unlink_f(int, long);
214 void    unresvsp_f(int, long);
215 void    write_f(int, long);
216 void    writev_f(int, long);
217
218 opdesc_t        ops[] = {
219      /* { OP_ENUM, "name", function, freq, iswrite }, */
220         { OP_AFSYNC, "afsync", afsync_f, 0, 1 },
221         { OP_ALLOCSP, "allocsp", allocsp_f, 1, 1 },
222         { OP_AREAD, "aread", aread_f, 1, 0 },
223         { OP_ATTR_REMOVE, "attr_remove", attr_remove_f, /* 1 */ 0, 1 },
224         { OP_ATTR_SET, "attr_set", attr_set_f, /* 2 */ 0, 1 },
225         { OP_AWRITE, "awrite", awrite_f, 1, 1 },
226         { OP_BULKSTAT, "bulkstat", bulkstat_f, 1, 0 },
227         { OP_BULKSTAT1, "bulkstat1", bulkstat1_f, 1, 0 },
228         { OP_CHOWN, "chown", chown_f, 3, 1 },
229         { OP_CLONERANGE, "clonerange", clonerange_f, 4, 1 },
230         { OP_CREAT, "creat", creat_f, 4, 1 },
231         { OP_DEDUPERANGE, "deduperange", deduperange_f, 4, 1},
232         { OP_DREAD, "dread", dread_f, 4, 0 },
233         { OP_DWRITE, "dwrite", dwrite_f, 4, 1 },
234         { OP_FALLOCATE, "fallocate", fallocate_f, 1, 1 },
235         { OP_FDATASYNC, "fdatasync", fdatasync_f, 1, 1 },
236         { OP_FIEMAP, "fiemap", fiemap_f, 1, 1 },
237         { OP_FREESP, "freesp", freesp_f, 1, 1 },
238         { OP_FSYNC, "fsync", fsync_f, 1, 1 },
239         { OP_GETATTR, "getattr", getattr_f, 1, 0 },
240         { OP_GETDENTS, "getdents", getdents_f, 1, 0 },
241         { OP_LINK, "link", link_f, 1, 1 },
242         { OP_MKDIR, "mkdir", mkdir_f, 2, 1 },
243         { OP_MKNOD, "mknod", mknod_f, 2, 1 },
244         { OP_MREAD, "mread", mread_f, 2, 0 },
245         { OP_MWRITE, "mwrite", mwrite_f, 2, 1 },
246         { OP_PUNCH, "punch", punch_f, 1, 1 },
247         { OP_ZERO, "zero", zero_f, 1, 1 },
248         { OP_COLLAPSE, "collapse", collapse_f, 1, 1 },
249         { OP_INSERT, "insert", insert_f, 1, 1 },
250         { OP_READ, "read", read_f, 1, 0 },
251         { OP_READLINK, "readlink", readlink_f, 1, 0 },
252         { OP_READV, "readv", readv_f, 1, 0 },
253         { OP_RENAME, "rename", rename_f, 2, 1 },
254         { OP_RESVSP, "resvsp", resvsp_f, 1, 1 },
255         { OP_RMDIR, "rmdir", rmdir_f, 1, 1 },
256         { OP_SETATTR, "setattr", setattr_f, 0, 1 },
257         { OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
258         { OP_STAT, "stat", stat_f, 1, 0 },
259         { OP_SYMLINK, "symlink", symlink_f, 2, 1 },
260         { OP_SYNC, "sync", sync_f, 1, 1 },
261         { OP_TRUNCATE, "truncate", truncate_f, 2, 1 },
262         { OP_UNLINK, "unlink", unlink_f, 1, 1 },
263         { OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1 },
264         { OP_WRITE, "write", write_f, 4, 1 },
265         { OP_WRITEV, "writev", writev_f, 4, 1 },
266 }, *ops_end;
267
268 flist_t flist[FT_nft] = {
269         { 0, 0, 'd', NULL },
270         { 0, 0, 'f', NULL },
271         { 0, 0, 'l', NULL },
272         { 0, 0, 'c', NULL },
273         { 0, 0, 'r', NULL },
274 };
275
276 int             dcache[NDCACHE];
277 int             errrange;
278 int             errtag;
279 opty_t          *freq_table;
280 int             freq_table_size;
281 xfs_fsop_geom_t geom;
282 char            *homedir;
283 int             *ilist;
284 int             ilistlen;
285 off64_t         maxfsize;
286 char            *myprog;
287 int             namerand;
288 int             nameseq;
289 int             nops;
290 int             nproc = 1;
291 int             operations = 1;
292 unsigned int    idmodulo = XFS_IDMODULO_MAX;
293 unsigned int    attr_mask = ~0;
294 int             procid;
295 int             rtpct;
296 unsigned long   seed = 0;
297 ino_t           top_ino;
298 int             cleanup = 0;
299 int             verbose = 0;
300 int             verifiable_log = 0;
301 sig_atomic_t    should_stop = 0;
302 sigjmp_buf      *sigbus_jmp = NULL;
303 char            *execute_cmd = NULL;
304 int             execute_freq = 1;
305 struct print_string     flag_str = {0};
306
307 void    add_to_flist(int, int, int);
308 void    append_pathname(pathname_t *, char *);
309 int     attr_list_path(pathname_t *, char *, const int, int, attrlist_cursor_t *);
310 int     attr_remove_path(pathname_t *, const char *, int);
311 int     attr_set_path(pathname_t *, const char *, const char *, const int, int);
312 void    check_cwd(void);
313 void    cleanup_flist(void);
314 int     creat_path(pathname_t *, mode_t);
315 void    dcache_enter(int, int);
316 void    dcache_init(void);
317 fent_t  *dcache_lookup(int);
318 void    dcache_purge(int);
319 void    del_from_flist(int, int);
320 int     dirid_to_name(char *, int);
321 void    doproc(void);
322 int     fent_to_name(pathname_t *, flist_t *, fent_t *);
323 void    fix_parent(int, int);
324 void    free_pathname(pathname_t *);
325 int     generate_fname(fent_t *, int, pathname_t *, int *, int *);
326 int     get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *);
327 void    init_pathname(pathname_t *);
328 int     lchown_path(pathname_t *, uid_t, gid_t);
329 int     link_path(pathname_t *, pathname_t *);
330 int     lstat64_path(pathname_t *, struct stat64 *);
331 void    make_freq_table(void);
332 int     mkdir_path(pathname_t *, mode_t);
333 int     mknod_path(pathname_t *, mode_t, dev_t);
334 void    namerandpad(int, char *, int);
335 int     open_path(pathname_t *, int);
336 DIR     *opendir_path(pathname_t *);
337 void    process_freq(char *);
338 int     readlink_path(pathname_t *, char *, size_t);
339 int     rename_path(pathname_t *, pathname_t *);
340 int     rmdir_path(pathname_t *);
341 void    separate_pathname(pathname_t *, char *, pathname_t *);
342 void    show_ops(int, char *);
343 int     stat64_path(pathname_t *, struct stat64 *);
344 int     symlink_path(const char *, pathname_t *);
345 int     truncate64_path(pathname_t *, off64_t);
346 int     unlink_path(pathname_t *);
347 void    usage(void);
348 void    write_freq(void);
349 void    zero_freq(void);
350
351 void sg_handler(int signum)
352 {
353         switch (signum) {
354         case SIGTERM:
355                 should_stop = 1;
356                 break;
357         case SIGBUS:
358                 /*
359                  * Only handle SIGBUS when mmap write to a hole and no
360                  * block can be allocated due to ENOSPC, abort otherwise.
361                  */
362                 if (sigbus_jmp) {
363                         siglongjmp(*sigbus_jmp, -1);
364                 } else {
365                         printf("Unknown SIGBUS is caught, Abort!\n");
366                         abort();
367                 }
368                 /* should not reach here */
369                 break;
370         default:
371                 break;
372         }
373 }
374
375 int main(int argc, char **argv)
376 {
377         char            buf[10];
378         int             c;
379         char            *dirname = NULL;
380         char            *logname = NULL;
381         char            rpath[PATH_MAX];
382         int             fd;
383         int             i;
384         int             j;
385         char            *p;
386         int             stat;
387         struct timeval  t;
388         ptrdiff_t       srval;
389         int             nousage = 0;
390         xfs_error_injection_t           err_inj;
391         struct sigaction action;
392         int             loops = 1;
393         const char      *allopts = "cd:e:f:i:l:m:M:n:o:p:rs:S:vVwx:X:zH";
394
395         errrange = errtag = 0;
396         umask(0);
397         nops = sizeof(ops) / sizeof(ops[0]);
398         ops_end = &ops[nops];
399         myprog = argv[0];
400         while ((c = getopt(argc, argv, allopts)) != -1) {
401                 switch (c) {
402                 case 'c':
403                         cleanup = 1;
404                         break;
405                 case 'd':
406                         dirname = optarg;
407                         break;
408                 case 'e':
409                         sscanf(optarg, "%d", &errtag);
410                         if (errtag < 0) {
411                                 errtag = -errtag;
412                                 errrange = 1;
413                         } else if (errtag == 0)
414                                 errtag = -1;
415                         if (errtag >= XFS_ERRTAG_MAX) {
416                                 fprintf(stderr,
417                                         "error tag %d too large (max %d)\n",
418                                         errtag, XFS_ERRTAG_MAX - 1);
419                                 exit(1);
420                         }
421                         break;
422                 case 'f':
423                         process_freq(optarg);
424                         break;
425                 case 'i':
426                         ilist = realloc(ilist, ++ilistlen * sizeof(*ilist));
427                         ilist[ilistlen - 1] = strtol(optarg, &p, 16);
428                         break;
429                 case 'm':
430                         idmodulo = strtoul(optarg, NULL, 0);
431                         if (idmodulo > XFS_IDMODULO_MAX) {
432                                 fprintf(stderr,
433                                         "chown modulo %d too big (max %d)\n",
434                                         idmodulo, XFS_IDMODULO_MAX);
435                                 exit(1);
436                         }
437                         break;
438                 case 'l':
439                         loops = atoi(optarg);
440                         break;
441                 case 'n':
442                         operations = atoi(optarg);
443                         break;
444                 case 'o':
445                         logname = optarg;
446                         break;
447
448                 case 'p':
449                         nproc = atoi(optarg);
450                         break;
451                 case 'r':
452                         namerand = 1;
453                         break;
454                 case 's':
455                         seed = strtoul(optarg, NULL, 0);
456                         break;
457                 case 'v':
458                         verbose = 1;
459                         break;
460                 case 'w':
461                         write_freq();
462                         break;
463                 case 'x':
464                         execute_cmd = optarg;
465                         break;
466                 case 'z':
467                         zero_freq();
468                         break;
469                 case 'M':
470                         attr_mask = strtoul(optarg, NULL, 0);
471                         break;
472                 case 'S':
473                         i = 0;
474                         if (optarg[0] == 'c')
475                                 i = 1;
476                         show_ops(i, NULL);
477                         printf("\n");
478                         nousage=1;
479                         break;
480                 case 'V':
481                         verifiable_log = 1;
482                         break;
483
484                 case 'X':
485                         execute_freq = strtoul(optarg, NULL, 0);
486                         break;
487                 case '?':
488                         fprintf(stderr, "%s - invalid parameters\n",
489                                 myprog);
490                         /* fall through */
491                 case 'H':
492                         usage();
493                         exit(1);
494                 }
495         }
496
497         if (!dirname) {
498             /* no directory specified */
499             if (!nousage) usage();
500             exit(1);
501         }
502
503         (void)mkdir(dirname, 0777);
504         if (logname && logname[0] != '/') {
505                 if (!getcwd(rpath, sizeof(rpath))){
506                         perror("getcwd failed");
507                         exit(1);
508                 }
509         } else {
510                 rpath[0] = '\0';
511         }
512         if (chdir(dirname) < 0) {
513                 perror(dirname);
514                 exit(1);
515         }
516         if (logname) {
517                 char path[PATH_MAX];
518                 snprintf(path, sizeof(path), "%s/%s", rpath, logname);
519                 if (freopen(path, "a", stdout) == NULL) {
520                         perror("freopen logfile failed");
521                         exit(1);
522                 }
523         }
524         sprintf(buf, "fss%x", (unsigned int)getpid());
525         fd = creat(buf, 0666);
526         if (lseek64(fd, (off64_t)(MAXFSIZE32 + 1ULL), SEEK_SET) < 0)
527                 maxfsize = (off64_t)MAXFSIZE32;
528         else
529                 maxfsize = (off64_t)MAXFSIZE;
530         make_freq_table();
531         dcache_init();
532         setlinebuf(stdout);
533         if (!seed) {
534                 gettimeofday(&t, (void *)NULL);
535                 seed = (int)t.tv_sec ^ (int)t.tv_usec;
536                 printf("seed = %ld\n", seed);
537         }
538         i = xfsctl(buf, fd, XFS_IOC_FSGEOMETRY, &geom);
539         if (i >= 0 && geom.rtblocks)
540                 rtpct = MIN(MAX(geom.rtblocks * 100 /
541                                 (geom.rtblocks + geom.datablocks), 1), 99);
542         else
543                 rtpct = 0;
544         if (errtag != 0) {
545                 if (errrange == 0) {
546                         if (errtag <= 0) {
547                                 srandom(seed);
548                                 j = random() % 100;
549
550                                 for (i = 0; i < j; i++)
551                                         (void) random();
552
553                                 errtag = (random() % (XFS_ERRTAG_MAX-1)) + 1;
554                         }
555                 } else {
556                         srandom(seed);
557                         j = random() % 100;
558
559                         for (i = 0; i < j; i++)
560                                 (void) random();
561
562                         errtag += (random() % (XFS_ERRTAG_MAX - errtag));
563                 }
564                 printf("Injecting failure on tag #%d\n", errtag);
565                 err_inj.errtag = errtag;
566                 err_inj.fd = fd;
567                 srval = xfsctl(buf, fd, XFS_IOC_ERROR_INJECTION, &err_inj);
568                 if (srval < -1) {
569                         perror("fsstress - XFS_SYSSGI error injection call");
570                         close(fd);
571                         unlink(buf);
572                         exit(1);
573                 }
574         } else
575                 close(fd);
576
577         setpgid(0, 0);
578         action.sa_handler = sg_handler;
579         sigemptyset(&action.sa_mask);
580         action.sa_flags = 0;
581         if (sigaction(SIGTERM, &action, 0)) {
582                 perror("sigaction failed");
583                 exit(1);
584         }
585
586         for (i = 0; i < nproc; i++) {
587                 if (fork() == 0) {
588                         sigemptyset(&action.sa_mask);
589                         action.sa_handler = SIG_DFL;
590                         if (sigaction(SIGTERM, &action, 0))
591                                 return 1;
592                         action.sa_handler = sg_handler;
593                         if (sigaction(SIGBUS, &action, 0))
594                                 return 1;
595 #ifdef HAVE_SYS_PRCTL_H
596                         prctl(PR_SET_PDEATHSIG, SIGKILL);
597                         if (getppid() == 1) /* parent died already? */
598                                 return 0;
599 #endif
600                         if (logname) {
601                                 char path[PATH_MAX];
602                                 snprintf(path, sizeof(path), "%s/%s.%d",
603                                          rpath, logname, i);
604                                 if (freopen(path, "a", stdout) == NULL) {
605                                         perror("freopen logfile failed");
606                                         exit(1);
607                                 }
608                         }
609                         procid = i;
610 #ifdef AIO
611                         if (io_setup(128, &io_ctx) != 0) {
612                                 fprintf(stderr, "io_setup failed");
613                                 exit(1);
614                         }
615 #endif
616                         for (i = 0; !loops || (i < loops); i++)
617                                 doproc();
618 #ifdef AIO
619                         if(io_destroy(io_ctx) != 0) {
620                                 fprintf(stderr, "io_destroy failed");
621                                 return 1;
622                         }
623 #endif
624
625                         cleanup_flist();
626                         free(freq_table);
627                         return 0;
628                 }
629         }
630         while (wait(&stat) > 0 && !should_stop) {
631                 continue;
632         }
633         action.sa_flags = SA_RESTART;
634         sigaction(SIGTERM, &action, 0);
635         kill(-getpid(), SIGTERM);
636         while (wait(&stat) > 0)
637                 continue;
638
639         if (errtag != 0) {
640                 err_inj.errtag = 0;
641                 err_inj.fd = fd;
642                 srval = xfsctl(buf, fd, XFS_IOC_ERROR_CLEARALL, &err_inj);
643                 if (srval != 0) {
644                         fprintf(stderr, "Bad ej clear on %s fd=%d (%d).\n",
645                                 buf, fd, errno);
646                         perror("xfsctl(XFS_IOC_ERROR_CLEARALL)");
647                         close(fd);
648                         exit(1);
649                 }
650                 close(fd);
651         }
652
653         free(freq_table);
654         unlink(buf);
655         return 0;
656 }
657
658 int
659 add_string(struct print_string *str, const char *add)
660 {
661         int len = strlen(add);
662
663         if (len <= 0)
664                 return 0;
665
666         if (len > (str->max - 1) - str->len) {
667                 str->len = str->max - 1;
668                 return 0;
669         }
670
671         memcpy(str->buffer + str->len, add, len);
672         str->len += len;
673         str->buffer[str->len] = '\0';
674
675         return len;
676 }
677
678 char *
679 translate_flags(int flags, const char *delim,
680                 const struct print_flags *flag_array)
681 {
682         int i, mask, first = 1;
683         const char *add;
684
685         if (!flag_str.buffer) {
686                 flag_str.buffer = malloc(4096);
687                 flag_str.max = 4096;
688                 flag_str.len = 0;
689         }
690         if (!flag_str.buffer)
691                 return NULL;
692         flag_str.len = 0;
693         flag_str.buffer[0] = '\0';
694
695         for (i = 0;  flag_array[i].name && flags; i++) {
696                 mask = flag_array[i].mask;
697                 if ((flags & mask) != mask)
698                         continue;
699
700                 add = flag_array[i].name;
701                 flags &= ~mask;
702                 if (!first && delim)
703                         add_string(&flag_str, delim);
704                 else
705                         first = 0;
706                 add_string(&flag_str, add);
707         }
708
709         /* Check whether there are any leftover flags. */
710         if (flags) {
711                 int ret;
712                 char number[11];
713
714                 if (!first && delim)
715                         add_string(&flag_str, delim);
716
717                 ret = snprintf(number, 11, "0x%x", flags) > 0;
718                 if (ret > 0 && ret <= 11)
719                         add_string(&flag_str, number);
720         }
721
722         return flag_str.buffer;
723 }
724
725 void
726 add_to_flist(int ft, int id, int parent)
727 {
728         fent_t  *fep;
729         flist_t *ftp;
730
731         ftp = &flist[ft];
732         if (ftp->nfiles == ftp->nslots) {
733                 ftp->nslots += FLIST_SLOT_INCR;
734                 ftp->fents = realloc(ftp->fents, ftp->nslots * sizeof(fent_t));
735         }
736         fep = &ftp->fents[ftp->nfiles++];
737         fep->id = id;
738         fep->parent = parent;
739 }
740
741 void
742 append_pathname(pathname_t *name, char *str)
743 {
744         int     len;
745
746         len = strlen(str);
747 #ifdef DEBUG
748         /* attempting to append to a dir a zero length path */
749         if (len && *str == '/' && name->len == 0) {
750                 fprintf(stderr, "fsstress: append_pathname failure\n");
751                 chdir(homedir);
752                 abort();
753                 /* NOTREACHED */
754         }
755 #endif
756         name->path = realloc(name->path, name->len + 1 + len);
757         strcpy(&name->path[name->len], str);
758         name->len += len;
759 }
760
761 int
762 attr_list_path(pathname_t *name,
763                char *buffer,
764                const int buffersize,
765                int flags,
766                attrlist_cursor_t *cursor)
767 {
768         char            buf[NAME_MAX + 1];
769         pathname_t      newname;
770         int             rval;
771
772         if (flags != ATTR_DONTFOLLOW) {
773                 errno = EINVAL;
774                 return -1;
775         }
776
777         rval = attr_list(name->path, buffer, buffersize, flags, cursor);
778         if (rval >= 0 || errno != ENAMETOOLONG)
779                 return rval;
780         separate_pathname(name, buf, &newname);
781         if (chdir(buf) == 0) {
782                 rval = attr_list_path(&newname, buffer, buffersize, flags, cursor);
783                 chdir("..");
784         }
785         free_pathname(&newname);
786         return rval;
787 }
788
789 int
790 attr_remove_path(pathname_t *name, const char *attrname, int flags)
791 {
792         char            buf[NAME_MAX + 1];
793         pathname_t      newname;
794         int             rval;
795
796         rval = attr_remove(name->path, attrname, flags);
797         if (rval >= 0 || errno != ENAMETOOLONG)
798                 return rval;
799         separate_pathname(name, buf, &newname);
800         if (chdir(buf) == 0) {
801                 rval = attr_remove_path(&newname, attrname, flags);
802                 chdir("..");
803         }
804         free_pathname(&newname);
805         return rval;
806 }
807
808 int
809 attr_set_path(pathname_t *name, const char *attrname, const char *attrvalue,
810               const int valuelength, int flags)
811 {
812         char            buf[NAME_MAX + 1];
813         pathname_t      newname;
814         int             rval;
815
816         rval = attr_set(name->path, attrname, attrvalue, valuelength, flags);
817         if (rval >= 0 || errno != ENAMETOOLONG)
818                 return rval;
819         separate_pathname(name, buf, &newname);
820         if (chdir(buf) == 0) {
821                 rval = attr_set_path(&newname, attrname, attrvalue, valuelength,
822                         flags);
823                 chdir("..");
824         }
825         free_pathname(&newname);
826         return rval;
827 }
828
829 void
830 check_cwd(void)
831 {
832 #ifdef DEBUG
833         struct stat64   statbuf;
834
835         if (stat64(".", &statbuf) == 0 && statbuf.st_ino == top_ino)
836                 return;
837         chdir(homedir);
838         fprintf(stderr, "fsstress: check_cwd failure\n");
839         abort();
840         /* NOTREACHED */
841 #endif
842 }
843
844 /*
845  * go thru flist and release all entries
846  *
847  * NOTE: this function shouldn't be called until the end of a process
848  */
849 void
850 cleanup_flist(void)
851 {
852         flist_t *flp;
853         int     i;
854
855         for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
856                 flp->nslots = 0;
857                 flp->nfiles = 0;
858                 free(flp->fents);
859                 flp->fents = NULL;
860         }
861 }
862
863 int
864 creat_path(pathname_t *name, mode_t mode)
865 {
866         char            buf[NAME_MAX + 1];
867         pathname_t      newname;
868         int             rval;
869
870         rval = creat(name->path, mode);
871         if (rval >= 0 || errno != ENAMETOOLONG)
872                 return rval;
873         separate_pathname(name, buf, &newname);
874         if (chdir(buf) == 0) {
875                 rval = creat_path(&newname, mode);
876                 chdir("..");
877         }
878         free_pathname(&newname);
879         return rval;
880 }
881
882 void
883 dcache_enter(int dirid, int slot)
884 {
885         dcache[dirid % NDCACHE] = slot;
886 }
887
888 void
889 dcache_init(void)
890 {
891         int     i;
892
893         for (i = 0; i < NDCACHE; i++)
894                 dcache[i] = -1;
895 }
896
897 fent_t *
898 dcache_lookup(int dirid)
899 {
900         fent_t  *fep;
901         int     i;
902
903         i = dcache[dirid % NDCACHE];
904         if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
905                 return fep;
906         return NULL;
907 }
908
909 void
910 dcache_purge(int dirid)
911 {
912         int     *dcp;
913
914         dcp = &dcache[dirid % NDCACHE];
915         if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
916                 *dcp = -1;
917 }
918
919 /*
920  * Delete the item from the list by
921  * moving last entry over the deleted one;
922  * unless deleted entry is the last one.
923  * Input: which file list array and which slot in array
924  */
925 void
926 del_from_flist(int ft, int slot)
927 {
928         flist_t *ftp;
929
930         ftp = &flist[ft];
931         if (ft == FT_DIR)
932                 dcache_purge(ftp->fents[slot].id);
933         if (slot != ftp->nfiles - 1) {
934                 if (ft == FT_DIR)
935                         dcache_purge(ftp->fents[ftp->nfiles - 1].id);
936                 ftp->fents[slot] = ftp->fents[--ftp->nfiles];
937         } else
938                 ftp->nfiles--;
939 }
940
941 fent_t *
942 dirid_to_fent(int dirid)
943 {
944         fent_t  *efep;
945         fent_t  *fep;
946         flist_t *flp;
947
948         if ((fep = dcache_lookup(dirid)))
949                 return fep;
950         flp = &flist[FT_DIR];
951         for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
952                 if (fep->id == dirid) {
953                         dcache_enter(dirid, fep - flp->fents);
954                         return fep;
955                 }
956         }
957         return NULL;
958 }
959
960 void
961 doproc(void)
962 {
963         struct stat64   statbuf;
964         char            buf[10];
965         char            cmd[64];
966         int             opno;
967         int             rval;
968         opdesc_t        *p;
969         int             dividend;
970
971         dividend = (operations + execute_freq) / (execute_freq + 1);
972         sprintf(buf, "p%x", procid);
973         (void)mkdir(buf, 0777);
974         if (chdir(buf) < 0 || stat64(".", &statbuf) < 0) {
975                 perror(buf);
976                 _exit(1);
977         }
978         top_ino = statbuf.st_ino;
979         homedir = getcwd(NULL, 0);
980         if (!homedir) {
981                 perror("getcwd failed");
982                 _exit(1);
983         }
984         seed += procid;
985         srandom(seed);
986         if (namerand)
987                 namerand = random();
988         for (opno = 0; opno < operations; opno++) {
989                 if (execute_cmd && opno && opno % dividend == 0) {
990                         if (verbose)
991                                 printf("%d: execute command %s\n", opno,
992                                         execute_cmd);
993                         rval = system(execute_cmd);
994                         if (rval)
995                                 fprintf(stderr, "execute command failed with "
996                                         "%d\n", rval);
997                 }
998                 p = &ops[freq_table[random() % freq_table_size]];
999                 p->func(opno, random());
1000                 /*
1001                  * test for forced shutdown by stat'ing the test
1002                  * directory.  If this stat returns EIO, assume
1003                  * the forced shutdown happened.
1004                  */
1005                 if (errtag != 0 && opno % 100 == 0)  {
1006                         rval = stat64(".", &statbuf);
1007                         if (rval == EIO)  {
1008                                 fprintf(stderr, "Detected EIO\n");
1009                                 goto errout;
1010                         }
1011                 }
1012         }
1013 errout:
1014         chdir("..");
1015         free(homedir);
1016         if (cleanup) {
1017                 sprintf(cmd, "rm -rf %s", buf);
1018                 system(cmd);
1019                 cleanup_flist();
1020         }
1021 }
1022
1023 /*
1024  * build up a pathname going thru the file entry and all
1025  * its parent entries
1026  * Return 0 on error, 1 on success;
1027  */
1028 int
1029 fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
1030 {
1031         char    buf[NAME_MAX + 1];
1032         int     i;
1033         fent_t  *pfep;
1034         int     e;
1035
1036         if (fep == NULL)
1037                 return 0;
1038
1039         /* build up parent directory name */
1040         if (fep->parent != -1) {
1041                 pfep = dirid_to_fent(fep->parent);
1042 #ifdef DEBUG
1043                 if (pfep == NULL) {
1044                         fprintf(stderr, "%d: fent-id = %d: can't find parent id: %d\n",
1045                                 procid, fep->id, fep->parent);
1046                 } 
1047 #endif
1048                 if (pfep == NULL)
1049                         return 0;
1050                 e = fent_to_name(name, &flist[FT_DIR], pfep);
1051                 if (!e)
1052                         return 0;
1053                 append_pathname(name, "/");
1054         }
1055
1056         i = sprintf(buf, "%c%x", flp->tag, fep->id);
1057         namerandpad(fep->id, buf, i);
1058         append_pathname(name, buf);
1059         return 1;
1060 }
1061
1062 void
1063 fix_parent(int oldid, int newid)
1064 {
1065         fent_t  *fep;
1066         flist_t *flp;
1067         int     i;
1068         int     j;
1069
1070         for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
1071                 for (j = 0, fep = flp->fents; j < flp->nfiles; j++, fep++) {
1072                         if (fep->parent == oldid)
1073                                 fep->parent = newid;
1074                 }
1075         }
1076 }
1077
1078 void
1079 free_pathname(pathname_t *name)
1080 {
1081         if (name->path) {
1082                 free(name->path);
1083                 name->path = NULL;
1084                 name->len = 0;
1085         }
1086 }
1087
1088 /*
1089  * Generate a filename of type ft.
1090  * If we have a fep which should be a directory then use it
1091  * as the parent path for this new filename i.e. prepend with it.
1092  */
1093 int
1094 generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v)
1095 {
1096         char    buf[NAME_MAX + 1];
1097         flist_t *flp;
1098         int     id;
1099         int     j;
1100         int     len;
1101         int     e;
1102
1103         /* create name */
1104         flp = &flist[ft];
1105         len = sprintf(buf, "%c%x", flp->tag, id = nameseq++);
1106         namerandpad(id, buf, len);
1107
1108         /* prepend fep parent dir-name to it */
1109         if (fep) {
1110                 e = fent_to_name(name, &flist[FT_DIR], fep);
1111                 if (!e)
1112                         return 0;
1113                 append_pathname(name, "/");
1114         }
1115         append_pathname(name, buf);
1116
1117         *idp = id;
1118         *v = verbose;
1119         for (j = 0; !*v && j < ilistlen; j++) {
1120                 if (ilist[j] == id) {
1121                         *v = 1;
1122                         break;
1123                 }
1124         }
1125         return 1;
1126 }
1127
1128 /*
1129  * Get file 
1130  * Input: "which" to choose the file-types eg. non-directory
1131  * Input: "r" to choose which file
1132  * Output: file-list, file-entry, name for the chosen file.
1133  * Output: verbose if chosen file is on the ilist.
1134  */
1135 int
1136 get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp,
1137           int *v)
1138 {
1139         int     totalsum = 0; /* total number of matching files */
1140         int     partialsum = 0; /* partial sum of matching files */
1141         fent_t  *fep;
1142         flist_t *flp;
1143         int     i;
1144         int     j;
1145         int     x;
1146         int     e = 1; /* success */
1147
1148         /*
1149          * go thru flist and add up number of files for each
1150          * category that matches with <which>.
1151          */
1152         for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
1153                 if (which & (1 << i))
1154                         totalsum += flp->nfiles;
1155         }
1156         if (totalsum == 0) {
1157                 if (flpp)
1158                         *flpp = NULL;
1159                 if (fepp)
1160                         *fepp = NULL;
1161                 *v = verbose;
1162                 return 0;
1163         }
1164
1165         /*
1166          * Now we have possible matches between 0..totalsum-1.
1167          * And we use r to help us choose which one we want,
1168          * which when bounded by totalsum becomes x.
1169          */ 
1170         x = (int)(r % totalsum);
1171         for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
1172                 if (which & (1 << i)) {
1173                         if (x < partialsum + flp->nfiles) {
1174
1175                                 /* found the matching file entry */
1176                                 fep = &flp->fents[x - partialsum];
1177
1178                                 /* fill-in what we were asked for */
1179                                 if (name) {
1180                                         e = fent_to_name(name, flp, fep);
1181 #ifdef DEBUG
1182                                         if (!e) {
1183                                                 fprintf(stderr, "%d: failed to get path for entry:"
1184                                                                 " id=%d,parent=%d\n",   
1185                                                         procid, fep->id, fep->parent);
1186                                         }
1187 #endif
1188                                 }
1189                                 if (flpp)
1190                                         *flpp = flp;
1191                                 if (fepp)
1192                                         *fepp = fep;
1193
1194                                 /* turn on verbose if its an ilisted file */
1195                                 *v = verbose;
1196                                 for (j = 0; !*v && j < ilistlen; j++) {
1197                                         if (ilist[j] == fep->id) {
1198                                                 *v = 1;
1199                                                 break;
1200                                         }
1201                                 }
1202                                 return e;
1203                         }
1204                         partialsum += flp->nfiles;
1205                 }
1206         }
1207 #ifdef DEBUG
1208         fprintf(stderr, "fsstress: get_fname failure\n");
1209         abort();
1210 #endif
1211         return 0;
1212 }
1213
1214 void
1215 init_pathname(pathname_t *name)
1216 {
1217         name->len = 0;
1218         name->path = NULL;
1219 }
1220
1221 int
1222 lchown_path(pathname_t *name, uid_t owner, gid_t group)
1223 {
1224         char            buf[NAME_MAX + 1];
1225         pathname_t      newname;
1226         int             rval;
1227
1228         rval = lchown(name->path, owner, group);
1229         if (rval >= 0 || errno != ENAMETOOLONG)
1230                 return rval;
1231         separate_pathname(name, buf, &newname);
1232         if (chdir(buf) == 0) {
1233                 rval = lchown_path(&newname, owner, group);
1234                 chdir("..");
1235         }
1236         free_pathname(&newname);
1237         return rval;
1238 }
1239
1240 int
1241 link_path(pathname_t *name1, pathname_t *name2)
1242 {
1243         char            buf1[NAME_MAX + 1];
1244         char            buf2[NAME_MAX + 1];
1245         int             down1;
1246         pathname_t      newname1;
1247         pathname_t      newname2;
1248         int             rval;
1249
1250         rval = link(name1->path, name2->path);
1251         if (rval >= 0 || errno != ENAMETOOLONG)
1252                 return rval;
1253         separate_pathname(name1, buf1, &newname1);
1254         separate_pathname(name2, buf2, &newname2);
1255         if (strcmp(buf1, buf2) == 0) {
1256                 if (chdir(buf1) == 0) {
1257                         rval = link_path(&newname1, &newname2);
1258                         chdir("..");
1259                 }
1260         } else {
1261                 if (strcmp(buf1, "..") == 0)
1262                         down1 = 0;
1263                 else if (strcmp(buf2, "..") == 0)
1264                         down1 = 1;
1265                 else if (strlen(buf1) == 0)
1266                         down1 = 0;
1267                 else if (strlen(buf2) == 0)
1268                         down1 = 1;
1269                 else
1270                         down1 = MAX(newname1.len, 3 + name2->len) <=
1271                                 MAX(3 + name1->len, newname2.len);
1272                 if (down1) {
1273                         free_pathname(&newname2);
1274                         append_pathname(&newname2, "../");
1275                         append_pathname(&newname2, name2->path);
1276                         if (chdir(buf1) == 0) {
1277                                 rval = link_path(&newname1, &newname2);
1278                                 chdir("..");
1279                         }
1280                 } else {
1281                         free_pathname(&newname1);
1282                         append_pathname(&newname1, "../");
1283                         append_pathname(&newname1, name1->path);
1284                         if (chdir(buf2) == 0) {
1285                                 rval = link_path(&newname1, &newname2);
1286                                 chdir("..");
1287                         }
1288                 }
1289         }
1290         free_pathname(&newname1);
1291         free_pathname(&newname2);
1292         return rval;
1293 }
1294
1295 int
1296 lstat64_path(pathname_t *name, struct stat64 *sbuf)
1297 {
1298         char            buf[NAME_MAX + 1];
1299         pathname_t      newname;
1300         int             rval;
1301
1302         rval = lstat64(name->path, sbuf);
1303         if (rval >= 0 || errno != ENAMETOOLONG)
1304                 return rval;
1305         separate_pathname(name, buf, &newname);
1306         if (chdir(buf) == 0) {
1307                 rval = lstat64_path(&newname, sbuf);
1308                 chdir("..");
1309         }
1310         free_pathname(&newname);
1311         return rval;
1312 }
1313
1314 void
1315 make_freq_table(void)
1316 {
1317         int             f;
1318         int             i;
1319         opdesc_t        *p;
1320
1321         for (p = ops, f = 0; p < ops_end; p++)
1322                 f += p->freq;
1323         freq_table = malloc(f * sizeof(*freq_table));
1324         freq_table_size = f;
1325         for (p = ops, i = 0; p < ops_end; p++) {
1326                 for (f = 0; f < p->freq; f++, i++)
1327                         freq_table[i] = p->op;
1328         }
1329 }
1330
1331 int
1332 mkdir_path(pathname_t *name, mode_t mode)
1333 {
1334         char            buf[NAME_MAX + 1];
1335         pathname_t      newname;
1336         int             rval;
1337
1338         rval = mkdir(name->path, mode);
1339         if (rval >= 0 || errno != ENAMETOOLONG)
1340                 return rval;
1341         separate_pathname(name, buf, &newname);
1342         if (chdir(buf) == 0) {
1343                 rval = mkdir_path(&newname, mode);
1344                 chdir("..");
1345         }
1346         free_pathname(&newname);
1347         return rval;
1348 }
1349
1350 int
1351 mknod_path(pathname_t *name, mode_t mode, dev_t dev)
1352 {
1353         char            buf[NAME_MAX + 1];
1354         pathname_t      newname;
1355         int             rval;
1356
1357         rval = mknod(name->path, mode, dev);
1358         if (rval >= 0 || errno != ENAMETOOLONG)
1359                 return rval;
1360         separate_pathname(name, buf, &newname);
1361         if (chdir(buf) == 0) {
1362                 rval = mknod_path(&newname, mode, dev);
1363                 chdir("..");
1364         }
1365         free_pathname(&newname);
1366         return rval;
1367 }
1368
1369 void
1370 namerandpad(int id, char *buf, int i)
1371 {
1372         int             bucket;
1373         static int      buckets[] =
1374                                 { 2, 4, 8, 16, 32, 64, 128, NAME_MAX };
1375         int             padlen;
1376         int             padmod;
1377
1378         if (namerand == 0)
1379                 return;
1380         bucket = (id ^ namerand) % (sizeof(buckets) / sizeof(buckets[0]));
1381         padmod = buckets[bucket] + 1 - i;
1382         if (padmod <= 0)
1383                 return;
1384         padlen = (id ^ namerand) % padmod;
1385         if (padlen) {
1386                 memset(&buf[i], 'X', padlen);
1387                 buf[i + padlen] = '\0';
1388         }
1389 }
1390
1391 int
1392 open_path(pathname_t *name, int oflag)
1393 {
1394         char            buf[NAME_MAX + 1];
1395         pathname_t      newname;
1396         int             rval;
1397
1398         rval = open(name->path, oflag);
1399         if (rval >= 0 || errno != ENAMETOOLONG)
1400                 return rval;
1401         separate_pathname(name, buf, &newname);
1402         if (chdir(buf) == 0) {
1403                 rval = open_path(&newname, oflag);
1404                 chdir("..");
1405         }
1406         free_pathname(&newname);
1407         return rval;
1408 }
1409
1410 DIR *
1411 opendir_path(pathname_t *name)
1412 {
1413         char            buf[NAME_MAX + 1];
1414         pathname_t      newname;
1415         DIR             *rval;
1416
1417         rval = opendir(name->path);
1418         if (rval || errno != ENAMETOOLONG)
1419                 return rval;
1420         separate_pathname(name, buf, &newname);
1421         if (chdir(buf) == 0) {
1422                 rval = opendir_path(&newname);
1423                 chdir("..");
1424         }
1425         free_pathname(&newname);
1426         return rval;
1427 }
1428
1429 void
1430 process_freq(char *arg)
1431 {
1432         opdesc_t        *p;
1433         char            *s;
1434
1435         s = strchr(arg, '=');
1436         if (s == NULL) {
1437                 fprintf(stderr, "bad argument '%s'\n", arg);
1438                 exit(1);
1439         }
1440         *s++ = '\0';
1441         for (p = ops; p < ops_end; p++) {
1442                 if (strcmp(arg, p->name) == 0) {
1443                         p->freq = atoi(s);
1444                         return;
1445                 }
1446         }
1447         fprintf(stderr, "can't find op type %s for -f\n", arg);
1448         exit(1);
1449 }
1450
1451 int
1452 readlink_path(pathname_t *name, char *lbuf, size_t lbufsiz)
1453 {
1454         char            buf[NAME_MAX + 1];
1455         pathname_t      newname;
1456         int             rval;
1457
1458         rval = readlink(name->path, lbuf, lbufsiz);
1459         if (rval >= 0 || errno != ENAMETOOLONG)
1460                 return rval;
1461         separate_pathname(name, buf, &newname);
1462         if (chdir(buf) == 0) {
1463                 rval = readlink_path(&newname, lbuf, lbufsiz);
1464                 chdir("..");
1465         }
1466         free_pathname(&newname);
1467         return rval;
1468 }
1469
1470 int
1471 rename_path(pathname_t *name1, pathname_t *name2)
1472 {
1473         char            buf1[NAME_MAX + 1];
1474         char            buf2[NAME_MAX + 1];
1475         int             down1;
1476         pathname_t      newname1;
1477         pathname_t      newname2;
1478         int             rval;
1479
1480         rval = rename(name1->path, name2->path);
1481         if (rval >= 0 || errno != ENAMETOOLONG)
1482                 return rval;
1483         separate_pathname(name1, buf1, &newname1);
1484         separate_pathname(name2, buf2, &newname2);
1485         if (strcmp(buf1, buf2) == 0) {
1486                 if (chdir(buf1) == 0) {
1487                         rval = rename_path(&newname1, &newname2);
1488                         chdir("..");
1489                 }
1490         } else {
1491                 if (strcmp(buf1, "..") == 0)
1492                         down1 = 0;
1493                 else if (strcmp(buf2, "..") == 0)
1494                         down1 = 1;
1495                 else if (strlen(buf1) == 0)
1496                         down1 = 0;
1497                 else if (strlen(buf2) == 0)
1498                         down1 = 1;
1499                 else
1500                         down1 = MAX(newname1.len, 3 + name2->len) <=
1501                                 MAX(3 + name1->len, newname2.len);
1502                 if (down1) {
1503                         free_pathname(&newname2);
1504                         append_pathname(&newname2, "../");
1505                         append_pathname(&newname2, name2->path);
1506                         if (chdir(buf1) == 0) {
1507                                 rval = rename_path(&newname1, &newname2);
1508                                 chdir("..");
1509                         }
1510                 } else {
1511                         free_pathname(&newname1);
1512                         append_pathname(&newname1, "../");
1513                         append_pathname(&newname1, name1->path);
1514                         if (chdir(buf2) == 0) {
1515                                 rval = rename_path(&newname1, &newname2);
1516                                 chdir("..");
1517                         }
1518                 }
1519         }
1520         free_pathname(&newname1);
1521         free_pathname(&newname2);
1522         return rval;
1523 }
1524
1525 int
1526 rmdir_path(pathname_t *name)
1527 {
1528         char            buf[NAME_MAX + 1];
1529         pathname_t      newname;
1530         int             rval;
1531
1532         rval = rmdir(name->path);
1533         if (rval >= 0 || errno != ENAMETOOLONG)
1534                 return rval;
1535         separate_pathname(name, buf, &newname);
1536         if (chdir(buf) == 0) {
1537                 rval = rmdir_path(&newname);
1538                 chdir("..");
1539         }
1540         free_pathname(&newname);
1541         return rval;
1542 }
1543
1544 void
1545 separate_pathname(pathname_t *name, char *buf, pathname_t *newname)
1546 {
1547         char    *slash;
1548
1549         init_pathname(newname);
1550         slash = strchr(name->path, '/');
1551         if (slash == NULL) {
1552                 buf[0] = '\0';
1553                 return;
1554         }
1555         *slash = '\0';
1556         strcpy(buf, name->path);
1557         *slash = '/';
1558         append_pathname(newname, slash + 1);
1559 }
1560
1561 #define WIDTH 80
1562
1563 void
1564 show_ops(int flag, char *lead_str)
1565 {
1566         opdesc_t        *p;
1567
1568         if (flag<0) {
1569                 /* print in list form */
1570                 int             x = WIDTH;
1571                 
1572                 for (p = ops; p < ops_end; p++) {
1573                         if (lead_str != NULL && x+strlen(p->name)>=WIDTH-5)
1574                                 x=printf("%s%s", (p==ops)?"":"\n", lead_str);
1575                         x+=printf("%s ", p->name);
1576                 }
1577                 printf("\n");
1578         } else if (flag == 0) {
1579                 /* Table view style */
1580                 int             f;
1581                 for (f = 0, p = ops; p < ops_end; p++)
1582                         f += p->freq;
1583
1584                 if (f == 0)
1585                         flag = 1;
1586
1587                 for (p = ops; p < ops_end; p++) {
1588                         if (flag != 0 || p->freq > 0) {
1589                                 if (lead_str != NULL)
1590                                         printf("%s", lead_str);
1591                                 printf("%20s %d/%d %s\n",
1592                                 p->name, p->freq, f,
1593                                 (p->iswrite == 0) ? " " : "write op");
1594                         }
1595                 }
1596         } else {
1597                 /* Command line style */
1598                 if (lead_str != NULL)
1599                         printf("%s", lead_str);
1600                 printf ("-z -s %ld -m %d -n %d -p %d \\\n", seed, idmodulo,
1601                         operations, nproc);
1602                 for (p = ops; p < ops_end; p++)
1603                         if (p->freq > 0)
1604                                 printf("-f %s=%d \\\n",p->name, p->freq);
1605         }
1606 }
1607
1608 int
1609 stat64_path(pathname_t *name, struct stat64 *sbuf)
1610 {
1611         char            buf[NAME_MAX + 1];
1612         pathname_t      newname;
1613         int             rval;
1614
1615         rval = stat64(name->path, sbuf);
1616         if (rval >= 0 || errno != ENAMETOOLONG)
1617                 return rval;
1618         separate_pathname(name, buf, &newname);
1619         if (chdir(buf) == 0) {
1620                 rval = stat64_path(&newname, sbuf);
1621                 chdir("..");
1622         }
1623         free_pathname(&newname);
1624         return rval;
1625 }
1626
1627 int
1628 symlink_path(const char *name1, pathname_t *name)
1629 {
1630         char            buf[NAME_MAX + 1];
1631         pathname_t      newname;
1632         int             rval;
1633         
1634         if (!strcmp(name1, name->path)) {
1635             printf("yikes! %s %s\n", name1, name->path);
1636             return 0;
1637         }
1638
1639         rval = symlink(name1, name->path);
1640         if (rval >= 0 || errno != ENAMETOOLONG)
1641                 return rval;
1642         separate_pathname(name, buf, &newname);
1643         if (chdir(buf) == 0) {
1644                 rval = symlink_path(name1, &newname);
1645                 chdir("..");
1646         }
1647         free_pathname(&newname);
1648         return rval;
1649 }
1650
1651 int
1652 truncate64_path(pathname_t *name, off64_t length)
1653 {
1654         char            buf[NAME_MAX + 1];
1655         pathname_t      newname;
1656         int             rval;
1657
1658         rval = truncate64(name->path, length);
1659         if (rval >= 0 || errno != ENAMETOOLONG)
1660                 return rval;
1661         separate_pathname(name, buf, &newname);
1662         if (chdir(buf) == 0) {
1663                 rval = truncate64_path(&newname, length);
1664                 chdir("..");
1665         }
1666         free_pathname(&newname);
1667         return rval;
1668 }
1669
1670 int
1671 unlink_path(pathname_t *name)
1672 {
1673         char            buf[NAME_MAX + 1];
1674         pathname_t      newname;
1675         int             rval;
1676
1677         rval = unlink(name->path);
1678         if (rval >= 0 || errno != ENAMETOOLONG)
1679                 return rval;
1680         separate_pathname(name, buf, &newname);
1681         if (chdir(buf) == 0) {
1682                 rval = unlink_path(&newname);
1683                 chdir("..");
1684         }
1685         free_pathname(&newname);
1686         return rval;
1687 }
1688
1689 void
1690 usage(void)
1691 {
1692         printf("Usage: %s -H   or\n", myprog);
1693         printf("       %s [-c][-d dir][-e errtg][-f op_name=freq][-l loops][-n nops]\n",
1694                 myprog);
1695         printf("          [-p nproc][-r len][-s seed][-v][-w][-x cmd][-z][-S][-X ncmd]\n");
1696         printf("where\n");
1697         printf("   -c               clean up the test directory after each run\n");
1698         printf("   -d dir           specifies the base directory for operations\n");
1699         printf("   -e errtg         specifies error injection stuff\n");
1700         printf("   -f op_name=freq  changes the frequency of option name to freq\n");
1701         printf("                    the valid operation names are:\n");
1702         show_ops(-1, "                        ");
1703         printf("   -i filenum       get verbose output for this nth file object\n");
1704         printf("   -l loops         specifies the no. of times the testrun should loop.\n");
1705         printf("                     *use 0 for infinite (default 1)\n");
1706         printf("   -m modulo        uid/gid modulo for chown/chgrp (default 32)\n");
1707         printf("   -n nops          specifies the no. of operations per process (default 1)\n");
1708         printf("   -o logfile       specifies logfile name\n");
1709         printf("   -p nproc         specifies the no. of processes (default 1)\n");
1710         printf("   -r               specifies random name padding\n");
1711         printf("   -s seed          specifies the seed for the random generator (default random)\n");
1712         printf("   -v               specifies verbose mode\n");
1713         printf("   -w               zeros frequencies of non-write operations\n");
1714         printf("   -x cmd           execute command in the middle of operations\n");
1715         printf("   -z               zeros frequencies of all operations\n");
1716         printf("   -S [c,t]         prints the list of operations (omitting zero frequency) in command line or table style\n");
1717         printf("   -V               specifies verifiable logging mode (omitting inode numbers)\n");
1718         printf("   -X ncmd          number of calls to the -x command (default 1)\n");
1719         printf("   -H               prints usage and exits\n");
1720 }
1721
1722 void
1723 write_freq(void)
1724 {
1725         opdesc_t        *p;
1726
1727         for (p = ops; p < ops_end; p++) {
1728                 if (!p->iswrite)
1729                         p->freq = 0;
1730         }
1731 }
1732
1733 void
1734 zero_freq(void)
1735 {
1736         opdesc_t        *p;
1737
1738         for (p = ops; p < ops_end; p++)
1739                 p->freq = 0;
1740 }
1741
1742 void inode_info(char *str, size_t sz, struct stat64 *s, int verbose)
1743 {
1744         if (verbose)
1745                 snprintf(str, sz, "[%ld %ld %d %d %lld %lld]",
1746                          verifiable_log ? -1: (long)s->st_ino,
1747                          (long)s->st_nlink,  s->st_uid, s->st_gid,
1748                          (long long) s->st_blocks, (long long) s->st_size);
1749 }
1750
1751 void
1752 afsync_f(int opno, long r)
1753 {
1754 #ifdef AIO
1755         int             e;
1756         pathname_t      f;
1757         int             fd;
1758         int             v;
1759         struct iocb     iocb;
1760         struct iocb     *iocbs[] = { &iocb };
1761         struct io_event event;
1762
1763         init_pathname(&f);
1764         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1765                 if (v)
1766                         printf("%d/%d: afsync - no filename\n", procid, opno);
1767                 free_pathname(&f);
1768                 return;
1769         }
1770         fd = open_path(&f, O_WRONLY | O_DIRECT);
1771         e = fd < 0 ? errno : 0;
1772         check_cwd();
1773         if (fd < 0) {
1774                 if (v)
1775                         printf("%d/%d: afsync - open %s failed %d\n",
1776                                procid, opno, f.path, e);
1777                 free_pathname(&f);
1778                 return;
1779         }
1780
1781         io_prep_fsync(&iocb, fd);
1782         if ((e = io_submit(io_ctx, 1, iocbs)) != 1) {
1783                 if (v)
1784                         printf("%d/%d: afsync - io_submit %s %d\n",
1785                                procid, opno, f.path, e);
1786                 free_pathname(&f);
1787                 close(fd);
1788                 return;
1789         }
1790         if ((e = io_getevents(io_ctx, 1, 1, &event, NULL)) != 1) {
1791                 if (v)
1792                         printf("%d/%d: afsync - io_getevents failed %d\n",
1793                                procid, opno, e);
1794                 free_pathname(&f);
1795                 close(fd);
1796                 return;
1797         }
1798
1799         e = event.res2;
1800         if (v)
1801                 printf("%d/%d: afsync %s %d\n", procid, opno, f.path, e);
1802         free_pathname(&f);
1803         close(fd);
1804 #endif
1805 }
1806
1807 void
1808 allocsp_f(int opno, long r)
1809 {
1810         int             e;
1811         pathname_t      f;
1812         int             fd;
1813         struct xfs_flock64      fl;
1814         __int64_t       lr;
1815         off64_t         off;
1816         struct stat64   stb;
1817         int             v;
1818         char            st[1024];
1819
1820         init_pathname(&f);
1821         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1822                 if (v)
1823                         printf("%d/%d: allocsp - no filename\n", procid, opno);
1824                 free_pathname(&f);
1825                 return;
1826         }
1827         fd = open_path(&f, O_RDWR);
1828         e = fd < 0 ? errno : 0;
1829         check_cwd();
1830         if (fd < 0) {
1831                 if (v)
1832                         printf("%d/%d: allocsp - open %s failed %d\n",
1833                                 procid, opno, f.path, e);
1834                 free_pathname(&f);
1835                 return;
1836         }
1837         if (fstat64(fd, &stb) < 0) {
1838                 if (v)
1839                         printf("%d/%d: allocsp - fstat64 %s failed %d\n",
1840                                 procid, opno, f.path, errno);
1841                 free_pathname(&f);
1842                 close(fd);
1843                 return;
1844         }
1845         inode_info(st, sizeof(st), &stb, v);
1846         lr = ((__int64_t)random() << 32) + random();
1847         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
1848         off %= maxfsize;
1849         fl.l_whence = SEEK_SET;
1850         fl.l_start = off;
1851         fl.l_len = 0;
1852         e = xfsctl(f.path, fd, XFS_IOC_ALLOCSP64, &fl) < 0 ? errno : 0;
1853         if (v) {
1854                 printf("%d/%d: xfsctl(XFS_IOC_ALLOCSP64) %s%s %lld 0 %d\n",
1855                        procid, opno, f.path, st, (long long)off, e);
1856         }
1857         free_pathname(&f);
1858         close(fd);
1859 }
1860
1861 #ifdef AIO
1862 void
1863 do_aio_rw(int opno, long r, int flags)
1864 {
1865         __int64_t       align;
1866         char            *buf;
1867         struct dioattr  diob;
1868         int             e;
1869         pathname_t      f;
1870         int             fd;
1871         size_t          len;
1872         __int64_t       lr;
1873         off64_t         off;
1874         struct stat64   stb;
1875         int             v;
1876         char            st[1024];
1877         char            *dio_env;
1878         struct iocb     iocb;
1879         struct io_event event;
1880         struct iocb     *iocbs[] = { &iocb };
1881         int             iswrite = (flags & (O_WRONLY | O_RDWR)) ? 1 : 0;
1882
1883         init_pathname(&f);
1884         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1885                 if (v)
1886                         printf("%d/%d: do_aio_rw - no filename\n", procid, opno);
1887                 free_pathname(&f);
1888                 return;
1889         }
1890         fd = open_path(&f, flags|O_DIRECT);
1891         e = fd < 0 ? errno : 0;
1892         check_cwd();
1893         if (fd < 0) {
1894                 if (v)
1895                         printf("%d/%d: do_aio_rw - open %s failed %d\n",
1896                                procid, opno, f.path, e);
1897                 free_pathname(&f);
1898                 return;
1899         }
1900         if (fstat64(fd, &stb) < 0) {
1901                 if (v)
1902                         printf("%d/%d: do_aio_rw - fstat64 %s failed %d\n",
1903                                procid, opno, f.path, errno);
1904                 free_pathname(&f);
1905                 close(fd);
1906                 return;
1907         }
1908         inode_info(st, sizeof(st), &stb, v);
1909         if (!iswrite && stb.st_size == 0) {
1910                 if (v)
1911                         printf("%d/%d: do_aio_rw - %s%s zero size\n", procid, opno,
1912                                f.path, st);
1913                 free_pathname(&f);
1914                 close(fd);
1915                 return;
1916         }
1917         if (xfsctl(f.path, fd, XFS_IOC_DIOINFO, &diob) < 0) {
1918                 if (v)
1919                         printf(
1920                         "%d/%d: do_aio_rw - xfsctl(XFS_IOC_DIOINFO) %s%s return %d,"
1921                         " fallback to stat()\n",
1922                                 procid, opno, f.path, st, errno);
1923                 diob.d_mem = diob.d_miniosz = stb.st_blksize;
1924                 diob.d_maxiosz = INT_MAX & ~(diob.d_miniosz - 1);
1925         }
1926         dio_env = getenv("XFS_DIO_MIN");
1927         if (dio_env)
1928                 diob.d_mem = diob.d_miniosz = atoi(dio_env);
1929         align = (__int64_t)diob.d_miniosz;
1930         lr = ((__int64_t)random() << 32) + random();
1931         len = (random() % FILELEN_MAX) + 1;
1932         len -= (len % align);
1933         if (len <= 0)
1934                 len = align;
1935         else if (len > diob.d_maxiosz)
1936                 len = diob.d_maxiosz;
1937         buf = memalign(diob.d_mem, len);
1938
1939         if (iswrite) {
1940                 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
1941                 off -= (off % align);
1942                 off %= maxfsize;
1943                 memset(buf, nameseq & 0xff, len);
1944                 io_prep_pwrite(&iocb, fd, buf, len, off);
1945         } else {
1946                 off = (off64_t)(lr % stb.st_size);
1947                 off -= (off % align);
1948                 io_prep_pread(&iocb, fd, buf, len, off);
1949         }
1950         if ((e = io_submit(io_ctx, 1, iocbs)) != 1) {
1951                 if (v)
1952                         printf("%d/%d: %s - io_submit failed %d\n",
1953                                procid, opno, iswrite ? "awrite" : "aread", e);
1954                 free_pathname(&f);
1955                 close(fd);
1956                 return;
1957         }
1958         if ((e = io_getevents(io_ctx, 1, 1, &event, NULL)) != 1) {
1959                 if (v)
1960                         printf("%d/%d: %s - io_getevents failed %d\n",
1961                                procid, opno, iswrite ? "awrite" : "aread", e);
1962                 free_pathname(&f);
1963                 close(fd);
1964                 return;
1965         }
1966
1967         e = event.res != len ? event.res2 : 0;
1968         free(buf);
1969         if (v)
1970                 printf("%d/%d: %s %s%s [%lld,%d] %d\n",
1971                        procid, opno, iswrite ? "awrite" : "aread",
1972                        f.path, st, (long long)off, (int)len, e);
1973         free_pathname(&f);
1974         close(fd);
1975 }
1976 #endif
1977
1978 void
1979 aread_f(int opno, long r)
1980 {
1981 #ifdef AIO
1982         do_aio_rw(opno, r, O_RDONLY);
1983 #endif
1984 }
1985
1986 void
1987 attr_remove_f(int opno, long r)
1988 {
1989         attrlist_ent_t          *aep;
1990         attrlist_t              *alist;
1991         char                    *aname;
1992         char                    buf[4096];
1993         attrlist_cursor_t       cursor;
1994         int                     e;
1995         int                     ent;
1996         pathname_t              f;
1997         int                     total;
1998         int                     v;
1999         int                     which;
2000
2001         init_pathname(&f);
2002         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2003                 append_pathname(&f, ".");
2004         total = 0;
2005         bzero(&cursor, sizeof(cursor));
2006         do {
2007                 bzero(buf, sizeof(buf));
2008                 e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW, &cursor);
2009                 check_cwd();
2010                 if (e)
2011                         break;
2012                 alist = (attrlist_t *)buf;
2013                 total += alist->al_count;
2014         } while (alist->al_more);
2015         if (total == 0) {
2016                 if (v)
2017                         printf("%d/%d: attr_remove - no attrs for %s\n",
2018                                 procid, opno, f.path);
2019                 free_pathname(&f);
2020                 return;
2021         }
2022         which = (int)(random() % total);
2023         bzero(&cursor, sizeof(cursor));
2024         ent = 0;
2025         aname = NULL;
2026         do {
2027                 bzero(buf, sizeof(buf));
2028                 e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW, &cursor);
2029                 check_cwd();
2030                 if (e)
2031                         break;
2032                 alist = (attrlist_t *)buf;
2033                 if (which < ent + alist->al_count) {
2034                         aep = (attrlist_ent_t *)
2035                                 &buf[alist->al_offset[which - ent]];
2036                         aname = aep->a_name;
2037                         break;
2038                 }
2039                 ent += alist->al_count;
2040         } while (alist->al_more);
2041         if (aname == NULL) {
2042                 if (v)
2043                         printf(
2044                         "%d/%d: attr_remove - name %d not found at %s\n",
2045                                 procid, opno, which, f.path);
2046                 free_pathname(&f);
2047                 return;
2048         }
2049         e = attr_remove_path(&f, aname, ATTR_DONTFOLLOW) < 0 ? errno : 0;
2050         check_cwd();
2051         if (v)
2052                 printf("%d/%d: attr_remove %s %s %d\n",
2053                         procid, opno, f.path, aname, e);
2054         free_pathname(&f);
2055 }
2056
2057 void
2058 attr_set_f(int opno, long r)
2059 {
2060         char            aname[10];
2061         char            *aval;
2062         int             e;
2063         pathname_t      f;
2064         int             len;
2065         static int      lengths[] = { 10, 100, 1000, 10000 };
2066         int             li;
2067         int             v;
2068
2069         init_pathname(&f);
2070         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2071                 append_pathname(&f, ".");
2072         sprintf(aname, "a%x", nameseq++);
2073         li = (int)(random() % (sizeof(lengths) / sizeof(lengths[0])));
2074         len = (int)(random() % lengths[li]);
2075         if (len == 0)
2076                 len = 1;
2077         aval = malloc(len);
2078         memset(aval, nameseq & 0xff, len);
2079         e = attr_set_path(&f, aname, aval, len, ATTR_DONTFOLLOW) < 0 ?
2080                 errno : 0;
2081         check_cwd();
2082         free(aval);
2083         if (v)
2084                 printf("%d/%d: attr_set %s %s %d\n", procid, opno, f.path,
2085                         aname, e);
2086         free_pathname(&f);
2087 }
2088
2089 void
2090 awrite_f(int opno, long r)
2091 {
2092 #ifdef AIO
2093         do_aio_rw(opno, r, O_WRONLY);
2094 #endif
2095 }
2096
2097 void
2098 bulkstat_f(int opno, long r)
2099 {
2100         int             count;
2101         int             fd;
2102         __u64           last;
2103         int             nent;
2104         xfs_bstat_t     *t;
2105         __int64_t       total;
2106         xfs_fsop_bulkreq_t bsr;
2107
2108         last = 0;
2109         nent = (r % 999) + 2;
2110         t = malloc(nent * sizeof(*t));
2111         fd = open(".", O_RDONLY);
2112         total = 0;
2113
2114         bsr.lastip=&last;
2115         bsr.icount=nent;
2116         bsr.ubuffer=t;
2117         bsr.ocount=&count;
2118             
2119         while (xfsctl(".", fd, XFS_IOC_FSBULKSTAT, &bsr) == 0 && count > 0)
2120                 total += count;
2121         free(t);
2122         if (verbose)
2123                 printf("%d/%d: bulkstat nent %d total %lld\n",
2124                         procid, opno, nent, (long long)total);
2125         close(fd);
2126 }
2127
2128 void
2129 bulkstat1_f(int opno, long r)
2130 {
2131         int             e;
2132         pathname_t      f;
2133         int             fd;
2134         int             good;
2135         __u64           ino;
2136         struct stat64   s;
2137         xfs_bstat_t     t;
2138         int             v;
2139         xfs_fsop_bulkreq_t bsr;
2140         
2141
2142         good = random() & 1;
2143         if (good) {
2144                /* use an inode we know exists */
2145                 init_pathname(&f);
2146                 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2147                         append_pathname(&f, ".");
2148                 ino = stat64_path(&f, &s) < 0 ? (ino64_t)r : s.st_ino;
2149                 check_cwd();
2150                 free_pathname(&f);
2151         } else {
2152                 /* 
2153                  * pick a random inode 
2154                  *
2155                  * note this can generate kernel warning messages
2156                  * since bulkstat_one will read the disk block that
2157                  * would contain a given inode even if that disk
2158                  * block doesn't contain inodes.
2159                  *
2160                  * this is detected later, but not until after the
2161                  * warning is displayed.
2162                  *
2163                  * "XFS: device 0x825- bad inode magic/vsn daddr 0x0 #0"
2164                  *
2165                  */
2166                 ino = (ino64_t)r;
2167                 v = verbose;
2168         }
2169         fd = open(".", O_RDONLY);
2170         
2171         bsr.lastip=&ino;
2172         bsr.icount=1;
2173         bsr.ubuffer=&t;
2174         bsr.ocount=NULL;
2175         e = xfsctl(".", fd, XFS_IOC_FSBULKSTAT_SINGLE, &bsr) < 0 ? errno : 0;
2176         if (v)
2177                 printf("%d/%d: bulkstat1 %s ino %lld %d\n", 
2178                        procid, opno, good?"real":"random",
2179                        verifiable_log ? -1LL : (long long)ino, e);
2180         close(fd);
2181 }
2182
2183 void
2184 chown_f(int opno, long r)
2185 {
2186         int             e;
2187         pathname_t      f;
2188         int             nbits;
2189         uid_t           u;
2190         gid_t           g;
2191         int             v;
2192
2193         init_pathname(&f);
2194         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2195                 append_pathname(&f, ".");
2196         u = (uid_t)random();
2197         g = (gid_t)random();
2198         nbits = (int)(random() % idmodulo);
2199         u &= (1 << nbits) - 1;
2200         g &= (1 << nbits) - 1;
2201         e = lchown_path(&f, u, g) < 0 ? errno : 0;
2202         check_cwd();
2203         if (v)
2204                 printf("%d/%d: chown %s %d/%d %d\n", procid, opno, f.path, (int)u, (int)g, e);
2205         free_pathname(&f);
2206 }
2207
2208 /* reflink some arbitrary range of f1 to f2. */
2209 void
2210 clonerange_f(
2211         int                     opno,
2212         long                    r)
2213 {
2214 #ifdef FICLONERANGE
2215         struct file_clone_range fcr;
2216         struct pathname         fpath1;
2217         struct pathname         fpath2;
2218         struct stat64           stat1;
2219         struct stat64           stat2;
2220         char                    inoinfo1[1024];
2221         char                    inoinfo2[1024];
2222         off64_t                 lr;
2223         off64_t                 off1;
2224         off64_t                 off2;
2225         size_t                  len;
2226         int                     v1;
2227         int                     v2;
2228         int                     fd1;
2229         int                     fd2;
2230         int                     ret;
2231         int                     e;
2232
2233         /* Load paths */
2234         init_pathname(&fpath1);
2235         if (!get_fname(FT_REGm, r, &fpath1, NULL, NULL, &v1)) {
2236                 if (v1)
2237                         printf("%d/%d: clonerange read - no filename\n",
2238                                 procid, opno);
2239                 goto out_fpath1;
2240         }
2241
2242         init_pathname(&fpath2);
2243         if (!get_fname(FT_REGm, random(), &fpath2, NULL, NULL, &v2)) {
2244                 if (v2)
2245                         printf("%d/%d: clonerange write - no filename\n",
2246                                 procid, opno);
2247                 goto out_fpath2;
2248         }
2249
2250         /* Open files */
2251         fd1 = open_path(&fpath1, O_RDONLY);
2252         e = fd1 < 0 ? errno : 0;
2253         check_cwd();
2254         if (fd1 < 0) {
2255                 if (v1)
2256                         printf("%d/%d: clonerange read - open %s failed %d\n",
2257                                 procid, opno, fpath1.path, e);
2258                 goto out_fpath2;
2259         }
2260
2261         fd2 = open_path(&fpath2, O_WRONLY);
2262         e = fd2 < 0 ? errno : 0;
2263         check_cwd();
2264         if (fd2 < 0) {
2265                 if (v2)
2266                         printf("%d/%d: clonerange write - open %s failed %d\n",
2267                                 procid, opno, fpath2.path, e);
2268                 goto out_fd1;
2269         }
2270
2271         /* Get file stats */
2272         if (fstat64(fd1, &stat1) < 0) {
2273                 if (v1)
2274                         printf("%d/%d: clonerange read - fstat64 %s failed %d\n",
2275                                 procid, opno, fpath1.path, errno);
2276                 goto out_fd2;
2277         }
2278         inode_info(inoinfo1, sizeof(inoinfo1), &stat1, v1);
2279
2280         if (fstat64(fd2, &stat2) < 0) {
2281                 if (v2)
2282                         printf("%d/%d: clonerange write - fstat64 %s failed %d\n",
2283                                 procid, opno, fpath2.path, errno);
2284                 goto out_fd2;
2285         }
2286         inode_info(inoinfo2, sizeof(inoinfo2), &stat2, v2);
2287
2288         /* Calculate offsets */
2289         len = (random() % FILELEN_MAX) + 1;
2290         len &= ~(stat1.st_blksize - 1);
2291         if (len == 0)
2292                 len = stat1.st_blksize;
2293         if (len > stat1.st_size)
2294                 len = stat1.st_size;
2295
2296         lr = ((__int64_t)random() << 32) + random();
2297         if (stat1.st_size == len)
2298                 off1 = 0;
2299         else
2300                 off1 = (off64_t)(lr % MIN(stat1.st_size - len, MAXFSIZE));
2301         off1 %= maxfsize;
2302         off1 &= ~(stat1.st_blksize - 1);
2303
2304         /*
2305          * If srcfile == destfile, randomly generate destination ranges
2306          * until we find one that doesn't overlap the source range.
2307          */
2308         do {
2309                 lr = ((__int64_t)random() << 32) + random();
2310                 off2 = (off64_t)(lr % MIN(stat2.st_size + (1024 * 1024), MAXFSIZE));
2311                 off2 %= maxfsize;
2312                 off2 &= ~(stat2.st_blksize - 1);
2313         } while (stat1.st_ino == stat2.st_ino && llabs(off2 - off1) < len);
2314
2315         /* Clone data blocks */
2316         fcr.src_fd = fd1;
2317         fcr.src_offset = off1;
2318         fcr.src_length = len;
2319         fcr.dest_offset = off2;
2320
2321         ret = ioctl(fd2, FICLONERANGE, &fcr);
2322         e = ret < 0 ? errno : 0;
2323         if (v1 || v2) {
2324                 printf("%d/%d: clonerange %s%s [%lld,%lld] -> %s%s [%lld,%lld]",
2325                         procid, opno,
2326                         fpath1.path, inoinfo1, (long long)off1, (long long)len,
2327                         fpath2.path, inoinfo2, (long long)off2, (long long)len);
2328
2329                 if (ret < 0)
2330                         printf(" error %d", e);
2331                 printf("\n");
2332         }
2333
2334 out_fd2:
2335         close(fd2);
2336 out_fd1:
2337         close(fd1);
2338 out_fpath2:
2339         free_pathname(&fpath2);
2340 out_fpath1:
2341         free_pathname(&fpath1);
2342 #endif
2343 }
2344
2345 /* dedupe some arbitrary range of f1 to f2...fn. */
2346 void
2347 deduperange_f(
2348         int                     opno,
2349         long                    r)
2350 {
2351 #ifdef FIDEDUPERANGE
2352 #define INFO_SZ                 1024
2353         struct file_dedupe_range *fdr;
2354         struct pathname         *fpath;
2355         struct stat64           *stat;
2356         char                    *info;
2357         off64_t                 *off;
2358         int                     *v;
2359         int                     *fd;
2360         int                     nr;
2361         off64_t                 lr;
2362         size_t                  len;
2363         int                     ret;
2364         int                     i;
2365         int                     e;
2366
2367         if (flist[FT_REG].nfiles < 2)
2368                 return;
2369
2370         /* Pick somewhere between 2 and 128 files. */
2371         do {
2372                 nr = random() % (flist[FT_REG].nfiles + 1);
2373         } while (nr < 2 || nr > 128);
2374
2375         /* Alloc memory */
2376         fdr = malloc(nr * sizeof(struct file_dedupe_range_info) +
2377                      sizeof(struct file_dedupe_range));
2378         if (!fdr) {
2379                 printf("%d/%d: line %d error %d\n",
2380                         procid, opno, __LINE__, errno);
2381                 return;
2382         }
2383         memset(fdr, 0, (nr * sizeof(struct file_dedupe_range_info) +
2384                         sizeof(struct file_dedupe_range)));
2385
2386         fpath = calloc(nr, sizeof(struct pathname));
2387         if (!fpath) {
2388                 printf("%d/%d: line %d error %d\n",
2389                         procid, opno, __LINE__, errno);
2390                 goto out_fdr;
2391         }
2392
2393         stat = calloc(nr, sizeof(struct stat64));
2394         if (!stat) {
2395                 printf("%d/%d: line %d error %d\n",
2396                         procid, opno, __LINE__, errno);
2397                 goto out_paths;
2398         }
2399
2400         info = calloc(nr, INFO_SZ);
2401         if (!info) {
2402                 printf("%d/%d: line %d error %d\n",
2403                         procid, opno, __LINE__, errno);
2404                 goto out_stats;
2405         }
2406
2407         off = calloc(nr, sizeof(off64_t));
2408         if (!off) {
2409                 printf("%d/%d: line %d error %d\n",
2410                         procid, opno, __LINE__, errno);
2411                 goto out_info;
2412         }
2413
2414         v = calloc(nr, sizeof(int));
2415         if (!v) {
2416                 printf("%d/%d: line %d error %d\n",
2417                         procid, opno, __LINE__, errno);
2418                 goto out_offsets;
2419         }
2420         fd = calloc(nr, sizeof(int));
2421         if (!fd) {
2422                 printf("%d/%d: line %d error %d\n",
2423                         procid, opno, __LINE__, errno);
2424                 goto out_v;
2425         }
2426         memset(fd, 0xFF, nr * sizeof(int));
2427
2428         /* Get paths for all files */
2429         for (i = 0; i < nr; i++)
2430                 init_pathname(&fpath[i]);
2431
2432         if (!get_fname(FT_REGm, r, &fpath[0], NULL, NULL, &v[0])) {
2433                 if (v[0])
2434                         printf("%d/%d: deduperange read - no filename\n",
2435                                 procid, opno);
2436                 goto out_pathnames;
2437         }
2438
2439         for (i = 1; i < nr; i++) {
2440                 if (!get_fname(FT_REGm, random(), &fpath[i], NULL, NULL, &v[i])) {
2441                         if (v[i])
2442                                 printf("%d/%d: deduperange write - no filename\n",
2443                                         procid, opno);
2444                         goto out_pathnames;
2445                 }
2446         }
2447
2448         /* Open files */
2449         fd[0] = open_path(&fpath[0], O_RDONLY);
2450         e = fd[0] < 0 ? errno : 0;
2451         check_cwd();
2452         if (fd[0] < 0) {
2453                 if (v[0])
2454                         printf("%d/%d: deduperange read - open %s failed %d\n",
2455                                 procid, opno, fpath[0].path, e);
2456                 goto out_pathnames;
2457         }
2458
2459         for (i = 1; i < nr; i++) {
2460                 fd[i] = open_path(&fpath[i], O_WRONLY);
2461                 e = fd[i] < 0 ? errno : 0;
2462                 check_cwd();
2463                 if (fd[i] < 0) {
2464                         if (v[i])
2465                                 printf("%d/%d: deduperange write - open %s failed %d\n",
2466                                         procid, opno, fpath[i].path, e);
2467                         goto out_fds;
2468                 }
2469         }
2470
2471         /* Get file stats */
2472         if (fstat64(fd[0], &stat[0]) < 0) {
2473                 if (v[0])
2474                         printf("%d/%d: deduperange read - fstat64 %s failed %d\n",
2475                                 procid, opno, fpath[0].path, errno);
2476                 goto out_fds;
2477         }
2478
2479         inode_info(&info[0], INFO_SZ, &stat[0], v[0]);
2480
2481         for (i = 1; i < nr; i++) {
2482                 if (fstat64(fd[i], &stat[i]) < 0) {
2483                         if (v[i])
2484                                 printf("%d/%d: deduperange write - fstat64 %s failed %d\n",
2485                                         procid, opno, fpath[i].path, errno);
2486                         goto out_fds;
2487                 }
2488                 inode_info(&info[i * INFO_SZ], INFO_SZ, &stat[i], v[i]);
2489         }
2490
2491         /* Never try to dedupe more than half of the src file. */
2492         len = (random() % FILELEN_MAX) + 1;
2493         len &= ~(stat[0].st_blksize - 1);
2494         if (len == 0)
2495                 len = stat[0].st_blksize / 2;
2496         if (len > stat[0].st_size / 2)
2497                 len = stat[0].st_size / 2;
2498
2499         /* Calculate offsets */
2500         lr = ((__int64_t)random() << 32) + random();
2501         if (stat[0].st_size == len)
2502                 off[0] = 0;
2503         else
2504                 off[0] = (off64_t)(lr % MIN(stat[0].st_size - len, MAXFSIZE));
2505         off[0] %= maxfsize;
2506         off[0] &= ~(stat[0].st_blksize - 1);
2507
2508         /*
2509          * If srcfile == destfile[i], randomly generate destination ranges
2510          * until we find one that doesn't overlap the source range.
2511          */
2512         for (i = 1; i < nr; i++) {
2513                 int     tries = 0;
2514
2515                 do {
2516                         lr = ((__int64_t)random() << 32) + random();
2517                         if (stat[i].st_size <= len)
2518                                 off[i] = 0;
2519                         else
2520                                 off[i] = (off64_t)(lr % MIN(stat[i].st_size - len, MAXFSIZE));
2521                         off[i] %= maxfsize;
2522                         off[i] &= ~(stat[i].st_blksize - 1);
2523                 } while (stat[0].st_ino == stat[i].st_ino &&
2524                          llabs(off[i] - off[0]) < len &&
2525                          tries++ < 10);
2526         }
2527
2528         /* Clone data blocks */
2529         fdr->src_offset = off[0];
2530         fdr->src_length = len;
2531         fdr->dest_count = nr - 1;
2532         for (i = 1; i < nr; i++) {
2533                 fdr->info[i - 1].dest_fd = fd[i];
2534                 fdr->info[i - 1].dest_offset = off[i];
2535         }
2536
2537         ret = ioctl(fd[0], FIDEDUPERANGE, fdr);
2538         e = ret < 0 ? errno : 0;
2539         if (v[0]) {
2540                 printf("%d/%d: deduperange from %s%s [%lld,%lld]",
2541                         procid, opno,
2542                         fpath[0].path, &info[0], (long long)off[0],
2543                         (long long)len);
2544                 if (ret < 0)
2545                         printf(" error %d", e);
2546                 printf("\n");
2547         }
2548         if (ret < 0)
2549                 goto out_fds;
2550
2551         for (i = 1; i < nr; i++) {
2552                 e = fdr->info[i - 1].status < 0 ? fdr->info[i - 1].status : 0;
2553                 if (v[i]) {
2554                         printf("%d/%d: ...to %s%s [%lld,%lld]",
2555                                 procid, opno,
2556                                 fpath[i].path, &info[i * INFO_SZ],
2557                                 (long long)off[i], (long long)len);
2558                         if (fdr->info[i - 1].status < 0)
2559                                 printf(" error %d", e);
2560                         if (fdr->info[i - 1].status == FILE_DEDUPE_RANGE_SAME)
2561                                 printf(" %llu bytes deduplicated",
2562                                         fdr->info[i - 1].bytes_deduped);
2563                         if (fdr->info[i - 1].status == FILE_DEDUPE_RANGE_DIFFERS)
2564                                 printf(" differed");
2565                         printf("\n");
2566                 }
2567         }
2568
2569 out_fds:
2570         for (i = 0; i < nr; i++)
2571                 if (fd[i] >= 0)
2572                         close(fd[i]);
2573 out_pathnames:
2574         for (i = 0; i < nr; i++)
2575                 free_pathname(&fpath[i]);
2576
2577         free(fd);
2578 out_v:
2579         free(v);
2580 out_offsets:
2581         free(off);
2582 out_info:
2583         free(info);
2584 out_stats:
2585         free(stat);
2586 out_paths:
2587         free(fpath);
2588 out_fdr:
2589         free(fdr);
2590 #endif
2591 }
2592
2593 void
2594 setxattr_f(int opno, long r)
2595 {
2596 #ifdef XFS_XFLAG_EXTSIZE
2597         struct fsxattr  fsx;
2598         int             fd;
2599         int             e;
2600         pathname_t      f;
2601         int             nbits;
2602         uint            p;
2603         int             v;
2604
2605         init_pathname(&f);
2606         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2607                 append_pathname(&f, ".");
2608         fd = open_path(&f, O_RDWR);
2609         e = fd < 0 ? errno : 0;
2610         check_cwd();
2611
2612         /* project ID */
2613         p = (uint)random();
2614         e = MIN(idmodulo, XFS_PROJIDMODULO_MAX);
2615         nbits = (int)(random() % e);
2616         p &= (1 << nbits) - 1;
2617
2618         if ((e = xfsctl(f.path, fd, XFS_IOC_FSGETXATTR, &fsx)) == 0) {
2619                 fsx.fsx_projid = p;
2620                 e = xfsctl(f.path, fd, XFS_IOC_FSSETXATTR, &fsx);
2621         }
2622         if (v)
2623                 printf("%d/%d: setxattr %s %u %d\n", procid, opno, f.path, p, e);
2624         free_pathname(&f);
2625         close(fd);
2626 #endif
2627 }
2628
2629 void
2630 creat_f(int opno, long r)
2631 {
2632         struct fsxattr  a;
2633         int             e;
2634         int             e1;
2635         int             extsize;
2636         pathname_t      f;
2637         int             fd;
2638         fent_t          *fep;
2639         int             id;
2640         int             parid;
2641         int             type;
2642         int             v;
2643         int             v1;
2644
2645         if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
2646                 parid = -1;
2647         else
2648                 parid = fep->id;
2649         init_pathname(&f);
2650         e1 = (random() % 100);
2651         type = rtpct ? ((e1 > rtpct) ? FT_REG : FT_RTF) : FT_REG;
2652 #ifdef NOTYET
2653         if (type == FT_RTF)     /* rt always gets an extsize */
2654                 extsize = (random() % 10) + 1;
2655         else if (e1 < 10)       /* one-in-ten get an extsize */
2656                 extsize = random() % 1024;
2657         else
2658 #endif
2659                 extsize = 0;
2660         e = generate_fname(fep, type, &f, &id, &v);
2661         v |= v1;
2662         if (!e) {
2663                 if (v) {
2664                         (void)fent_to_name(&f, &flist[FT_DIR], fep);
2665                         printf("%d/%d: creat - no filename from %s\n",
2666                                 procid, opno, f.path);
2667                 }
2668                 free_pathname(&f);
2669                 return;
2670         }
2671         fd = creat_path(&f, 0666);
2672         e = fd < 0 ? errno : 0;
2673         e1 = 0;
2674         check_cwd();
2675         if (fd >= 0) {
2676                 if (extsize &&
2677                     xfsctl(f.path, fd, XFS_IOC_FSGETXATTR, &a) >= 0) {
2678                         if (type == FT_RTF) {
2679                                 a.fsx_xflags |= XFS_XFLAG_REALTIME;
2680                                 a.fsx_extsize = extsize *
2681                                                 geom.rtextsize * geom.blocksize;
2682 #ifdef NOTYET
2683                         } else if (extsize) {
2684                                 a.fsx_xflags |= XFS_XFLAG_EXTSIZE;
2685                                 a.fsx_extsize = extsize * geom.blocksize;
2686 #endif
2687                         }
2688                         if (xfsctl(f.path, fd, XFS_IOC_FSSETXATTR, &a) < 0)
2689                                 e1 = errno;
2690                 }
2691                 add_to_flist(type, id, parid);
2692                 close(fd);
2693         }
2694         if (v) {
2695                 printf("%d/%d: creat %s x:%d %d %d\n", procid, opno, f.path,
2696                         extsize ? a.fsx_extsize : 0, e, e1);
2697                 printf("%d/%d: creat add id=%d,parent=%d\n", procid, opno, id, parid);
2698         }
2699         free_pathname(&f);
2700 }
2701
2702 void
2703 dread_f(int opno, long r)
2704 {
2705         __int64_t       align;
2706         char            *buf;
2707         struct dioattr  diob;
2708         int             e;
2709         pathname_t      f;
2710         int             fd;
2711         size_t          len;
2712         __int64_t       lr;
2713         off64_t         off;
2714         struct stat64   stb;
2715         int             v;
2716         char            st[1024];
2717         char            *dio_env;
2718
2719         init_pathname(&f);
2720         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2721                 if (v)
2722                         printf("%d/%d: dread - no filename\n", procid, opno);
2723                 free_pathname(&f);
2724                 return;
2725         }
2726         fd = open_path(&f, O_RDONLY|O_DIRECT);
2727         e = fd < 0 ? errno : 0;
2728         check_cwd();
2729         if (fd < 0) {
2730                 if (v)
2731                         printf("%d/%d: dread - open %s failed %d\n",
2732                                 procid, opno, f.path, e);
2733                 free_pathname(&f);
2734                 return;
2735         }
2736         if (fstat64(fd, &stb) < 0) {
2737                 if (v)
2738                         printf("%d/%d: dread - fstat64 %s failed %d\n",
2739                                procid, opno, f.path, errno);
2740                 free_pathname(&f);
2741                 close(fd);
2742                 return;
2743         }
2744         inode_info(st, sizeof(st), &stb, v);
2745         if (stb.st_size == 0) {
2746                 if (v)
2747                         printf("%d/%d: dread - %s%s zero size\n", procid, opno,
2748                                f.path, st);
2749                 free_pathname(&f);
2750                 close(fd);
2751                 return;
2752         }
2753         if (xfsctl(f.path, fd, XFS_IOC_DIOINFO, &diob) < 0) {
2754                 if (v)
2755                         printf(
2756                         "%d/%d: dread - xfsctl(XFS_IOC_DIOINFO) %s%s return %d,"
2757                         " fallback to stat()\n",
2758                                 procid, opno, f.path, st, errno);
2759                 diob.d_mem = diob.d_miniosz = stb.st_blksize;
2760                 diob.d_maxiosz = INT_MAX & ~(diob.d_miniosz - 1);
2761         }
2762
2763         dio_env = getenv("XFS_DIO_MIN");
2764         if (dio_env)
2765                 diob.d_mem = diob.d_miniosz = atoi(dio_env);
2766
2767         align = (__int64_t)diob.d_miniosz;
2768         lr = ((__int64_t)random() << 32) + random();
2769         off = (off64_t)(lr % stb.st_size);
2770         off -= (off % align);
2771         lseek64(fd, off, SEEK_SET);
2772         len = (random() % FILELEN_MAX) + 1;
2773         len -= (len % align);
2774         if (len <= 0)
2775                 len = align;
2776         else if (len > diob.d_maxiosz) 
2777                 len = diob.d_maxiosz;
2778         buf = memalign(diob.d_mem, len);
2779         e = read(fd, buf, len) < 0 ? errno : 0;
2780         free(buf);
2781         if (v)
2782                 printf("%d/%d: dread %s%s [%lld,%d] %d\n",
2783                        procid, opno, f.path, st, (long long)off, (int)len, e);
2784         free_pathname(&f);
2785         close(fd);
2786 }
2787
2788 void
2789 dwrite_f(int opno, long r)
2790 {
2791         __int64_t       align;
2792         char            *buf;
2793         struct dioattr  diob;
2794         int             e;
2795         pathname_t      f;
2796         int             fd;
2797         size_t          len;
2798         __int64_t       lr;
2799         off64_t         off;
2800         struct stat64   stb;
2801         int             v;
2802         char            st[1024];
2803         char            *dio_env;
2804
2805         init_pathname(&f);
2806         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2807                 if (v)
2808                         printf("%d/%d: dwrite - no filename\n", procid, opno);
2809                 free_pathname(&f);
2810                 return;
2811         }
2812         fd = open_path(&f, O_WRONLY|O_DIRECT);
2813         e = fd < 0 ? errno : 0;
2814         check_cwd();
2815         if (fd < 0) {
2816                 if (v)
2817                         printf("%d/%d: dwrite - open %s failed %d\n",
2818                                 procid, opno, f.path, e);
2819                 free_pathname(&f);
2820                 return;
2821         }
2822         if (fstat64(fd, &stb) < 0) {
2823                 if (v)
2824                         printf("%d/%d: dwrite - fstat64 %s failed %d\n",
2825                                 procid, opno, f.path, errno);
2826                 free_pathname(&f);
2827                 close(fd);
2828                 return;
2829         }
2830         inode_info(st, sizeof(st), &stb, v);
2831         if (xfsctl(f.path, fd, XFS_IOC_DIOINFO, &diob) < 0) {
2832                 if (v)
2833                         printf("%d/%d: dwrite - xfsctl(XFS_IOC_DIOINFO)"
2834                                 " %s%s return %d, fallback to stat()\n",
2835                                procid, opno, f.path, st, errno);
2836                 diob.d_mem = diob.d_miniosz = stb.st_blksize;
2837                 diob.d_maxiosz = INT_MAX & ~(diob.d_miniosz - 1);
2838         }
2839
2840         dio_env = getenv("XFS_DIO_MIN");
2841         if (dio_env)
2842                 diob.d_mem = diob.d_miniosz = atoi(dio_env);
2843
2844         align = (__int64_t)diob.d_miniosz;
2845         lr = ((__int64_t)random() << 32) + random();
2846         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2847         off -= (off % align);
2848         lseek64(fd, off, SEEK_SET);
2849         len = (random() % FILELEN_MAX) + 1;
2850         len -= (len % align);
2851         if (len <= 0)
2852                 len = align;
2853         else if (len > diob.d_maxiosz) 
2854                 len = diob.d_maxiosz;
2855         buf = memalign(diob.d_mem, len);
2856         off %= maxfsize;
2857         lseek64(fd, off, SEEK_SET);
2858         memset(buf, nameseq & 0xff, len);
2859         e = write(fd, buf, len) < 0 ? errno : 0;
2860         free(buf);
2861         if (v)
2862                 printf("%d/%d: dwrite %s%s [%lld,%d] %d\n",
2863                        procid, opno, f.path, st, (long long)off, (int)len, e);
2864         free_pathname(&f);
2865         close(fd);
2866 }
2867
2868
2869 #ifdef HAVE_LINUX_FALLOC_H
2870 struct print_flags falloc_flags [] = {
2871         { FALLOC_FL_KEEP_SIZE, "KEEP_SIZE"},
2872         { FALLOC_FL_PUNCH_HOLE, "PUNCH_HOLE"},
2873         { FALLOC_FL_NO_HIDE_STALE, "NO_HIDE_STALE"},
2874         { FALLOC_FL_COLLAPSE_RANGE, "COLLAPSE_RANGE"},
2875         { FALLOC_FL_ZERO_RANGE, "ZERO_RANGE"},
2876         { FALLOC_FL_INSERT_RANGE, "INSERT_RANGE"},
2877         { -1, NULL}
2878 };
2879
2880 #define translate_falloc_flags(mode)    \
2881         ({translate_flags(mode, "|", falloc_flags);})
2882 #endif
2883
2884 void
2885 do_fallocate(int opno, long r, int mode)
2886 {
2887 #ifdef HAVE_LINUX_FALLOC_H
2888         int             e;
2889         pathname_t      f;
2890         int             fd;
2891         __int64_t       lr;
2892         off64_t         off;
2893         off64_t         len;
2894         struct stat64   stb;
2895         int             v;
2896         char            st[1024];
2897
2898         init_pathname(&f);
2899         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2900                 if (v)
2901                         printf("%d/%d: do_fallocate - no filename\n", procid, opno);
2902                 free_pathname(&f);
2903                 return;
2904         }
2905         fd = open_path(&f, O_RDWR);
2906         if (fd < 0) {
2907                 if (v)
2908                         printf("%d/%d: do_fallocate - open %s failed %d\n",
2909                                 procid, opno, f.path, errno);
2910                 free_pathname(&f);
2911                 return;
2912         }
2913         check_cwd();
2914         if (fstat64(fd, &stb) < 0) {
2915                 if (v)
2916                         printf("%d/%d: do_fallocate - fstat64 %s failed %d\n",
2917                                 procid, opno, f.path, errno);
2918                 free_pathname(&f);
2919                 close(fd);
2920                 return;
2921         }
2922         inode_info(st, sizeof(st), &stb, v);
2923         lr = ((__int64_t)random() << 32) + random();
2924         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2925         off %= maxfsize;
2926         len = (off64_t)(random() % (1024 * 1024));
2927         /*
2928          * Collapse/insert range requires off and len to be block aligned,
2929          * make it more likely to be the case.
2930          */
2931         if ((mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)) &&
2932                 (opno % 2)) {
2933                 off = ((off + stb.st_blksize - 1) & ~(stb.st_blksize - 1));
2934                 len = ((len + stb.st_blksize - 1) & ~(stb.st_blksize - 1));
2935         }
2936         mode |= FALLOC_FL_KEEP_SIZE & random();
2937         e = fallocate(fd, mode, (loff_t)off, (loff_t)len) < 0 ? errno : 0;
2938         if (v)
2939                 printf("%d/%d: fallocate(%s) %s %st %lld %lld %d\n",
2940                        procid, opno, translate_falloc_flags(mode),
2941                        f.path, st, (long long)off, (long long)len, e);
2942         free_pathname(&f);
2943         close(fd);
2944 #endif
2945 }
2946
2947 void
2948 fallocate_f(int opno, long r)
2949 {
2950 #ifdef HAVE_LINUX_FALLOC_H
2951         do_fallocate(opno, r, 0);
2952 #endif
2953 }
2954
2955 void
2956 fdatasync_f(int opno, long r)
2957 {
2958         int             e;
2959         pathname_t      f;
2960         int             fd;
2961         int             v;
2962
2963         init_pathname(&f);
2964         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2965                 if (v)
2966                         printf("%d/%d: fdatasync - no filename\n",
2967                                 procid, opno);
2968                 free_pathname(&f);
2969                 return;
2970         }
2971         fd = open_path(&f, O_WRONLY);
2972         e = fd < 0 ? errno : 0;
2973         check_cwd();
2974         if (fd < 0) {
2975                 if (v)
2976                         printf("%d/%d: fdatasync - open %s failed %d\n",
2977                                 procid, opno, f.path, e);
2978                 free_pathname(&f);
2979                 return;
2980         }
2981         e = fdatasync(fd) < 0 ? errno : 0;
2982         if (v)
2983                 printf("%d/%d: fdatasync %s %d\n", procid, opno, f.path, e);
2984         free_pathname(&f);
2985         close(fd);
2986 }
2987
2988 #ifdef HAVE_LINUX_FIEMAP_H
2989 struct print_flags fiemap_flags[] = {
2990         { FIEMAP_FLAG_SYNC, "SYNC"},
2991         { FIEMAP_FLAG_XATTR, "XATTR"},
2992         { -1, NULL}
2993 };
2994
2995 #define translate_fiemap_flags(mode)    \
2996         ({translate_flags(mode, "|", fiemap_flags);})
2997 #endif
2998
2999 void
3000 fiemap_f(int opno, long r)
3001 {
3002 #ifdef HAVE_LINUX_FIEMAP_H
3003         int             e;
3004         pathname_t      f;
3005         int             fd;
3006         __int64_t       lr;
3007         off64_t         off;
3008         struct stat64   stb;
3009         int             v;
3010         char            st[1024];
3011         int blocks_to_map;
3012         struct fiemap *fiemap;
3013
3014         init_pathname(&f);
3015         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3016                 if (v)
3017                         printf("%d/%d: fiemap - no filename\n", procid, opno);
3018                 free_pathname(&f);
3019                 return;
3020         }
3021         fd = open_path(&f, O_RDWR);
3022         e = fd < 0 ? errno : 0;
3023         check_cwd();
3024         if (fd < 0) {
3025                 if (v)
3026                         printf("%d/%d: fiemap - open %s failed %d\n",
3027                                 procid, opno, f.path, e);
3028                 free_pathname(&f);
3029                 return;
3030         }
3031         if (fstat64(fd, &stb) < 0) {
3032                 if (v)
3033                         printf("%d/%d: fiemap - fstat64 %s failed %d\n",
3034                                 procid, opno, f.path, errno);
3035                 free_pathname(&f);
3036                 close(fd);
3037                 return;
3038         }
3039         inode_info(st, sizeof(st), &stb, v);
3040         blocks_to_map = random() & 0xffff;
3041         fiemap = (struct fiemap *)malloc(sizeof(struct fiemap) +
3042                         (blocks_to_map * sizeof(struct fiemap_extent)));
3043         if (!fiemap) {
3044                 if (v)
3045                         printf("%d/%d: malloc failed \n", procid, opno);
3046                 free_pathname(&f);
3047                 close(fd);
3048                 return;
3049         }
3050         lr = ((__int64_t)random() << 32) + random();
3051         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
3052         off %= maxfsize;
3053         fiemap->fm_flags = random() & (FIEMAP_FLAGS_COMPAT | 0x10000);
3054         fiemap->fm_extent_count = blocks_to_map;
3055         fiemap->fm_mapped_extents = random() & 0xffff;
3056         fiemap->fm_start = off;
3057         fiemap->fm_length = ((__int64_t)random() << 32) + random();
3058
3059         e = ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fiemap);
3060         if (v)
3061                 printf("%d/%d: ioctl(FIEMAP) %s%s %lld %lld (%s) %d\n",
3062                        procid, opno, f.path, st, (long long)fiemap->fm_start,
3063                        (long long) fiemap->fm_length,
3064                        translate_fiemap_flags(fiemap->fm_flags), e);
3065         free(fiemap);
3066         free_pathname(&f);
3067         close(fd);
3068 #endif
3069 }
3070
3071 void
3072 freesp_f(int opno, long r)
3073 {
3074         int             e;
3075         pathname_t      f;
3076         int             fd;
3077         struct xfs_flock64      fl;
3078         __int64_t       lr;
3079         off64_t         off;
3080         struct stat64   stb;
3081         int             v;
3082         char            st[1024];
3083
3084         init_pathname(&f);
3085         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3086                 if (v)
3087                         printf("%d/%d: freesp - no filename\n", procid, opno);
3088                 free_pathname(&f);
3089                 return;
3090         }
3091         fd = open_path(&f, O_RDWR);
3092         e = fd < 0 ? errno : 0;
3093         check_cwd();
3094         if (fd < 0) {
3095                 if (v)
3096                         printf("%d/%d: freesp - open %s failed %d\n",
3097                                 procid, opno, f.path, e);
3098                 free_pathname(&f);
3099                 return;
3100         }
3101         if (fstat64(fd, &stb) < 0) {
3102                 if (v)
3103                         printf("%d/%d: freesp - fstat64 %s failed %d\n",
3104                                 procid, opno, f.path, errno);
3105                 free_pathname(&f);
3106                 close(fd);
3107                 return;
3108         }
3109         inode_info(st, sizeof(st), &stb, v);
3110         lr = ((__int64_t)random() << 32) + random();
3111         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
3112         off %= maxfsize;
3113         fl.l_whence = SEEK_SET;
3114         fl.l_start = off;
3115         fl.l_len = 0;
3116         e = xfsctl(f.path, fd, XFS_IOC_FREESP64, &fl) < 0 ? errno : 0;
3117         if (v)
3118                 printf("%d/%d: xfsctl(XFS_IOC_FREESP64) %s%s %lld 0 %d\n",
3119                        procid, opno, f.path, st, (long long)off, e);
3120         free_pathname(&f);
3121         close(fd);
3122 }
3123
3124 void
3125 fsync_f(int opno, long r)
3126 {
3127         int             e;
3128         pathname_t      f;
3129         int             fd;
3130         int             v;
3131
3132         init_pathname(&f);
3133         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3134                 if (v)
3135                         printf("%d/%d: fsync - no filename\n", procid, opno);
3136                 free_pathname(&f);
3137                 return;
3138         }
3139         fd = open_path(&f, O_WRONLY);
3140         e = fd < 0 ? errno : 0;
3141         check_cwd();
3142         if (fd < 0) {
3143                 if (v)
3144                         printf("%d/%d: fsync - open %s failed %d\n",
3145                                 procid, opno, f.path, e);
3146                 free_pathname(&f);
3147                 return;
3148         }
3149         e = fsync(fd) < 0 ? errno : 0;
3150         if (v)
3151                 printf("%d/%d: fsync %s %d\n", procid, opno, f.path, e);
3152         free_pathname(&f);
3153         close(fd);
3154 }
3155
3156 void
3157 getattr_f(int opno, long r)
3158 {
3159         int             fd;
3160         int             e;
3161         pathname_t      f;
3162         uint            fl;
3163         int             v;
3164
3165         init_pathname(&f);
3166         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
3167                 append_pathname(&f, ".");
3168         fd = open_path(&f, O_RDWR);
3169         e = fd < 0 ? errno : 0;
3170         check_cwd();
3171
3172         e = ioctl(fd, FS_IOC_GETFLAGS, &fl);
3173         if (v)
3174                 printf("%d/%d: getattr %s %u %d\n", procid, opno, f.path, fl, e);
3175         free_pathname(&f);
3176         close(fd);
3177 }
3178
3179 void
3180 getdents_f(int opno, long r)
3181 {
3182         DIR             *dir;
3183         pathname_t      f;
3184         int             v;
3185
3186         init_pathname(&f);
3187         if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
3188                 append_pathname(&f, ".");
3189         dir = opendir_path(&f);
3190         check_cwd();
3191         if (dir == NULL) {
3192                 if (v)
3193                         printf("%d/%d: getdents - can't open %s\n",
3194                                 procid, opno, f.path);
3195                 free_pathname(&f);
3196                 return;
3197         }
3198         while (readdir64(dir) != NULL)
3199                 continue;
3200         if (v)
3201                 printf("%d/%d: getdents %s 0\n", procid, opno, f.path);
3202         free_pathname(&f);
3203         closedir(dir);
3204 }
3205
3206 void
3207 link_f(int opno, long r)
3208 {
3209         int             e;
3210         pathname_t      f;
3211         fent_t          *fep;
3212         flist_t         *flp;
3213         int             id;
3214         pathname_t      l;
3215         int             parid;
3216         int             v;
3217         int             v1;
3218
3219         init_pathname(&f);
3220         if (!get_fname(FT_NOTDIR, r, &f, &flp, NULL, &v1)) {
3221                 if (v1)
3222                         printf("%d/%d: link - no file\n", procid, opno);
3223                 free_pathname(&f);
3224                 return;
3225         }
3226         if (!get_fname(FT_DIRm, random(), NULL, NULL, &fep, &v))
3227                 parid = -1;
3228         else
3229                 parid = fep->id;
3230         v |= v1;
3231         init_pathname(&l);
3232         e = generate_fname(fep, flp - flist, &l, &id, &v1);
3233         v |= v1;
3234         if (!e) {
3235                 if (v) {
3236                         (void)fent_to_name(&l, &flist[FT_DIR], fep);
3237                         printf("%d/%d: link - no filename from %s\n",
3238                                 procid, opno, l.path);
3239                 }
3240                 free_pathname(&l);
3241                 free_pathname(&f);
3242                 return;
3243         }
3244         e = link_path(&f, &l) < 0 ? errno : 0;
3245         check_cwd();
3246         if (e == 0)
3247                 add_to_flist(flp - flist, id, parid);
3248         if (v) {
3249                 printf("%d/%d: link %s %s %d\n", procid, opno, f.path, l.path,
3250                         e);
3251                 printf("%d/%d: link add id=%d,parent=%d\n", procid, opno, id, parid);
3252         }
3253         free_pathname(&l);
3254         free_pathname(&f);
3255 }
3256
3257 void
3258 mkdir_f(int opno, long r)
3259 {
3260         int             e;
3261         pathname_t      f;
3262         fent_t          *fep;
3263         int             id;
3264         int             parid;
3265         int             v;
3266         int             v1;
3267
3268         if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
3269                 parid = -1;
3270         else
3271                 parid = fep->id;
3272         init_pathname(&f);
3273         e = generate_fname(fep, FT_DIR, &f, &id, &v1);
3274         v |= v1;
3275         if (!e) {
3276                 if (v) {
3277                         (void)fent_to_name(&f, &flist[FT_DIR], fep);
3278                         printf("%d/%d: mkdir - no filename from %s\n",
3279                                 procid, opno, f.path);
3280                 }
3281                 free_pathname(&f);
3282                 return;
3283         }
3284         e = mkdir_path(&f, 0777) < 0 ? errno : 0;
3285         check_cwd();
3286         if (e == 0)
3287                 add_to_flist(FT_DIR, id, parid);
3288         if (v) {
3289                 printf("%d/%d: mkdir %s %d\n", procid, opno, f.path, e);
3290                 printf("%d/%d: mkdir add id=%d,parent=%d\n", procid, opno, id, parid);
3291         }
3292         free_pathname(&f);
3293 }
3294
3295 void
3296 mknod_f(int opno, long r)
3297 {
3298         int             e;
3299         pathname_t      f;
3300         fent_t          *fep;
3301         int             id;
3302         int             parid;
3303         int             v;
3304         int             v1;
3305
3306         if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
3307                 parid = -1;
3308         else
3309                 parid = fep->id;
3310         init_pathname(&f);
3311         e = generate_fname(fep, FT_DEV, &f, &id, &v1);
3312         v |= v1;
3313         if (!e) {
3314                 if (v) {
3315                         (void)fent_to_name(&f, &flist[FT_DIR], fep);
3316                         printf("%d/%d: mknod - no filename from %s\n",
3317                                 procid, opno, f.path);
3318                 }
3319                 free_pathname(&f);
3320                 return;
3321         }
3322         e = mknod_path(&f, S_IFCHR|0444, 0) < 0 ? errno : 0;
3323         check_cwd();
3324         if (e == 0)
3325                 add_to_flist(FT_DEV, id, parid);
3326         if (v) {
3327                 printf("%d/%d: mknod %s %d\n", procid, opno, f.path, e);
3328                 printf("%d/%d: mknod add id=%d,parent=%d\n", procid, opno, id, parid);
3329         }
3330         free_pathname(&f);
3331 }
3332
3333 #ifdef HAVE_SYS_MMAN_H
3334 struct print_flags mmap_flags[] = {
3335         { MAP_SHARED, "SHARED"},
3336         { MAP_PRIVATE, "PRIVATE"},
3337         { -1, NULL}
3338 };
3339
3340 #define translate_mmap_flags(flags)       \
3341         ({translate_flags(flags, "|", mmap_flags);})
3342 #endif
3343
3344 void
3345 do_mmap(int opno, long r, int prot)
3346 {
3347 #ifdef HAVE_SYS_MMAN_H
3348         char            *addr;
3349         int             e;
3350         pathname_t      f;
3351         int             fd;
3352         size_t          len;
3353         __int64_t       lr;
3354         off64_t         off;
3355         int             flags;
3356         struct stat64   stb;
3357         int             v;
3358         char            st[1024];
3359         sigjmp_buf      sigbus_jmpbuf;
3360
3361         init_pathname(&f);
3362         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3363                 if (v)
3364                         printf("%d/%d: do_mmap - no filename\n", procid, opno);
3365                 free_pathname(&f);
3366                 return;
3367         }
3368         fd = open_path(&f, O_RDWR);
3369         e = fd < 0 ? errno : 0;
3370         check_cwd();
3371         if (fd < 0) {
3372                 if (v)
3373                         printf("%d/%d: do_mmap - open %s failed %d\n",
3374                                procid, opno, f.path, e);
3375                 free_pathname(&f);
3376                 return;
3377         }
3378         if (fstat64(fd, &stb) < 0) {
3379                 if (v)
3380                         printf("%d/%d: do_mmap - fstat64 %s failed %d\n",
3381                                procid, opno, f.path, errno);
3382                 free_pathname(&f);
3383                 close(fd);
3384                 return;
3385         }
3386         inode_info(st, sizeof(st), &stb, v);
3387         if (stb.st_size == 0) {
3388                 if (v)
3389                         printf("%d/%d: do_mmap - %s%s zero size\n", procid, opno,
3390                                f.path, st);
3391                 free_pathname(&f);
3392                 close(fd);
3393                 return;
3394         }
3395
3396         lr = ((__int64_t)random() << 32) + random();
3397         off = (off64_t)(lr % stb.st_size);
3398         off &= (off64_t)(~(sysconf(_SC_PAGE_SIZE) - 1));
3399         len = (size_t)(random() % MIN(stb.st_size - off, FILELEN_MAX)) + 1;
3400
3401         flags = (random() % 2) ? MAP_SHARED : MAP_PRIVATE;
3402         addr = mmap(NULL, len, prot, flags, fd, off);
3403         e = (addr == MAP_FAILED) ? errno : 0;
3404         if (e) {
3405                 if (v)
3406                         printf("%d/%d: do_mmap - mmap failed %s%s [%lld,%d,%s] %d\n",
3407                                procid, opno, f.path, st, (long long)off,
3408                                (int)len, translate_mmap_flags(flags), e);
3409                 free_pathname(&f);
3410                 close(fd);
3411                 return;
3412         }
3413
3414         if (prot & PROT_WRITE) {
3415                 if ((e = sigsetjmp(sigbus_jmpbuf, 1)) == 0) {
3416                         sigbus_jmp = &sigbus_jmpbuf;
3417                         memset(addr, nameseq & 0xff, len);
3418                 }
3419         } else {
3420                 char *buf;
3421                 if ((buf = malloc(len)) != NULL) {
3422                         memcpy(buf, addr, len);
3423                         free(buf);
3424                 }
3425         }
3426         munmap(addr, len);
3427         /* set NULL to stop other functions from doing siglongjmp */
3428         sigbus_jmp = NULL;
3429
3430         if (v)
3431                 printf("%d/%d: %s %s%s [%lld,%d,%s] %s\n",
3432                        procid, opno, (prot & PROT_WRITE) ? "mwrite" : "mread",
3433                        f.path, st, (long long)off, (int)len,
3434                        translate_mmap_flags(flags),
3435                        (e == 0) ? "0" : "Bus error");
3436
3437         free_pathname(&f);
3438         close(fd);
3439 #endif
3440 }
3441
3442 void
3443 mread_f(int opno, long r)
3444 {
3445 #ifdef HAVE_SYS_MMAN_H
3446         do_mmap(opno, r, PROT_READ);
3447 #endif
3448 }
3449
3450 void
3451 mwrite_f(int opno, long r)
3452 {
3453 #ifdef HAVE_SYS_MMAN_H
3454         do_mmap(opno, r, PROT_WRITE);
3455 #endif
3456 }
3457
3458 void
3459 punch_f(int opno, long r)
3460 {
3461 #ifdef HAVE_LINUX_FALLOC_H
3462         do_fallocate(opno, r, FALLOC_FL_PUNCH_HOLE);
3463 #endif
3464 }
3465
3466 void
3467 zero_f(int opno, long r)
3468 {
3469 #ifdef HAVE_LINUX_FALLOC_H
3470         do_fallocate(opno, r, FALLOC_FL_ZERO_RANGE);
3471 #endif
3472 }
3473
3474 void
3475 collapse_f(int opno, long r)
3476 {
3477 #ifdef HAVE_LINUX_FALLOC_H
3478         do_fallocate(opno, r, FALLOC_FL_COLLAPSE_RANGE);
3479 #endif
3480 }
3481
3482 void
3483 insert_f(int opno, long r)
3484 {
3485 #ifdef HAVE_LINUX_FALLOC_H
3486         do_fallocate(opno, r, FALLOC_FL_INSERT_RANGE);
3487 #endif
3488 }
3489
3490 void
3491 read_f(int opno, long r)
3492 {
3493         char            *buf;
3494         int             e;
3495         pathname_t      f;
3496         int             fd;
3497         size_t          len;
3498         __int64_t       lr;
3499         off64_t         off;
3500         struct stat64   stb;
3501         int             v;
3502         char            st[1024];
3503
3504         init_pathname(&f);
3505         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3506                 if (v)
3507                         printf("%d/%d: read - no filename\n", procid, opno);
3508                 free_pathname(&f);
3509                 return;
3510         }
3511         fd = open_path(&f, O_RDONLY);
3512         e = fd < 0 ? errno : 0;
3513         check_cwd();
3514         if (fd < 0) {
3515                 if (v)
3516                         printf("%d/%d: read - open %s failed %d\n",
3517                                 procid, opno, f.path, e);
3518                 free_pathname(&f);
3519                 return;
3520         }
3521         if (fstat64(fd, &stb) < 0) {
3522                 if (v)
3523                         printf("%d/%d: read - fstat64 %s failed %d\n",
3524                                 procid, opno, f.path, errno);
3525                 free_pathname(&f);
3526                 close(fd);
3527                 return;
3528         }
3529         inode_info(st, sizeof(st), &stb, v);
3530         if (stb.st_size == 0) {
3531                 if (v)
3532                         printf("%d/%d: read - %s%s zero size\n", procid, opno,
3533                                f.path, st);
3534                 free_pathname(&f);
3535                 close(fd);
3536                 return;
3537         }
3538         lr = ((__int64_t)random() << 32) + random();
3539         off = (off64_t)(lr % stb.st_size);
3540         lseek64(fd, off, SEEK_SET);
3541         len = (random() % FILELEN_MAX) + 1;
3542         buf = malloc(len);
3543         e = read(fd, buf, len) < 0 ? errno : 0;
3544         free(buf);
3545         if (v)
3546                 printf("%d/%d: read %s%s [%lld,%d] %d\n",
3547                        procid, opno, f.path, st, (long long)off, (int)len, e);
3548         free_pathname(&f);
3549         close(fd);
3550 }
3551
3552 void
3553 readlink_f(int opno, long r)
3554 {
3555         char            buf[PATH_MAX];
3556         int             e;
3557         pathname_t      f;
3558         int             v;
3559
3560         init_pathname(&f);
3561         if (!get_fname(FT_SYMm, r, &f, NULL, NULL, &v)) {
3562                 if (v)
3563                         printf("%d/%d: readlink - no filename\n", procid, opno);
3564                 free_pathname(&f);
3565                 return;
3566         }
3567         e = readlink_path(&f, buf, PATH_MAX) < 0 ? errno : 0;
3568         check_cwd();
3569         if (v)
3570                 printf("%d/%d: readlink %s %d\n", procid, opno, f.path, e);
3571         free_pathname(&f);
3572 }
3573
3574 void
3575 readv_f(int opno, long r)
3576 {
3577         char            *buf;
3578         int             e;
3579         pathname_t      f;
3580         int             fd;
3581         size_t          len;
3582         __int64_t       lr;
3583         off64_t         off;
3584         struct stat64   stb;
3585         int             v;
3586         char            st[1024];
3587         struct iovec    *iov = NULL;
3588         int             iovcnt;
3589         size_t          iovb;
3590         size_t          iovl;
3591         int             i;
3592
3593         init_pathname(&f);
3594         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3595                 if (v)
3596                         printf("%d/%d: readv - no filename\n", procid, opno);
3597                 free_pathname(&f);
3598                 return;
3599         }
3600         fd = open_path(&f, O_RDONLY);
3601         e = fd < 0 ? errno : 0;
3602         check_cwd();
3603         if (fd < 0) {
3604                 if (v)
3605                         printf("%d/%d: readv - open %s failed %d\n",
3606                                 procid, opno, f.path, e);
3607                 free_pathname(&f);
3608                 return;
3609         }
3610         if (fstat64(fd, &stb) < 0) {
3611                 if (v)
3612                         printf("%d/%d: readv - fstat64 %s failed %d\n",
3613                                 procid, opno, f.path, errno);
3614                 free_pathname(&f);
3615                 close(fd);
3616                 return;
3617         }
3618         inode_info(st, sizeof(st), &stb, v);
3619         if (stb.st_size == 0) {
3620                 if (v)
3621                         printf("%d/%d: readv - %s%s zero size\n", procid, opno,
3622                                f.path, st);
3623                 free_pathname(&f);
3624                 close(fd);
3625                 return;
3626         }
3627         lr = ((__int64_t)random() << 32) + random();
3628         off = (off64_t)(lr % stb.st_size);
3629         lseek64(fd, off, SEEK_SET);
3630         len = (random() % FILELEN_MAX) + 1;
3631         buf = malloc(len);
3632
3633         iovcnt = (random() % MIN(len, IOV_MAX)) + 1;
3634         iov = calloc(iovcnt, sizeof(struct iovec));
3635         iovl = len / iovcnt;
3636         iovb = 0;
3637         for (i=0; i<iovcnt; i++) {
3638                 (iov + i)->iov_base = (buf + iovb);
3639                 (iov + i)->iov_len  = iovl;
3640                 iovb += iovl;
3641         }
3642
3643         e = readv(fd, iov, iovcnt) < 0 ? errno : 0;
3644         free(buf);
3645         if (v)
3646                 printf("%d/%d: readv %s%s [%lld,%d,%d] %d\n",
3647                        procid, opno, f.path, st, (long long)off, (int)iovl,
3648                        iovcnt, e);
3649         free_pathname(&f);
3650         close(fd);
3651 }
3652
3653 void
3654 rename_f(int opno, long r)
3655 {
3656         fent_t          *dfep;
3657         int             e;
3658         pathname_t      f;
3659         fent_t          *fep;
3660         flist_t         *flp;
3661         int             id;
3662         pathname_t      newf;
3663         int             oldid;
3664         int             parid;
3665         int             v;
3666         int             v1;
3667
3668         /* get an existing path for the source of the rename */
3669         init_pathname(&f);
3670         if (!get_fname(FT_ANYm, r, &f, &flp, &fep, &v1)) {
3671                 if (v1)
3672                         printf("%d/%d: rename - no filename\n", procid, opno);
3673                 free_pathname(&f);
3674                 return;
3675         }
3676
3677         /* get an existing directory for the destination parent directory name */
3678         if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
3679                 parid = -1;
3680         else
3681                 parid = dfep->id;
3682         v |= v1;
3683
3684         /* generate a new path using an existing parent directory in name */
3685         init_pathname(&newf);
3686         e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
3687         v |= v1;
3688         if (!e) {
3689                 if (v) {
3690                         (void)fent_to_name(&f, &flist[FT_DIR], dfep);
3691                         printf("%d/%d: rename - no filename from %s\n",
3692                                 procid, opno, f.path);
3693                 }
3694                 free_pathname(&newf);
3695                 free_pathname(&f);
3696                 return;
3697         }
3698         e = rename_path(&f, &newf) < 0 ? errno : 0;
3699         check_cwd();
3700         if (e == 0) {
3701                 if (flp - flist == FT_DIR) {
3702                         oldid = fep->id;
3703                         fix_parent(oldid, id);
3704                 }
3705                 del_from_flist(flp - flist, fep - flp->fents);
3706                 add_to_flist(flp - flist, id, parid);
3707         }
3708         if (v) {
3709                 printf("%d/%d: rename %s to %s %d\n", procid, opno, f.path,
3710                         newf.path, e);
3711                 if (e == 0) {
3712                         printf("%d/%d: rename del entry: id=%d,parent=%d\n",
3713                                 procid, opno, fep->id, fep->parent);
3714                         printf("%d/%d: rename add entry: id=%d,parent=%d\n",
3715                                 procid, opno, id, parid);
3716                 }
3717         }
3718         free_pathname(&newf);
3719         free_pathname(&f);
3720 }
3721
3722 void
3723 resvsp_f(int opno, long r)
3724 {
3725         int             e;
3726         pathname_t      f;
3727         int             fd;
3728         struct xfs_flock64      fl;
3729         __int64_t       lr;
3730         off64_t         off;
3731         struct stat64   stb;
3732         int             v;
3733         char            st[1024];
3734
3735         init_pathname(&f);
3736         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3737                 if (v)
3738                         printf("%d/%d: resvsp - no filename\n", procid, opno);
3739                 free_pathname(&f);
3740                 return;
3741         }
3742         fd = open_path(&f, O_RDWR);
3743         e = fd < 0 ? errno : 0;
3744         check_cwd();
3745         if (fd < 0) {
3746                 if (v)
3747                         printf("%d/%d: resvsp - open %s failed %d\n",
3748                                 procid, opno, f.path, e);
3749                 free_pathname(&f);
3750                 return;
3751         }
3752         if (fstat64(fd, &stb) < 0) {
3753                 if (v)
3754                         printf("%d/%d: resvsp - fstat64 %s failed %d\n",
3755                                 procid, opno, f.path, errno);
3756                 free_pathname(&f);
3757                 close(fd);
3758                 return;
3759         }
3760         inode_info(st, sizeof(st), &stb, v);
3761         lr = ((__int64_t)random() << 32) + random();
3762         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
3763         off %= maxfsize;
3764         fl.l_whence = SEEK_SET;
3765         fl.l_start = off;
3766         fl.l_len = (off64_t)(random() % (1024 * 1024));
3767         e = xfsctl(f.path, fd, XFS_IOC_RESVSP64, &fl) < 0 ? errno : 0;
3768         if (v)
3769                 printf("%d/%d: xfsctl(XFS_IOC_RESVSP64) %s%s %lld %lld %d\n",
3770                        procid, opno, f.path, st,
3771                         (long long)off, (long long)fl.l_len, e);
3772         free_pathname(&f);
3773         close(fd);
3774 }
3775
3776 void
3777 rmdir_f(int opno, long r)
3778 {
3779         int             e;
3780         pathname_t      f;
3781         fent_t          *fep;
3782         int             v;
3783
3784         init_pathname(&f);
3785         if (!get_fname(FT_DIRm, r, &f, NULL, &fep, &v)) {
3786                 if (v)
3787                         printf("%d/%d: rmdir - no directory\n", procid, opno);
3788                 free_pathname(&f);
3789                 return;
3790         }
3791         e = rmdir_path(&f) < 0 ? errno : 0;
3792         check_cwd();
3793         if (e == 0)
3794                 del_from_flist(FT_DIR, fep - flist[FT_DIR].fents);
3795         if (v) {
3796                 printf("%d/%d: rmdir %s %d\n", procid, opno, f.path, e);
3797                 if (e == 0)
3798                         printf("%d/%d: rmdir del entry: id=%d,parent=%d\n",
3799                                 procid, opno, fep->id, fep->parent);
3800         }
3801         free_pathname(&f);
3802 }
3803
3804 void
3805 setattr_f(int opno, long r)
3806 {
3807         int             fd;
3808         int             e;
3809         pathname_t      f;
3810         uint            fl;
3811         int             v;
3812
3813         init_pathname(&f);
3814         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
3815                 append_pathname(&f, ".");
3816         fd = open_path(&f, O_RDWR);
3817         e = fd < 0 ? errno : 0;
3818         check_cwd();
3819
3820         fl = attr_mask & (uint)random();
3821         e = ioctl(fd, FS_IOC_SETFLAGS, &fl);
3822         if (v)
3823                 printf("%d/%d: setattr %s %x %d\n", procid, opno, f.path, fl, e);
3824         free_pathname(&f);
3825         close(fd);
3826 }
3827
3828 void
3829 stat_f(int opno, long r)
3830 {
3831         int             e;
3832         pathname_t      f;
3833         struct stat64   stb;
3834         int             v;
3835
3836         init_pathname(&f);
3837         if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v)) {
3838                 if (v)
3839                         printf("%d/%d: stat - no entries\n", procid, opno);
3840                 free_pathname(&f);
3841                 return;
3842         }
3843         e = lstat64_path(&f, &stb) < 0 ? errno : 0;
3844         check_cwd();
3845         if (v)
3846                 printf("%d/%d: stat %s %d\n", procid, opno, f.path, e);
3847         free_pathname(&f);
3848 }
3849
3850 void
3851 symlink_f(int opno, long r)
3852 {
3853         int             e;
3854         pathname_t      f;
3855         fent_t          *fep;
3856         int             i;
3857         int             id;
3858         int             len;
3859         int             parid;
3860         int             v;
3861         int             v1;
3862         char            *val;
3863
3864         if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
3865                 parid = -1;
3866         else
3867                 parid = fep->id;
3868         init_pathname(&f);
3869         e = generate_fname(fep, FT_SYM, &f, &id, &v1);
3870         v |= v1;
3871         if (!e) {
3872                 if (v) {
3873                         (void)fent_to_name(&f, &flist[FT_DIR], fep);
3874                         printf("%d/%d: symlink - no filename from %s\n",
3875                                 procid, opno, f.path);
3876                 }
3877                 free_pathname(&f);
3878                 return;
3879         }
3880         len = (int)(random() % PATH_MAX);
3881         val = malloc(len + 1);
3882         if (len)
3883                 memset(val, 'x', len);
3884         val[len] = '\0';
3885         for (i = 10; i < len - 1; i += 10)
3886                 val[i] = '/';
3887         e = symlink_path(val, &f) < 0 ? errno : 0;
3888         check_cwd();
3889         if (e == 0)
3890                 add_to_flist(FT_SYM, id, parid);
3891         free(val);
3892         if (v) {
3893                 printf("%d/%d: symlink %s %d\n", procid, opno, f.path, e);
3894                 printf("%d/%d: symlink add id=%d,parent=%d\n", procid, opno, id, parid);
3895         }
3896         free_pathname(&f);
3897 }
3898
3899 /* ARGSUSED */
3900 void
3901 sync_f(int opno, long r)
3902 {
3903         sync();
3904         if (verbose)
3905                 printf("%d/%d: sync\n", procid, opno);
3906 }
3907
3908 void
3909 truncate_f(int opno, long r)
3910 {
3911         int             e;
3912         pathname_t      f;
3913         __int64_t       lr;
3914         off64_t         off;
3915         struct stat64   stb;
3916         int             v;
3917         char            st[1024];
3918
3919         init_pathname(&f);
3920         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3921                 if (v)
3922                         printf("%d/%d: truncate - no filename\n", procid, opno);
3923                 free_pathname(&f);
3924                 return;
3925         }
3926         e = stat64_path(&f, &stb) < 0 ? errno : 0;
3927         check_cwd();
3928         if (e > 0) {
3929                 if (v)
3930                         printf("%d/%d: truncate - stat64 %s failed %d\n",
3931                                 procid, opno, f.path, e);
3932                 free_pathname(&f);
3933                 return;
3934         }
3935         inode_info(st, sizeof(st), &stb, v);
3936         lr = ((__int64_t)random() << 32) + random();
3937         off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
3938         off %= maxfsize;
3939         e = truncate64_path(&f, off) < 0 ? errno : 0;
3940         check_cwd();
3941         if (v)
3942                 printf("%d/%d: truncate %s%s %lld %d\n", procid, opno, f.path,
3943                        st, (long long)off, e);
3944         free_pathname(&f);
3945 }
3946
3947 void
3948 unlink_f(int opno, long r)
3949 {
3950         int             e;
3951         pathname_t      f;
3952         fent_t          *fep;
3953         flist_t         *flp;
3954         int             v;
3955
3956         init_pathname(&f);
3957         if (!get_fname(FT_NOTDIR, r, &f, &flp, &fep, &v)) {
3958                 if (v)
3959                         printf("%d/%d: unlink - no file\n", procid, opno);
3960                 free_pathname(&f);
3961                 return;
3962         }
3963         e = unlink_path(&f) < 0 ? errno : 0;
3964         check_cwd();
3965         if (e == 0)
3966                 del_from_flist(flp - flist, fep - flp->fents);
3967         if (v) {
3968                 printf("%d/%d: unlink %s %d\n", procid, opno, f.path, e);
3969                 if (e == 0)
3970                         printf("%d/%d: unlink del entry: id=%d,parent=%d\n",
3971                                 procid, opno, fep->id, fep->parent);
3972         }
3973         free_pathname(&f);
3974 }
3975
3976 void
3977 unresvsp_f(int opno, long r)
3978 {
3979         int             e;
3980         pathname_t      f;
3981         int             fd;
3982         struct xfs_flock64      fl;
3983         __int64_t       lr;
3984         off64_t         off;
3985         struct stat64   stb;
3986         int             v;
3987         char            st[1024];
3988
3989         init_pathname(&f);
3990         if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
3991                 if (v)
3992                         printf("%d/%d: unresvsp - no filename\n", procid, opno);