2 * Copyright (c) 2000 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * This program will grow a list of files.
20 * Each file will grow by grow_incr before the same
21 * file grows twice. Each file is open and closed before next file is opened.
23 * To just verify file contents: growfiles -g 0 -c 1 filename
25 * See help and prt_examples functions below.
29 * print debug message about options used
30 * setup signal handlers
31 * return control to user (if wanted - default action)
32 * fork number of desired childern (if wanted)
33 * re-exec self (if wanted)
34 * Determine number of files
35 * malloc space or i/o buffer
36 * Loop until stop is set
37 * Determine if hit iteration, time, max errors or num bytes reached
38 * Loop through each file
40 * fstat file - to determine if file is a fifo
41 * prealloc file space (if wanted)
50 * remove all files (if wanted)
52 * Author: Richard Logan
58 #ifdef HAVE_SYS_FILE_H
62 #include "dataascii.h"
63 #include "random_range.h"
67 extern char *openflags2symbols();
69 extern int parse_open_flags();
70 extern int background();
72 extern int datapidgen();
73 extern void databingen();
74 extern int datapidchk();
75 extern int databinchk();
76 extern int file_lock();
91 static void notify_others();
97 #define NEWIO 1 /* Use the tlibio.c functions */
100 #define NEWIO 0 /* specifies to use original iowrite.c */
101 /* functions instead of tlibio.c functions */
102 /* Once it is proven tlibio.c functions work properly, */
103 /* only tlibio.c functions will be used */
109 #define PATH_MAX 1023
114 #define DEF_FILE "gf"
121 int io_type = 0; /* I/O type -sync */
122 int open_flags = O_RDWR|O_CREAT; /* open flags */
124 #define MAX_FC_READ 196608 /* 4096 * 48 - 48 blocks */
126 #define PATTERN_ASCII 1 /* repeating alphabet letter pattern */
127 /* allows multiple writers and to be checked */
128 #define PATTERN_PID 2 /* <pid><words byte offset><pid> */
129 /* Assumes 64 bit word. Only allows single */
130 /* process to write and check */
132 * 1234567890123456789012345678901234567890123456789012345678901234
133 * ________________________________________________________________
134 * < pid >< offset in file of this word >< pid >
137 #define PATTERN_OFFSET 3 /* Like PATTERN_PID but has a fixed number */
138 /* (STATIC_NUM) instead of pid. */
139 /* Allows multiple processes to write/read */
140 #define PATTERN_ALT 4 /* alternating bit pattern (i.e. 0x5555555...) */
141 #define PATTERN_CHKER 5 /* checkerboard pattern (i.e. 0xff00ff00ff00...) */
142 #define PATTERN_CNTING 6 /* counting pattern (i.e. 0 - 07, 0 - 07, ...) */
143 #define PATTERN_ONES 7 /* all bits set (i.e. 0xffffffffffffff...) */
144 #define PATTERN_ZEROS 8 /* all bits cleared (i.e. 0x000000000...) */
145 #define PATTERN_RANDOM 9 /* random integers - can not be checked */
146 #define STATIC_NUM 221849 /* used instead of pid when PATTERN_OFFSET */
148 #define MODE_RAND_SIZE 1 /* random write and trunc */
149 #define MODE_RAND_LSEEK 2 /* random lseek before write */
150 #define MODE_GROW_BY_LSEEK 4 /* lseek beyond end of file then write a byte */
151 #define RANDOM_OPEN 999876 /* if Open_flags set to this value, open flags */
152 /* will be randomly choosen from Open_flags[] */
153 #define MODE_FIFO S_IFIFO /* defined in stat.h 0010000 */
155 int num_files = 0; /* num_auto_files + cmd line files */
156 char *filenames; /* pointer to space containing filenames */
157 int remove_files = 0; /* if set, cleanup default is not to cleanup */
158 int bytes_consumed = 0; /* total bytes consumed, all files */
159 int bytes_to_consume = 0; /* non-zero if -B was specified, total bytes */
160 int Maxerrs = 100; /* Max number errors before forced exit */
161 int Errors = 0; /* number of encountered errors */
162 int Upanic_on_error = 0; /* call upanic if error and this variable set */
164 /* The *_size variables are only used when random iosize option (-r) is used */
166 int min_size=1; /* also set in option parsing */
167 int mult_size=1; /* when random iosz, iosz must be mult of mult_size */
168 /* the *_lseek variables are only used when radon lseek option (-R) is used */
169 int min_lseek=0; /* also set in option parsing */
170 int max_lseek=-1; /* -1 means size of file */
172 int Pattern=PATTERN_OFFSET; /* This pattern is 64 bit word based */
174 int Pattern=PATTERN_ASCII;
176 int Seed=-1; /* random number seed, < 0 == uninitialized */
177 int Nseeds=0; /* Number of seed specified by the user */
178 int *Seeds; /* malloc'ed arrary of ints holding user spec seeds */
180 int using_random=0; /* flag indicating randomization is being used */
181 float delaysecs=0.0; /* delay between iterations (in seconds) */
182 int delaytime; /* delay between iterations in clocks/uses */
183 int lockfile=0; /* if set, do file locking */
184 /* 1 = do file locking around write, trunc */
186 /* 2 = write lock around all file operations */
188 int Woffset=0; /* offset before last write */
189 int Grow_incr=4096; /* sz of last write */
190 int Mode=0; /* bitmask of write/trunc mode */
191 /* also knows if dealing with fifo */
192 char *Buffer = NULL; /* buffer used by write and write check */
193 int Alignment=0; /* if non word multiple, io will not be word aligned */
194 int Opid=0; /* original pid */
196 int Sync_with_others = 0; /* Flag indicating to stop other if we stop before DONE */
197 int Iter_cnt = 0; /* contains current iteration count value */
198 char TagName[40]; /* name of this growfiles (see Monster) */
208 * Define open flags that will be used when '-o random' option is used.
209 * Note: If there is more than one growfiles doing its thing to the same
210 * file, O_TRUNC will cause data mismatches. How you ask?
211 * timing of events, example:
212 * Process one Process two
213 * --------------- -------------
219 * write with wrong pattern
220 * because offset is wrong
222 * The second process truncated the file after the pattern was
223 * determined, thus the pattern is wrong for the file location.
225 * There can also be a timing problem with open flag O_APPEND if
226 * file locks are not being used (-l option). Things could happen
227 * between the fstat and the write. Thus, writing the wrong pattern.
228 * If all processes observe the file locks, O_APPEND should be ok
234 O_RDWR|O_CREAT|O_RAW,
235 O_RDWR|O_CREAT|O_BIG,
236 O_RDWR|O_CREAT|O_APPEND,
237 O_RDWR|O_CREAT|O_NDELAY,
238 O_RDWR|O_CREAT|O_PLACE,
239 O_RDWR|O_CREAT|O_SYNC,
240 O_RDWR|O_CREAT|O_RAW|O_SYNC,
241 O_RDWR|O_CREAT|O_NDELAY|O_SYNC,
242 O_RDWR|O_CREAT|O_NDELAY|O_SYNC|O_BIG,
243 O_RDWR|O_CREAT|O_RAW,
244 O_RDWR|O_CREAT|O_RAW|O_APPEND,
245 O_RDWR|O_CREAT|O_RAW|O_BIG,
246 O_RDWR|O_CREAT|O_RAW|O_APPEND|O_BIG,
248 * O_WELLFORMED makes -o random require well formed i/o
250 #if ALLOW_O_WELLFORMED
252 O_RDWR|O_CREAT|O_PARALLEL|O_WELLFORMED|O_RAW,
253 O_RDWR|O_CREAT|O_PARALLEL|O_WELLFORMED|O_RAW|O_TRUNC,
254 #endif /* O_PARALLEL */
259 O_RDWR|O_CREAT|O_APPEND,
260 O_RDWR|O_CREAT|O_NDELAY,
261 O_RDWR|O_CREAT|O_SYNC,
262 O_RDWR|O_CREAT|O_SYNC|O_NDELAY,
263 O_RDWR|O_CREAT|O_APPEND|O_NDELAY,
268 #define REXEC_INIT 0 /* don't do re-exec of childern */
269 #define REXEC_DOIT 1 /* Do re-exec of childern */
270 #define REXEC_DONE 2 /* We've already been re-exec'ed */
280 #define USECS_PER_SEC 1000000 /* microseconds per second */
283 * Define marcos used when dealing with file locks.
285 #define LKLVL0 1 /* file lock around write/read/trunc */
286 #define LKLVL1 2 /* file lock after open to before close */
289 * Define special max lseek values
291 #define LSK_EOF -1 /* set fptr up to EOF */
292 #define LSK_EOFPLUSGROW -2 /* set fptr up to EOF + grow - leave whole */
293 #define LSK_EOFMINUSGROW -3 /* set fptr up to EOF-grow - no grow */
296 /***********************************************************************
298 ***********************************************************************/
304 extern char *optarg; /* used by getopt */
309 int first_file_ind = 0;
310 int num_auto_files = 0; /* files created by tool */
311 int seq_auto_files = 0; /* auto files created by tool created by tool */
312 char *auto_dir = DEF_DIR;
313 char *auto_file = DEF_FILE;
314 int grow_incr = 4096;
315 int trunc_incr = 4096;
316 int trunc_inter = 0; /* 0 means none, */
317 int unlink_inter = 0; /* 0 means none, 1 means always unlink */
318 int unlink_inter_ran = -1; /* -1 -use unlink_inter, otherwise randomly choose */
319 /* between unlink_inter and unlink_inter_ran */
320 int file_check_inter = 0; /* 0 means never, 1 means always */
321 int write_check_inter = 1; /* 0 means never, 1 means always */
322 int iterations = 1; /* number of increments to be added */
323 int no_file_check = 0; /* if set, no whole file checking will be done */
325 int fd; /* file descriptor */
326 int stop = 0; /* loop stopper if set */
330 int pre_alloc_space = 0;
332 int total_grow_value = 0; /* used in pre-allocations */
334 int backgrnd = 1; /* return control to user */
336 int time_iterval = -1;
337 time_t start_time = 0;
338 char reason[40]; /* reason for loop termination */
341 int reexec=REXEC_INIT; /* reexec info */
342 char *exec_path=NULL;
346 char *filename; /* name of file specified by user */
347 char *cptr; /* temp char pointer */
348 extern int Forker_npids; /* num of forked pid, defined in forker.c */
351 if ( argv[0][0] == '-' )
354 * Determine name of file used to invoke this program
356 if ((Progname=strrchr(argv[0], '/')) != NULL)
366 while ((ind=getopt(argc, argv,
367 "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")) != EOF) {
375 switch (sscanf(optarg, "%i%c",
376 &bytes_to_consume, &chr)) {
382 bytes_to_consume *= BSIZE;
385 "%s%s: --B option arg invalid\n",
393 fprintf(stderr, "%s%s: --B option arg invalid\n",
403 prt_examples(stdout);
406 case 'b' : /* batch */
411 if (sscanf(optarg, "%i", &write_check_inter) != 1 ) {
412 fprintf(stderr, "%s%s: --c option arg invalid\n",
420 if (sscanf(optarg, "%i", &file_check_inter) != 1 ) {
421 fprintf(stderr, "%s%s: --c option arg invalid\n",
432 unsetenv("TMPDIR"); /* force the use of auto_dir */
434 if ( stat(auto_dir, &statbuf) == -1 ) {
435 if ( mkdir(auto_dir, 0777) == -1 ) {
436 if ( errno != EEXIST ) {
438 "%s%s: Unable to make dir %s\n",
439 Progname, TagName, auto_dir);
445 if ( ! (statbuf.st_mode & S_IFDIR) ) {
447 "%s%s: %s already exists and is not a directory\n",
448 Progname, TagName, auto_dir);
455 if (sscanf(optarg, "%i", &Debug) != 1 ) {
456 fprintf(stderr, "%s%s: --D option arg invalid\n",
464 if (sscanf(optarg, "%i", &Maxerrs) != 1 ) {
465 fprintf(stderr, "%s%s: --e option arg invalid\n",
477 if ((ret=sscanf(optarg, "%i%c", &grow_incr, &chr)) < 1 ||
480 fprintf(stderr, "%s%s: --g option arg invalid\n",
486 if ( chr == 'b' || chr == 'B' )
490 "%s%s: --g option arg invalid\n",
499 if (sscanf(optarg, "%f", &delaysecs) != 1 || delaysecs < 0 ) {
501 fprintf(stderr, "%s%s: --H option arg invalid\n",
509 if (sscanf(optarg, "%i", &iterations) != 1 ||
512 fprintf(stderr, "%s%s: --i option arg invalid\n",
521 if((io_type=lio_parse_io_arg1(optarg)) == -1 ) {
523 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
527 if( io_type & LIO_RANDOM )
530 if((io_type=parse_io_arg(optarg)) == -1 ) {
532 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
536 if( io_type == 99 ) /* hold-over until tlibio.h */
544 lockfile=2; /* lockfile can only be 1 or 2 */
548 if (sscanf(optarg, "%i", &time_iterval) != 1 ||
550 fprintf(stderr, "%s%s: --L option arg invalid\n",
558 if (sscanf(optarg, "%i:%i", &num_procs, &forker_mode) < 1 ||
561 fprintf(stderr, "%s%s: --n option arg invalid\n",
570 if (sscanf(optarg, "%i", &num_auto_files) != 1 ||
571 num_auto_files < 0 ) {
573 fprintf(stderr, "%s%s: --N option arg invalid\n",
581 if (sscanf(optarg, "%i", &Alignment) != 1 ||
582 num_auto_files < 0 ) {
584 fprintf(stderr, "%s%s: --O option arg invalid\n",
592 if ( strcmp(optarg, "random") == 0 ){
593 open_flags=RANDOM_OPEN;
596 } else if ((open_flags=parse_open_flags(optarg, NULL)) == -1 ) {
597 fprintf(stderr, "%s%s: --o arg contains invalid flag\n",
604 case 'p' : /* pre allocate space */
606 printf("%s%s: --p is illegal option on this system\n",
616 if (strcmp(optarg, "PANIC") != 0 ) {
617 fprintf(stderr, "%s%s: --P arg must be PANIC\n", Progname, TagName);
621 printf("%s: Will call upanic after writes\n");
623 printf("%s%s: --P is illegal option on non-cray system\n",
629 case 'q': /* file content or pattern */
632 Pattern = PATTERN_ALT;
635 Pattern = PATTERN_ASCII;
638 Pattern = PATTERN_PID;
641 Pattern = PATTERN_OFFSET;
644 Pattern = PATTERN_CHKER;
647 Pattern = PATTERN_CNTING;
650 Pattern = PATTERN_RANDOM;
654 Pattern = PATTERN_ZEROS;
657 Pattern = PATTERN_ONES;
661 "%s%s: --C option arg invalid, A, a, p, o, c, C, r, z, or 0\n",
668 case 'R': /* random lseek before write arg: [min-]max*/
669 if (sscanf(optarg, "%i-%i", &min_lseek, &max_lseek) != 2 ) {
670 min_lseek=1; /* same as default in define */
671 if (sscanf(optarg, "%i%c", &max_lseek, &chr) != 1 ) {
672 fprintf(stderr, "%s%s: --R option arg invalid: [min-]max\n",
677 if ( max_lseek < LSK_EOFMINUSGROW ) {
678 fprintf(stderr, "%s%s: --R option, max_lseek is invalid\n",
682 Mode |= MODE_RAND_LSEEK;
686 case 'r': /* random io size arg: [min-]max[:mult] */
688 /* min-max:mult format */
689 if (sscanf(optarg, "%i-%i:%i%c", &min_size, &max_size,
690 &mult_size, &chr) != 3 ) {
692 /* max:mult format */
693 if (sscanf(optarg, "%i:%i%c", &max_size,
694 &mult_size, &chr) != 2 ) {
696 if (sscanf(optarg, "%i-%i%c", &min_size,
697 &max_size, &chr) != 2 ) {
699 if (sscanf(optarg, "%i%c", &max_size, &chr) != 1 ) {
701 "%s%s: --r option arg invalid: [min-]max[:mult]\n",
709 if ( max_size < 0 ) {
710 fprintf(stderr, "%s%s: --r option, max_size is invalid\n",
715 * If min and max are the same, no randomness
717 if ( min_size != max_size ) {
718 Mode |= MODE_RAND_SIZE;
724 if (sscanf(optarg, "%i", &seq_auto_files) != 1 ||
725 seq_auto_files < 0 ) {
727 fprintf(stderr, "%s%s: --S option arg invalid\n",
734 case 's': /* format: seed[,seed...] */
736 /* count the number of seeds */
738 for(Nseeds=1; *cptr ; Nseeds++) {
739 if ( (filename=strchr(cptr, ',')) == NULL )
744 Seeds=(int *)malloc(Nseeds*sizeof(int));
747 * check that each seed is valid and put them in
748 * the newly malloc'ed Seeds arrary.
750 filename=cptr=optarg;
751 for(Nseeds=0; *cptr; Nseeds++) {
752 if ( (filename=strchr(cptr, ',')) == NULL ) {
753 if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
754 fprintf(stderr, "%s%s: --s option arg %s invalid\n",
755 Progname, TagName, cptr);
764 if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
765 fprintf(stderr, "%s%s: --s option arg %s invalid\n",
766 Progname, TagName, cptr);
770 *filename=','; /* restore string */
777 if ((ret=sscanf(optarg, "%i%c", &trunc_incr, &chr)) < 1 ||
780 fprintf(stderr, "%s%s: --t option arg invalid\n",
786 if ( chr == 'b' || chr == 'B' )
790 "%s%s: --t option arg invalid\n",
798 case 'T': /* truncate interval */
799 if (sscanf(optarg, "%i%c", &trunc_inter, &chr) != 1 ||
802 fprintf(stderr, "%s%s: --T option arg invalid\n",
813 case 'U': /* how often to unlink file */
816 * A-B - randomly pick interval between A and B
817 * X - unlink file every X iteration
819 if (sscanf(optarg, "%i-%i", &unlink_inter,
820 &unlink_inter_ran) == 2 ) {
822 if ( unlink_inter < 0 || unlink_inter_ran < 0 ) {
823 fprintf(stderr, "%s%s: --U option arg invalid\n",
828 /* ensure unlink_inter contains smaller value */
829 if ( unlink_inter > unlink_inter_ran ) {
830 tmp=unlink_inter_ran;
831 unlink_inter_ran=unlink_inter;
836 } else if (sscanf(optarg, "%i%c", &unlink_inter, &chr) != 1 ||
839 fprintf(stderr, "%s%s: --U option arg invalid\n",
847 if ( reexec != REXEC_DONE )
852 Mode |= MODE_GROW_BY_LSEEK;
856 sprintf( TagName, "(%.39s)", optarg );
871 cptr = getenv("TOUTPUT");
872 if( (cptr != NULL) && (strcmp( cptr, "NOPASS" ) == 0) ){
877 if ( Pattern == PATTERN_RANDOM ) {
879 if ( write_check_inter || file_check_inter )
880 printf("%s%s: %d Using random pattern - no data checking will be performed!\n",
881 Progname, TagName, (int)getpid());
883 else if ( max_lseek == LSK_EOFPLUSGROW || Mode & MODE_GROW_BY_LSEEK ) {
886 if ( file_check_inter )
887 printf("%s%s: %d Using random lseek beyond EOF or lseek grow,\n\
888 no whole file checking will be performed!\n", Progname, TagName, (int)getpid());
892 if ( Mode & MODE_RAND_SIZE )
902 printf("%s: %d DEBUG2 forking, returning control to the user\n",
904 background(Progname); /* give user their prompt back */
908 if ( Sync_with_others )
914 lio_set_debug(Debug-3);
916 set_iowrite_debug(Debug-3);
921 * Print some program information here if debug is turned on to
927 if ( Mode & MODE_GROW_BY_LSEEK )
928 printf("%s: %d DEBUG lseeking past end of file, writting a \"w\"\n",
930 else if ( Pattern == PATTERN_OFFSET )
931 printf("%s: %d DEBUG3 %d<byteoffset>%d per word pattern multi-writers.\n",
932 Progname, Pid, STATIC_NUM, STATIC_NUM);
933 else if ( Pattern == PATTERN_PID )
934 printf("%s: %d DEBUG3 <pid><byteoffset><pid> per word pattern - 1 writer\n",
936 else if ( Pattern == PATTERN_ASCII )
937 printf("%s: %d DEBUG3 ascii pattern (vi'able)- allows multiple writers\n",
939 else if ( Pattern == PATTERN_ALT )
940 printf("%s: %d DEBUG3 alt bit pattern - allows multiple writers\n",
942 else if ( Pattern == PATTERN_CHKER )
943 printf("%s: %d DEBUG3 checkerboard pattern - allows multiple writers\n",
945 else if ( Pattern == PATTERN_CNTING )
946 printf("%s: %d DEBUG3 counting pattern - allows multiple writers\n",
948 else if ( Pattern == PATTERN_RANDOM )
949 printf("%s: %d DEBUG3 random integer pattern - no write/file checking\n",
951 else if ( Pattern == PATTERN_ONES )
952 printf("%s: %d DEBUG3 all ones pattern - allows multiple writers\n",
954 else if ( Pattern == PATTERN_ZEROS )
955 printf("%s: %d DEBUG3 all zeros pattern - allows multiple writers\n",
959 printf("%s: %d DEBUG3 unknown pattern\n",
961 if ( bytes_to_consume )
962 printf("%s: %d DEBUG3 bytes_to_consume = %d\n",
963 Progname, Pid, bytes_to_consume);
964 printf("%s: %d DEBUG3 Maxerrs = %d, pre_alloc_space = %d, filelocking = %d\n",
965 Progname, Pid, Maxerrs, pre_alloc_space, lockfile);
967 printf("%s: %d DEBUG3 Debug = %d, remove files in cleanup : %d\n",
968 Progname, Pid, Debug, remove_files);
970 printf("%s: %d DEBUG3 Mode = %#o\n", Progname, Pid, Mode);
972 if ( open_flags == RANDOM_OPEN )
973 printf("%s: %d DEBUG3 open_flags = (random), io_type = %#o\n", Progname,
976 printf("%s: %d DEBUG3 open_flags = %#o, io_type = %#o\n", Progname,
977 Pid, open_flags, io_type);
979 if ( Mode & MODE_RAND_SIZE ) {
980 printf("%s: %d DEBUG3 random write/trunc: min=%d, max=%d, mult = %d\n",
981 Progname, Pid, min_size, max_size, mult_size);
984 printf("%s: %d DEBUG3 grow_incr = %d\n",
985 Progname, Pid, grow_incr);
987 if ( Mode & MODE_RAND_LSEEK ) {
988 if ( max_lseek == LSK_EOF )
989 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile>\n",
990 Progname, Pid, min_lseek);
991 else if ( max_lseek == LSK_EOFPLUSGROW )
992 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile+iosize>\n",
993 Progname, Pid, min_lseek);
994 else if ( max_lseek == LSK_EOFMINUSGROW )
995 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile-iosize>\n",
996 Progname, Pid, min_lseek);
998 printf("%s: %d DEBUG3 random lseek: min=%d, max=%d\n",
999 Progname, Pid, min_lseek, max_lseek);
1002 printf("%s: %d DEBUG3 check write interval = %d, check file interval = %d\n",
1003 Progname, Pid, write_check_inter, file_check_inter);
1005 printf("%s: %d DEBUG3 trunc interval = %d, trunc_incr = %d\n",
1006 Progname, Pid, trunc_inter, trunc_incr);
1008 if ( no_file_check )
1009 printf("%s: %d DEBUG3 no whole file checking will be done\n",
1012 if ( unlink_inter_ran == -1 ) {
1013 printf("%s: %d DEBUG3 unlink_inter = %d\n",
1014 Progname, Pid, unlink_inter);
1016 printf("%s: %d DEBUG3 unlink_inter = %d, unlink_inter_ran = %d\n",
1017 Progname, Pid, unlink_inter, unlink_inter_ran);
1021 num=sizeof(Open_flags)/sizeof(int);
1022 printf("%s: %d DEBUG9 random open flags values:\n", Progname, Pid);
1023 for(ind=0; ind<num; ind++) {
1024 printf("\t%#o\n", Open_flags[ind]);
1027 } /* end of DEBUG > 2 */
1029 if ( Debug > 1 && num_procs > 1 ) {
1030 printf("%s: %d DEBUG2 about to fork %d more copies\n", Progname,
1034 fflush(stdout); /* ensure pending i/o is flushed before forking */
1037 forker(num_procs, forker_mode, Progname);
1039 Pid=getpid(); /* reset after the forks */
1041 * If user specified random seed(s), get that random seed value.
1042 * get random seed if it was not specified by the user.
1043 * This is done after the forks, because pid is used to get the seed.
1045 if ( Nseeds == 1 ) {
1047 * If only one seed specified, all processes will get that seed.
1050 } else if ( Nseeds > 1 ) {
1052 * More than one seed was specified.
1053 * The original process gets the first seed. Each
1054 * process will be get the next seed in the specified list.
1056 if ( Opid == Pid ) {
1060 * If user didn't specify enough seeds, use default method.
1062 if ( Forker_npids >= Nseeds )
1063 Seed=time(0) + Pid; /* default random seed */
1065 Seed=Seeds[Forker_npids];
1070 * Generate a random seed based on time and pid.
1071 * It has a good chance of being unique for each pid.
1073 Seed=time(0) + Pid; /* default random seed */
1076 random_range_seed(Seed);
1078 if ( using_random && Debug > 0 )
1079 printf("%s%s: %d DEBUG1 Using random seed of %d\n",
1080 Progname, TagName, Pid, Seed);
1082 if ( unlink_inter_ran > 0 ) {
1084 * Find unlinking file interval. This must be done after
1085 * the seed was set. This allows multiple copies to
1086 * get different intervals.
1089 unlink_inter=random_range(tmp, unlink_inter_ran, 1, NULL);
1092 printf("%s: %d DEBUG3 Unlink interval is %d (random %d - %d)\n",
1093 Progname, Pid, unlink_inter, tmp, unlink_inter_ran);
1097 * re-exec all childern if reexec is set to REXEC_DOIT.
1098 * This is useful on MPP systems to get the
1099 * child process on another PE.
1101 if ( reexec == REXEC_DOIT && Opid != Pid ) {
1102 if ( exec_path == NULL ) {
1103 exec_path = argv[0];
1104 /* Get space for cmd (2 extra, 1 for - and 1 fro NULL */
1105 argv[0] = (char *)malloc(strlen(exec_path) + 2);
1106 sprintf(argv[0], "-%s", exec_path);
1110 printf("%s: %d DEBUG3 %s/%d: execvp(%s, argv)\n",
1111 Progname, Pid, __FILE__, __LINE__, argv[0]);
1113 execvp(argv[0], argv);
1116 /*** begin filename stuff here *****/
1118 * Determine the number of files to be dealt with
1120 if ( optind == argc ) {
1122 * no cmd line files, therfore, set
1123 * the default number of auto created files
1125 if ( ! num_auto_files && ! seq_auto_files )
1129 first_file_ind=optind;
1130 num_files += argc-optind;
1133 if ( num_auto_files ) {
1134 num_files += num_auto_files;
1137 if ( seq_auto_files ) {
1138 num_files += seq_auto_files;
1142 * get space for file names
1144 if ((filenames=(char *)malloc(num_files*PATH_MAX)) == NULL) {
1145 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1146 Progname, TagName, Pid, __FILE__, __LINE__, num_files*PATH_MAX,
1152 * fill in filename cmd files then auto files.
1156 if ( first_file_ind ) {
1157 for(ind=first_file_ind; ind<argc; ind++, num++) {
1158 strcpy((char *)filenames+(num*PATH_MAX), argv[ind]);
1163 * construct auto filename and insert them into filenames space
1166 for(ind=0;ind<num_auto_files; ind++, num++) {
1167 sprintf((char *)filenames+(num*PATH_MAX), "%s.%d",
1168 tempnam(auto_dir, auto_file), ind );
1172 * construct auto seq filenames
1174 for(ind=1; ind<=seq_auto_files; ind++, num++) {
1175 sprintf((char *)filenames+(num*PATH_MAX), "%s/%s%d",
1176 auto_dir, auto_file, ind);
1179 /**** end filename stuff ****/
1181 if ( time_iterval > 0 )
1185 * get space for I/O buffer
1188 if ((Buffer=(char *)malloc(grow_incr+Alignment)) == NULL) {
1189 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1190 Progname, TagName, Pid, __FILE__, __LINE__, grow_incr, strerror(errno));
1194 Buffer = Buffer + Alignment;
1199 printf("%s: %d DEBUG3 num_files = %d\n",
1200 Progname, Pid, num_files);
1204 if ( pre_alloc_space ) {
1205 if ( iterations == 0 ) {
1206 fprintf(stderr, "%s%s: %d %s/%d: can NOT pre-alloc and grow forever\n",
1207 Progname, TagName, Pid, __FILE__, __LINE__);
1210 if ( Mode & MODE_RAND_SIZE ) {
1212 "%s%s: %d %s/%d: can NOT pre-alloc and do random io size\n",
1213 Progname, TagName, Pid, __FILE__, __LINE__);
1217 total_grow_value=grow_incr * iterations;
1222 if ( bytes_to_consume && bytes_to_consume < total_grow_value ) {
1223 total_grow_value=bytes_to_consume;
1229 * If delaying between iterations, get amount time to
1230 * delaysecs in clocks or usecs.
1231 * If on the CRAY, delaytime is in clocks since
1232 * _rtc() will be used, which does not have the overhead
1233 * of gettimeofday(2).
1238 hz=sysconf(_SC_CLK_TCK);
1239 delaytime=(int)((float)hz * delaysecs);
1241 delaytime=(int)((float)USECS_PER_SEC * delaysecs);
1246 * This is the main iteration loop.
1247 * Each iteration, all files can be opened, written to,
1248 * read to check the write, check the whole file,
1249 * truncated, and closed.
1251 for(Iter_cnt=1; ! stop ; Iter_cnt++) {
1253 if ( iterations && Iter_cnt >= iterations+1 ) {
1254 strcpy(reason, "Hit iteration value");
1259 if ( (time_iterval > 0) && (start_time + time_iterval < time(0)) ) {
1260 sprintf(reason, "Hit time value of %d", time_iterval);
1265 if ( bytes_to_consume && bytes_consumed >= bytes_to_consume) {
1266 sprintf(reason, "Hit bytes consumed value of %d", bytes_to_consume);
1272 * This loop will loop through all files.
1273 * Each iteration, a single file can be opened, written to,
1274 * read to check the write, check the whole file,
1275 * truncated, and closed.
1277 for(ind=0; ind<num_files; ind++) {
1282 filename=(char *)filenames+(ind*PATH_MAX);
1283 Fileinfo.filename=(char *)filenames+(ind*PATH_MAX);
1286 if ( open_flags == RANDOM_OPEN ) {
1287 ret=Open_flags[random_range(0, sizeof(Open_flags)/sizeof(int)-1, 1, NULL)];
1293 Fileinfo.openflags=ret;
1296 printf("%s: %d DEBUG3 %s/%d: %d Open filename = %s, open flags = %#o %s\n",
1297 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, ret,
1298 openflags2symbols(ret, ",", NULL));
1299 } else if ( Debug > 2 ) {
1300 printf("%s: %d DEBUG3 %s/%d: %d filename = %s, open flags = %#o\n",
1301 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, ret);
1305 * open file with desired flags.
1307 if ( (fd=open(filename, ret, 0777)) == -1 ) {
1309 "%s%s: %d %s/%d: open(%s, %#o, 0777) returned -1, errno:%d %s\n",
1310 Progname, TagName, Pid, __FILE__, __LINE__, filename, ret, errno, strerror(errno));
1317 lkfile(fd, LOCK_EX, LKLVL1); /* lock if lockfile is LKLVL1 */
1321 * preallocation is only done once, if specified.
1323 if ( pre_alloc_space ) {
1324 if (pre_alloc(filename, fd, total_grow_value) != 0 ) {
1329 printf("%s: %d DEBUG2 %s/%d: pre_allocated %d for file %s\n",
1330 Progname, Pid, __FILE__, __LINE__, total_grow_value, filename);
1332 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1334 Iter_cnt=0; /* reset outside loop to restart from one */
1340 * grow file by desired amount.
1341 * growfile() will set the Grow_incr variable and
1342 * possiblly update the Mode variable indicating
1343 * if we are dealing with a FIFO file.
1346 if (growfile(fd, filename, grow_incr, Buffer) != 0 ) {
1348 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1354 * check if last write is not corrupted
1356 if ( check_write(fd, write_check_inter, filename,
1362 * Check that whole file is not corrupted.
1364 if ( check_file(fd, file_check_inter, filename,
1365 no_file_check) != 0 ) {
1370 * shrink file by desired amount if it is time
1373 if ( shrinkfile(fd, filename, trunc_incr, trunc_inter, Mode) != 0 ) {
1377 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1380 printf("%s: %d DEBUG5 %s/%d: %d Closing file %s fd:%d \n",
1381 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, fd);
1385 * Unlink the file if that is desired
1387 if ( unlink_inter && (Iter_cnt % unlink_inter == 0) ) {
1390 printf("%s: %d DEBUG5 %s/%d: %d Unlinking file %s\n",
1391 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename);
1397 * delay while staying active for "delaysecs" seconds.
1405 while ( ct < end ) {
1409 struct timeval curtime;
1410 gettimeofday(&curtime, NULL);
1411 ct=curtime.tv_sec*USECS_PER_SEC + curtime.tv_usec;
1413 while ( ct < end ) {
1415 gettimeofday(&curtime, NULL);
1416 ct=curtime.tv_sec*USECS_PER_SEC + curtime.tv_usec;
1423 * if Iter_cnt == 0, then we pre allocated space to all files
1424 * and we are starting outside loop over. Set pre_alloc_space
1425 * to zero otherwise we get in infinite loop
1427 if ( Iter_cnt == 0 ) {
1433 } /* end iteration for loop */
1437 printf("%s%s: %d %s/%d: DONE %d iterations to %d files. %s\n",
1438 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, num_files, reason);
1447 printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1448 Progname, TagName, Pid, Errors);
1449 printf("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", Progname, TagName, Pid, __FILE__, __LINE__);
1454 printf("%s%s: %d DEBUG3 %s/%d: no errors, exiting with value of 0\n", Progname, TagName, Pid, __FILE__, __LINE__);
1458 /***********************************************************************
1460 ***********************************************************************/
1468 * now loop through all signals and set the handlers
1471 for (sig = 1; sig < NSIG; sig++) {
1482 #endif /* SIGCKPT */
1485 #endif /* SIGRESTART */
1491 sigset( sig, sig_handler );
1493 /* linux and cray */
1494 signal(sig, sig_handler);
1504 /***********************************************************************
1506 ***********************************************************************/
1513 if ( sig == SIGUSR2 ) {
1514 fprintf(stdout, "%s%s: %d %s/%d: received SIGUSR2 (%d) - stopping.\n",
1515 Progname, TagName, Pid, __FILE__, __LINE__, sig);
1517 signal(sig, sig_handler); /* allow us to get this signal more than once */
1520 } else if( sig == SIGINT ){
1521 /* The user has told us to cleanup, don't pretend it's an error. */
1524 fprintf(stderr, "%s%s: %d %s/%d: received unexpected signal: %d\n", Progname, TagName,
1525 Pid, __FILE__, __LINE__, sig);
1528 fprintf(stderr, "%s%s: %d %s/%d: received unexpected signal: %d\n", Progname, TagName,
1529 Pid, __FILE__, __LINE__, sig);
1535 printf("%s%s: %d DEBUG3 %s/%d: Exiting with a value of %d\n",
1536 Progname, TagName, Pid, __FILE__, __LINE__, exit_stat);
1541 /***********************************************************************
1542 * this function attempts to send SIGUSR2 to other growfiles processes
1543 * telling them to stop.
1545 ***********************************************************************/
1549 static int send_signals = 0;
1551 extern int Forker_pids[];
1552 extern int Forker_npids;
1554 if ( Sync_with_others && send_signals == 0 ) {
1557 send_signals=1; /* only send signals once */
1559 printf("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pgrp\n",
1560 Progname, TagName, Pid, __FILE__, __LINE__);
1561 killm(C_PGRP, getpgrp(), SIGUSR2);
1563 send_signals=1; /* only send signals once */
1565 for (ind=0; ind< Forker_npids; ind++) {
1566 if ( Forker_pids[ind] != Pid )
1568 printf("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pid %d\n",
1569 Progname, TagName, Pid, __FILE__, __LINE__, Forker_pids[ind]);
1570 kill(Forker_pids[ind], SIGUSR2);
1577 /***********************************************************************
1578 * this function will count the number of errors encountered.
1579 * This function will call upanic if wanted or cleanup and
1580 * and exit is Maxerrs were encountered.
1581 ***********************************************************************/
1588 if ( Errors & Upanic_on_error ) {
1593 if ( Maxerrs && Errors >= Maxerrs ) {
1594 printf("%s%s: %d %s/%d: %d Hit max errors value of %d\n",
1595 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, Maxerrs);
1600 printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1601 Progname, TagName, Pid, Errors);
1602 printf("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", Progname, TagName, Pid, __FILE__, __LINE__);
1611 /***********************************************************************
1613 ***********************************************************************/
1619 if ( remove_files ) {
1621 printf("%s: %d DEBUG3 Removing all %d files\n",
1622 Progname, Pid, num_files);
1623 for(ind=0; ind<=num_files; ind++) {
1624 unlink(filenames+(ind*PATH_MAX));
1627 if ( using_random && Debug > 1 )
1628 printf("%s%s: %d DEBUG2 Used random seed: %d\n",
1629 Progname, TagName, Pid, Seed);
1633 /***********************************************************************
1635 ***********************************************************************/
1640 "Usage: %s%s [-bhEluy][[-g grow_incr][-i num][-t trunc_incr][-T trunc_inter]\n",
1641 Progname, TagName );
1643 "[-d auto_dir][-e maxerrs][-f auto_file][-N num_files][-w][-c chk_inter][-D debug]\n");
1645 "[-s seed][-S seq_auto_files][-p][-P PANIC][-I io_type][-o open_flags][-B maxbytes]\n");
1647 "[-r iosizes][-R lseeks][-U unlk_inter][-W tagname] [files]\n");
1651 } /* end of usage */
1653 /***********************************************************************
1655 ***********************************************************************/
1662 -h Specfied to print this help and exit.\n\
1663 -b Specfied to execute in sync mode.(def async mode)\n\
1664 -B maxbytes Max bytes to consume by all files. growfiles exits when more\n\
1665 than maxbytes have been consumed. (def no chk) If maxbytes ends\n\
1666 with the letter 'b', maxbytes is multiplied by BSIZE\n\
1667 -C write_chk Specifies how often to check the last write (default 1)\n\
1668 -c file_chk Specifies how often to check whole file (default 0)\n\
1669 -d auto_dir Specifies the directory to auto created files. (default .)\n\
1670 -D debug_lvl Specifies the debug level (default 1)\n\
1671 -E Print examples and exit\n\
1672 -e errs The number errors that will terminate this program (def 100)\n\
1673 -f auto_file Specifies the base filename files created. (default \"gf\")\n\
1674 -g grow_incr Specfied to grow by incr for each num. (default 4096)\n\
1675 grow_incr may end in b for blocks\n\
1676 If -r option is used, this option is ignored and size is random\n\
1677 -H delay Amount of time to delay between each file (default 0.0)\n\
1678 -I io_type Specifies io type: s - sync, p - polled async, a - async (def s)\n\
1679 l - listio sync, L - listio async, r - random\n\
1680 -i iteration Specfied to grow each file num times. 0 means forever (default 1)\n\
1681 -l Specfied to do file locking around write/read/trunc\n\
1682 If specified twice, file locking after open to just before close\n\
1683 -L time Specfied to exit after time secs, must be used with -i.\n\
1684 -N num_files Specifies the number of files to be created.\n\
1685 The default is zero if cmd line files.\n\
1686 The default is one if no cmd line files.\n\
1687 -n num_procs Specifies the number of copies of this cmd.\n\
1688 -o op_type Specifies open flages: (def O_RDWR,O_CREAT) op_type can be 'random'\n\
1689 -O offset adjust i/o buffer alignment by offset bytes\n\
1690 -P PANIC Specifies to call upanic on error.\n\
1691 -p Specifies to pre-allocate space\n\
1692 -q pattern pattern can be a - ascii, p - pid with boff, o boff (def)\n\
1693 A - Alternating bits, r - random, O - all ones, z - all zeros,\n\
1694 c - checkboard, C - counting\n\
1695 -R [min-]max random lseek before write and trunc, max of -1 means filesz,\n\
1696 -2 means filesz+grow, -3 filesz-grow. (min def is 0)\n\
1697 -r [min-]max random io write size (min def is 1)\n\
1698 -S seq_auto_files Specifies the number of seqental auto files (default 0)\n\
1699 -s seed[,seed...] Specifies the random number seed (default time(0)+pid)\n\
1700 -t trunc_incr Specfied the amount to shrink file. (default 4096)\n\
1701 trunc_inter may end in b for blocks\n\
1702 If -R option is used, this option is ignored and trunc is random\n\
1703 -T trunc_inter Specfied the how many grows happen before shrink. (default 0)\n\
1704 -u unlink files before exit\n\
1705 -U ui[-ui2] Unlink files each ui iteration (def 0)\n\
1706 -w Specfied to grow via lseek instead of writes.\n\
1707 -W tag-name Who-am-i. My Monster tag name. (used by Monster).\n\
1708 -x Re-exec children before continuing - useful on MPP systems\n\
1709 -y Attempt to sync copies - if one fails it will send sigusr2 to others\n\
1710 Action to each file every iteration is open, write, write check\n\
1711 file check, trunc and closed.\n");
1716 /***********************************************************************
1718 ***********************************************************************/
1720 prt_examples(FILE *stream)
1722 /* This example creates 200 files in directory dir1. It writes */
1723 /* 4090 bytes 100 times then truncates 408990 bytes off the file */
1724 /* The file contents are checked every 1000 grow. */
1726 "# run forever: writes of 4090 bytes then on every 100 iterval\n\
1727 # truncate file by 408990 bytes. Done to 200 files in dir1.\n\
1728 %s -i 0 -g 4090 -T 100 -t 408990 -l -C 10 -c 1000 -d dir1 -S 200\n\n", Progname);
1730 /* same as above with 5000 byte grow and a 499990 byte tuncate */
1732 "# same as above with writes of 5000 bytes and truncs of 499990\n\
1733 %s -i 0 -g 5000 -T 100 -t 499990 -l -C 10 -c 1000 -d dir2 -S 200\n\n", Progname);
1735 /* This example beats on opens and closes */
1737 "# runs forever: beats on opens and closes of file ocfile - no io\n\
1738 %s -i 0 -g 0 -c 0 -C 0 ocfile\n\n", Progname);
1741 "# writes 4096 to files until 50 blocks are written\n\
1742 %s -i 0 -g 4096 -B 50b file1 file2\n\n", Progname);
1745 "# write one byte to 750 files in gdir then unlinks them\n\
1746 %s -g 1 -C 0 -d gdir -u -S 750\n\n", Progname);
1749 "# run 30 secs: random iosize, random lseek up to eof\n\
1750 %s -r 1-5000 -R 0--1 -i 0 -L 30 -C 1 g_rand1 g_rand2\n\n", Progname);
1753 "# run 30 secs: grow by lseek then write single byte, trunc every 10 itervals\n\
1754 %s -g 5000 -wlu -i 0 -L 30 -C 1 -T 10 g_sleek1 g_lseek2\n\n", Progname);
1757 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1758 # rand io types doing a trunc every 5 iterations, with unlinks.\n\
1759 %s -i0 -r 1-50000 -R 0--2 -I r -C1 -l -n5 -u -U 100-200 gf_rana gf_ranb\n\n",
1763 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1764 # random open flags, rand io types doing a trunc every 10 iterations.\n\
1765 %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",
1772 /***********************************************************************
1774 * The file descriptor current offset is assumed to be the end of the
1776 * Woffset will be set to the offset before the write.
1777 * Grow_incr will be set to the size of the write or lseek write.
1778 ***********************************************************************/
1780 growfile(fd, file, grow_incr, buf)
1791 int fsize; /* current size of file */
1792 int size_grew; /* size the file grew */
1797 * Do a stat on the open file.
1798 * If the file is a fifo, set the bit in Mode variable.
1799 * This fifo check must be done prior to growfile() returning.
1800 * Also get the current size of the file.
1802 if ( fstat(fd, &stbuf) != -1 ) {
1803 if ( S_ISFIFO(stbuf.st_mode) ) {
1804 Fileinfo.mode |= MODE_FIFO;
1807 printf("%s: %d DEBUG4 %s/%d: file is a fifo - no lseek or truncs,\n",
1808 Progname, Pid, __FILE__, __LINE__);
1810 fsize = stbuf.st_size;
1813 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1814 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
1820 if ( grow_incr <= 0 ) { /* don't attempt i/o if grow_incr <= 0 */
1822 Grow_incr=grow_incr;
1824 printf("%s: %d DEBUG3 %s/%d: Not attempting to grow, growsize == %d\n",
1825 Progname, Pid, __FILE__, __LINE__, grow_incr);
1829 if ( Mode & MODE_RAND_SIZE ) {
1830 grow_incr=random_range(min_size, max_size, mult_size, &errmsg);
1831 if (errmsg != NULL) {
1832 fprintf(stderr, "%s%s: %d %s/%d: random_range() failed - %s\n", Progname, TagName, Pid, __FILE__, __LINE__, errmsg);
1835 Grow_incr=grow_incr;
1838 Grow_incr=grow_incr;
1840 if ( ! (Mode & MODE_FIFO) ) {
1841 if ((cur_offset=lseek(fd,0,SEEK_CUR)) == -1 ) {
1842 fprintf(stderr, "%s%s: %d %s/%d: tell failed: %s\n",
1843 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
1848 if ( Mode & MODE_GROW_BY_LSEEK ) {
1851 printf("%s: %d DEBUG3 %s/%d: Current size of file is %d\n", Progname,
1852 Pid, __FILE__, __LINE__, Woffset);
1853 printf("%s: %d DEBUG3 %s/%d: lseeking to %d byte with SEEK_END\n", Progname,
1854 Pid, __FILE__, __LINE__, grow_incr-1);
1857 if ((noffset=lseek(fd, grow_incr-1, SEEK_END)) == -1 ) {
1858 fprintf(stderr, "%s%s: %s/%d: lseek(fd, %d, SEEK_END) failed: %s\n",
1859 Progname, TagName, __FILE__, __LINE__, grow_incr-1, strerror(errno));
1863 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1866 ret=lio_write_buffer(fd, io_type, "w", 1, SIGUSR1, &errmsg,0);
1868 ret=write_buffer(fd, io_type, "w", 1, 0, &errmsg);
1872 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
1873 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
1874 if ( ret == -ENOSPC ) {
1883 lkfile(fd, LOCK_UN, LKLVL0);
1886 printf("%s: %d DEBUG3 %s/%d: %d wrote 1 byte to file\n",
1887 Progname, Pid, __FILE__, __LINE__, Iter_cnt);
1889 } else { /* end of grow by lseek */
1891 if ( Fileinfo.openflags & O_APPEND ) {
1893 * Deal with special case of the open flag containing O_APPEND.
1894 * If it does, the current offset does not matter since the write
1895 * will be done end of the file.
1898 printf("%s: %d DEBUG5 %s/%d: dealing with O_APPEND condition\n",
1899 Progname, Pid, __FILE__, __LINE__ );
1900 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1903 * do fstat again to get size of the file.
1904 * This is done inside a file lock (if locks are being used).
1906 if ( fstat(fd, &stbuf) != -1 ) {
1907 Woffset = stbuf.st_size;
1909 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1910 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
1912 lkfile(fd, LOCK_UN, LKLVL0); /* release lock */
1916 printf("%s: %d DEBUG3 %s/%d: dealing with O_APPEND condition (offset:fsz:%d)\n",
1917 Progname, Pid, __FILE__, __LINE__, (int)stbuf.st_size);
1920 } else if ( Mode & MODE_RAND_LSEEK ) {
1921 if ( max_lseek == LSK_EOF ) { /* within file size */
1922 noffset=random_range(min_lseek, fsize, 1, NULL);
1924 else if ( max_lseek == LSK_EOFPLUSGROW ) {
1925 /* max to beyond file size */
1926 noffset=random_range(min_lseek, fsize+grow_incr, 1, NULL);
1928 else if ( max_lseek == LSK_EOFMINUSGROW ) {
1930 * Attempt to not grow the file.
1931 * If the i/o will fit from min_lseek to EOF,
1932 * pick offset to allow it to fit.
1933 * Otherwise, pick the min_lseek offset and grow
1934 * file by smallest amount.
1935 * If min_lseek is != 0, there will be a problem
1936 * with whole file checking if file is ever smaller
1939 if ( fsize <= min_lseek + grow_incr )
1940 noffset=min_lseek; /* file will still grow */
1942 noffset=random_range(min_lseek, fsize-grow_incr, 1, NULL);
1945 noffset=random_range(min_lseek, max_lseek, 1, NULL);
1948 if ((Woffset=lseek(fd, noffset, SEEK_SET)) == -1 ) {
1949 fprintf(stderr, "%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l2 failed: %s\n",
1950 Progname, TagName, Pid, __FILE__, __LINE__, fd, noffset, strerror(errno));
1953 else if ( Debug > 2 )
1954 printf("%s: %d DEBUG3 %s/%d: lseeked to random offset %d (fsz:%d)\n",
1955 Progname, Pid, __FILE__, __LINE__, Woffset,
1956 (int)stbuf.st_size);
1961 * lseek to end of file only if not fifo
1963 else if ( ! (Mode & MODE_FIFO) ) {
1964 if ((Woffset=lseek(fd, 0, SEEK_END)) == -1 ) {
1965 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, 0, SEEK_END) failed: %s\n",
1966 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
1969 else if ( Debug > 2 )
1970 printf("%s: %d DEBUG3 %s/%d: lseeked to end of file, offset %d\n",
1971 Progname, Pid, __FILE__, __LINE__, Woffset);
1974 if ( Pattern == PATTERN_OFFSET )
1975 datapidgen(STATIC_NUM, buf, grow_incr, Woffset);
1976 else if ( Pattern == PATTERN_PID )
1977 datapidgen(Pid, buf, grow_incr, Woffset);
1978 else if ( Pattern == PATTERN_ASCII )
1979 dataasciigen(NULL, (char *)buf, grow_incr, Woffset);
1980 else if ( Pattern == PATTERN_RANDOM )
1981 databingen('r', buf, grow_incr, Woffset);
1982 else if ( Pattern == PATTERN_ALT )
1983 databingen('a', buf, grow_incr, Woffset);
1984 else if ( Pattern == PATTERN_CHKER )
1985 databingen('c', buf, grow_incr, Woffset);
1986 else if ( Pattern == PATTERN_CNTING )
1987 databingen('C', buf, grow_incr, Woffset);
1988 else if ( Pattern == PATTERN_ZEROS )
1989 databingen('z', buf, grow_incr, Woffset);
1990 else if ( Pattern == PATTERN_ONES )
1991 databingen('o', buf, grow_incr, Woffset);
1993 dataasciigen(NULL, (char *)buf, grow_incr, Woffset);
1996 printf("%s: %d DEBUG3 %s/%d: attempting to write %d bytes\n",
1997 Progname, Pid, __FILE__, __LINE__, grow_incr);
1999 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
2002 ret=write(fd, buf, grow_incr);
2006 lkfile(fd, LOCK_UN, LKLVL0);
2008 if ( ret != grow_incr) {
2009 fprintf(stderr, "%s: %s/%d: write failed: %s\n",
2010 Progname, __FILE__, __LINE__, strerror(errno));
2016 ret=lio_write_buffer(fd, io_type, (char *)buf, grow_incr,
2017 SIGUSR1, &errmsg,0);
2019 ret=write_buffer(fd, io_type, buf, grow_incr, 0, &errmsg);
2022 if( Mode & MODE_FIFO ){
2023 /* If it is a fifo then just pretend the file
2024 * offset is where we think it should be.
2026 tmp = Woffset + grow_incr;
2029 if( (tmp=lseek(fd,0,SEEK_CUR)) < 0 ){ /* get offset after the write */
2030 fprintf(stderr, "%s%s: %s/%d: tell(2) failed: %d %s\n",
2031 Progname, TagName, __FILE__, __LINE__, errno, strerror(errno) );
2036 /* If this is POSIX I/O and it is via aio_{read,write}
2037 * or lio_listio then after completion of the I/O the
2038 * value of the file offset for the file is
2039 * unspecified--which means we cannot trust what
2040 * tell() told us. Fudge it here.
2042 if( (io_type & LIO_IO_ASYNC_TYPES) || (io_type & LIO_RANDOM) ){
2043 if( tmp != Woffset + grow_incr ){
2045 printf("%s: %d DEBUG6 %s/%d: posix fudge, forcing tmp (%d) to match Woffset+grow_incr (%d)\n",
2046 Progname, Pid, __FILE__, __LINE__, tmp, Woffset+grow_incr);
2048 tmp = Woffset + grow_incr;
2055 lkfile(fd, LOCK_UN, LKLVL0);
2057 if ( ret != grow_incr ) {
2058 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
2059 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2060 if ( ret == -ENOSPC ) {
2068 * Check for a condition where the file was truncated just before
2071 if ( tmp != Woffset + grow_incr) {
2073 * The offset after the write was not as expected.
2074 * This could be caused by the following:
2075 * - file truncated after the lseek and before the write.
2076 * - the file was written to after fstat and before the write
2077 * and the file was opened with O_APPEND.
2079 * The pattern written to the file will be considered corrupted.
2081 if ( Debug > 0 && lockfile ) {
2082 printf("%s%s: %d DEBUG1 %s/%d: offset after write(%d) not as exp(%d+%d=%d)\n",
2083 Progname, TagName, Pid, __FILE__, __LINE__, tmp, Woffset, grow_incr, Woffset+grow_incr);
2084 printf("%s%s: %d DEBUG1 %s/%d: %d Assuming file changed by another process, resetting offset:%d (expect pattern mismatch)\n",
2085 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, tmp-grow_incr);
2088 printf("%s: %d DEBUG5 %s/%d: about to chop Woffset. tmp=%d, grow_incr=%d, Woffset was %d\n",
2089 Progname, Pid, __FILE__, __LINE__, tmp, grow_incr, Woffset);
2091 Woffset=tmp-grow_incr;
2096 } /* end of grow by write */
2100 * Woffset - holds start of grow (start of write expect in grow by lseek)
2101 * Grow_incr - holds size of grow (write).
2102 * fsize - holds size of file before write
2104 size_grew=(Woffset + Grow_incr) - fsize;
2106 if ( Mode & MODE_FIFO ) {
2107 printf("%s: %d DEBUG2 %s/%d: file is fifo, %d wrote %d bytes\n",
2108 Progname, Pid, __FILE__, __LINE__, Grow_incr, Iter_cnt);
2111 else if ( size_grew > 0 )
2112 printf("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%d), grew file by %d bytes\n",
2113 Progname, Pid, __FILE__, __LINE__, Iter_cnt, Grow_incr, Woffset, size_grew);
2115 printf("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%d), did not grow file\n",
2116 Progname, Pid, __FILE__, __LINE__, Iter_cnt, Grow_incr, Woffset);
2119 bytes_consumed += size_grew;
2122 } /* end of growfile */
2124 /***********************************************************************
2125 * shrinkfile file by trunc_incr. file can not be made smaller than
2126 * size zero. Therefore, if trunc_incr is larger than file size,
2127 * file will be truncated to zero.
2128 * The file descriptor current offset is assumed to be the end of the
2131 ***********************************************************************/
2133 shrinkfile(fd, filename, trunc_incr, trunc_inter, just_trunc)
2137 int trunc_inter; /* interval */
2138 int just_trunc; /* lseek has already been done for you */
2140 static int shrink_cnt = 0;
2150 if ( trunc_inter == 0 || (shrink_cnt % trunc_inter != 0)) {
2152 printf("%s: %d DEBUG4 %s/%d: Not shrinking file - not time, iter=%d, cnt=%d\n",
2153 Progname, Pid, __FILE__, __LINE__, trunc_inter, shrink_cnt);
2154 return 0; /* not this time */
2157 if ( Mode & MODE_FIFO ) {
2159 printf("%s: %d DEBUG5 %s/%d: Not attempting to shrink a FIFO\n",
2160 Progname, Pid, __FILE__, __LINE__);
2161 return 0; /* can not truncate fifo */
2164 lkfile(fd, LOCK_EX, LKLVL0);
2166 if ((cur_offset=lseek(fd,0,SEEK_CUR)) == -1 ) {
2167 fprintf(stderr, "%s%s: %d %s/%d: tell(%d) failed: %s\n",
2168 Progname, TagName, Pid, __FILE__, __LINE__, fd, strerror(errno));
2169 lkfile(fd, LOCK_UN, LKLVL0);
2173 if ( Mode & MODE_RAND_LSEEK ) {
2174 if ( max_lseek <= -1 ) {
2175 if ( (new_offset=file_size(fd)) == -1 ) {
2176 lkfile(fd, LOCK_UN, LKLVL0);
2180 if ( new_offset < min_lseek )
2181 new_offset=min_lseek;
2183 new_offset=random_range(min_lseek, new_offset, 1, NULL);
2186 new_offset=random_range(min_lseek, max_lseek, 1, NULL);
2190 if ((offset=lseek(fd, new_offset, SEEK_SET)) == -1 ) {
2191 fprintf(stderr, "%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l3 failed: %s\n",
2192 Progname, TagName, Pid, __FILE__, __LINE__, fd, new_offset, strerror(errno));
2193 lkfile(fd, LOCK_UN, LKLVL0);
2196 else if ( Debug > 3 )
2197 printf("%s: %d DEBUG4 %s/%d: lseeked to random offset %d\n",
2198 Progname, Pid, __FILE__, __LINE__, offset);
2203 else { /* remove trunc_incr from file */
2205 new_offset = cur_offset-trunc_incr;
2207 if ( new_offset < 0 )
2211 if ( lseek(fd, new_offset, SEEK_SET) == -1 ) {
2212 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, %d, SEEK_SET) l4 failed: %s\n",
2213 Progname, TagName, Pid, __FILE__, __LINE__, new_offset, strerror(errno));
2214 lkfile(fd, LOCK_UN, LKLVL0);
2217 else if ( Debug > 3 )
2218 printf("%s: %d DEBUG4 %s/%d: lseeked to offset %d, %d bytes from end\n",
2219 Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr);
2227 ret=ftruncate(fd, new_offset );
2228 if( (ret == 0) && (Debug > 3) ){
2229 printf("%s: %d DEBUG4 %s/%d: ftruncated to offset %d, %d bytes from end\n",
2230 Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr);
2234 lkfile(fd, LOCK_UN, LKLVL0);
2238 fprintf(stderr, "%s%s: %d %s/%d: trunc failed: %s\n",
2239 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
2241 fprintf(stderr, "%s%s: %d %s/%d: ftruncate failed: %s\n",
2242 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
2248 printf("%s: %d DEBUG2 %s/%d: trunc file by %d bytes, to size of = %d bytes\n",
2249 Progname, Pid, __FILE__, __LINE__, cur_offset-new_offset, new_offset);
2253 bytes_consumed -= (cur_offset - new_offset);
2256 } /* end of shrinkfile */
2258 /***********************************************************************
2260 ***********************************************************************/
2262 check_write(fd, cf_inter, filename, mode)
2264 int cf_inter; /* check file interval */
2265 char *filename; /* needed for error messages */
2266 int mode; /* write mode */
2269 static int cf_count = 0;
2277 if ( cf_inter == 0 || (cf_count % cf_inter != 0)) {
2279 printf("%s: %d DEBUG5 %s/%d: no write check, not time iter=%d, cnt=%d\n",
2280 Progname, Pid, __FILE__, __LINE__, cf_inter, cf_count);
2281 return 0; /* no check done */
2284 if ( Grow_incr <= 0 ) {
2286 printf("%s: %d DEBUG4 %s/%d: No write validation, Grow_incr = %d, offset = %d\n",
2287 Progname, Pid, __FILE__, __LINE__, Grow_incr, Woffset);
2288 return 0; /* no check */
2294 * Get the shared file lock. We need to hold the lock from before
2295 * we do the stat until after the read.
2297 lkfile(fd, LOCK_SH, LKLVL0);
2299 if ((fsize=file_size(fd)) == -1 ) {
2300 lkfile(fd, LOCK_UN, LKLVL0);
2303 } else if ( fsize <= Woffset ) {
2305 * The file was truncated between write and now.
2306 * The contents of our last write is totally gone, no check.
2309 printf("%s%s: %d DEBUG2 %s/%d: %d File size (%d) smaller than where last wrote (%d)- no write validation\n",
2310 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, fsize, Woffset);
2311 lkfile(fd, LOCK_UN, LKLVL0);
2312 return 0; /* no validation, but not an error */
2314 } else if ( fsize < (Woffset + Grow_incr)) {
2316 * The file was truncated between write and now.
2317 * Part of our last write has been truncated, adjust our Grow_incr
2322 Grow_incr=fsize-Woffset;
2326 printf("%s%s: %d DEBUG2 %s/%d: %d fsz:%d, lost(%d)of wrt(off:%d, sz:%d), adj=%d\n",
2327 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, fsize, tmp-Grow_incr, Woffset, tmp, Grow_incr);
2333 printf("%s: %d DEBUG3 %s/%d: about to do write validation, offset = %d, size = %d\n",
2334 Progname, Pid, __FILE__, __LINE__, Woffset, Grow_incr);
2336 if ( ! (mode & MODE_FIFO) ) {
2338 if ( lseek(fd, Woffset, 0) == -1 ) {
2339 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, %d, 0) failed: %s\n",
2340 Progname, TagName, Pid, __FILE__, __LINE__, Woffset, strerror(errno));
2343 printf("%s: %d DEBUG4 %s/%d: lseeked to offset:%d\n",
2344 Progname, Pid, __FILE__, __LINE__, Woffset);
2348 * Read last writes data
2351 ret=lio_read_buffer(fd, io_type, Buffer, Grow_incr, SIGUSR1, &errmsg,0);
2353 ret=read_buffer(fd, io_type, Buffer, Grow_incr, 0, &errmsg);
2357 * report the error and debug information before releasing
2360 if ( ret != Grow_incr ) {
2361 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s\n", Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2366 printf("%s%s: %d DEBUG3 %s/%d: fd:%d, offset:%d, fsize:%d, openflags:%#o\n",
2367 Progname, TagName, Pid, __FILE__, __LINE__, fd,
2368 (int)lseek(fd,SEEK_CUR,0), /* FIXME: 64bit/LFS ? */
2370 Fileinfo.openflags);
2373 lkfile(fd, LOCK_UN, LKLVL0);
2378 lkfile(fd, LOCK_UN, LKLVL0);
2380 if ( Mode & MODE_GROW_BY_LSEEK ) {
2381 /* check that all zeros upto last character */
2382 for(ptr=Buffer; ptr < (Buffer+Grow_incr-1); ptr++) {
2383 if ( *ptr != '\0' ) {
2385 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2386 Progname, TagName, Pid, __FILE__, __LINE__,
2387 (int)(Woffset+(Grow_incr-(Buffer-ptr))),
2393 /* check that the last char is a 'w' */
2394 if ( *ptr != 'w' ) {
2396 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2397 Progname, TagName, Pid, __FILE__, __LINE__,
2398 (int)(Woffset+(Grow_incr-(Buffer-ptr))), 'w',
2403 return 0; /* all is well */
2406 else if ( Pattern == PATTERN_OFFSET )
2407 ret=datapidchk(STATIC_NUM, Buffer, Grow_incr, Woffset, &errmsg);
2408 else if ( Pattern == PATTERN_PID )
2409 ret=datapidchk(Pid, Buffer, Grow_incr, Woffset, &errmsg);
2410 else if ( Pattern == PATTERN_ASCII )
2411 ret=dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2412 else if ( Pattern == PATTERN_RANDOM )
2413 ; /* no check for random */
2414 else if ( Pattern == PATTERN_ALT )
2415 ret=databinchk('a', Buffer, Grow_incr, Woffset, &errmsg);
2416 else if ( Pattern == PATTERN_CHKER )
2417 ret=databinchk('c', Buffer, Grow_incr, Woffset, &errmsg);
2418 else if ( Pattern == PATTERN_CNTING )
2419 ret=databinchk('C', Buffer, Grow_incr, Woffset, &errmsg);
2420 else if ( Pattern == PATTERN_ZEROS )
2421 ret=databinchk('z', Buffer, Grow_incr, Woffset, &errmsg);
2422 else if ( Pattern == PATTERN_ONES )
2423 ret=databinchk('o', Buffer, Grow_incr, Woffset, &errmsg);
2425 ret=dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2428 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s in file %s\n",
2429 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2432 printf("%s%s: %d DEBUG1 %s/%d: **fd:%d, lk:%d, offset:%d, sz:%d open flags:%#o %s\n",
2433 Progname, TagName, Pid, __FILE__, __LINE__, fd, lockfile,
2434 Woffset, Grow_incr, Fileinfo.openflags, openflags2symbols(Fileinfo.openflags, ",", NULL));
2441 printf("%s: %d DEBUG7 %s/%d: No corruption detected on write validation , offset = %d, size = %d\n",
2442 Progname, Pid, __FILE__, __LINE__, Woffset, Grow_incr);
2444 return 0; /* all is well */
2449 /***********************************************************************
2451 ***********************************************************************/
2453 check_file(fd, cf_inter, filename, no_file_check)
2455 int cf_inter; /* check file interval */
2456 char *filename; /* needed for error messages */
2457 int no_file_check; /* if set, do not do file content check */
2460 static int cf_count = 0;
2470 if ( cf_inter == 0 || (cf_count % cf_inter != 0)) {
2472 printf("%s: %d DEBUG5 %s/%d: No file check - not time, iter=%d, cnt=%d\n",
2473 Progname, Pid, __FILE__, __LINE__, cf_inter, cf_count);
2474 return 0; /* no check done */
2478 * if we can't determine file content, don't bother checking
2480 if ( no_file_check ) {
2482 printf("%s: %d DEBUG5 %s/%d: No file check, lseek grow or random lseeks\n",
2483 Progname, Pid, __FILE__, __LINE__);
2488 * Lock the file. We need to have the file lock before
2489 * the stat and until after the last read to prevent
2490 * a trunc/truncate from "corrupting" our data.
2492 lkfile(fd, LOCK_SH, LKLVL0);
2494 if ((fsize=file_size(fd)) == -1 ) {
2495 lkfile(fd, LOCK_UN, LKLVL0);
2501 printf("%s: %d DEBUG3 %s/%d: No file validation, file size == 0\n",
2502 Progname, Pid, __FILE__, __LINE__);
2504 lkfile(fd, LOCK_UN, LKLVL0);
2509 printf("%s: %d DEBUG3 %s/%d: about to do file validation\n",
2510 Progname, Pid, __FILE__, __LINE__);
2512 if ( fsize > MAX_FC_READ ) {
2514 * read the file in MAX_FC_READ chuncks.
2517 if ((buf=(char *)malloc(MAX_FC_READ)) == NULL ) {
2518 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", Progname, TagName,
2519 __FILE__, __LINE__, MAX_FC_READ, strerror(errno));
2520 lkfile(fd, LOCK_UN, LKLVL0);
2524 lseek(fd, 0, SEEK_SET);
2526 lkfile(fd, LOCK_SH, LKLVL0); /* get lock on file before getting file size */
2529 while (rd_cnt < fsize ) {
2530 if ( fsize - rd_cnt > MAX_FC_READ )
2531 rd_size=MAX_FC_READ;
2533 rd_size=fsize - rd_cnt;
2536 ret=lio_read_buffer(fd, io_type, buf, rd_size,
2537 SIGUSR1, &errmsg,0);
2539 ret=read_buffer(fd, io_type, buf, rd_size, 0, &errmsg);
2542 if (ret != rd_size ) {
2543 fprintf(stderr, "%s%s: %d %s/%d: %d CFa %s\n",
2544 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2546 lkfile(fd, LOCK_UN, LKLVL0);
2550 read(fd, buf, rd_size);
2553 if ( Pattern == PATTERN_OFFSET )
2554 ret=datapidchk(STATIC_NUM, buf, rd_size, rd_cnt, &errmsg);
2555 else if ( Pattern == PATTERN_PID )
2556 ret=datapidchk(Pid, buf, rd_size, rd_cnt, &errmsg);
2557 else if ( Pattern == PATTERN_ASCII )
2558 ret=dataasciichk(NULL, buf, rd_size, rd_cnt, &errmsg);
2559 else if ( Pattern == PATTERN_RANDOM )
2560 ; /* no checks for random */
2561 else if ( Pattern == PATTERN_ALT )
2562 ret=databinchk('a', buf, rd_size, rd_cnt, &errmsg);
2563 else if ( Pattern == PATTERN_CHKER )
2564 ret=databinchk('c', buf, rd_size, rd_cnt, &errmsg);
2565 else if ( Pattern == PATTERN_CNTING )
2566 ret=databinchk('C', buf, rd_size, rd_cnt, &errmsg);
2567 else if ( Pattern == PATTERN_ZEROS )
2568 ret=databinchk('z', buf, rd_size, rd_cnt, &errmsg);
2569 else if ( Pattern == PATTERN_ONES )
2570 ret=databinchk('o', buf, rd_size, rd_cnt, &errmsg);
2572 ret=dataasciichk(NULL, buf, rd_size, rd_cnt, &errmsg);
2577 "%s%s: %d %s/%d: %d CFp %s in file %s\n",
2578 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2581 lkfile(fd, LOCK_UN, LKLVL0);
2587 lkfile(fd, LOCK_UN, LKLVL0);
2594 * Read the whole file in a single read
2596 if((buf=(char *)malloc(fsize)) == NULL ) {
2597 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", Progname, TagName,
2598 __FILE__, __LINE__, fsize, strerror(errno));
2603 lseek(fd, 0, SEEK_SET);
2606 read(fd, buf, fsize);
2609 ret=lio_read_buffer(fd, io_type, buf, fsize, SIGUSR1, &errmsg,0);
2611 ret=read_buffer(fd, io_type, buf, fsize, 0, &errmsg);
2614 /* unlock the file as soon as we can */
2615 lkfile(fd, LOCK_UN, LKLVL0);
2618 if ( ret != fsize ) {
2619 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s\n",
2620 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2624 if ( Pattern == PATTERN_OFFSET )
2625 ret=datapidchk(STATIC_NUM, buf, fsize, 0, &errmsg);
2626 else if ( Pattern == PATTERN_PID )
2627 ret=datapidchk(Pid, buf, fsize, 0, &errmsg);
2628 else if ( Pattern == PATTERN_ASCII )
2629 ret=dataasciichk(NULL, buf, fsize, 0, &errmsg);
2630 else if ( Pattern == PATTERN_RANDOM )
2631 ; /* no check for random */
2632 else if ( Pattern == PATTERN_ALT )
2633 ret=databinchk('a', buf, fsize, 0, &errmsg);
2634 else if ( Pattern == PATTERN_CHKER )
2635 ret=databinchk('c', buf, fsize, 0, &errmsg);
2636 else if ( Pattern == PATTERN_CNTING )
2637 ret=databinchk('C', buf, fsize, 0, &errmsg);
2638 else if ( Pattern == PATTERN_ZEROS )
2639 ret=databinchk('z', buf, fsize, 0, &errmsg);
2640 else if ( Pattern == PATTERN_ONES )
2641 ret=databinchk('o', buf, fsize, 0, &errmsg);
2643 ret=dataasciichk(NULL, buf, fsize, 0, &errmsg);
2646 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s in file %s\n",
2647 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2657 } /* end of check_file */
2659 /***********************************************************************
2661 ***********************************************************************/
2667 if (fstat(fd, &sb) < 0) {
2668 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
2669 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
2677 /***********************************************************************
2678 * do file lock/unlock action.
2679 ***********************************************************************/
2681 lkfile(int fd, int operation, int lklevel)
2686 if ( lockfile == lklevel) {
2689 switch (operation) {
2691 printf("%s: %d DEBUG6 %s/%d: Attempting to release lock on fd %d\n",
2692 Progname, Pid, __FILE__, __LINE__, fd);
2696 printf("%s: %d DEBUG6 %s/%d: Attempting to get read/shared lock on fd %d\n",
2697 Progname, Pid, __FILE__, __LINE__, fd);
2701 printf("%s: %d DEBUG6 %s/%d: Attempting to get write/exclusive lock on fd %d\n",
2702 Progname, Pid, __FILE__, __LINE__, fd);
2708 * Attempt to get/release desired lock.
2709 * file_lock will attempt to do action over and over again until
2710 * either an unretryable error or the action is completed.
2713 if ( file_lock(fd, operation, &errmsg) != 0 ) {
2714 printf("%s%s: %d %s/%d: Unable to perform lock operation. %s\n",
2715 Progname, TagName, Pid, __FILE__, __LINE__, errmsg);
2717 /* do we count this as an error? handle_error(); */
2722 switch (operation) {
2724 printf("%s: %d DEBUG3 %s/%d: Released lock on fd %d\n",
2725 Progname, Pid, __FILE__, __LINE__, fd);
2729 printf("%s: %d DEBUG3 %s/%d: Got read/shared lock on fd %d\n",
2730 Progname, Pid, __FILE__, __LINE__, fd);
2734 printf("%s: %d DEBUG3 %s/%d: Got write/exclusive lock on fd %d\n",
2735 Progname, Pid, __FILE__, __LINE__, fd);
2739 printf("%s: %d DEBUG3 %s/%d: Completed action %d on fd %d\n",
2740 Progname, Pid, __FILE__, __LINE__, operation, fd);
2750 /***********************************************************************
2752 ***********************************************************************/
2754 pre_alloc(file, fd, size)
2763 if ( ialloc(fd, size, IA_CONT, &avl) == -1 ) {
2764 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: ialloc failed: %d %s\n",
2766 __FILE__, __LINE__, errno, strerror(errno));
2772 #ifdef XFS_IOC_RESVSP
2773 struct xfs_flock64 f;
2779 /* non-zeroing reservation */
2780 if( xfsctl( file, fd, XFS_IOC_RESVSP, &f ) == -1 ){
2781 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: xfsctl(XFS_IOC_RESVSP) failed: %d %s\n",
2783 __FILE__, __LINE__, errno, strerror(errno));
2793 /* non-zeroing reservation */
2794 if( fcntl( fd, F_RESVSP64, &f ) == -1 ){
2795 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: fcntl(F_RESVSP) failed: %d %s\n",
2797 __FILE__, __LINE__, errno, strerror(errno));