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