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