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)
myexit(int 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 ***********************************************************************/
main(int argc,char ** argv)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 ***********************************************************************/
set_sig(void)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 ***********************************************************************/
sig_handler(int sig)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 ***********************************************************************/
notify_others(void)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 ***********************************************************************/
handle_error(void)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 ***********************************************************************/
cleanup(void)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 ***********************************************************************/
usage(void)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 ***********************************************************************/
help(void)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 ***********************************************************************/
prt_examples(FILE * stream)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 ***********************************************************************/
growfile(int fd,char * file,int grow_incr,char * buf,unsigned long * curr_size_ptr)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
shrinkfile(int fd,char * filename,int trunc_incr,int trunc_inter,int just_trunc)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 ***********************************************************************/
check_write(int fd,int cf_inter,char * filename,int mode)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 ***********************************************************************/
check_file(int fd,int cf_inter,char * filename,int no_file_check)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 if (fsize - rd_cnt > MAX_FC_READ)
2760 rd_size = MAX_FC_READ;
2761 else
2762 rd_size = fsize - rd_cnt;
2763
2764 #if NEWIO
2765 ret = lio_read_buffer(fd, io_type, buf, rd_size,
2766 SIGUSR1, &errmsg, 0);
2767 #else
2768 ret =
2769 read_buffer(fd, io_type, buf, rd_size, 0, &errmsg);
2770 #endif
2771
2772 if (ret != rd_size) {
2773 fprintf(stderr, "%s%s: %d %s/%d: %d CFa %s\n",
2774 Progname, TagName, Pid, __FILE__,
2775 __LINE__, Iter_cnt, errmsg);
2776 free(buf);
2777 lkfile(fd, LOCK_UN, LKLVL0);
2778 return -1;
2779 }
2780 /**
2781 read(fd, buf, rd_size);
2782 ***/
2783
2784 if (Pattern == PATTERN_OFFSET)
2785 ret =
2786 datapidchk(STATIC_NUM, buf, rd_size, rd_cnt,
2787 &errmsg);
2788 else if (Pattern == PATTERN_PID)
2789 ret =
2790 datapidchk(Pid, buf, rd_size, rd_cnt,
2791 &errmsg);
2792 else if (Pattern == PATTERN_ASCII)
2793 ret =
2794 dataasciichk(NULL, buf, rd_size, rd_cnt,
2795 &errmsg);
2796 else if (Pattern == PATTERN_RANDOM) ; /* no checks for random */
2797 else if (Pattern == PATTERN_ALT)
2798 ret =
2799 databinchk('a', buf, rd_size, rd_cnt,
2800 &errmsg);
2801 else if (Pattern == PATTERN_CHKER)
2802 ret =
2803 databinchk('c', buf, rd_size, rd_cnt,
2804 &errmsg);
2805 else if (Pattern == PATTERN_CNTING)
2806 ret =
2807 databinchk('C', buf, rd_size, rd_cnt,
2808 &errmsg);
2809 else if (Pattern == PATTERN_ZEROS)
2810 ret =
2811 databinchk('z', buf, rd_size, rd_cnt,
2812 &errmsg);
2813 else if (Pattern == PATTERN_ONES)
2814 ret =
2815 databinchk('o', buf, rd_size, rd_cnt,
2816 &errmsg);
2817 else
2818 ret =
2819 dataasciichk(NULL, buf, rd_size, rd_cnt,
2820 &errmsg);
2821
2822 if (ret >= 0) {
2823 fprintf(stderr,
2824 "%s%s: %d %s/%d: %d CFp %s in file %s\n",
2825 Progname, TagName, Pid, __FILE__,
2826 __LINE__, Iter_cnt, errmsg, filename);
2827 fflush(stderr);
2828 ret_val = 1;
2829 lkfile(fd, LOCK_UN, LKLVL0);
2830 break;
2831 }
2832 rd_cnt += rd_size;
2833 }
2834
2835 lkfile(fd, LOCK_UN, LKLVL0);
2836
2837 free(buf);
2838
2839 } else {
2840 /*
2841 * Read the whole file in a single read
2842 */
2843 if ((buf = malloc(fsize)) == NULL) {
2844 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n",
2845 Progname, TagName, __FILE__, __LINE__, fsize,
2846 strerror(errno));
2847 fflush(stderr);
2848 return -1;
2849 }
2850
2851 lseek(fd, 0, SEEK_SET);
2852
2853 /****
2854 read(fd, buf, fsize);
2855 ****/
2856 #if NEWIO
2857 ret =
2858 lio_read_buffer(fd, io_type, buf, fsize, SIGUSR1, &errmsg,
2859 0);
2860 #else
2861 ret = read_buffer(fd, io_type, buf, fsize, 0, &errmsg);
2862 #endif
2863
2864 /* unlock the file as soon as we can */
2865 lkfile(fd, LOCK_UN, LKLVL0);
2866
2867 if (ret != fsize) {
2868 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s\n",
2869 Progname, TagName, Pid, __FILE__, __LINE__,
2870 Iter_cnt, errmsg);
2871 ret_val = 1;
2872 } else {
2873 if (Pattern == PATTERN_OFFSET)
2874 ret =
2875 datapidchk(STATIC_NUM, buf, fsize, 0,
2876 &errmsg);
2877 else if (Pattern == PATTERN_PID)
2878 ret = datapidchk(Pid, buf, fsize, 0, &errmsg);
2879 else if (Pattern == PATTERN_ASCII)
2880 ret =
2881 dataasciichk(NULL, buf, fsize, 0, &errmsg);
2882 else if (Pattern == PATTERN_RANDOM) ; /* no check for random */
2883 else if (Pattern == PATTERN_ALT)
2884 ret = databinchk('a', buf, fsize, 0, &errmsg);
2885 else if (Pattern == PATTERN_CHKER)
2886 ret = databinchk('c', buf, fsize, 0, &errmsg);
2887 else if (Pattern == PATTERN_CNTING)
2888 ret = databinchk('C', buf, fsize, 0, &errmsg);
2889 else if (Pattern == PATTERN_ZEROS)
2890 ret = databinchk('z', buf, fsize, 0, &errmsg);
2891 else if (Pattern == PATTERN_ONES)
2892 ret = databinchk('o', buf, fsize, 0, &errmsg);
2893 else
2894 ret =
2895 dataasciichk(NULL, buf, fsize, 0, &errmsg);
2896
2897 if (ret >= 0) {
2898 fprintf(stderr,
2899 "%s%s: %d %s/%d: %d CFw %s in file %s\n",
2900 Progname, TagName, Pid, __FILE__,
2901 __LINE__, Iter_cnt, errmsg, filename);
2902 fflush(stderr);
2903 ret_val = 1;
2904 }
2905 }
2906 free(buf);
2907 }
2908
2909 return ret_val;
2910
2911 } /* end of check_file */
2912
2913 /***********************************************************************
2914 *
2915 ***********************************************************************/
file_size(int fd)2916 int file_size(int fd)
2917 {
2918 struct stat sb;
2919
2920 if (fstat(fd, &sb) < 0) {
2921 fprintf(stderr,
2922 "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
2923 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno,
2924 strerror(errno));
2925 return -1;
2926
2927 }
2928
2929 return sb.st_size;
2930 }
2931
2932 /***********************************************************************
2933 * do file lock/unlock action.
2934 ***********************************************************************/
lkfile(int fd,int operation,int lklevel)2935 int lkfile(int fd, int operation, int lklevel)
2936 {
2937 char *errmsg;
2938
2939 if (lockfile == lklevel) {
2940
2941 if (Debug > 5) {
2942 switch (operation) {
2943 case LOCK_UN:
2944 printf
2945 ("%s: %d DEBUG6 %s/%d: Attempting to release lock on fd %d\n",
2946 Progname, Pid, __FILE__, __LINE__, fd);
2947 break;
2948
2949 case LOCK_SH:
2950 printf
2951 ("%s: %d DEBUG6 %s/%d: Attempting to get read/shared lock on fd %d\n",
2952 Progname, Pid, __FILE__, __LINE__, fd);
2953 break;
2954
2955 case LOCK_EX:
2956 printf
2957 ("%s: %d DEBUG6 %s/%d: Attempting to get write/exclusive lock on fd %d\n",
2958 Progname, Pid, __FILE__, __LINE__, fd);
2959 break;
2960 }
2961 }
2962
2963 /*
2964 * Attempt to get/release desired lock.
2965 * file_lock will attempt to do action over and over again until
2966 * either an unretryable error or the action is completed.
2967 */
2968
2969 if (file_lock(fd, operation, &errmsg) != 0) {
2970 printf
2971 ("%s%s: %d %s/%d: Unable to perform lock operation. %s\n",
2972 Progname, TagName, Pid, __FILE__, __LINE__,
2973 errmsg);
2974
2975 /* do we count this as an error? handle_error(); */
2976 return -1;
2977 }
2978
2979 if (Debug > 2) {
2980 switch (operation) {
2981 case LOCK_UN:
2982 printf
2983 ("%s: %d DEBUG3 %s/%d: Released lock on fd %d\n",
2984 Progname, Pid, __FILE__, __LINE__, fd);
2985 break;
2986
2987 case LOCK_SH:
2988 printf
2989 ("%s: %d DEBUG3 %s/%d: Got read/shared lock on fd %d\n",
2990 Progname, Pid, __FILE__, __LINE__, fd);
2991 break;
2992
2993 case LOCK_EX:
2994 printf
2995 ("%s: %d DEBUG3 %s/%d: Got write/exclusive lock on fd %d\n",
2996 Progname, Pid, __FILE__, __LINE__, fd);
2997 break;
2998
2999 default:
3000 printf
3001 ("%s: %d DEBUG3 %s/%d: Completed action %d on fd %d\n",
3002 Progname, Pid, __FILE__, __LINE__,
3003 operation, fd);
3004 break;
3005 }
3006 }
3007 }
3008
3009 return 0;
3010 }
3011
3012 #ifndef linux
3013 /***********************************************************************
3014 *
3015 ***********************************************************************/
pre_alloc(int fd,long size)3016 int pre_alloc(int fd, long size)
3017 {
3018
3019 #ifdef CRAY
3020 long avl;
3021
3022 if (ialloc(fd, size, IA_CONT, &avl) == -1) {
3023 fprintf(stderr,
3024 "%s%s %s/%d: Unable to pre-alloc space: ialloc failed: %d %s\n",
3025 Progname, TagName, __FILE__, __LINE__, errno,
3026 strerror(errno));
3027 return -1;
3028 }
3029 #endif
3030
3031 #ifdef sgi
3032 struct flock f;
3033
3034 f.l_whence = 0;
3035 f.l_start = 0;
3036 f.l_len = size;
3037
3038 /* non-zeroing reservation */
3039 if (fcntl(fd, F_RESVSP, &f) == -1) {
3040 fprintf(stderr,
3041 "%s%s %s/%d: Unable to pre-alloc space: fcntl(F_RESVSP) failed: %d %s\n",
3042 Progname, TagName, __FILE__, __LINE__, errno,
3043 strerror(errno));
3044 return -1;
3045 }
3046 #endif
3047
3048 return 0;
3049 }
3050 #endif
3051