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/NoticeExplan/ 31 */ 32 /* 33 * This program will grow a list of files. 34 * Each file will grow by grow_incr before the same 35 * file grows twice. Each file is open and closed before next file is opened. 36 * 37 * To just verify file contents: growfiles -g 0 -c 1 filename 38 * 39 * See help and prt_examples functions below. 40 * 41 * Basic code layout 42 * process cmdline 43 * print debug message about options used 44 * setup signal handlers 45 * return control to user (if wanted - default action) 46 * fork number of desired childern (if wanted) 47 * re-exec self (if wanted) 48 * Determine number of files 49 * malloc space or i/o buffer 50 * Loop until stop is set 51 * Determine if hit iteration, time, max errors or num bytes reached 52 * Loop through each file 53 * open file 54 * fstat file - to determine if file if a fifo 55 * prealloc file space (if wanted) 56 * growfile 57 * check last write 58 * check whole file 59 * shrink file 60 * close file 61 * delay (if wanted) 62 * End loop 63 * End loop 64 * remove all files (if wanted) 65 * 66 * Author: Richard Logan 67 * 68 */ 69 #include <stdio.h> 70 #include <errno.h> 71 #include <stdlib.h> 72 #include <ctype.h> 73 #include <sys/types.h> 74 #include <time.h> 75 #include <sys/file.h> 76 #include <unistd.h> 77 #include <sys/stat.h> 78 #include <sys/time.h> 79 #include <sys/param.h> 80 #include <sys/signal.h> 81 #include <fcntl.h> 82 #include <errno.h> 83 #include <string.h> 84 #include <inttypes.h> 85 #include "dataascii.h" 86 #include "random_range.h" 87 #include "databin.h" 88 #include "open_flags.h" 89 #include "forker.h" 90 #include "file_lock.h" 91 92 #ifdef CRAY 93 #include <sys/panic.h> 94 #include <sys/category.h> 95 #endif 96 97 #include "test.h" 98 99 int set_sig(void); 100 void sig_handler(int sig); 101 static void notify_others(void); 102 int handle_error(void); 103 int cleanup(void); 104 void usage(void); 105 void help(void); 106 void prt_examples(FILE * stream); 107 int growfile(int fd, char *file, int grow_incr, char *buf, 108 unsigned long *curr_size_ptr); 109 int shrinkfile(int fd, char *filename, int trunc_incr, 110 int trunc_inter, int just_trunc); 111 int check_write(int fd, int cf_inter, char *filename, int mode); 112 int check_file(int fd, int cf_inter, char *filename, int no_file_check); 113 int file_size(int fd); 114 int lkfile(int fd, int operation, int lklevel); 115 116 #ifndef linux 117 int pre_alloc(int fd, long size); 118 #endif /* !linux */ 119 120 extern int datapidgen(int, char *, int, int); 121 extern int datapidchk(int, char *, int, int, char **); 122 123 /* LTP status reporting */ 124 char *TCID = "growfiles"; /* Default test program identifier. */ 125 int TST_TOTAL = 1; /* Total number of test cases. */ 126 127 /* To avoid extensive modifications to the code, use this bodge */ 128 #define exit(x) myexit(x) 129 void myexit(int x) 130 { 131 if (x) 132 tst_resm(TFAIL, "Test failed"); 133 else 134 tst_resm(TPASS, "Test passed"); 135 tst_exit(); 136 } 137 138 #define NEWIO 1 /* Use the tlibio.c functions */ 139 140 #ifndef NEWIO 141 #define NEWIO 0 /* specifies to use original iowrite.c */ 142 /* functions instead of tlibio.c functions */ 143 /* Once it is proven tlibio.c functions work properly, */ 144 /* only tlibio.c functions will be used */ 145 #else 146 #include "tlibio.h" 147 #endif 148 149 #ifndef PATH_MAX 150 #define PATH_MAX 1023 151 #endif 152 153 #define DEF_DIR "." 154 #define DEF_FILE "gf" 155 156 char *Progname; 157 int Debug = 0; 158 159 int Pid = 0; 160 161 int io_type = 0; /* I/O type -sync */ 162 163 #ifdef O_LARGEFILE 164 int open_flags = O_RDWR | O_CREAT | O_LARGEFILE; /* open flags */ 165 #else 166 #warning O_LARGEFILE is not defined! 167 int open_flags = O_RDWR | O_CREAT; /* open flags */ 168 #endif 169 170 #define MAX_FC_READ 196608 /* 4096 * 48 - 48 blocks */ 171 172 #define PATTERN_ASCII 1 /* repeating alphabet letter pattern */ 173 /* allows multiple writers and to be checked */ 174 #define PATTERN_PID 2 /* <pid><words byte offset><pid> */ 175 /* Assumes 64 bit word. Only allows single */ 176 /* process to write and check */ 177 /* 178 * 1234567890123456789012345678901234567890123456789012345678901234 179 * ________________________________________________________________ 180 * < pid >< offset in file of this word >< pid > 181 */ 182 183 #define PATTERN_OFFSET 3 /* Like PATTERN_PID but has a fixed number */ 184 /* (STATIC_NUM) instead of pid. */ 185 /* Allows multiple processes to write/read */ 186 #define PATTERN_ALT 4 /* alternating bit pattern (i.e. 0x5555555...) */ 187 #define PATTERN_CHKER 5 /* checkerboard pattern (i.e. 0xff00ff00ff00...) */ 188 #define PATTERN_CNTING 6 /* counting pattern (i.e. 0 - 07, 0 - 07, ...) */ 189 #define PATTERN_ONES 7 /* all bits set (i.e. 0xffffffffffffff...) */ 190 #define PATTERN_ZEROS 8 /* all bits cleared (i.e. 0x000000000...) */ 191 #define PATTERN_RANDOM 9 /* random integers - can not be checked */ 192 #define STATIC_NUM 221849 /* used instead of pid when PATTERN_OFFSET */ 193 194 #define MODE_RAND_SIZE 1 /* random write and trunc */ 195 #define MODE_RAND_LSEEK 2 /* random lseek before write */ 196 #define MODE_GROW_BY_LSEEK 4 /* lseek beyond end of file then write a byte */ 197 #define RANDOM_OPEN 999876 /* if Open_flags set to this value, open flags */ 198 /* will be randomly choosen from Open_flags[] */ 199 #define MODE_FIFO S_IFIFO /* defined in stat.h 0010000 */ 200 201 int num_files = 0; /* num_auto_files + cmd line files */ 202 char *filenames; /* pointer to space containing filenames */ 203 int remove_files = 0; /* if set, cleanup default is not to cleanup */ 204 int bytes_consumed = 0; /* total bytes consumed, all files */ 205 int bytes_to_consume = 0; /* non-zero if -B was specified, total bytes */ 206 int Maxerrs = 100; /* Max number errors before forced exit */ 207 int Errors = 0; /* number of encountered errors */ 208 int Upanic_on_error = 0; /* call upanic if error and this variable set */ 209 210 /* The *_size variables are only used when random iosize option (-r) is used */ 211 int max_size = 5000; 212 int min_size = 1; /* also set in option parsing */ 213 int mult_size = 1; /* when random iosz, iosz must be mult of mult_size */ 214 /* the *_lseek variables are only used when radon lseek option (-R) is used */ 215 int min_lseek = 0; /* also set in option parsing */ 216 int max_lseek = -1; /* -1 means size of file */ 217 #ifdef CRAY 218 int Pattern = PATTERN_OFFSET; /* This pattern is 64 bit word based */ 219 #else 220 int Pattern = PATTERN_ASCII; 221 #endif 222 int Seed = -1; /* random number seed, < 0 == uninitialized */ 223 int Nseeds = 0; /* Number of seed specified by the user */ 224 int *Seeds; /* malloc'ed arrary of ints holding user spec seeds */ 225 226 int using_random = 0; /* flag indicating randomization is being used */ 227 float delaysecs = 0.0; /* delay between iterations (in seconds) */ 228 int delaytime; /* delay between iterations in clocks/uses */ 229 int lockfile = 0; /* if set, do file locking */ 230 /* 1 = do file locking around write, trunc */ 231 /* and reads. */ 232 /* 2 = write lock around all file operations */ 233 234 off_t Woffset = 0; /* offset before last write */ 235 int Grow_incr = 4096; /* sz of last write */ 236 int Mode = 0; /* bitmask of write/trunc mode */ 237 /* also knows if dealing with fifo */ 238 char *Buffer = NULL; /* buffer used by write and write check */ 239 int Alignment = 0; /* if non word multiple, io will not be word aligned */ 240 int Opid = 0; /* original pid */ 241 242 int Sync_with_others = 0; /* Flag indicating to stop other if we stop before DONE */ 243 int Iter_cnt = 0; /* contains current iteration count value */ 244 char TagName[40]; /* name of this growfiles (see Monster) */ 245 246 struct fileinfo_t { 247 char *filename; 248 int fd; 249 int openflags; 250 int mode; 251 } Fileinfo; 252 253 /* 254 * Define open flags that will be used when '-o random' option is used. 255 * Note: If there is more than one growfiles doing its thing to the same 256 * file, O_TRUNC will cause data mismatches. How you ask? 257 * timing of events, example: 258 * Process one Process two 259 * --------------- ------------- 260 * get write lock 261 * fstat file 262 * lseek 263 * generate pattern 264 * open with O_TRUNC 265 * write with wrong pattern 266 * because offset is wrong 267 * 268 * The second process truncated the file after the pattern was 269 * determined, thus the pattern is wrong for the file location. 270 * 271 * There can also be a timing problem with open flag O_APPEND if 272 * file locks are not being used (-l option). Things could happen 273 * between the fstat and the write. Thus, writing the wrong pattern. 274 * If all processes observe the file locks, O_APPEND should be ok 275 * to use. 276 */ 277 int Open_flags[] = { 278 #ifdef CRAY 279 O_RDWR | O_CREAT, 280 O_RDWR | O_CREAT | O_RAW, 281 O_RDWR | O_CREAT | O_BIG, 282 O_RDWR | O_CREAT | O_APPEND, 283 O_RDWR | O_CREAT | O_NDELAY, 284 O_RDWR | O_CREAT | O_PLACE, 285 O_RDWR | O_CREAT | O_SYNC, 286 O_RDWR | O_CREAT | O_RAW | O_SYNC, 287 O_RDWR | O_CREAT | O_NDELAY | O_SYNC, 288 O_RDWR | O_CREAT | O_NDELAY | O_SYNC | O_BIG, 289 O_RDWR | O_CREAT | O_RAW, 290 O_RDWR | O_CREAT | O_RAW | O_APPEND, 291 O_RDWR | O_CREAT | O_RAW | O_BIG, 292 O_RDWR | O_CREAT | O_RAW | O_APPEND | O_BIG, 293 /*** 294 * O_WELLFORMED makes -o random require well formed i/o 295 ***/ 296 #if ALLOW_O_WELLFORMED 297 #if O_PARALLEL 298 O_RDWR | O_CREAT | O_PARALLEL | O_WELLFORMED | O_RAW, 299 O_RDWR | O_CREAT | O_PARALLEL | O_WELLFORMED | O_RAW | O_TRUNC, 300 #endif /* O_PARALLEL */ 301 #endif 302 303 #else /* CRAY */ 304 O_RDWR | O_CREAT, 305 O_RDWR | O_CREAT | O_APPEND, 306 O_RDWR | O_CREAT | O_NDELAY, 307 O_RDWR | O_CREAT | O_SYNC, 308 O_RDWR | O_CREAT | O_SYNC | O_NDELAY, 309 O_RDWR | O_CREAT | O_APPEND | O_NDELAY, 310 311 #endif /* CRAY */ 312 }; 313 314 #define REXEC_INIT 0 /* don't do re-exec of childern */ 315 #define REXEC_DOIT 1 /* Do re-exec of childern */ 316 #define REXEC_DONE 2 /* We've already been re-exec'ed */ 317 318 #ifndef BSIZE 319 #ifdef CRAY 320 #define BSIZE 1024 321 #else 322 #define BSIZE 512 323 #endif /* CRAY */ 324 #endif /* BSIZE */ 325 326 #define USECS_PER_SEC 1000000 /* microseconds per second */ 327 328 /* 329 * Define marcos used when dealing with file locks. 330 */ 331 #define LKLVL0 1 /* file lock around write/read/trunc */ 332 #define LKLVL1 2 /* file lock after open to before close */ 333 334 /* 335 * Define special max lseek values 336 */ 337 #define LSK_EOF -1 /* set fptr up to EOF */ 338 #define LSK_EOFPLUSGROW -2 /* set fptr up to EOF + grow - leave whole */ 339 #define LSK_EOFMINUSGROW -3 /* set fptr up to EOF-grow - no grow */ 340 341 /*********************************************************************** 342 * MAIN 343 ***********************************************************************/ 344 int main(int argc, char **argv) 345 { 346 extern char *optarg; /* used by getopt */ 347 extern int optind; 348 349 int ind; 350 int first_file_ind = 0; 351 int num_auto_files = 0; /* files created by tool */ 352 int seq_auto_files = 0; /* auto files created by tool created by tool */ 353 char *auto_dir = DEF_DIR; 354 char *auto_file = DEF_FILE; 355 int grow_incr = 4096; 356 int trunc_incr = 4096; 357 int trunc_inter = 0; /* 0 means none, */ 358 int unlink_inter = 0; /* 0 means none, 1 means always unlink */ 359 int unlink_inter_ran = -1; /* -1 -use unlink_inter, otherwise randomly choose */ 360 /* between unlink_inter and unlink_inter_ran */ 361 int file_check_inter = 0; /* 0 means never, 1 means always */ 362 int write_check_inter = 1; /* 0 means never, 1 means always */ 363 int iterations = 1; /* number of increments to be added */ 364 int no_file_check = 0; /* if set, no whole file checking will be done */ 365 int num; 366 int fd; /* file descriptor */ 367 int stop = 0; /* loop stopper if set */ 368 369 unsigned long curr_size = 0; /* BUG:14136 (keep track of file size) */ 370 const unsigned long ext2_limit = 2147483647; /* BUG:14136 (2GB ext2 filesize limit) */ 371 372 int tmp; 373 char chr; 374 int ret; 375 int pre_alloc_space = 0; 376 #ifndef linux 377 long total_grow_value; /* used in pre-allocations */ 378 #endif 379 int backgrnd = 1; /* return control to user */ 380 struct stat statbuf; 381 int time_iterval = -1; 382 time_t start_time = 0; 383 char reason[128]; /* reason for loop termination */ 384 int num_procs = 1; 385 int forker_mode = 0; 386 int reexec = REXEC_INIT; /* reexec info */ 387 char *exec_path = NULL; 388 389 /*char *strrchr();*/ 390 391 char *filename; /* name of file specified by user */ 392 char *cptr; /* temp char pointer */ 393 extern int Forker_npids; /* num of forked pid, defined in forker.c */ 394 struct timeval tv1; 395 396 if (argv[0][0] == '-') 397 reexec = REXEC_DONE; 398 /* 399 * Determine name of file used to invoke this program 400 */ 401 if ((Progname = strrchr(argv[0], '/')) != NULL) 402 Progname++; 403 else 404 Progname = argv[0]; 405 406 TagName[0] = '\0'; 407 408 /* 409 * Process options 410 */ 411 while ((ind = getopt(argc, argv, 412 "hB:C:c:bd:D:e:Ef:g:H:I:i:lL:n:N:O:o:pP:q:wt:r:R:s:S:T:uU:W:xy")) 413 != EOF) { 414 switch (ind) { 415 416 case 'h': 417 help(); 418 tst_exit(); 419 420 case 'B': 421 switch (sscanf(optarg, "%i%c", &bytes_to_consume, &chr)) { 422 case 1: /* noop */ 423 break; 424 425 case 2: 426 if (chr == 'b') { 427 bytes_to_consume *= BSIZE; 428 } else { 429 fprintf(stderr, 430 "%s%s: --B option arg invalid\n", 431 Progname, TagName); 432 usage(); 433 exit(1); 434 } 435 break; 436 437 default: 438 fprintf(stderr, 439 "%s%s: --B option arg invalid\n", 440 Progname, TagName); 441 usage(); 442 exit(1); 443 break; 444 } 445 446 break; 447 448 case 'E': 449 prt_examples(stdout); 450 exit(0); 451 452 case 'b': /* batch */ 453 backgrnd = 0; 454 break; 455 456 case 'C': 457 if (sscanf(optarg, "%i", &write_check_inter) != 1) { 458 fprintf(stderr, 459 "%s%s: --c option arg invalid\n", 460 Progname, TagName); 461 usage(); 462 exit(1); 463 } 464 break; 465 466 case 'c': 467 if (sscanf(optarg, "%i", &file_check_inter) != 1) { 468 fprintf(stderr, 469 "%s%s: --c option arg invalid\n", 470 Progname, TagName); 471 usage(); 472 exit(1); 473 } 474 break; 475 476 case 'd': 477 auto_dir = optarg; 478 #ifdef CRAY 479 unsetenv("TMPDIR"); /* force the use of auto_dir */ 480 #endif 481 if (stat(auto_dir, &statbuf) == -1) { 482 if (mkdir(auto_dir, 0777) == -1) { 483 if (errno != EEXIST) { 484 fprintf(stderr, 485 "%s%s: Unable to make dir %s\n", 486 Progname, TagName, 487 auto_dir); 488 exit(1); 489 } 490 } 491 } else { 492 if (!(statbuf.st_mode & S_IFDIR)) { 493 fprintf(stderr, 494 "%s%s: %s already exists and is not a directory\n", 495 Progname, TagName, auto_dir); 496 exit(1); 497 } 498 } 499 break; 500 501 case 'D': 502 if (sscanf(optarg, "%i", &Debug) != 1) { 503 fprintf(stderr, 504 "%s%s: --D option arg invalid\n", 505 Progname, TagName); 506 usage(); 507 exit(1); 508 } 509 break; 510 511 case 'e': 512 if (sscanf(optarg, "%i", &Maxerrs) != 1) { 513 fprintf(stderr, 514 "%s%s: --e option arg invalid\n", 515 Progname, TagName); 516 usage(); 517 exit(1); 518 } 519 break; 520 521 case 'f': 522 auto_file = optarg; 523 break; 524 525 case 'g': 526 if ((ret = sscanf(optarg, "%i%c", &grow_incr, &chr)) < 1 527 || grow_incr < 0) { 528 529 fprintf(stderr, 530 "%s%s: --g option arg invalid\n", 531 Progname, TagName); 532 usage(); 533 exit(1); 534 } 535 if (ret == 2) { 536 if (chr == 'b' || chr == 'B') 537 grow_incr *= 4096; 538 else { 539 fprintf(stderr, 540 "%s%s: --g option arg invalid\n", 541 Progname, TagName); 542 usage(); 543 exit(1); 544 } 545 } 546 break; 547 548 case 'H': 549 if (sscanf(optarg, "%f", &delaysecs) != 1 550 || delaysecs < 0) { 551 552 fprintf(stderr, 553 "%s%s: --H option arg invalid\n", 554 Progname, TagName); 555 usage(); 556 exit(1); 557 } 558 break; 559 560 case 'i': 561 if (sscanf(optarg, "%i", &iterations) != 1 || 562 iterations < 0) { 563 564 fprintf(stderr, 565 "%s%s: --i option arg invalid\n", 566 Progname, TagName); 567 usage(); 568 exit(1); 569 } 570 break; 571 572 case 'I': 573 #if NEWIO 574 if ((io_type = lio_parse_io_arg1(optarg)) == -1) { 575 fprintf(stderr, 576 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n", 577 Progname, TagName); 578 exit(1); 579 } 580 if (io_type & LIO_RANDOM) 581 using_random++; 582 #else 583 if ((io_type = parse_io_arg(optarg)) == -1) { 584 fprintf(stderr, 585 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n", 586 Progname, TagName); 587 exit(1); 588 } 589 if (io_type == 99) /* hold-over until tlibio.h */ 590 using_random++; 591 #endif 592 break; 593 594 case 'l': 595 lockfile++; 596 if (lockfile > 2) 597 lockfile = 2; /* lockfile can only be 1 or 2 */ 598 break; 599 600 case 'L': 601 if (sscanf(optarg, "%i", &time_iterval) != 1 || 602 time_iterval < 0) { 603 fprintf(stderr, 604 "%s%s: --L option arg invalid\n", 605 Progname, TagName); 606 usage(); 607 exit(1); 608 } 609 break; 610 611 case 'n': 612 if (sscanf(optarg, "%i:%i", &num_procs, &forker_mode) < 613 1 || num_procs < 0) { 614 615 fprintf(stderr, 616 "%s%s: --n option arg invalid\n", 617 Progname, TagName); 618 usage(); 619 exit(1); 620 } 621 622 break; 623 624 case 'N': 625 if (sscanf(optarg, "%i", &num_auto_files) != 1 || 626 num_auto_files < 0) { 627 628 fprintf(stderr, 629 "%s%s: --N option arg invalid\n", 630 Progname, TagName); 631 usage(); 632 exit(1); 633 } 634 break; 635 636 case 'O': 637 if (sscanf(optarg, "%i", &Alignment) != 1 || 638 Alignment < 0) { 639 640 fprintf(stderr, 641 "%s%s: --O option arg invalid\n", 642 Progname, TagName); 643 usage(); 644 exit(1); 645 } 646 break; 647 648 case 'o': 649 if (strcmp(optarg, "random") == 0) { 650 open_flags = RANDOM_OPEN; 651 using_random++; 652 653 } else if ((open_flags = parse_open_flags(optarg, NULL)) 654 == -1) { 655 fprintf(stderr, 656 "%s%s: --o arg contains invalid flag\n", 657 Progname, TagName); 658 exit(1); 659 } 660 break; 661 662 case 'p': /* pre allocate space */ 663 #ifdef linux 664 printf("%s%s: --p is illegal option on linux system\n", 665 Progname, TagName); 666 exit(1); 667 #else 668 pre_alloc_space++; 669 #endif 670 break; 671 672 case 'P': 673 #ifdef CRAY 674 if (strcmp(optarg, "PANIC") != 0) { 675 fprintf(stderr, "%s%s: --P arg must be PANIC\n", 676 Progname, TagName); 677 exit(1); 678 } 679 Upanic_on_error++; 680 printf("%s%s: Will call upanic after writes\n", Progname, TagName); 681 #else 682 printf 683 ("%s%s: --P is illegal option on non-cray system\n", 684 Progname, TagName); 685 exit(1); 686 #endif 687 break; 688 689 case 'q': /* file content or pattern */ 690 switch (optarg[0]) { 691 case 'A': 692 Pattern = PATTERN_ALT; 693 break; 694 case 'a': 695 Pattern = PATTERN_ASCII; 696 break; 697 case 'p': 698 Pattern = PATTERN_PID; 699 break; 700 case 'o': 701 Pattern = PATTERN_OFFSET; 702 break; 703 case 'c': 704 Pattern = PATTERN_CHKER; 705 break; 706 case 'C': 707 Pattern = PATTERN_CNTING; 708 break; 709 case 'r': 710 Pattern = PATTERN_RANDOM; 711 using_random++; 712 break; 713 case 'z': 714 Pattern = PATTERN_ZEROS; 715 break; 716 case 'O': 717 Pattern = PATTERN_ONES; 718 break; 719 default: 720 fprintf(stderr, 721 "%s%s: --C option arg invalid, A, a, p, o, c, C, r, z, or 0\n", 722 Progname, TagName); 723 usage(); 724 exit(1); 725 } 726 break; 727 728 case 'R': /* random lseek before write arg: [min-]max */ 729 if (sscanf(optarg, "%i-%i", &min_lseek, &max_lseek) != 730 2) { 731 min_lseek = 1; /* same as default in define */ 732 if (sscanf(optarg, "%i%c", &max_lseek, &chr) != 733 1) { 734 fprintf(stderr, 735 "%s%s: --R option arg invalid: [min-]max\n", 736 Progname, TagName); 737 exit(1); 738 } 739 } 740 if (max_lseek < LSK_EOFMINUSGROW) { 741 fprintf(stderr, 742 "%s%s: --R option, max_lseek is invalid\n", 743 Progname, TagName); 744 exit(1); 745 } 746 Mode |= MODE_RAND_LSEEK; 747 using_random++; 748 break; 749 750 case 'r': /* random io size arg: [min-]max[:mult] */ 751 752 /* min-max:mult format */ 753 if (sscanf(optarg, "%i-%i:%i%c", &min_size, &max_size, 754 &mult_size, &chr) != 3) { 755 min_size = 1; 756 /* max:mult format */ 757 if (sscanf(optarg, "%i:%i%c", &max_size, 758 &mult_size, &chr) != 2) { 759 /* min-max format */ 760 if (sscanf(optarg, "%i-%i%c", &min_size, 761 &max_size, &chr) != 2) { 762 min_size = 1; 763 if (sscanf 764 (optarg, "%i%c", &max_size, 765 &chr) != 1) { 766 fprintf(stderr, 767 "%s%s: --r option arg invalid: [min-]max[:mult]\n", 768 Progname, 769 TagName); 770 exit(1); 771 } 772 } 773 } 774 } 775 776 if (max_size < 0) { 777 fprintf(stderr, 778 "%s%s: --r option, max_size is invalid\n", 779 Progname, TagName); 780 exit(1); 781 } 782 /* 783 * If min and max are the same, no randomness 784 */ 785 if (min_size != max_size) { 786 Mode |= MODE_RAND_SIZE; 787 using_random++; 788 } 789 break; 790 791 case 'S': 792 if (sscanf(optarg, "%i", &seq_auto_files) != 1 || 793 seq_auto_files < 0) { 794 795 fprintf(stderr, 796 "%s%s: --S option arg invalid\n", 797 Progname, TagName); 798 usage(); 799 exit(1); 800 } 801 break; 802 803 case 's': /* format: seed[,seed...] */ 804 805 /* count the number of seeds */ 806 cptr = optarg; 807 for (Nseeds = 1; *cptr; Nseeds++) { 808 if ((filename = strchr(cptr, ',')) == NULL) 809 break; 810 cptr = filename; 811 cptr++; 812 } 813 Seeds = malloc(Nseeds * sizeof(int)); 814 815 /* 816 * check that each seed is valid and put them in 817 * the newly malloc'ed Seeds arrary. 818 */ 819 filename = cptr = optarg; 820 for (Nseeds = 0; *cptr; Nseeds++) { 821 if ((filename = strchr(cptr, ',')) == NULL) { 822 if (sscanf(cptr, "%i", &Seeds[Nseeds]) < 823 1) { 824 fprintf(stderr, 825 "%s%s: --s option arg %s invalid\n", 826 Progname, TagName, 827 cptr); 828 usage(); 829 exit(1); 830 } 831 Nseeds++; 832 break; 833 } 834 835 *filename = '\0'; 836 if (sscanf(cptr, "%i", &Seeds[Nseeds]) < 1) { 837 fprintf(stderr, 838 "%s%s: --s option arg %s invalid\n", 839 Progname, TagName, cptr); 840 usage(); 841 exit(1); 842 } 843 *filename = ','; /* restore string */ 844 cptr = filename; 845 cptr++; 846 } 847 break; 848 849 case 't': 850 if ((ret = 851 sscanf(optarg, "%i%c", &trunc_incr, &chr)) < 1 852 || trunc_incr < 0) { 853 854 fprintf(stderr, 855 "%s%s: --t option arg invalid\n", 856 Progname, TagName); 857 usage(); 858 exit(1); 859 } 860 if (ret == 2) { 861 if (chr == 'b' || chr == 'B') 862 trunc_incr *= 4096; 863 else { 864 fprintf(stderr, 865 "%s%s: --t option arg invalid\n", 866 Progname, TagName); 867 usage(); 868 exit(1); 869 } 870 } 871 break; 872 873 case 'T': /* truncate interval */ 874 if (sscanf(optarg, "%i%c", &trunc_inter, &chr) != 1 || 875 trunc_inter < 0) { 876 877 fprintf(stderr, 878 "%s%s: --T option arg invalid\n", 879 Progname, TagName); 880 usage(); 881 exit(1); 882 } 883 break; 884 885 case 'u': 886 remove_files++; 887 break; 888 889 case 'U': /* how often to unlink file */ 890 /* 891 * formats: 892 * A-B - randomly pick interval between A and B 893 * X - unlink file every X iteration 894 */ 895 if (sscanf(optarg, "%i-%i", &unlink_inter, 896 &unlink_inter_ran) == 2) { 897 898 if (unlink_inter < 0 || unlink_inter_ran < 0) { 899 fprintf(stderr, 900 "%s%s: --U option arg invalid\n", 901 Progname, TagName); 902 usage(); 903 exit(1); 904 } 905 /* ensure unlink_inter contains smaller value */ 906 if (unlink_inter > unlink_inter_ran) { 907 tmp = unlink_inter_ran; 908 unlink_inter_ran = unlink_inter; 909 unlink_inter = tmp; 910 } 911 using_random++; 912 913 } else if (sscanf(optarg, "%i%c", &unlink_inter, &chr) 914 != 1 || unlink_inter < 0) { 915 916 fprintf(stderr, 917 "%s%s: --U option arg invalid\n", 918 Progname, TagName); 919 usage(); 920 exit(1); 921 } 922 break; 923 924 case 'x': 925 if (reexec != REXEC_DONE) 926 reexec = REXEC_DOIT; 927 break; 928 929 case 'w': 930 Mode |= MODE_GROW_BY_LSEEK; 931 break; 932 933 case 'W': 934 TCID = optarg; 935 sprintf(TagName, "(%.39s)", optarg); 936 break; 937 938 case 'y': 939 Sync_with_others = 1; 940 break; 941 942 case '?': 943 usage(); 944 exit(1); 945 break; 946 } 947 } 948 949 if (Debug == 1) { 950 cptr = getenv("TOUTPUT"); 951 if ((cptr != NULL) && (strcmp(cptr, "NOPASS") == 0)) { 952 Debug = 0; 953 } 954 } 955 956 if (Pattern == PATTERN_RANDOM) { 957 no_file_check = 1; 958 if (write_check_inter || file_check_inter) 959 printf 960 ("%s%s: %d Using random pattern - no data checking will be performed!\n", 961 Progname, TagName, getpid()); 962 } else if (max_lseek == LSK_EOFPLUSGROW || Mode & MODE_GROW_BY_LSEEK) { 963 no_file_check = 1; 964 965 if (file_check_inter) 966 printf("%s%s: %d Using random lseek beyond EOF or lseek grow,\n\ 967 no whole file checking will be performed!\n", Progname, TagName, 968 getpid()); 969 970 } 971 972 if (Mode & MODE_RAND_SIZE) 973 grow_incr = max_size; 974 975 set_sig(); 976 977 Opid = getpid(); 978 Pid = Opid; 979 980 if (backgrnd) { 981 if (Debug > 1) 982 printf 983 ("%s: %d DEBUG2 forking, returning control to the user\n", 984 Progname, Opid); 985 background(Progname); /* give user their prompt back */ 986 } 987 #if CRAY 988 if (Sync_with_others) 989 setpgrp(); 990 #endif 991 992 if (Debug > 3) { 993 #if NEWIO 994 lio_set_debug(Debug - 3); 995 #else 996 set_iowrite_debug(Debug - 3); 997 #endif 998 } 999 1000 /* 1001 * Print some program information here if debug is turned on to 1002 * level 3 or higher. 1003 */ 1004 1005 if (Debug > 2) { 1006 1007 if (Mode & MODE_GROW_BY_LSEEK) 1008 printf 1009 ("%s: %d DEBUG lseeking past end of file, writting a \"w\"\n", 1010 Progname, Pid); 1011 else if (Pattern == PATTERN_OFFSET) 1012 printf 1013 ("%s: %d DEBUG3 %d<byteoffset>%d per word pattern multi-writers.\n", 1014 Progname, Pid, STATIC_NUM, STATIC_NUM); 1015 else if (Pattern == PATTERN_PID) 1016 printf 1017 ("%s: %d DEBUG3 <pid><byteoffset><pid> per word pattern - 1 writer\n", 1018 Progname, Pid); 1019 else if (Pattern == PATTERN_ASCII) 1020 printf 1021 ("%s: %d DEBUG3 ascii pattern (vi'able)- allows multiple writers\n", 1022 Progname, Pid); 1023 else if (Pattern == PATTERN_ALT) 1024 printf 1025 ("%s: %d DEBUG3 alt bit pattern - allows multiple writers\n", 1026 Progname, Pid); 1027 else if (Pattern == PATTERN_CHKER) 1028 printf 1029 ("%s: %d DEBUG3 checkerboard pattern - allows multiple writers\n", 1030 Progname, Pid); 1031 else if (Pattern == PATTERN_CNTING) 1032 printf 1033 ("%s: %d DEBUG3 counting pattern - allows multiple writers\n", 1034 Progname, Pid); 1035 else if (Pattern == PATTERN_RANDOM) 1036 printf 1037 ("%s: %d DEBUG3 random integer pattern - no write/file checking\n", 1038 Progname, Pid); 1039 else if (Pattern == PATTERN_ONES) 1040 printf 1041 ("%s: %d DEBUG3 all ones pattern - allows multiple writers\n", 1042 Progname, Pid); 1043 else if (Pattern == PATTERN_ZEROS) 1044 printf 1045 ("%s: %d DEBUG3 all zeros pattern - allows multiple writers\n", 1046 Progname, Pid); 1047 1048 else 1049 printf("%s: %d DEBUG3 unknown pattern\n", 1050 Progname, Pid); 1051 if (bytes_to_consume) 1052 printf("%s: %d DEBUG3 bytes_to_consume = %d\n", 1053 Progname, Pid, bytes_to_consume); 1054 printf 1055 ("%s: %d DEBUG3 Maxerrs = %d, pre_alloc_space = %d, filelocking = %d\n", 1056 Progname, Pid, Maxerrs, pre_alloc_space, lockfile); 1057 1058 printf 1059 ("%s: %d DEBUG3 Debug = %d, remove files in cleanup : %d\n", 1060 Progname, Pid, Debug, remove_files); 1061 1062 printf("%s: %d DEBUG3 Mode = %#o\n", Progname, Pid, Mode); 1063 1064 if (open_flags == RANDOM_OPEN) 1065 printf 1066 ("%s: %d DEBUG3 open_flags = (random), io_type = %#o\n", 1067 Progname, Pid, io_type); 1068 else 1069 printf 1070 ("%s: %d DEBUG3 open_flags = %#o, io_type = %#o\n", 1071 Progname, Pid, open_flags, io_type); 1072 1073 if (Mode & MODE_RAND_SIZE) { 1074 printf 1075 ("%s: %d DEBUG3 random write/trunc: min=%d, max=%d, mult = %d\n", 1076 Progname, Pid, min_size, max_size, mult_size); 1077 } else { 1078 printf("%s: %d DEBUG3 grow_incr = %d\n", 1079 Progname, Pid, grow_incr); 1080 } 1081 if (Mode & MODE_RAND_LSEEK) { 1082 if (max_lseek == LSK_EOF) 1083 printf 1084 ("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile>\n", 1085 Progname, Pid, min_lseek); 1086 else if (max_lseek == LSK_EOFPLUSGROW) 1087 printf 1088 ("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile+iosize>\n", 1089 Progname, Pid, min_lseek); 1090 else if (max_lseek == LSK_EOFMINUSGROW) 1091 printf 1092 ("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile-iosize>\n", 1093 Progname, Pid, min_lseek); 1094 else 1095 printf 1096 ("%s: %d DEBUG3 random lseek: min=%d, max=%d\n", 1097 Progname, Pid, min_lseek, max_lseek); 1098 } 1099 1100 printf 1101 ("%s: %d DEBUG3 check write interval = %d, check file interval = %d\n", 1102 Progname, Pid, write_check_inter, file_check_inter); 1103 1104 printf("%s: %d DEBUG3 trunc interval = %d, trunc_incr = %d\n", 1105 Progname, Pid, trunc_inter, trunc_incr); 1106 1107 if (no_file_check) 1108 printf 1109 ("%s: %d DEBUG3 no whole file checking will be done\n", 1110 Progname, Pid); 1111 1112 if (unlink_inter_ran == -1) { 1113 printf("%s: %d DEBUG3 unlink_inter = %d\n", 1114 Progname, Pid, unlink_inter); 1115 } else { 1116 printf 1117 ("%s: %d DEBUG3 unlink_inter = %d, unlink_inter_ran = %d\n", 1118 Progname, Pid, unlink_inter, unlink_inter_ran); 1119 } 1120 1121 if (Debug > 8) { 1122 num = sizeof(Open_flags) / sizeof(int); 1123 printf("%s: %d DEBUG9 random open flags values:\n", 1124 Progname, Pid); 1125 for (ind = 0; ind < num; ind++) { 1126 printf("\t%#o\n", Open_flags[ind]); 1127 } 1128 } 1129 } 1130 /* end of DEBUG > 2 */ 1131 if (Debug > 1 && num_procs > 1) { 1132 printf("%s: %d DEBUG2 about to fork %d more copies\n", Progname, 1133 Opid, num_procs - 1); 1134 } 1135 1136 fflush(stdout); /* ensure pending i/o is flushed before forking */ 1137 fflush(stderr); 1138 1139 forker(num_procs, forker_mode, Progname); 1140 1141 Pid = getpid(); /* reset after the forks */ 1142 /* 1143 * If user specified random seed(s), get that random seed value. 1144 * get random seed if it was not specified by the user. 1145 * This is done after the forks, because pid is used to get the seed. 1146 */ 1147 if (Nseeds == 1) { 1148 /* 1149 * If only one seed specified, all processes will get that seed. 1150 */ 1151 Seed = Seeds[0]; 1152 } else if (Nseeds > 1) { 1153 /* 1154 * More than one seed was specified. 1155 * The original process gets the first seed. Each 1156 * process will be get the next seed in the specified list. 1157 */ 1158 if (Opid == Pid) { 1159 Seed = Seeds[0]; 1160 } else { 1161 /* 1162 * If user didn't specify enough seeds, use default method. 1163 */ 1164 if (Forker_npids >= Nseeds) { 1165 struct timeval ts; 1166 gettimeofday(&ts, NULL); 1167 Seed = ts.tv_sec + Pid; /* default random seed */ 1168 } else { 1169 Seed = Seeds[Forker_npids]; 1170 } 1171 } 1172 } else { 1173 /* 1174 * Generate a random seed based on time and pid. 1175 * It has a good chance of being unique for each pid. 1176 */ 1177 struct timeval ts; 1178 gettimeofday(&ts, NULL); 1179 Seed = ts.tv_sec + Pid; /* default random seed */ 1180 //Seed=time(0) + Pid; /* default random seed */ 1181 1182 } 1183 1184 random_range_seed(Seed); 1185 1186 if (using_random && Debug > 0) 1187 printf("%s%s: %d DEBUG1 Using random seed of %d\n", 1188 Progname, TagName, Pid, Seed); 1189 1190 if (unlink_inter_ran > 0) { 1191 /* 1192 * Find unlinking file interval. This must be done after 1193 * the seed was set. This allows multiple copies to 1194 * get different intervals. 1195 */ 1196 tmp = unlink_inter; 1197 unlink_inter = 1198 (int)random_range(tmp, unlink_inter_ran, 1, NULL); 1199 1200 if (Debug > 2) 1201 printf 1202 ("%s: %d DEBUG3 Unlink interval is %d (random %d - %d)\n", 1203 Progname, Pid, unlink_inter, tmp, 1204 unlink_inter_ran); 1205 } 1206 1207 /* 1208 * re-exec all childern if reexec is set to REXEC_DOIT. 1209 * This is useful on MPP systems to get the 1210 * child process on another PE. 1211 */ 1212 if (reexec == REXEC_DOIT && Opid != Pid) { 1213 if (exec_path == NULL) { 1214 exec_path = argv[0]; 1215 /* Get space for cmd (2 extra, 1 for - and 1 fro NULL */ 1216 argv[0] = malloc(strlen(exec_path) + 2); 1217 sprintf(argv[0], "-%s", exec_path); 1218 } 1219 1220 if (Debug > 2) 1221 printf("%s: %d DEBUG3 %s/%d: execvp(%s, argv)\n", 1222 Progname, Pid, __FILE__, __LINE__, argv[0]); 1223 1224 execvp(argv[0], argv); 1225 } 1226 1227 /*** begin filename stuff here *****/ 1228 /* 1229 * Determine the number of files to be dealt with 1230 */ 1231 if (optind == argc) { 1232 /* 1233 * no cmd line files, therfore, set 1234 * the default number of auto created files 1235 */ 1236 if (!num_auto_files && !seq_auto_files) 1237 num_auto_files = 1; 1238 } else { 1239 first_file_ind = optind; 1240 num_files += argc - optind; 1241 } 1242 1243 if (num_auto_files) { 1244 num_files += num_auto_files; 1245 } 1246 1247 if (seq_auto_files) { 1248 num_files += seq_auto_files; 1249 } 1250 1251 /* 1252 * get space for file names 1253 */ 1254 if ((filenames = malloc(num_files * PATH_MAX)) == NULL) { 1255 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n", 1256 Progname, TagName, Pid, __FILE__, __LINE__, 1257 num_files * PATH_MAX, strerror(errno)); 1258 exit(1); 1259 } 1260 1261 /* 1262 * fill in filename cmd files then auto files. 1263 */ 1264 1265 num = 0; 1266 if (first_file_ind) { 1267 for (ind = first_file_ind; ind < argc; ind++, num++) { 1268 strcpy((char *)filenames + (num * PATH_MAX), argv[ind]); 1269 } 1270 } 1271 1272 /* 1273 * construct auto filename and insert them into filenames space 1274 */ 1275 1276 for (ind = 0; ind < num_auto_files; ind++, num++) { 1277 gettimeofday(&tv1, NULL); 1278 sprintf((char *)filenames + (num * PATH_MAX), 1279 "%s/%s%ld%ld%d.%d", auto_dir, auto_file, 1280 (long)tv1.tv_sec, (long)tv1.tv_usec, rand(), ind); 1281 } 1282 1283 /* 1284 * construct auto seq filenames 1285 */ 1286 for (ind = 1; ind <= seq_auto_files; ind++, num++) { 1287 sprintf((char *)filenames + (num * PATH_MAX), "%s/%s%d", 1288 auto_dir, auto_file, ind); 1289 } 1290 1291 /**** end filename stuff ****/ 1292 1293 if (time_iterval > 0) { 1294 struct timeval ts; 1295 gettimeofday(&ts, NULL); 1296 start_time = ts.tv_sec; 1297 //start_time=time(0); 1298 } 1299 1300 /* 1301 * get space for I/O buffer 1302 */ 1303 if (grow_incr) { 1304 if ((Buffer = malloc(grow_incr + Alignment)) == NULL) { 1305 fprintf(stderr, 1306 "%s%s: %d %s/%d: malloc(%d) failed: %s\n", 1307 Progname, TagName, Pid, __FILE__, __LINE__, 1308 grow_incr, strerror(errno)); 1309 exit(1); 1310 } 1311 if (Alignment) 1312 Buffer = Buffer + Alignment; 1313 1314 } 1315 1316 if (Debug > 2) { 1317 printf("%s: %d DEBUG3 num_files = %d\n", 1318 Progname, Pid, num_files); 1319 } 1320 #ifndef linux 1321 if (pre_alloc_space) { 1322 if (iterations == 0) { 1323 fprintf(stderr, 1324 "%s%s: %d %s/%d: can NOT pre-alloc and grow forever\n", 1325 Progname, TagName, Pid, __FILE__, __LINE__); 1326 exit(1); 1327 } 1328 if (Mode & MODE_RAND_SIZE) { 1329 fprintf(stderr, 1330 "%s%s: %d %s/%d: can NOT pre-alloc and do random io size\n", 1331 Progname, TagName, Pid, __FILE__, __LINE__); 1332 exit(1); 1333 } 1334 1335 total_grow_value = grow_incr * iterations; 1336 1337 /* 1338 * attempt to limit 1339 */ 1340 if (bytes_to_consume && bytes_to_consume < total_grow_value) { 1341 total_grow_value = bytes_to_consume; 1342 } 1343 } 1344 #endif 1345 1346 /* 1347 * If delaying between iterations, get amount time to 1348 * delaysecs in clocks or usecs. 1349 * If on the CRAY, delaytime is in clocks since 1350 * _rtc() will be used, which does not have the overhead 1351 * of gettimeofday(2). 1352 */ 1353 if (delaysecs) { 1354 #if CRAY 1355 int hz; 1356 hz = sysconf(_SC_CLK_TCK); 1357 delaytime = (int)((float)hz * delaysecs); 1358 #else 1359 delaytime = (int)((float)USECS_PER_SEC * delaysecs); 1360 #endif 1361 } 1362 1363 /* 1364 * This is the main iteration loop. 1365 * Each iteration, all files can be opened, written to, 1366 * read to check the write, check the whole file, 1367 * truncated, and closed. 1368 */ 1369 for (Iter_cnt = 1; !stop; Iter_cnt++) { 1370 struct timeval ts; 1371 if (iterations && (Iter_cnt >= iterations + 1)) { 1372 strcpy(reason, "Hit iteration value"); 1373 stop = 1; 1374 continue; 1375 } 1376 gettimeofday(&ts, NULL); 1377 if ((time_iterval > 0) 1378 && (start_time + time_iterval < ts.tv_sec)) { 1379 1380 sprintf(reason, "Hit time value of %d", time_iterval); 1381 stop = 1; 1382 continue; 1383 } 1384 1385 if (bytes_to_consume && bytes_consumed >= bytes_to_consume) { 1386 sprintf(reason, "Hit bytes consumed value of %d", 1387 bytes_to_consume); 1388 stop = 1; 1389 continue; 1390 } 1391 1392 /* 1393 * This loop will loop through all files. 1394 * Each iteration, a single file can be opened, written to, 1395 * read to check the write, check the whole file, 1396 * truncated, and closed. 1397 */ 1398 for (ind = 0; ind < num_files; ind++) { 1399 1400 fflush(stdout); 1401 fflush(stderr); 1402 1403 filename = (char *)filenames + (ind * PATH_MAX); 1404 Fileinfo.filename = 1405 (char *)filenames + (ind * PATH_MAX); 1406 1407 if (open_flags == RANDOM_OPEN) { 1408 ret = 1409 Open_flags[random_range 1410 (0, 1411 sizeof(Open_flags) / 1412 sizeof(int) - 1, 1, NULL)]; 1413 } 1414 1415 else 1416 ret = open_flags; 1417 1418 Fileinfo.openflags = ret; 1419 1420 if (Debug > 3) { 1421 printf 1422 ("%s: %d DEBUG3 %s/%d: %d Open filename = %s, open flags = %#o %s\n", 1423 Progname, Pid, __FILE__, __LINE__, 1424 Iter_cnt, filename, ret, 1425 openflags2symbols(ret, ",", 0)); 1426 } else if (Debug > 2) { 1427 printf 1428 ("%s: %d DEBUG3 %s/%d: %d filename = %s, open flags = %#o\n", 1429 Progname, Pid, __FILE__, __LINE__, 1430 Iter_cnt, filename, ret); 1431 } 1432 1433 /* 1434 * open file with desired flags. 1435 */ 1436 if ((fd = open(filename, ret, 0777)) == -1) { 1437 fprintf(stderr, 1438 "%s%s: %d %s/%d: open(%s, %#o, 0777) returned -1, errno:%d %s\n", 1439 Progname, TagName, Pid, __FILE__, 1440 __LINE__, filename, ret, errno, 1441 strerror(errno)); 1442 handle_error(); 1443 continue; 1444 } 1445 1446 Fileinfo.fd = fd; 1447 1448 lkfile(fd, LOCK_EX, LKLVL1); /* lock if lockfile is LKLVL1 */ 1449 1450 #ifndef linux 1451 /* 1452 * preallocation is only done once, if specified. 1453 */ 1454 if (pre_alloc_space) { 1455 if (pre_alloc(fd, total_grow_value) != 0) { 1456 cleanup(); 1457 exit(2); 1458 } 1459 if (Debug > 1) { 1460 printf 1461 ("%s: %d DEBUG2 %s/%d: pre_allocated %ld for file %s\n", 1462 Progname, Pid, __FILE__, __LINE__, 1463 total_grow_value, filename); 1464 } 1465 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */ 1466 close(fd); 1467 Iter_cnt = 0; /* reset outside loop to restart from one */ 1468 continue; 1469 } 1470 #endif 1471 1472 /* 1473 * grow file by desired amount. 1474 * growfile() will set the Grow_incr variable and 1475 * possiblly update the Mode variable indicating 1476 * if we are dealing with a FIFO file. 1477 */ 1478 1479 /* BUG:14136 (don't go past ext2's filesize limit) */ 1480 curr_size = file_size(fd); 1481 if (curr_size + grow_incr >= ext2_limit) { 1482 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */ 1483 close(fd); 1484 sprintf(reason, 1485 "Reached %ld filesize which is almost %ld limit.", 1486 curr_size, ext2_limit); 1487 stop = 1; 1488 continue; 1489 } 1490 1491 if (growfile(fd, filename, grow_incr, Buffer, &curr_size) != 0) { /* BUG:14136 */ 1492 handle_error(); 1493 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */ 1494 close(fd); 1495 continue; 1496 } 1497 1498 /* 1499 * check if last write is not corrupted 1500 */ 1501 if (check_write(fd, write_check_inter, filename, 1502 Mode) != 0) { 1503 handle_error(); 1504 } 1505 1506 /* 1507 * Check that whole file is not corrupted. 1508 */ 1509 if (check_file(fd, file_check_inter, filename, 1510 no_file_check) != 0) { 1511 handle_error(); 1512 } 1513 1514 /* 1515 * shrink file by desired amount if it is time 1516 */ 1517 1518 if (shrinkfile 1519 (fd, filename, trunc_incr, trunc_inter, 1520 Mode) != 0) { 1521 handle_error(); 1522 } 1523 1524 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */ 1525 1526 if (Debug > 4) 1527 printf 1528 ("%s: %d DEBUG5 %s/%d: %d Closing file %s fd:%d \n", 1529 Progname, Pid, __FILE__, __LINE__, 1530 Iter_cnt, filename, fd); 1531 close(fd); 1532 1533 /* 1534 * Unlink the file if that is desired 1535 */ 1536 if (unlink_inter && (Iter_cnt % unlink_inter == 0)) { 1537 1538 if (Debug > 4) 1539 printf 1540 ("%s: %d DEBUG5 %s/%d: %d Unlinking file %s\n", 1541 Progname, Pid, __FILE__, __LINE__, 1542 Iter_cnt, filename); 1543 1544 unlink(filename); 1545 } 1546 1547 /* 1548 * delay while staying active for "delaysecs" seconds. 1549 */ 1550 if (delaytime) { 1551 1552 int ct, end; 1553 #ifdef CRAY 1554 ct = _rtc(); 1555 end = ct + delaytime; 1556 while (ct < end) { 1557 ct = _rtc(); 1558 } 1559 #else 1560 struct timeval curtime; 1561 gettimeofday(&curtime, NULL); 1562 ct = curtime.tv_sec * USECS_PER_SEC + 1563 curtime.tv_usec; 1564 end = ct + delaytime; 1565 while (ct < end) { 1566 1567 gettimeofday(&curtime, NULL); 1568 ct = curtime.tv_sec * USECS_PER_SEC + 1569 curtime.tv_usec; 1570 } 1571 #endif 1572 } 1573 } 1574 #ifndef linux 1575 /* 1576 * if Iter_cnt == 0, then we pre allocated space to all files 1577 * and we are starting outside loop over. Set pre_alloc_space 1578 * to zero otherwise we get in infinite loop 1579 */ 1580 if (Iter_cnt == 0) { 1581 pre_alloc_space = 0; 1582 } 1583 #endif 1584 1585 } /* end iteration for loop */ 1586 1587 if (Debug) { 1588 printf("%s%s: %d %s/%d: DONE %d iterations to %d files. %s\n", 1589 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, 1590 num_files, reason); 1591 } 1592 fflush(stdout); 1593 fflush(stderr); 1594 1595 cleanup(); 1596 1597 if (Errors) { 1598 if (Debug > 2) { 1599 printf("%s%s: %d DEBUG3 %d error(s) encountered\n", 1600 Progname, TagName, Pid, Errors); 1601 printf 1602 ("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", 1603 Progname, TagName, Pid, __FILE__, __LINE__); 1604 } 1605 exit(1); 1606 } 1607 if (Debug > 2) { 1608 printf 1609 ("%s%s: %d DEBUG3 %s/%d: no errors, exiting with value of 0\n", 1610 Progname, TagName, Pid, __FILE__, __LINE__); 1611 } 1612 1613 exit(0); 1614 tst_exit(); /* to keep compiler happy */ 1615 } 1616 1617 /*********************************************************************** 1618 * 1619 ***********************************************************************/ 1620 int set_sig(void) 1621 { 1622 int sig; 1623 1624 /* 1625 * now loop through all signals and set the handlers 1626 */ 1627 1628 for (sig = 1; sig < NSIG; sig++) { 1629 switch (sig) { 1630 case SIGKILL: 1631 case SIGSTOP: 1632 case SIGCONT: 1633 #ifdef CRAY 1634 case SIGINFO: 1635 case SIGRECOVERY: 1636 #endif /* CRAY */ 1637 #ifdef SIGCKPT 1638 case SIGCKPT: 1639 #endif /* SIGCKPT */ 1640 #ifdef SIGRESTART 1641 case SIGRESTART: 1642 #endif /* SIGRESTART */ 1643 case SIGCHLD: 1644 break; 1645 1646 default: 1647 #ifdef sgi 1648 sigset(sig, sig_handler); 1649 #else 1650 /* linux and cray */ 1651 signal(sig, sig_handler); 1652 #endif 1653 break; 1654 } 1655 } /* endfor */ 1656 1657 return 0; 1658 } 1659 1660 /*********************************************************************** 1661 * 1662 ***********************************************************************/ 1663 void sig_handler(int sig) 1664 { 1665 int exit_stat = 2; 1666 1667 if (sig == SIGUSR2) { 1668 fprintf(stdout, 1669 "%s%s: %d %s/%d: received SIGUSR2 (%d) - stopping.\n", 1670 Progname, TagName, Pid, __FILE__, __LINE__, sig); 1671 #ifndef sgi 1672 signal(sig, sig_handler); /* allow us to get this signal more than once */ 1673 #endif 1674 1675 } else if (sig == SIGINT) { 1676 /* The user has told us to cleanup, don't pretend it's an error. */ 1677 exit_stat = 0; 1678 if (Debug != 0) { 1679 fprintf(stderr, 1680 "%s%s: %d %s/%d: received unexpected signal: %d\n", 1681 Progname, TagName, Pid, __FILE__, __LINE__, 1682 sig); 1683 } 1684 } else { 1685 fprintf(stderr, 1686 "%s%s: %d %s/%d: received unexpected signal: %d\n", 1687 Progname, TagName, Pid, __FILE__, __LINE__, sig); 1688 } 1689 1690 notify_others(); 1691 cleanup(); 1692 if (Debug > 2) { 1693 printf("%s%s: %d DEBUG3 %s/%d: Exiting with a value of %d\n", 1694 Progname, TagName, Pid, __FILE__, __LINE__, exit_stat); 1695 } 1696 exit(exit_stat); 1697 } 1698 1699 /*********************************************************************** 1700 * this function attempts to send SIGUSR2 to other growfiles processes 1701 * telling them to stop. 1702 * 1703 ***********************************************************************/ 1704 static void notify_others(void) 1705 { 1706 static int send_signals = 0; 1707 int ind; 1708 1709 if (Sync_with_others && send_signals == 0) { 1710 1711 #if CRAY 1712 send_signals = 1; /* only send signals once */ 1713 if (Debug > 1) 1714 printf 1715 ("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pgrp\n", 1716 Progname, TagName, Pid, __FILE__, __LINE__); 1717 killm(C_PGRP, getpgrp(), SIGUSR2); 1718 #else 1719 send_signals = 1; /* only send signals once */ 1720 1721 for (ind = 0; ind < Forker_npids; ind++) { 1722 if (Forker_pids[ind] != Pid) 1723 if (Debug > 1) 1724 printf 1725 ("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pid %d\n", 1726 Progname, TagName, Pid, __FILE__, 1727 __LINE__, Forker_pids[ind]); 1728 kill(Forker_pids[ind], SIGUSR2); 1729 } 1730 #endif 1731 } 1732 1733 } 1734 1735 /*********************************************************************** 1736 * this function will count the number of errors encountered. 1737 * This function will call upanic if wanted or cleanup and 1738 * and exit is Maxerrs were encountered. 1739 ***********************************************************************/ 1740 int handle_error(void) 1741 { 1742 Errors++; 1743 1744 #ifdef CRAY 1745 if (Errors & Upanic_on_error) { 1746 upanic(PA_PANIC); 1747 } 1748 #endif 1749 1750 if (Maxerrs && Errors >= Maxerrs) { 1751 printf("%s%s: %d %s/%d: %d Hit max errors value of %d\n", 1752 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, 1753 Maxerrs); 1754 notify_others(); 1755 cleanup(); 1756 1757 if (Debug > 2) { 1758 printf("%s%s: %d DEBUG3 %d error(s) encountered\n", 1759 Progname, TagName, Pid, Errors); 1760 printf 1761 ("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", 1762 Progname, TagName, Pid, __FILE__, __LINE__); 1763 } 1764 1765 exit(1); 1766 } 1767 1768 return 0; 1769 } 1770 1771 /*********************************************************************** 1772 * 1773 ***********************************************************************/ 1774 int cleanup(void) 1775 { 1776 int ind; 1777 1778 if (remove_files) { 1779 if (Debug > 2) 1780 printf("%s: %d DEBUG3 Removing all %d files\n", 1781 Progname, Pid, num_files); 1782 for (ind = 0; ind <= num_files; ind++) { 1783 unlink(filenames + (ind * PATH_MAX)); 1784 } 1785 } 1786 if (using_random && Debug > 1) 1787 printf("%s%s: %d DEBUG2 Used random seed: %d\n", 1788 Progname, TagName, Pid, Seed); 1789 return 0; 1790 } 1791 1792 /*********************************************************************** 1793 * 1794 ***********************************************************************/ 1795 void usage(void) 1796 { 1797 fprintf(stderr, 1798 "Usage: %s%s [-bhEluy][[-g grow_incr][-i num][-t trunc_incr][-T trunc_inter]\n", 1799 Progname, TagName); 1800 fprintf(stderr, 1801 "[-d auto_dir][-e maxerrs][-f auto_file][-N num_files][-w][-c chk_inter][-D debug]\n"); 1802 fprintf(stderr, 1803 "[-s seed][-S seq_auto_files][-p][-P PANIC][-I io_type][-o open_flags][-B maxbytes]\n"); 1804 fprintf(stderr, 1805 "[-r iosizes][-R lseeks][-U unlk_inter][-W tagname] [files]\n"); 1806 1807 return; 1808 1809 } /* end of usage */ 1810 1811 /*********************************************************************** 1812 * 1813 ***********************************************************************/ 1814 void help(void) 1815 { 1816 usage(); 1817 1818 fprintf(stdout, "\ 1819 -h Specfied to print this help and exit.\n\ 1820 -b Specfied to execute in sync mode.(def async mode)\n\ 1821 -B maxbytes Max bytes to consume by all files. growfiles exits when more\n\ 1822 than maxbytes have been consumed. (def no chk) If maxbytes ends\n\ 1823 with the letter 'b', maxbytes is multiplied by BSIZE\n\ 1824 -C write_chk Specifies how often to check the last write (default 1)\n\ 1825 -c file_chk Specifies how often to check whole file (default 0)\n\ 1826 -d auto_dir Specifies the directory to auto created files. (default .)\n\ 1827 -D debug_lvl Specifies the debug level (default 1)\n\ 1828 -E Print examples and exit\n\ 1829 -e errs The number errors that will terminate this program (def 100)\n\ 1830 -f auto_file Specifies the base filename files created. (default \"gf\")\n\ 1831 -g grow_incr Specfied to grow by incr for each num. (default 4096)\n\ 1832 grow_incr may end in b for blocks\n\ 1833 If -r option is used, this option is ignored and size is random\n\ 1834 -H delay Amount of time to delay between each file (default 0.0)\n\ 1835 -I io_type Specifies io type: s - sync, p - polled async, a - async (def s)\n\ 1836 l - listio sync, L - listio async, r - random\n\ 1837 -i iteration Specfied to grow each file num times. 0 means forever (default 1)\n\ 1838 -l Specfied to do file locking around write/read/trunc\n\ 1839 If specified twice, file locking after open to just before close\n\ 1840 -L time Specfied to exit after time secs, must be used with -i.\n\ 1841 -N num_files Specifies the number of files to be created.\n\ 1842 The default is zero if cmd line files.\n\ 1843 The default is one if no cmd line files.\n\ 1844 -n num_procs Specifies the number of copies of this cmd.\n\ 1845 -o op_type Specifies open flages: (def O_RDWR,O_CREAT) op_type can be 'random'\n\ 1846 -O offset adjust i/o buffer alignment by offset bytes\n\ 1847 -P PANIC Specifies to call upanic on error.\n\ 1848 -p Specifies to pre-allocate space\n\ 1849 -q pattern pattern can be a - ascii, p - pid with boff, o boff (def)\n\ 1850 A - Alternating bits, r - random, O - all ones, z - all zeros,\n\ 1851 c - checkboard, C - counting\n\ 1852 -R [min-]max random lseek before write and trunc, max of -1 means filesz,\n\ 1853 -2 means filesz+grow, -3 filesz-grow. (min def is 0)\n\ 1854 -r [min-]max random io write size (min def is 1)\n\ 1855 -S seq_auto_files Specifies the number of seqental auto files (default 0)\n\ 1856 -s seed[,seed...] Specifies the random number seed (default time(0)+pid)\n\ 1857 -t trunc_incr Specfied the amount to shrink file. (default 4096)\n\ 1858 trunc_inter may end in b for blocks\n\ 1859 If -R option is used, this option is ignored and trunc is random\n\ 1860 -T trunc_inter Specfied the how many grows happen before shrink. (default 0)\n\ 1861 -u unlink files before exit\n\ 1862 -U ui[-ui2] Unlink files each ui iteration (def 0)\n\ 1863 -w Specfied to grow via lseek instead of writes.\n\ 1864 -W tag-name Who-am-i. My Monster tag name. (used by Monster).\n\ 1865 -x Re-exec children before continuing - useful on MPP systems\n\ 1866 -y Attempt to sync copies - if one fails it will send sigusr2 to others\n\ 1867 Action to each file every iteration is open, write, write check\n\ 1868 file check, trunc and closed.\n"); 1869 1870 return; 1871 } 1872 1873 /*********************************************************************** 1874 * 1875 ***********************************************************************/ 1876 void prt_examples(FILE * stream) 1877 { 1878 /* This example creates 200 files in directory dir1. It writes */ 1879 /* 4090 bytes 100 times then truncates 408990 bytes off the file */ 1880 /* The file contents are checked every 1000 grow. */ 1881 fprintf(stream, 1882 "# run forever: writes of 4090 bytes then on every 100 iterval\n\ 1883 # truncate file by 408990 bytes. Done to 200 files in dir1.\n\ 1884 %s -i 0 -g 4090 -T 100 -t 408990 -l -C 10 -c 1000 -d dir1 -S 200\n\n", 1885 Progname); 1886 1887 /* same as above with 5000 byte grow and a 499990 byte tuncate */ 1888 fprintf(stream, 1889 "# same as above with writes of 5000 bytes and truncs of 499990\n\ 1890 %s -i 0 -g 5000 -T 100 -t 499990 -l -C 10 -c 1000 -d dir2 -S 200\n\n", 1891 Progname); 1892 1893 /* This example beats on opens and closes */ 1894 fprintf(stream, 1895 "# runs forever: beats on opens and closes of file ocfile - no io\n\ 1896 %s -i 0 -g 0 -c 0 -C 0 ocfile\n\n", 1897 Progname); 1898 1899 fprintf(stream, "# writes 4096 to files until 50 blocks are written\n\ 1900 %s -i 0 -g 4096 -B 50b file1 file2\n\n", Progname); 1901 1902 fprintf(stream, 1903 "# write one byte to 750 files in gdir then unlinks them\n\ 1904 %s -g 1 -C 0 -d gdir -u -S 750\n\n", Progname); 1905 1906 fprintf(stream, "# run 30 secs: random iosize, random lseek up to eof\n\ 1907 %s -r 1-5000 -R 0--1 -i 0 -L 30 -C 1 g_rand1 g_rand2\n\n", Progname); 1908 1909 fprintf(stream, 1910 "# run 30 secs: grow by lseek then write single byte, trunc every 10 itervals\n\ 1911 %s -g 5000 -wlu -i 0 -L 30 -C 1 -T 10 g_sleek1 g_lseek2\n\n", 1912 Progname); 1913 1914 fprintf(stream, 1915 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\ 1916 # rand io types doing a trunc every 5 iterations, with unlinks.\n\ 1917 %s -i0 -r 1-50000 -R 0--2 -I r -C1 -l -n5 -u -U 100-200 gf_rana gf_ranb\n\n", 1918 Progname); 1919 1920 fprintf(stream, 1921 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\ 1922 # random open flags, rand io types doing a trunc every 10 iterations.\n\ 1923 %s -i0 -r 1-50000 -R 0--2 -o random -I r -C0 -l -T 20 -uU100-200 -n 5 gf_rand1 gf_rand2\n", 1924 Progname); 1925 1926 return; 1927 } 1928 1929 /*********************************************************************** 1930 * 1931 * The file descriptor current offset is assumed to be the end of the 1932 * file. 1933 * Woffset will be set to the offset before the write. 1934 * Grow_incr will be set to the size of the write or lseek write. 1935 ***********************************************************************/ 1936 int /* BUG:14136 */ growfile(int fd, char *file, int grow_incr, char *buf, 1937 unsigned long *curr_size_ptr) 1938 { 1939 off_t noffset; 1940 int ret; 1941 int cur_offset; 1942 char *errmsg; 1943 off_t fsize; /* current size of file */ 1944 int size_grew; /* size the file grew */ 1945 struct stat stbuf; 1946 off_t off_tmp = 0; 1947 1948 /* 1949 * Do a stat on the open file. 1950 * If the file is a fifo, set the bit in Mode variable. 1951 * This fifo check must be done prior to growfile() returning. 1952 * Also get the current size of the file. 1953 */ 1954 if (fstat(fd, &stbuf) != -1) { 1955 if (S_ISFIFO(stbuf.st_mode)) { 1956 Fileinfo.mode |= MODE_FIFO; 1957 Mode |= MODE_FIFO; 1958 if (Debug > 3) 1959 printf 1960 ("%s: %d DEBUG4 %s/%d: file is a fifo - no lseek or truncs,\n", 1961 Progname, Pid, __FILE__, __LINE__); 1962 } 1963 fsize = stbuf.st_size; 1964 1965 } else { 1966 fprintf(stderr, 1967 "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n", 1968 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, 1969 strerror(errno)); 1970 1971 return -1; 1972 } 1973 1974 if (grow_incr <= 0) { /* don't attempt i/o if grow_incr <= 0 */ 1975 1976 Grow_incr = grow_incr; 1977 if (Debug > 2) 1978 printf 1979 ("%s: %d DEBUG3 %s/%d: Not attempting to grow, growsize == %d\n", 1980 Progname, Pid, __FILE__, __LINE__, grow_incr); 1981 return grow_incr; 1982 } 1983 1984 if (Mode & MODE_RAND_SIZE) { 1985 grow_incr = 1986 random_range(min_size, max_size, mult_size, &errmsg); 1987 if (errmsg != NULL) { 1988 fprintf(stderr, 1989 "%s%s: %d %s/%d: random_range() failed - %s\n", 1990 Progname, TagName, Pid, __FILE__, __LINE__, 1991 errmsg); 1992 return -1; 1993 } 1994 Grow_incr = grow_incr; 1995 } else 1996 Grow_incr = grow_incr; 1997 1998 if (!(Mode & MODE_FIFO)) { 1999 if ((cur_offset = lseek(fd, 0, SEEK_CUR)) == -1) { 2000 fprintf(stderr, "%s%s: %d %s/%d: tell failed: %s\n", 2001 Progname, TagName, Pid, __FILE__, __LINE__, 2002 strerror(errno)); 2003 return -1; 2004 } 2005 } 2006 2007 if (Mode & MODE_GROW_BY_LSEEK) { 2008 Woffset = fsize; 2009 if (Debug > 2) { 2010 printf 2011 ("%s: %d DEBUG3 %s/%d: Current size of file is %ld\n", 2012 Progname, Pid, __FILE__, __LINE__, (long)Woffset); 2013 printf 2014 ("%s: %d DEBUG3 %s/%d: lseeking to %d byte with SEEK_END\n", 2015 Progname, Pid, __FILE__, __LINE__, grow_incr - 1); 2016 } 2017 2018 if ((noffset = lseek(fd, grow_incr - 1, SEEK_END)) == -1) { 2019 fprintf(stderr, 2020 "%s%s: %s/%d: lseek(fd, %d, SEEK_END) failed: %s\n", 2021 Progname, TagName, __FILE__, __LINE__, 2022 grow_incr - 1, strerror(errno)); 2023 return -1; 2024 } 2025 2026 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */ 2027 2028 #if NEWIO 2029 ret = 2030 lio_write_buffer(fd, io_type, "w", 1, SIGUSR1, &errmsg, 0); 2031 #else 2032 ret = write_buffer(fd, io_type, "w", 1, 0, &errmsg); 2033 #endif 2034 2035 if (ret != 1) { 2036 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n", 2037 Progname, TagName, Pid, __FILE__, __LINE__, 2038 Iter_cnt, errmsg); 2039 if (ret == -ENOSPC) { 2040 cleanup(); 2041 exit(2); 2042 } 2043 } 2044 /*** 2045 write(fd, "w", 1); 2046 ****/ 2047 2048 lkfile(fd, LOCK_UN, LKLVL0); 2049 2050 if (Debug > 2) 2051 printf("%s: %d DEBUG3 %s/%d: %d wrote 1 byte to file\n", 2052 Progname, Pid, __FILE__, __LINE__, Iter_cnt); 2053 2054 } else { /* end of grow by lseek */ 2055 2056 if (Fileinfo.openflags & O_APPEND) { 2057 /* 2058 * Deal with special case of the open flag containing O_APPEND. 2059 * If it does, the current offset does not matter since the write 2060 * will be done end of the file. 2061 */ 2062 if (Debug > 4) 2063 printf 2064 ("%s: %d DEBUG5 %s/%d: dealing with O_APPEND condition\n", 2065 Progname, Pid, __FILE__, __LINE__); 2066 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */ 2067 2068 /* 2069 * do fstat again to get size of the file. 2070 * This is done inside a file lock (if locks are being used). 2071 */ 2072 if (fstat(fd, &stbuf) != -1) { 2073 Woffset = stbuf.st_size; 2074 } else { 2075 fprintf(stderr, 2076 "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n", 2077 Progname, TagName, Pid, __FILE__, 2078 __LINE__, fd, errno, strerror(errno)); 2079 2080 lkfile(fd, LOCK_UN, LKLVL0); /* release lock */ 2081 return -1; 2082 } 2083 if (Debug > 2) 2084 printf 2085 ("%s: %d DEBUG3 %s/%d: dealing with O_APPEND condition (offset:fsz:%d)\n", 2086 Progname, Pid, __FILE__, __LINE__, 2087 (int)stbuf.st_size); 2088 2089 } else if (Mode & MODE_RAND_LSEEK) { 2090 if (max_lseek == LSK_EOF) { /* within file size */ 2091 noffset = 2092 random_range(min_lseek, fsize, 1, NULL); 2093 } else if (max_lseek == LSK_EOFPLUSGROW) { 2094 /* max to beyond file size */ 2095 noffset = 2096 random_range(min_lseek, fsize + grow_incr, 2097 1, NULL); 2098 } else if (max_lseek == LSK_EOFMINUSGROW) { 2099 /* 2100 * Attempt to not grow the file. 2101 * If the i/o will fit from min_lseek to EOF, 2102 * pick offset to allow it to fit. 2103 * Otherwise, pick the min_lseek offset and grow 2104 * file by smallest amount. 2105 * If min_lseek is != 0, there will be a problem 2106 * with whole file checking if file is ever smaller 2107 * than min_lseek. 2108 */ 2109 if (fsize <= min_lseek + grow_incr) 2110 noffset = min_lseek; /* file will still grow */ 2111 else 2112 noffset = 2113 random_range(min_lseek, 2114 fsize - grow_incr, 1, 2115 NULL); 2116 } else { 2117 noffset = 2118 random_range(min_lseek, max_lseek, 1, NULL); 2119 } 2120 2121 if ((Woffset = lseek(fd, noffset, SEEK_SET)) == -1) { 2122 fprintf(stderr, 2123 "%s%s: %d %s/%d: lseek(%d, %ld, " 2124 "SEEK_SET) l2 failed: %s\n", Progname, 2125 TagName, Pid, __FILE__, __LINE__, fd, 2126 (long)noffset, strerror(errno)); 2127 return -1; 2128 } else if (Debug > 2) 2129 printf("%s: %d DEBUG3 %s/%d: lseeked to " 2130 "random offset %ld (fsz:%d)\n", 2131 Progname, Pid, __FILE__, __LINE__, 2132 (long)Woffset, (int)stbuf.st_size); 2133 2134 } 2135 2136 /* 2137 * lseek to end of file only if not fifo 2138 */ 2139 else if (!(Mode & MODE_FIFO)) { 2140 if ((Woffset = lseek(fd, 0, SEEK_END)) == -1) { 2141 fprintf(stderr, 2142 "%s%s: %d %s/%d: lseek(fd, 0, SEEK_END) failed: %s\n", 2143 Progname, TagName, Pid, __FILE__, 2144 __LINE__, strerror(errno)); 2145 return -1; 2146 } else if (Debug > 2) 2147 printf("%s: %d DEBUG3 %s/%d: lseeked to " 2148 "end of file, offset %ld\n", 2149 Progname, Pid, __FILE__, __LINE__, 2150 (long)Woffset); 2151 } 2152 2153 if (Pattern == PATTERN_OFFSET) 2154 datapidgen(STATIC_NUM, buf, grow_incr, Woffset); 2155 else if (Pattern == PATTERN_PID) 2156 datapidgen(Pid, buf, grow_incr, Woffset); 2157 else if (Pattern == PATTERN_ASCII) 2158 dataasciigen(NULL, buf, grow_incr, Woffset); 2159 else if (Pattern == PATTERN_RANDOM) 2160 databingen('r', buf, grow_incr, Woffset); 2161 else if (Pattern == PATTERN_ALT) 2162 databingen('a', buf, grow_incr, Woffset); 2163 else if (Pattern == PATTERN_CHKER) 2164 databingen('c', buf, grow_incr, Woffset); 2165 else if (Pattern == PATTERN_CNTING) 2166 databingen('C', buf, grow_incr, Woffset); 2167 else if (Pattern == PATTERN_ZEROS) 2168 databingen('z', buf, grow_incr, Woffset); 2169 else if (Pattern == PATTERN_ONES) 2170 databingen('o', buf, grow_incr, Woffset); 2171 else 2172 dataasciigen(NULL, buf, grow_incr, Woffset); 2173 2174 if (Debug > 2) 2175 printf 2176 ("%s: %d DEBUG3 %s/%d: attempting to write %d bytes\n", 2177 Progname, Pid, __FILE__, __LINE__, grow_incr); 2178 2179 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */ 2180 2181 /***** 2182 ret=write(fd, buf, grow_incr); 2183 2184 off_tmp = tell(fd); 2185 2186 lkfile(fd, LOCK_UN, LKLVL0); 2187 2188 if (ret != grow_incr) { 2189 fprintf(stderr, "%s: %s/%d: write failed: %s\n", 2190 Progname, __FILE__, __LINE__, strerror(errno)); 2191 return -1; 2192 } 2193 *****/ 2194 2195 #if NEWIO 2196 ret = lio_write_buffer(fd, io_type, buf, grow_incr, 2197 SIGUSR1, &errmsg, 0); 2198 #else 2199 ret = write_buffer(fd, io_type, buf, grow_incr, 0, &errmsg); 2200 #endif 2201 2202 if (Mode & MODE_FIFO) { 2203 /* If it is a fifo then just pretend the file 2204 * offset is where we think it should be. 2205 */ 2206 off_tmp = Woffset + grow_incr; 2207 } else { 2208 if ((off_tmp = lseek(fd, 0, SEEK_CUR)) < 0) { /* get offset after the write */ 2209 fprintf(stderr, 2210 "%s%s: %s/%d: tell(2) failed: %d %s\n", 2211 Progname, TagName, __FILE__, __LINE__, 2212 errno, strerror(errno)); 2213 return -1; 2214 } 2215 #if NEWIO 2216 #if defined(sgi) || defined(__linux__) 2217 /* If this is POSIX I/O and it is via aio_{read,write} 2218 * or lio_listio then after completion of the I/O the 2219 * value of the file offset for the file is 2220 * unspecified--which means we cannot trust what 2221 * tell() told us. Fudge it here. 2222 */ 2223 if ((io_type & LIO_IO_ASYNC_TYPES) 2224 || (io_type & LIO_RANDOM)) { 2225 if (off_tmp != Woffset + grow_incr) { 2226 if (Debug > 5) { 2227 printf 2228 ("%s: %d DEBUG6 %s/%d: posix fudge, forcing tmp (%" 2229 PRId64 2230 ") to match Woffset+grow_incr (%" 2231 PRId64 ")\n", Progname, 2232 Pid, __FILE__, __LINE__, 2233 (int64_t) off_tmp, 2234 (int64_t) Woffset + 2235 grow_incr); 2236 } 2237 off_tmp = Woffset + grow_incr; 2238 } 2239 } 2240 #endif /* sgi __linux__ */ 2241 #endif 2242 } 2243 *curr_size_ptr = off_tmp; /* BUG:14136 */ 2244 2245 lkfile(fd, LOCK_UN, LKLVL0); 2246 2247 if (ret != grow_incr) { 2248 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n", 2249 Progname, TagName, Pid, __FILE__, __LINE__, 2250 Iter_cnt, errmsg); 2251 if (ret == -ENOSPC) { 2252 cleanup(); 2253 exit(2); 2254 } 2255 return -1; 2256 } 2257 2258 /* 2259 * Check for a condition where the file was truncated just before 2260 * the write. 2261 */ 2262 if (off_tmp != Woffset + grow_incr) { 2263 /* 2264 * The offset after the write was not as expected. 2265 * This could be caused by the following: 2266 * - file truncated after the lseek and before the write. 2267 * - the file was written to after fstat and before the write 2268 * and the file was opened with O_APPEND. 2269 * 2270 * The pattern written to the file will be considered corrupted. 2271 */ 2272 if (Debug > 0 && lockfile) { 2273 printf("%s%s: %d DEBUG1 %s/%d: offset after " 2274 "write(%ld) not as exp(%ld+%d=%ld)\n", 2275 Progname, TagName, Pid, __FILE__, 2276 __LINE__, (long)off_tmp, (long)Woffset, 2277 grow_incr, (long)(Woffset + grow_incr)); 2278 printf 2279 ("%s%s: %d DEBUG1 %s/%d: %d Assuming file " 2280 "changed by another process, resetting " 2281 "offset:%ld (expect pattern mismatch)\n", 2282 Progname, TagName, Pid, __FILE__, __LINE__, 2283 Iter_cnt, (long)(off_tmp - grow_incr)); 2284 } 2285 if (Debug > 4) { 2286 printf 2287 ("%s: %d DEBUG5 %s/%d: about to chop Woffset. " 2288 "tmp=%ld, grow_incr=%d, Woffset was %ld\n", 2289 Progname, Pid, __FILE__, __LINE__, 2290 (long)off_tmp, grow_incr, (long)Woffset); 2291 } 2292 Woffset = off_tmp - grow_incr; 2293 if (Woffset < 0) 2294 Woffset = 0; 2295 } 2296 2297 } /* end of grow by write */ 2298 2299 /* 2300 * Woffset - holds start of grow (start of write expect in grow by lseek) 2301 * Grow_incr - holds size of grow (write). 2302 * fsize - holds size of file before write 2303 */ 2304 size_grew = (Woffset + Grow_incr) - fsize; 2305 if (Debug > 1) { 2306 if (Mode & MODE_FIFO) { 2307 printf 2308 ("%s: %d DEBUG2 %s/%d: file is fifo, %d wrote %d bytes\n", 2309 Progname, Pid, __FILE__, __LINE__, Grow_incr, 2310 Iter_cnt); 2311 } 2312 2313 else if (size_grew > 0) 2314 printf 2315 ("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%ld), " 2316 "grew file by %d bytes\n", Progname, Pid, __FILE__, 2317 __LINE__, Iter_cnt, Grow_incr, (long)Woffset, 2318 size_grew); 2319 else 2320 printf 2321 ("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%ld), " 2322 "did not grow file\n", Progname, Pid, __FILE__, 2323 __LINE__, Iter_cnt, Grow_incr, (long)Woffset); 2324 } 2325 2326 bytes_consumed += size_grew; 2327 return 0; 2328 2329 } /* end of growfile */ 2330 2331 /*********************************************************************** 2332 * shrinkfile file by trunc_incr. file can not be made smaller than 2333 * size zero. Therefore, if trunc_incr is larger than file size, 2334 * file will be truncated to zero. 2335 * The file descriptor current offset is assumed to be the end of the 2336 * file. 2337 * 2338 ***********************************************************************/ 2339 int 2340 shrinkfile(int fd, char *filename, int trunc_incr, int trunc_inter, 2341 int just_trunc) 2342 { 2343 static int shrink_cnt = 0; 2344 int cur_offset; 2345 int new_offset; 2346 int ret; 2347 #ifdef CRAY 2348 int offset; 2349 #endif 2350 2351 shrink_cnt++; 2352 2353 if (trunc_inter == 0 || (shrink_cnt % trunc_inter != 0)) { 2354 if (Debug > 3) 2355 printf 2356 ("%s: %d DEBUG4 %s/%d: Not shrinking file - not time, iter=%d, cnt=%d\n", 2357 Progname, Pid, __FILE__, __LINE__, trunc_inter, 2358 shrink_cnt); 2359 return 0; /* not this time */ 2360 } 2361 2362 if (Mode & MODE_FIFO) { 2363 if (Debug > 5) 2364 printf 2365 ("%s: %d DEBUG5 %s/%d: Not attempting to shrink a FIFO\n", 2366 Progname, Pid, __FILE__, __LINE__); 2367 return 0; /* can not truncate fifo */ 2368 } 2369 2370 lkfile(fd, LOCK_EX, LKLVL0); 2371 2372 if ((cur_offset = lseek(fd, 0, SEEK_CUR)) == -1) { 2373 fprintf(stderr, "%s%s: %d %s/%d: tell(%d) failed: %s\n", 2374 Progname, TagName, Pid, __FILE__, __LINE__, fd, 2375 strerror(errno)); 2376 lkfile(fd, LOCK_UN, LKLVL0); 2377 return -1; 2378 } 2379 2380 if (Mode & MODE_RAND_LSEEK) { 2381 if (max_lseek <= -1) { 2382 if ((new_offset = file_size(fd)) == -1) { 2383 lkfile(fd, LOCK_UN, LKLVL0); 2384 return -1; 2385 } 2386 2387 if (new_offset < min_lseek) 2388 new_offset = min_lseek; 2389 else 2390 new_offset = 2391 random_range(min_lseek, new_offset, 1, 2392 NULL); 2393 } else { 2394 new_offset = 2395 random_range(min_lseek, max_lseek, 1, NULL); 2396 } 2397 2398 #ifdef CRAY 2399 if ((offset = lseek(fd, new_offset, SEEK_SET)) == -1) { 2400 fprintf(stderr, 2401 "%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l3 failed: %s\n", 2402 Progname, TagName, Pid, __FILE__, __LINE__, fd, 2403 new_offset, strerror(errno)); 2404 lkfile(fd, LOCK_UN, LKLVL0); 2405 return -1; 2406 } else if (Debug > 3) 2407 printf 2408 ("%s: %d DEBUG4 %s/%d: lseeked to random offset %d\n", 2409 Progname, Pid, __FILE__, __LINE__, offset); 2410 2411 #endif 2412 } 2413 2414 else { /* remove trunc_incr from file */ 2415 2416 new_offset = cur_offset - trunc_incr; 2417 2418 if (new_offset < 0) 2419 new_offset = 0; 2420 2421 #ifdef CRAY 2422 if (lseek(fd, new_offset, SEEK_SET) == -1) { 2423 fprintf(stderr, 2424 "%s%s: %d %s/%d: lseek(fd, %d, SEEK_SET) l4 failed: %s\n", 2425 Progname, TagName, Pid, __FILE__, __LINE__, 2426 new_offset, strerror(errno)); 2427 lkfile(fd, LOCK_UN, LKLVL0); 2428 return -1; 2429 } else if (Debug > 3) 2430 printf 2431 ("%s: %d DEBUG4 %s/%d: lseeked to offset %d, %d bytes from end\n", 2432 Progname, Pid, __FILE__, __LINE__, new_offset, 2433 trunc_incr); 2434 #endif 2435 } 2436 2437 #ifdef CRAY 2438 ret = trunc(fd); 2439 #else 2440 ret = ftruncate(fd, new_offset); 2441 if (ret == 0 && Debug > 3) { 2442 printf 2443 ("%s: %d DEBUG4 %s/%d: ftruncated to offset %d, %d bytes from end\n", 2444 Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr); 2445 } 2446 #endif 2447 2448 lkfile(fd, LOCK_UN, LKLVL0); 2449 2450 if (ret == -1) { 2451 #ifdef CRAY 2452 fprintf(stderr, "%s%s: %d %s/%d: trunc failed: %s\n", 2453 Progname, TagName, Pid, __FILE__, __LINE__, 2454 strerror(errno)); 2455 #else 2456 fprintf(stderr, "%s%s: %d %s/%d: ftruncate failed: %s\n", 2457 Progname, TagName, Pid, __FILE__, __LINE__, 2458 strerror(errno)); 2459 #endif 2460 return -1; 2461 } 2462 2463 if (Debug > 2) { 2464 printf 2465 ("%s: %d DEBUG2 %s/%d: trunc file by %d bytes, to size of = %d bytes\n", 2466 Progname, Pid, __FILE__, __LINE__, cur_offset - new_offset, 2467 new_offset); 2468 } 2469 2470 bytes_consumed -= (cur_offset - new_offset); 2471 return 0; 2472 2473 } /* end of shrinkfile */ 2474 2475 /*********************************************************************** 2476 * 2477 ***********************************************************************/ 2478 int check_write(int fd, int cf_inter, char *filename, int mode) 2479 { 2480 int fsize; 2481 static int cf_count = 0; 2482 int ret = 0; 2483 int tmp; 2484 char *errmsg; 2485 char *ptr; 2486 2487 cf_count++; 2488 2489 if (cf_inter == 0 || (cf_count % cf_inter != 0)) { 2490 if (Debug > 4) 2491 printf 2492 ("%s: %d DEBUG5 %s/%d: no write check, not time iter=%d, cnt=%d\n", 2493 Progname, Pid, __FILE__, __LINE__, cf_inter, 2494 cf_count); 2495 return 0; /* no check done */ 2496 } 2497 2498 if (Grow_incr <= 0) { 2499 if (Debug > 3) 2500 printf("%s: %d DEBUG4 %s/%d: No write validation, " 2501 "Grow_incr = %d, offset = %ld\n", 2502 Progname, Pid, __FILE__, __LINE__, Grow_incr, 2503 (long)Woffset); 2504 return 0; /* no check */ 2505 } 2506 2507 /* 2508 * Get the shared file lock. We need to hold the lock from before 2509 * we do the stat until after the read. 2510 */ 2511 lkfile(fd, LOCK_SH, LKLVL0); 2512 2513 if ((fsize = file_size(fd)) == -1) { 2514 lkfile(fd, LOCK_UN, LKLVL0); 2515 return -1; 2516 2517 } else if (fsize <= Woffset) { 2518 /* 2519 * The file was truncated between write and now. 2520 * The contents of our last write is totally gone, no check. 2521 */ 2522 if (Debug > 1) 2523 printf 2524 ("%s%s: %d DEBUG2 %s/%d: %d File size (%d) smaller than " 2525 "where last wrote (%ld)- no write validation\n", 2526 Progname, TagName, Pid, __FILE__, __LINE__, 2527 Iter_cnt, fsize, (long)Woffset); 2528 lkfile(fd, LOCK_UN, LKLVL0); 2529 return 0; /* no validation, but not an error */ 2530 2531 } else if (fsize < (Woffset + Grow_incr)) { 2532 /* 2533 * The file was truncated between write and now. 2534 * Part of our last write has been truncated, adjust our Grow_incr 2535 * to reflect this. 2536 */ 2537 2538 tmp = Grow_incr; 2539 Grow_incr = fsize - Woffset; 2540 2541 if (Debug > 1) { 2542 2543 printf("%s%s: %d DEBUG2 %s/%d: %d fsz:%d, lost(%d)of " 2544 "wrt(off:%ld, sz:%d), adj=%d\n", Progname, 2545 TagName, Pid, __FILE__, __LINE__, Iter_cnt, 2546 fsize, tmp - Grow_incr, (long)Woffset, tmp, 2547 Grow_incr); 2548 } 2549 2550 } 2551 2552 if (Debug > 2) 2553 printf("%s: %d DEBUG3 %s/%d: about to do write validation, " 2554 "offset = %ld, size = %d\n", 2555 Progname, Pid, __FILE__, __LINE__, (long)Woffset, 2556 Grow_incr); 2557 2558 if (!(mode & MODE_FIFO)) { 2559 2560 if (lseek(fd, Woffset, 0) == -1) { 2561 fprintf(stderr, 2562 "%s%s: %d %s/%d: lseek(fd, %ld, 0) failed: %s\n", 2563 Progname, TagName, Pid, __FILE__, __LINE__, 2564 (long)Woffset, strerror(errno)); 2565 } 2566 if (Debug > 3) 2567 printf("%s: %d DEBUG4 %s/%d: lseeked to offset:%ld\n", 2568 Progname, Pid, __FILE__, __LINE__, 2569 (long)Woffset); 2570 } 2571 2572 /* 2573 * Read last writes data 2574 */ 2575 #if NEWIO 2576 ret = 2577 lio_read_buffer(fd, io_type, Buffer, Grow_incr, SIGUSR1, &errmsg, 2578 0); 2579 #else 2580 ret = read_buffer(fd, io_type, Buffer, Grow_incr, 0, &errmsg); 2581 #endif 2582 2583 /* 2584 * report the error and debug information before releasing 2585 * the file lock 2586 */ 2587 if (ret != Grow_incr) { 2588 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s\n", Progname, TagName, 2589 Pid, __FILE__, __LINE__, Iter_cnt, errmsg); 2590 { 2591 struct stat stbuf; 2592 fstat(fd, &stbuf); 2593 if (Debug > 2) 2594 printf("%s%s: %d DEBUG3 %s/%d: fd:%d, offset:%d, fsize:%d, openflags:%#o\n", Progname, TagName, Pid, __FILE__, __LINE__, fd, (int)lseek(fd, SEEK_CUR, 0), /* FIXME: 64bit/LFS ? */ 2595 (int)stbuf.st_size, Fileinfo.openflags); 2596 } 2597 2598 lkfile(fd, LOCK_UN, LKLVL0); 2599 return 1; 2600 } 2601 2602 lkfile(fd, LOCK_UN, LKLVL0); 2603 2604 if (Mode & MODE_GROW_BY_LSEEK) { 2605 /* check that all zeros upto last character */ 2606 for (ptr = Buffer; ptr < (Buffer + Grow_incr - 1); ptr++) { 2607 if (*ptr != '\0') { 2608 fprintf(stderr, 2609 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n", 2610 Progname, TagName, Pid, __FILE__, 2611 __LINE__, 2612 (int)(Woffset + 2613 (Grow_incr - (Buffer - ptr))), 0, 2614 *ptr, filename); 2615 fflush(stderr); 2616 return 1; 2617 } 2618 } 2619 /* check that the last char is a 'w' */ 2620 if (*ptr != 'w') { 2621 fprintf(stderr, 2622 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n", 2623 Progname, TagName, Pid, __FILE__, __LINE__, 2624 (int)(Woffset + (Grow_incr - (Buffer - ptr))), 2625 'w', *ptr, filename); 2626 fflush(stderr); 2627 return 1; 2628 } 2629 return 0; /* all is well */ 2630 2631 } else if (Pattern == PATTERN_OFFSET) 2632 ret = 2633 datapidchk(STATIC_NUM, Buffer, Grow_incr, Woffset, &errmsg); 2634 else if (Pattern == PATTERN_PID) 2635 ret = datapidchk(Pid, Buffer, Grow_incr, Woffset, &errmsg); 2636 else if (Pattern == PATTERN_ASCII) 2637 ret = dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg); 2638 else if (Pattern == PATTERN_RANDOM) ; /* no check for random */ 2639 else if (Pattern == PATTERN_ALT) 2640 ret = databinchk('a', Buffer, Grow_incr, Woffset, &errmsg); 2641 else if (Pattern == PATTERN_CHKER) 2642 ret = databinchk('c', Buffer, Grow_incr, Woffset, &errmsg); 2643 else if (Pattern == PATTERN_CNTING) 2644 ret = databinchk('C', Buffer, Grow_incr, Woffset, &errmsg); 2645 else if (Pattern == PATTERN_ZEROS) 2646 ret = databinchk('z', Buffer, Grow_incr, Woffset, &errmsg); 2647 else if (Pattern == PATTERN_ONES) 2648 ret = databinchk('o', Buffer, Grow_incr, Woffset, &errmsg); 2649 else 2650 ret = dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg); 2651 2652 if (ret >= 0) { 2653 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s in file %s\n", 2654 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, 2655 errmsg, filename); 2656 2657 if (Debug > 0) 2658 printf("%s%s: %d DEBUG1 %s/%d: **fd:%d, lk:%d, " 2659 "offset:%ld, sz:%d open flags:%#o %s\n", 2660 Progname, TagName, Pid, __FILE__, __LINE__, fd, 2661 lockfile, (long)Woffset, Grow_incr, 2662 Fileinfo.openflags, 2663 openflags2symbols(Fileinfo.openflags, ",", 0)); 2664 2665 fflush(stderr); 2666 return 1; 2667 } 2668 2669 if (Debug > 6) 2670 printf("%s: %d DEBUG7 %s/%d: No corruption detected on " 2671 "write validation , offset = %ld, size = %d\n", 2672 Progname, Pid, __FILE__, __LINE__, (long)Woffset, 2673 Grow_incr); 2674 2675 return 0; /* all is well */ 2676 } 2677 2678 /*********************************************************************** 2679 * 2680 ***********************************************************************/ 2681 int check_file(int fd, int cf_inter, char *filename, int no_file_check) 2682 { 2683 int fsize; 2684 static int cf_count = 0; 2685 char *buf; 2686 int ret; 2687 int ret_val = 0; 2688 int rd_cnt; 2689 int rd_size; 2690 char *errmsg; 2691 2692 cf_count++; 2693 2694 if (cf_inter == 0 || (cf_count % cf_inter != 0)) { 2695 if (Debug > 4) 2696 printf 2697 ("%s: %d DEBUG5 %s/%d: No file check - not time, iter=%d, cnt=%d\n", 2698 Progname, Pid, __FILE__, __LINE__, cf_inter, 2699 cf_count); 2700 return 0; /* no check done */ 2701 } 2702 2703 /* 2704 * if we can't determine file content, don't bother checking 2705 */ 2706 if (no_file_check) { 2707 if (Debug > 4) 2708 printf 2709 ("%s: %d DEBUG5 %s/%d: No file check, lseek grow or random lseeks\n", 2710 Progname, Pid, __FILE__, __LINE__); 2711 return 0; 2712 } 2713 2714 /* 2715 * Lock the file. We need to have the file lock before 2716 * the stat and until after the last read to prevent 2717 * a trunc/truncate from "corrupting" our data. 2718 */ 2719 lkfile(fd, LOCK_SH, LKLVL0); 2720 2721 if ((fsize = file_size(fd)) == -1) { 2722 lkfile(fd, LOCK_UN, LKLVL0); 2723 return -1; 2724 } 2725 2726 if (fsize == 0) { 2727 if (Debug > 2) 2728 printf 2729 ("%s: %d DEBUG3 %s/%d: No file validation, file size == 0\n", 2730 Progname, Pid, __FILE__, __LINE__); 2731 2732 lkfile(fd, LOCK_UN, LKLVL0); 2733 return 0; 2734 } 2735 2736 if (Debug > 2) 2737 printf("%s: %d DEBUG3 %s/%d: about to do file validation\n", 2738 Progname, Pid, __FILE__, __LINE__); 2739 2740 if (fsize > MAX_FC_READ) { 2741 /* 2742 * read the file in MAX_FC_READ chuncks. 2743 */ 2744 2745 if ((buf = malloc(MAX_FC_READ)) == NULL) { 2746 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", 2747 Progname, TagName, __FILE__, __LINE__, 2748 MAX_FC_READ, strerror(errno)); 2749 lkfile(fd, LOCK_UN, LKLVL0); 2750 return -1; 2751 } 2752 2753 lseek(fd, 0, SEEK_SET); 2754 2755 lkfile(fd, LOCK_SH, LKLVL0); /* get lock on file before getting file size */ 2756 2757 rd_cnt = 0; 2758 while (rd_cnt < fsize) { 2759 rd_size = MIN(MAX_FC_READ, fsize - rd_cnt); 2760 2761 #if NEWIO 2762 ret = lio_read_buffer(fd, io_type, buf, rd_size, 2763 SIGUSR1, &errmsg, 0); 2764 #else 2765 ret = 2766 read_buffer(fd, io_type, buf, rd_size, 0, &errmsg); 2767 #endif 2768 2769 if (ret != rd_size) { 2770 fprintf(stderr, "%s%s: %d %s/%d: %d CFa %s\n", 2771 Progname, TagName, Pid, __FILE__, 2772 __LINE__, Iter_cnt, errmsg); 2773 free(buf); 2774 lkfile(fd, LOCK_UN, LKLVL0); 2775 return -1; 2776 } 2777 /** 2778 read(fd, buf, rd_size); 2779 ***/ 2780 2781 if (Pattern == PATTERN_OFFSET) 2782 ret = 2783 datapidchk(STATIC_NUM, buf, rd_size, rd_cnt, 2784 &errmsg); 2785 else if (Pattern == PATTERN_PID) 2786 ret = 2787 datapidchk(Pid, buf, rd_size, rd_cnt, 2788 &errmsg); 2789 else if (Pattern == PATTERN_ASCII) 2790 ret = 2791 dataasciichk(NULL, buf, rd_size, rd_cnt, 2792 &errmsg); 2793 else if (Pattern == PATTERN_RANDOM) ; /* no checks for random */ 2794 else if (Pattern == PATTERN_ALT) 2795 ret = 2796 databinchk('a', buf, rd_size, rd_cnt, 2797 &errmsg); 2798 else if (Pattern == PATTERN_CHKER) 2799 ret = 2800 databinchk('c', buf, rd_size, rd_cnt, 2801 &errmsg); 2802 else if (Pattern == PATTERN_CNTING) 2803 ret = 2804 databinchk('C', buf, rd_size, rd_cnt, 2805 &errmsg); 2806 else if (Pattern == PATTERN_ZEROS) 2807 ret = 2808 databinchk('z', buf, rd_size, rd_cnt, 2809 &errmsg); 2810 else if (Pattern == PATTERN_ONES) 2811 ret = 2812 databinchk('o', buf, rd_size, rd_cnt, 2813 &errmsg); 2814 else 2815 ret = 2816 dataasciichk(NULL, buf, rd_size, rd_cnt, 2817 &errmsg); 2818 2819 if (ret >= 0) { 2820 fprintf(stderr, 2821 "%s%s: %d %s/%d: %d CFp %s in file %s\n", 2822 Progname, TagName, Pid, __FILE__, 2823 __LINE__, Iter_cnt, errmsg, filename); 2824 fflush(stderr); 2825 ret_val = 1; 2826 lkfile(fd, LOCK_UN, LKLVL0); 2827 break; 2828 } 2829 rd_cnt += rd_size; 2830 } 2831 2832 lkfile(fd, LOCK_UN, LKLVL0); 2833 2834 free(buf); 2835 2836 } else { 2837 /* 2838 * Read the whole file in a single read 2839 */ 2840 if ((buf = malloc(fsize)) == NULL) { 2841 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", 2842 Progname, TagName, __FILE__, __LINE__, fsize, 2843 strerror(errno)); 2844 fflush(stderr); 2845 return -1; 2846 } 2847 2848 lseek(fd, 0, SEEK_SET); 2849 2850 /**** 2851 read(fd, buf, fsize); 2852 ****/ 2853 #if NEWIO 2854 ret = 2855 lio_read_buffer(fd, io_type, buf, fsize, SIGUSR1, &errmsg, 2856 0); 2857 #else 2858 ret = read_buffer(fd, io_type, buf, fsize, 0, &errmsg); 2859 #endif 2860 2861 /* unlock the file as soon as we can */ 2862 lkfile(fd, LOCK_UN, LKLVL0); 2863 2864 if (ret != fsize) { 2865 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s\n", 2866 Progname, TagName, Pid, __FILE__, __LINE__, 2867 Iter_cnt, errmsg); 2868 ret_val = 1; 2869 } else { 2870 if (Pattern == PATTERN_OFFSET) 2871 ret = 2872 datapidchk(STATIC_NUM, buf, fsize, 0, 2873 &errmsg); 2874 else if (Pattern == PATTERN_PID) 2875 ret = datapidchk(Pid, buf, fsize, 0, &errmsg); 2876 else if (Pattern == PATTERN_ASCII) 2877 ret = 2878 dataasciichk(NULL, buf, fsize, 0, &errmsg); 2879 else if (Pattern == PATTERN_RANDOM) ; /* no check for random */ 2880 else if (Pattern == PATTERN_ALT) 2881 ret = databinchk('a', buf, fsize, 0, &errmsg); 2882 else if (Pattern == PATTERN_CHKER) 2883 ret = databinchk('c', buf, fsize, 0, &errmsg); 2884 else if (Pattern == PATTERN_CNTING) 2885 ret = databinchk('C', buf, fsize, 0, &errmsg); 2886 else if (Pattern == PATTERN_ZEROS) 2887 ret = databinchk('z', buf, fsize, 0, &errmsg); 2888 else if (Pattern == PATTERN_ONES) 2889 ret = databinchk('o', buf, fsize, 0, &errmsg); 2890 else 2891 ret = 2892 dataasciichk(NULL, buf, fsize, 0, &errmsg); 2893 2894 if (ret >= 0) { 2895 fprintf(stderr, 2896 "%s%s: %d %s/%d: %d CFw %s in file %s\n", 2897 Progname, TagName, Pid, __FILE__, 2898 __LINE__, Iter_cnt, errmsg, filename); 2899 fflush(stderr); 2900 ret_val = 1; 2901 } 2902 } 2903 free(buf); 2904 } 2905 2906 return ret_val; 2907 2908 } /* end of check_file */ 2909 2910 /*********************************************************************** 2911 * 2912 ***********************************************************************/ 2913 int file_size(int fd) 2914 { 2915 struct stat sb; 2916 2917 if (fstat(fd, &sb) < 0) { 2918 fprintf(stderr, 2919 "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n", 2920 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, 2921 strerror(errno)); 2922 return -1; 2923 2924 } 2925 2926 return sb.st_size; 2927 } 2928 2929 /*********************************************************************** 2930 * do file lock/unlock action. 2931 ***********************************************************************/ 2932 int lkfile(int fd, int operation, int lklevel) 2933 { 2934 char *errmsg; 2935 2936 if (lockfile == lklevel) { 2937 2938 if (Debug > 5) { 2939 switch (operation) { 2940 case LOCK_UN: 2941 printf 2942 ("%s: %d DEBUG6 %s/%d: Attempting to release lock on fd %d\n", 2943 Progname, Pid, __FILE__, __LINE__, fd); 2944 break; 2945 2946 case LOCK_SH: 2947 printf 2948 ("%s: %d DEBUG6 %s/%d: Attempting to get read/shared lock on fd %d\n", 2949 Progname, Pid, __FILE__, __LINE__, fd); 2950 break; 2951 2952 case LOCK_EX: 2953 printf 2954 ("%s: %d DEBUG6 %s/%d: Attempting to get write/exclusive lock on fd %d\n", 2955 Progname, Pid, __FILE__, __LINE__, fd); 2956 break; 2957 } 2958 } 2959 2960 /* 2961 * Attempt to get/release desired lock. 2962 * file_lock will attempt to do action over and over again until 2963 * either an unretryable error or the action is completed. 2964 */ 2965 2966 if (file_lock(fd, operation, &errmsg) != 0) { 2967 printf 2968 ("%s%s: %d %s/%d: Unable to perform lock operation. %s\n", 2969 Progname, TagName, Pid, __FILE__, __LINE__, 2970 errmsg); 2971 2972 /* do we count this as an error? handle_error(); */ 2973 return -1; 2974 } 2975 2976 if (Debug > 2) { 2977 switch (operation) { 2978 case LOCK_UN: 2979 printf 2980 ("%s: %d DEBUG3 %s/%d: Released lock on fd %d\n", 2981 Progname, Pid, __FILE__, __LINE__, fd); 2982 break; 2983 2984 case LOCK_SH: 2985 printf 2986 ("%s: %d DEBUG3 %s/%d: Got read/shared lock on fd %d\n", 2987 Progname, Pid, __FILE__, __LINE__, fd); 2988 break; 2989 2990 case LOCK_EX: 2991 printf 2992 ("%s: %d DEBUG3 %s/%d: Got write/exclusive lock on fd %d\n", 2993 Progname, Pid, __FILE__, __LINE__, fd); 2994 break; 2995 2996 default: 2997 printf 2998 ("%s: %d DEBUG3 %s/%d: Completed action %d on fd %d\n", 2999 Progname, Pid, __FILE__, __LINE__, 3000 operation, fd); 3001 break; 3002 } 3003 } 3004 } 3005 3006 return 0; 3007 } 3008 3009 #ifndef linux 3010 /*********************************************************************** 3011 * 3012 ***********************************************************************/ 3013 int pre_alloc(int fd, long size) 3014 { 3015 3016 #ifdef CRAY 3017 long avl; 3018 3019 if (ialloc(fd, size, IA_CONT, &avl) == -1) { 3020 fprintf(stderr, 3021 "%s%s %s/%d: Unable to pre-alloc space: ialloc failed: %d %s\n", 3022 Progname, TagName, __FILE__, __LINE__, errno, 3023 strerror(errno)); 3024 return -1; 3025 } 3026 #endif 3027 3028 #ifdef sgi 3029 struct flock f; 3030 3031 f.l_whence = 0; 3032 f.l_start = 0; 3033 f.l_len = size; 3034 3035 /* non-zeroing reservation */ 3036 if (fcntl(fd, F_RESVSP, &f) == -1) { 3037 fprintf(stderr, 3038 "%s%s %s/%d: Unable to pre-alloc space: fcntl(F_RESVSP) failed: %d %s\n", 3039 Progname, TagName, __FILE__, __LINE__, errno, 3040 strerror(errno)); 3041 return -1; 3042 } 3043 #endif 3044 3045 return 0; 3046 } 3047 #endif 3048