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 38struct 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 70typedef 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 110typedef void (*opfnc_t) (int, long); 111 112typedef 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 121typedef struct fent { 122 int id; 123 int parent; 124} fent_t; 125 126typedef struct flist { 127 int nfiles; 128 int nslots; 129 int tag; 130 fent_t *fents; 131} flist_t; 132 133typedef 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 159void allocsp_f(int, long); 160void attr_remove_f(int, long); 161void attr_set_f(int, long); 162void bulkstat_f(int, long); 163void bulkstat1_f(int, long); 164void chown_f(int, long); 165void creat_f(int, long); 166void dread_f(int, long); 167void dwrite_f(int, long); 168void fdatasync_f(int, long); 169void freesp_f(int, long); 170void fsync_f(int, long); 171void getdents_f(int, long); 172void link_f(int, long); 173void mkdir_f(int, long); 174void mknod_f(int, long); 175void read_f(int, long); 176void readlink_f(int, long); 177void rename_f(int, long); 178void resvsp_f(int, long); 179void rmdir_f(int, long); 180void stat_f(int, long); 181void symlink_f(int, long); 182void sync_f(int, long); 183void truncate_f(int, long); 184void unlink_f(int, long); 185void unresvsp_f(int, long); 186void write_f(int, long); 187 188opdesc_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 227flist_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 235int dcache[NDCACHE]; 236int errrange; 237int errtag; 238opty_t *freq_table; 239int freq_table_size; 240#ifndef NO_XFS 241xfs_fsop_geom_t geom; 242#endif 243char *homedir; 244int *ilist; 245int ilistlen; 246off64_t maxfsize; 247char *myprog; 248int namerand; 249int nameseq; 250int nops; 251int nproc = 1; 252int operations = 1; 253int procid; 254int rtpct; 255unsigned long seed = 0; 256ino_t top_ino; 257int verbose = 0; 258#ifndef NO_XFS 259int no_xfs = 0; 260#else 261int no_xfs = 1; 262#endif 263sig_atomic_t should_stop = 0; 264 265void add_to_flist(int, int, int); 266void append_pathname(pathname_t *, char *); 267#ifndef NO_XFS 268int attr_list_path(pathname_t *, char *, const int, int, attrlist_cursor_t *); 269int attr_remove_path(pathname_t *, const char *, int); 270int attr_set_path(pathname_t *, const char *, const char *, const int, int); 271#endif 272void check_cwd(void); 273int creat_path(pathname_t *, mode_t); 274void dcache_enter(int, int); 275void dcache_init(void); 276fent_t *dcache_lookup(int); 277void dcache_purge(int); 278void del_from_flist(int, int); 279int dirid_to_name(char *, int); 280void doproc(void); 281void fent_to_name(pathname_t *, flist_t *, fent_t *); 282void fix_parent(int, int); 283void free_pathname(pathname_t *); 284int generate_fname(fent_t *, int, pathname_t *, int *, int *); 285int get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *); 286void init_pathname(pathname_t *); 287int lchown_path(pathname_t *, uid_t, gid_t); 288int link_path(pathname_t *, pathname_t *); 289int lstat64_path(pathname_t *, struct stat64 *); 290void make_freq_table(void); 291int mkdir_path(pathname_t *, mode_t); 292int mknod_path(pathname_t *, mode_t, dev_t); 293void namerandpad(int, char *, int); 294int open_path(pathname_t *, int); 295DIR *opendir_path(pathname_t *); 296void process_freq(char *); 297int readlink_path(pathname_t *, char *, size_t); 298int rename_path(pathname_t *, pathname_t *); 299int rmdir_path(pathname_t *); 300void separate_pathname(pathname_t *, char *, pathname_t *); 301void show_ops(int, char *); 302int stat64_path(pathname_t *, struct stat64 *); 303int symlink_path(const char *, pathname_t *); 304int truncate64_path(pathname_t *, off64_t); 305int unlink_path(pathname_t *); 306void usage(void); 307void write_freq(void); 308void zero_freq(void); 309 310void sg_handler(int signum) 311{ 312 should_stop = 1; 313} 314 315int 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 584void 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 599void 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 618int 619attr_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 639int 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 657int 658attr_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 679void 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 693int 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 711void dcache_enter(int dirid, int slot) 712{ 713 dcache[dirid % NDCACHE] = slot; 714} 715 716void dcache_init(void) 717{ 718 int i; 719 720 for (i = 0; i < NDCACHE; i++) 721 dcache[i] = -1; 722} 723 724fent_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 735void 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 744void 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 759fent_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 777void 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 818void 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 836void 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 851void 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 860int 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 887int 888get_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 941void init_pathname(pathname_t * name) 942{ 943 name->len = 0; 944 name->path = NULL; 945} 946 947int 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 965int 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 1019int 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 1037void 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 1053int 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 1071int 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 1089void 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 1109int 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 1127DIR *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 1145void 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 1166int 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 1184int 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 1238int 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 1256void 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 1274void 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 1310int 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 1328int 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 1351int 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 1369int 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 1387void 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 1425void 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 1435void 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 1445void 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 1496void 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 1565void 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 1596void 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 1627void 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 1684void 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 1705void 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 1769int 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 1793void 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 1894void 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 1987void 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 2020void 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 2073void 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 2104void 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 2130void 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 2178void 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 2213void 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 2248void 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 2307void 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 2328void 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 2385void 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 2438void 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 2461void 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 2482void 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 */ 2529void sync_f(int opno, long r) 2530{ 2531 sync(); 2532 if (verbose) 2533 printf("%d/%d: sync\n", procid, opno); 2534} 2535 2536void 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 2572void 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 2597void 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 2650void 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