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. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 59 21 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 31 */ 32 /* 33 * $DragonFly: src/test/stress/fsstress/fsstress.c,v 1.2 2008/06/05 18:06:33 swildner Exp $ 34 */ 35 36 #include "global.h" 37 38 #define XFS_ERRTAG_MAX 17 39 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; 79 80 typedef void (*opfnc_t)(int, long); 81 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; 90 91 typedef struct fent { 92 int id; 93 int parent; 94 } fent_t; 95 96 typedef struct flist { 97 int nfiles; 98 int nslots; 99 int tag; 100 fent_t *fents; 101 } flist_t; 102 103 typedef struct pathname { 104 int len; 105 char *path; 106 } pathname_t; 107 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) 122 123 #define FLIST_SLOT_INCR 16 124 #define NDCACHE 64 125 126 #define MAXFSIZE ((1ULL << 63) - 1ULL) 127 #define MAXFSIZE32 ((1ULL << 40) - 1ULL) 128 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); 157 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; 196 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 }, 203 }; 204 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 233 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); 279 280 int main(int argc, char **argv) 281 { 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 298 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); 321 } 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; 366 } 367 } 368 369 if (no_xfs && errtag) { 370 fprintf(stderr, "error injection only works on XFS\n"); 371 exit(1); 372 } 373 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; 379 } 380 } 381 382 if (!dirname) { 383 /* no directory specified */ 384 if (!nousage) usage(); 385 exit(1); 386 } 387 388 (void)mkdir(dirname, 0777); 389 if (chdir(dirname) < 0) { 390 perror(dirname); 391 exit(1); 392 } 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); 406 } 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; 415 } 416 if (errtag != 0) { 417 if (errrange == 0) { 418 if (errtag <= 0) { 419 srandom(seed); 420 j = random() % 100; 421 422 for (i = 0; i < j; i++) 423 (void) random(); 424 425 errtag = (random() % (XFS_ERRTAG_MAX-1)) + 1; 426 } 427 } else { 428 srandom(seed); 429 j = random() % 100; 430 431 for (i = 0; i < j; i++) 432 (void) random(); 433 434 errtag += (random() % (XFS_ERRTAG_MAX - errtag)); 435 } 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); 445 } 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; 459 } 460 } 461 while (wait(&stat) > 0) 462 continue; 463 } 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); 473 } 474 close(fd); 475 } 476 #endif 477 478 return 0; 479 } 480 481 void 482 add_to_flist(int ft, int id, int parent) 483 { 484 fent_t *fep; 485 flist_t *ftp; 486 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)); 491 } 492 fep = &ftp->fents[ftp->nfiles++]; 493 fep->id = id; 494 fep->parent = parent; 495 } 496 497 void 498 append_pathname(pathname_t *name, char *str) 499 { 500 int len; 501 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 */ 509 } 510 #endif 511 name->path = realloc(name->path, name->len + 1 + len); 512 strcpy(&name->path[name->len], str); 513 name->len += len; 514 } 515 516 #ifndef NO_XFS 517 int 518 attr_list_path(pathname_t *name, char *buffer, const int buffersize, int flags, 519 attrlist_cursor_t *cursor) 520 { 521 char buf[MAXNAMELEN]; 522 pathname_t newname; 523 int rval; 524 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(".."); 533 } 534 free_pathname(&newname); 535 return rval; 536 } 537 538 int 539 attr_remove_path(pathname_t *name, const char *attrname, int flags) 540 { 541 char buf[MAXNAMELEN]; 542 pathname_t newname; 543 int rval; 544 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(".."); 552 } 553 free_pathname(&newname); 554 return rval; 555 } 556 557 int 558 attr_set_path(pathname_t *name, const char *attrname, const char *attrvalue, 559 const int valuelength, int flags) 560 { 561 char buf[MAXNAMELEN]; 562 pathname_t newname; 563 int rval; 564 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(".."); 573 } 574 free_pathname(&newname); 575 return rval; 576 } 577 #endif 578 579 void 580 check_cwd(void) 581 { 582 #ifdef DEBUG 583 struct stat64 statbuf; 584 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 592 } 593 594 int 595 creat_path(pathname_t *name, mode_t mode) 596 { 597 char buf[MAXNAMELEN]; 598 pathname_t newname; 599 int rval; 600 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(".."); 608 } 609 free_pathname(&newname); 610 return rval; 611 } 612 613 void 614 dcache_enter(int dirid, int slot) 615 { 616 dcache[dirid % NDCACHE] = slot; 617 } 618 619 void 620 dcache_init(void) 621 { 622 int i; 623 624 for (i = 0; i < NDCACHE; i++) 625 dcache[i] = -1; 626 } 627 628 fent_t * 629 dcache_lookup(int dirid) 630 { 631 fent_t *fep; 632 int i; 633 634 i = dcache[dirid % NDCACHE]; 635 if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid) 636 return fep; 637 return NULL; 638 } 639 640 void 641 dcache_purge(int dirid) 642 { 643 int *dcp; 644 645 dcp = &dcache[dirid % NDCACHE]; 646 if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid) 647 *dcp = -1; 648 } 649 650 void 651 del_from_flist(int ft, int slot) 652 { 653 flist_t *ftp; 654 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--; 664 } 665 666 fent_t * 667 dirid_to_fent(int dirid) 668 { 669 fent_t *efep; 670 fent_t *fep; 671 flist_t *flp; 672 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; 680 } 681 } 682 return NULL; 683 } 684 685 void 686 doproc(void) 687 { 688 struct stat64 statbuf; 689 char buf[10]; 690 int opno; 691 int rval; 692 opdesc_t *p; 693 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); 699 } 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(); 709 710 711 p->func(opno, random()); 712 /* 713 * test for forced shutdown by stat'ing the test 714 * directory. If this stat returns EIO, assume 715 * the forced shutdown happened. 716 */ 717 if (errtag != 0 && opno % 100 == 0) { 718 rval = stat64(".", &statbuf); 719 if (rval == EIO) { 720 fprintf(stderr, "Detected EIO\n"); 721 return; 722 } 723 } 724 } 725 } 726 727 void 728 fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep) 729 { 730 char buf[MAXNAMELEN]; 731 int i; 732 fent_t *pfep; 733 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, "/"); 740 } 741 i = sprintf(buf, "%c%x", flp->tag, fep->id); 742 namerandpad(fep->id, buf, i); 743 append_pathname(name, buf); 744 } 745 746 void 747 fix_parent(int oldid, int newid) 748 { 749 fent_t *fep; 750 flist_t *flp; 751 int i; 752 int j; 753 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; 758 } 759 } 760 } 761 762 void 763 free_pathname(pathname_t *name) 764 { 765 if (name->path) { 766 free(name->path); 767 name->path = NULL; 768 name->len = 0; 769 } 770 } 771 772 int 773 generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v) 774 { 775 char buf[MAXNAMELEN]; 776 flist_t *flp; 777 int id; 778 int j; 779 int len; 780 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, "/"); 787 } 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; 795 } 796 } 797 return 1; 798 } 799 800 int 801 get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp, 802 int *v) 803 { 804 int c; 805 fent_t *fep; 806 flist_t *flp; 807 int i; 808 int j; 809 int x; 810 811 for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) { 812 if (which & (1 << i)) 813 c += flp->nfiles; 814 } 815 if (c == 0) { 816 if (flpp) 817 *flpp = NULL; 818 if (fepp) 819 *fepp = NULL; 820 *v = verbose; 821 return 0; 822 } 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; 839 } 840 } 841 return 1; 842 } 843 c += flp->nfiles; 844 } 845 } 846 #ifdef DEBUG 847 fprintf(stderr, "fsstress: get_fname failure\n"); 848 abort(); 849 #endif 850 return -1; 851 /* NOTREACHED */ 852 } 853 854 void 855 init_pathname(pathname_t *name) 856 { 857 name->len = 0; 858 name->path = NULL; 859 } 860 861 int 862 lchown_path(pathname_t *name, uid_t owner, gid_t group) 863 { 864 char buf[MAXNAMELEN]; 865 pathname_t newname; 866 int rval; 867 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(".."); 875 } 876 free_pathname(&newname); 877 return rval; 878 } 879 880 int 881 link_path(pathname_t *name1, pathname_t *name2) 882 { 883 char buf1[MAXNAMELEN]; 884 char buf2[MAXNAMELEN]; 885 int down1; 886 pathname_t newname1; 887 pathname_t newname2; 888 int rval; 889 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(".."); 899 } 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(".."); 919 } 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(".."); 927 } 928 } 929 } 930 free_pathname(&newname1); 931 free_pathname(&newname2); 932 return rval; 933 } 934 935 int 936 lstat64_path(pathname_t *name, struct stat64 *sbuf) 937 { 938 char buf[MAXNAMELEN]; 939 pathname_t newname; 940 int rval; 941 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(".."); 949 } 950 free_pathname(&newname); 951 return rval; 952 } 953 954 void 955 make_freq_table(void) 956 { 957 int f; 958 int i; 959 opdesc_t *p; 960 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; 968 } 969 } 970 971 int 972 mkdir_path(pathname_t *name, mode_t mode) 973 { 974 char buf[MAXNAMELEN]; 975 pathname_t newname; 976 int rval; 977 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(".."); 985 } 986 free_pathname(&newname); 987 return rval; 988 } 989 990 int 991 mknod_path(pathname_t *name, mode_t mode, dev_t dev) 992 { 993 char buf[MAXNAMELEN]; 994 pathname_t newname; 995 int rval; 996 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(".."); 1004 } 1005 free_pathname(&newname); 1006 return rval; 1007 } 1008 1009 void 1010 namerandpad(int id, char *buf, int i) 1011 { 1012 int bucket; 1013 static int buckets[] = 1014 { 2, 4, 8, 16, 32, 64, 128, MAXNAMELEN - 1 }; 1015 int padlen; 1016 int padmod; 1017 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'; 1028 } 1029 } 1030 1031 int 1032 open_path(pathname_t *name, int oflag) 1033 { 1034 char buf[MAXNAMELEN]; 1035 pathname_t newname; 1036 int rval; 1037 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(".."); 1045 } 1046 free_pathname(&newname); 1047 return rval; 1048 } 1049 1050 DIR * 1051 opendir_path(pathname_t *name) 1052 { 1053 char buf[MAXNAMELEN]; 1054 pathname_t newname; 1055 DIR *rval; 1056 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(".."); 1064 } 1065 free_pathname(&newname); 1066 return rval; 1067 } 1068 1069 void 1070 process_freq(char *arg) 1071 { 1072 opdesc_t *p; 1073 char *s; 1074 1075 s = strchr(arg, '='); 1076 if (s == NULL) { 1077 fprintf(stderr, "bad argument '%s'\n", arg); 1078 exit(1); 1079 } 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; 1085 } 1086 } 1087 fprintf(stderr, "can't find op type %s for -f\n", arg); 1088 exit(1); 1089 } 1090 1091 int 1092 readlink_path(pathname_t *name, char *lbuf, size_t lbufsiz) 1093 { 1094 char buf[MAXNAMELEN]; 1095 pathname_t newname; 1096 int rval; 1097 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(".."); 1105 } 1106 free_pathname(&newname); 1107 return rval; 1108 } 1109 1110 int 1111 rename_path(pathname_t *name1, pathname_t *name2) 1112 { 1113 char buf1[MAXNAMELEN]; 1114 char buf2[MAXNAMELEN]; 1115 int down1; 1116 pathname_t newname1; 1117 pathname_t newname2; 1118 int rval; 1119 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(".."); 1129 } 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(".."); 1149 } 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(".."); 1157 } 1158 } 1159 } 1160 free_pathname(&newname1); 1161 free_pathname(&newname2); 1162 return rval; 1163 } 1164 1165 int 1166 rmdir_path(pathname_t *name) 1167 { 1168 char buf[MAXNAMELEN]; 1169 pathname_t newname; 1170 int rval; 1171 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(".."); 1179 } 1180 free_pathname(&newname); 1181 return rval; 1182 } 1183 1184 void 1185 separate_pathname(pathname_t *name, char *buf, pathname_t *newname) 1186 { 1187 char *slash; 1188 1189 init_pathname(newname); 1190 slash = strchr(name->path, '/'); 1191 if (slash == NULL) { 1192 buf[0] = '\0'; 1193 return; 1194 } 1195 *slash = '\0'; 1196 strcpy(buf, name->path); 1197 *slash = '/'; 1198 append_pathname(newname, slash + 1); 1199 } 1200 1201 #define WIDTH 80 1202 1203 void 1204 show_ops(int flag, char *lead_str) 1205 { 1206 opdesc_t *p; 1207 1208 if (flag<0) { 1209 /* print in list form */ 1210 int x = WIDTH; 1211 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); 1216 } 1217 printf("\n"); 1218 } else { 1219 int f; 1220 for (f = 0, p = ops; p < ops_end; p++) 1221 f += p->freq; 1222 1223 if (f == 0) 1224 flag = 1; 1225 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"); 1233 } 1234 } 1235 } 1236 } 1237 1238 int 1239 stat64_path(pathname_t *name, struct stat64 *sbuf) 1240 { 1241 char buf[MAXNAMELEN]; 1242 pathname_t newname; 1243 int rval; 1244 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(".."); 1252 } 1253 free_pathname(&newname); 1254 return rval; 1255 } 1256 1257 int 1258 symlink_path(const char *name1, pathname_t *name) 1259 { 1260 char buf[MAXNAMELEN]; 1261 pathname_t newname; 1262 int rval; 1263 1264 if (!strcmp(name1, name->path)) { 1265 printf("yikes! %s %s\n", name1, name->path); 1266 return 0; 1267 } 1268 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(".."); 1276 } 1277 free_pathname(&newname); 1278 return rval; 1279 } 1280 1281 int 1282 truncate64_path(pathname_t *name, off64_t length) 1283 { 1284 char buf[MAXNAMELEN]; 1285 pathname_t newname; 1286 int rval; 1287 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(".."); 1295 } 1296 free_pathname(&newname); 1297 return rval; 1298 } 1299 1300 int 1301 unlink_path(pathname_t *name) 1302 { 1303 char buf[MAXNAMELEN]; 1304 pathname_t newname; 1305 int rval; 1306 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(".."); 1314 } 1315 free_pathname(&newname); 1316 return rval; 1317 } 1318 1319 void 1320 usage(void) 1321 { 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"); 1342 } 1343 1344 void 1345 write_freq(void) 1346 { 1347 opdesc_t *p; 1348 1349 for (p = ops; p < ops_end; p++) { 1350 if (!p->iswrite) 1351 p->freq = 0; 1352 } 1353 } 1354 1355 void 1356 zero_freq(void) 1357 { 1358 opdesc_t *p; 1359 1360 for (p = ops; p < ops_end; p++) 1361 p->freq = 0; 1362 } 1363 1364 #ifndef NO_XFS 1365 1366 void 1367 allocsp_f(int opno, long r) 1368 { 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; 1377 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; 1384 } 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; 1394 } 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; 1402 } 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 %jd 0 %d\n", 1412 procid, opno, f.path, (intmax_t)off, e); 1413 free_pathname(&f); 1414 close(fd); 1415 } 1416 1417 void 1418 attr_remove_f(int opno, long r) 1419 { 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; 1431 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; 1452 } 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; 1469 } 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; 1479 } 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); 1486 } 1487 1488 void 1489 attr_set_f(int opno, long r) 1490 { 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; 1499 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); 1518 } 1519 1520 void 1521 bulkstat_f(int opno, long r) 1522 { 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; 1530 1531 last = 0; 1532 nent = (r % 999) + 2; 1533 t = malloc(nent * sizeof(*t)); 1534 fd = open(".", O_RDONLY); 1535 total = 0; 1536 1537 bsr.lastip=&last; 1538 bsr.icount=nent; 1539 bsr.ubuffer=t; 1540 bsr.ocount=&count; 1541 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 %jd\n", 1547 procid, opno, nent, (intmax_t)total); 1548 close(fd); 1549 } 1550 1551 void 1552 bulkstat1_f(int opno, long r) 1553 { 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; 1563 1564 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 { 1575 /* 1576 * pick a random inode 1577 * 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. 1582 * 1583 * this is detected later, but not until after the 1584 * warning is displayed. 1585 * 1586 * "XFS: device 0x825- bad inode magic/vsn daddr 0x0 #0" 1587 * 1588 */ 1589 ino = (ino64_t)r; 1590 v = verbose; 1591 } 1592 fd = open(".", O_RDONLY); 1593 1594 bsr.lastip=&ino; 1595 bsr.icount=1; 1596 bsr.ubuffer=&t; 1597 bsr.ocount=NULL; 1598 1599 e = ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bsr) < 0 ? errno : 0; 1600 if (v) 1601 printf("%d/%d: bulkstat1 %s ino %jd %d\n", 1602 procid, opno, good?"real":"random", (intmax_t)ino, e); 1603 close(fd); 1604 } 1605 1606 #endif 1607 1608 void 1609 chown_f(int opno, long r) 1610 { 1611 int e; 1612 pathname_t f; 1613 int nbits; 1614 uid_t u; 1615 int v; 1616 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); 1628 } 1629 1630 void 1631 creat_f(int opno, long r) 1632 { 1633 int e; 1634 int e1; 1635 int extsize __unused; 1636 pathname_t f; 1637 int fd; 1638 fent_t *fep; 1639 int id; 1640 int parid __unused; 1641 int type; 1642 int v; 1643 int v1; 1644 int esz=0; 1645 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); 1663 } 1664 free_pathname(&f); 1665 return; 1666 } 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; 1682 1683 } 1684 add_to_flist(type, id, parid); 1685 #endif 1686 close(fd); 1687 } 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); 1692 } 1693 1694 1695 1696 int 1697 setdirect(int fd) 1698 { 1699 static int no_direct; 1700 int flags; 1701 1702 if (no_direct) 1703 return 0; 1704 1705 flags = fcntl(fd, F_GETFL, 0); 1706 if (flags < 0) 1707 return 0; 1708 1709 if (fcntl(fd, F_SETFL, flags|O_DIRECT) < 0) { 1710 if (no_xfs) { 1711 no_direct = 1; 1712 return 0; 1713 } 1714 printf("cannot set O_DIRECT: %s\n", strerror(errno)); 1715 return 0; 1716 } 1717 1718 return 1; 1719 } 1720 1721 void 1722 dread_f(int opno, long r) 1723 { 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; 1735 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; 1742 } 1743 fd = open_path(&f, O_RDONLY); 1744 1745 if (!setdirect(fd)) { 1746 return; 1747 } 1748 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; 1757 } 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; 1765 } 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; 1773 } 1774 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; 1779 } 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; 1789 } 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 [%jd,%zd] %d\n", 1807 procid, opno, f.path, (intmax_t)off, len, e); 1808 free_pathname(&f); 1809 close(fd); 1810 } 1811 1812 void 1813 dwrite_f(int opno, long r) 1814 { 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; 1826 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; 1833 } 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; 1843 } 1844 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; 1854 } 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; 1859 } 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; 1869 } 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 [%jd,%zd] %d\n", 1890 procid, opno, f.path, (intmax_t)off, len, e); 1891 free_pathname(&f); 1892 close(fd); 1893 } 1894 1895 void 1896 fdatasync_f(int opno, long r) 1897 { 1898 int e; 1899 pathname_t f; 1900 int fd; 1901 int v; 1902 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; 1910 } 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; 1920 } 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); 1926 } 1927 1928 #ifndef NO_XFS 1929 void 1930 freesp_f(int opno, long r) 1931 { 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; 1940 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; 1947 } 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; 1957 } 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; 1965 } 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 %jd 0 %d\n", 1975 procid, opno, f.path, (intmax_t)off, e); 1976 free_pathname(&f); 1977 close(fd); 1978 } 1979 1980 #endif 1981 1982 void 1983 fsync_f(int opno, long r) 1984 { 1985 int e; 1986 pathname_t f; 1987 int fd; 1988 int v; 1989 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; 1996 } 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; 2006 } 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); 2012 } 2013 2014 void 2015 getdents_f(int opno, long r) 2016 { 2017 DIR *dir; 2018 pathname_t f; 2019 int v; 2020 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; 2032 } 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); 2039 } 2040 2041 void 2042 link_f(int opno, long r) 2043 { 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; 2053 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; 2060 } 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); 2074 } 2075 free_pathname(&l); 2076 free_pathname(&f); 2077 return; 2078 } 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, 2085 e); 2086 free_pathname(&l); 2087 free_pathname(&f); 2088 } 2089 2090 void 2091 mkdir_f(int opno, long r) 2092 { 2093 int e; 2094 pathname_t f; 2095 fent_t *fep; 2096 int id; 2097 int parid; 2098 int v; 2099 int v1; 2100 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); 2113 } 2114 free_pathname(&f); 2115 return; 2116 } 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); 2124 } 2125 2126 void 2127 mknod_f(int opno, long r) 2128 { 2129 int e; 2130 pathname_t f; 2131 fent_t *fep; 2132 int id; 2133 int parid; 2134 int v; 2135 int v1; 2136 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); 2149 } 2150 free_pathname(&f); 2151 return; 2152 } 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); 2160 } 2161 2162 void 2163 read_f(int opno, long r) 2164 { 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; 2174 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; 2181 } 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; 2191 } 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; 2199 } 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; 2207 } 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 [%jd,%zd] %d\n", 2217 procid, opno, f.path, (intmax_t)off, len, e); 2218 free_pathname(&f); 2219 close(fd); 2220 } 2221 2222 void 2223 readlink_f(int opno, long r) 2224 { 2225 char buf[PATH_MAX]; 2226 int e; 2227 pathname_t f; 2228 int v; 2229 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; 2236 } 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); 2242 } 2243 2244 void 2245 rename_f(int opno, long r) 2246 { 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; 2258 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; 2265 } 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); 2279 } 2280 free_pathname(&newf); 2281 free_pathname(&f); 2282 return; 2283 } 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); 2290 } 2291 del_from_flist(flp - flist, fep - flp->fents); 2292 add_to_flist(flp - flist, id, parid); 2293 } 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); 2299 } 2300 2301 #ifndef NO_XFS 2302 void 2303 resvsp_f(int opno, long r) 2304 { 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; 2313 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; 2320 } 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; 2330 } 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; 2338 } 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 %jd %jd %d\n", 2348 procid, opno, f.path, (intmax_t)off, 2349 (intmax_t)fl.l_len, e); 2350 free_pathname(&f); 2351 close(fd); 2352 } 2353 #endif 2354 2355 void 2356 rmdir_f(int opno, long r) 2357 { 2358 int e; 2359 pathname_t f; 2360 fent_t *fep; 2361 int v; 2362 2363 init_pathname(&f); 2364 if (!get_fname(FT_DIRm, r, &f, NULL, &fep, &v)) { 2365 if (v) 2366 printf("%d/%d: rmdir - no directory\n", procid, opno); 2367 free_pathname(&f); 2368 return; 2369 } 2370 e = rmdir_path(&f) < 0 ? errno : 0; 2371 check_cwd(); 2372 if (e == 0) 2373 del_from_flist(FT_DIR, fep - flist[FT_DIR].fents); 2374 if (v) 2375 printf("%d/%d: rmdir %s %d\n", procid, opno, f.path, e); 2376 free_pathname(&f); 2377 } 2378 2379 void 2380 stat_f(int opno, long r) 2381 { 2382 int e; 2383 pathname_t f; 2384 struct stat64 stb; 2385 int v; 2386 2387 init_pathname(&f); 2388 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v)) { 2389 if (v) 2390 printf("%d/%d: stat - no entries\n", procid, opno); 2391 free_pathname(&f); 2392 return; 2393 } 2394 e = lstat64_path(&f, &stb) < 0 ? errno : 0; 2395 check_cwd(); 2396 if (v) 2397 printf("%d/%d: stat %s %d\n", procid, opno, f.path, e); 2398 free_pathname(&f); 2399 } 2400 2401 void 2402 symlink_f(int opno, long r) 2403 { 2404 int e; 2405 pathname_t f; 2406 fent_t *fep; 2407 int i; 2408 int id; 2409 int len; 2410 int parid; 2411 int v; 2412 int v1; 2413 char *val; 2414 2415 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v)) 2416 parid = -1; 2417 else 2418 parid = fep->id; 2419 init_pathname(&f); 2420 e = generate_fname(fep, FT_SYM, &f, &id, &v1); 2421 v |= v1; 2422 if (!e) { 2423 if (v) { 2424 fent_to_name(&f, &flist[FT_DIR], fep); 2425 printf("%d/%d: symlink - no filename from %s\n", 2426 procid, opno, f.path); 2427 } 2428 free_pathname(&f); 2429 return; 2430 } 2431 len = (int)(random() % PATH_MAX); 2432 val = malloc(len + 1); 2433 if (len) 2434 memset(val, 'x', len); 2435 val[len] = '\0'; 2436 for (i = 10; i < len - 1; i += 10) 2437 val[i] = '/'; 2438 e = symlink_path(val, &f) < 0 ? errno : 0; 2439 check_cwd(); 2440 if (e == 0) 2441 add_to_flist(FT_SYM, id, parid); 2442 free(val); 2443 if (v) 2444 printf("%d/%d: symlink %s %d\n", procid, opno, f.path, e); 2445 free_pathname(&f); 2446 } 2447 2448 /* ARGSUSED */ 2449 void 2450 sync_f(int opno, long r) 2451 { 2452 sync(); 2453 if (verbose) 2454 printf("%d/%d: sync\n", procid, opno); 2455 } 2456 2457 void 2458 truncate_f(int opno, long r) 2459 { 2460 int e; 2461 pathname_t f; 2462 __int64_t lr; 2463 off64_t off; 2464 struct stat64 stb; 2465 int v; 2466 2467 init_pathname(&f); 2468 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) { 2469 if (v) 2470 printf("%d/%d: truncate - no filename\n", procid, opno); 2471 free_pathname(&f); 2472 return; 2473 } 2474 e = stat64_path(&f, &stb) < 0 ? errno : 0; 2475 check_cwd(); 2476 if (e > 0) { 2477 if (v) 2478 printf("%d/%d: truncate - stat64 %s failed %d\n", 2479 procid, opno, f.path, e); 2480 free_pathname(&f); 2481 return; 2482 } 2483 lr = ((__int64_t)random() << 32) + random(); 2484 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE)); 2485 off %= maxfsize; 2486 e = truncate64_path(&f, off) < 0 ? errno : 0; 2487 check_cwd(); 2488 if (v) 2489 printf("%d/%d: truncate %s %jd %d\n", 2490 procid, opno, f.path, (intmax_t)off, e); 2491 free_pathname(&f); 2492 } 2493 2494 void 2495 unlink_f(int opno, long r) 2496 { 2497 int e; 2498 pathname_t f; 2499 fent_t *fep; 2500 flist_t *flp; 2501 int v; 2502 2503 init_pathname(&f); 2504 if (!get_fname(FT_NOTDIR, r, &f, &flp, &fep, &v)) { 2505 if (v) 2506 printf("%d/%d: unlink - no file\n", procid, opno); 2507 free_pathname(&f); 2508 return; 2509 } 2510 e = unlink_path(&f) < 0 ? errno : 0; 2511 check_cwd(); 2512 if (e == 0) 2513 del_from_flist(flp - flist, fep - flp->fents); 2514 if (v) 2515 printf("%d/%d: unlink %s %d\n", procid, opno, f.path, e); 2516 free_pathname(&f); 2517 } 2518 2519 #ifndef NO_XFS 2520 void 2521 unresvsp_f(int opno, long r) 2522 { 2523 int e; 2524 pathname_t f; 2525 int fd; 2526 struct flock64 fl; 2527 __int64_t lr; 2528 off64_t off; 2529 struct stat64 stb; 2530 int v; 2531 2532 init_pathname(&f); 2533 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) { 2534 if (v) 2535 printf("%d/%d: unresvsp - no filename\n", procid, opno); 2536 free_pathname(&f); 2537 return; 2538 } 2539 fd = open_path(&f, O_RDWR); 2540 e = fd < 0 ? errno : 0; 2541 check_cwd(); 2542 if (fd < 0) { 2543 if (v) 2544 printf("%d/%d: unresvsp - open %s failed %d\n", 2545 procid, opno, f.path, e); 2546 free_pathname(&f); 2547 return; 2548 } 2549 if (fstat64(fd, &stb) < 0) { 2550 if (v) 2551 printf("%d/%d: unresvsp - fstat64 %s failed %d\n", 2552 procid, opno, f.path, errno); 2553 free_pathname(&f); 2554 close(fd); 2555 return; 2556 } 2557 lr = ((__int64_t)random() << 32) + random(); 2558 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE)); 2559 off %= maxfsize; 2560 fl.l_whence = SEEK_SET; 2561 fl.l_start = off; 2562 fl.l_len = (off64_t)(random() % (1 << 20)); 2563 e = ioctl(fd, XFS_IOC_UNRESVSP64, &fl) < 0 ? errno : 0; 2564 if (v) 2565 printf("%d/%d: ioctl(XFS_IOC_UNRESVSP64) %s %jd %jd %d\n", 2566 procid, opno, f.path, (intmax_t)off, 2567 (intmax_t)fl.l_len, e); 2568 free_pathname(&f); 2569 close(fd); 2570 } 2571 #endif 2572 2573 void 2574 write_f(int opno, long r) 2575 { 2576 char *buf; 2577 int e; 2578 pathname_t f; 2579 int fd; 2580 size_t len; 2581 __int64_t lr; 2582 off64_t off; 2583 struct stat64 stb; 2584 int v; 2585 2586 init_pathname(&f); 2587 if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) { 2588 if (v) 2589 printf("%d/%d: write - no filename\n", procid, opno); 2590 free_pathname(&f); 2591 return; 2592 } 2593 fd = open_path(&f, O_WRONLY); 2594 e = fd < 0 ? errno : 0; 2595 check_cwd(); 2596 if (fd < 0) { 2597 if (v) 2598 printf("%d/%d: write - open %s failed %d\n", 2599 procid, opno, f.path, e); 2600 free_pathname(&f); 2601 return; 2602 } 2603 if (fstat64(fd, &stb) < 0) { 2604 if (v) 2605 printf("%d/%d: write - fstat64 %s failed %d\n", 2606 procid, opno, f.path, errno); 2607 free_pathname(&f); 2608 close(fd); 2609 return; 2610 } 2611 lr = ((__int64_t)random() << 32) + random(); 2612 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE)); 2613 off %= maxfsize; 2614 lseek64(fd, off, SEEK_SET); 2615 len = (random() % (getpagesize() * 32)) + 1; 2616 buf = malloc(len); 2617 memset(buf, nameseq & 0xff, len); 2618 e = write(fd, buf, len) < 0 ? errno : 0; 2619 free(buf); 2620 if (v) 2621 printf("%d/%d: write %s [%jd,%zd] %d\n", 2622 procid, opno, f.path, (intmax_t)off, len, e); 2623 free_pathname(&f); 2624 close(fd); 2625 } 2626