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