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