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