2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
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.
37 * To just verify file contents: growfiles -g 0 -c 1 filename
39 * See help and prt_examples functions below.
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
54 * fstat file - to determine if file is a fifo
55 * prealloc file space (if wanted)
64 * remove all files (if wanted)
66 * Author: Richard Logan
72 #ifdef HAVE_SYS_FILE_H
76 #include "dataascii.h"
77 #include "random_range.h"
81 extern char *openflags2symbols();
83 extern int parse_open_flags();
84 extern int background();
86 extern int datapidgen();
87 extern void databingen();
88 extern int datapidchk();
89 extern int databinchk();
90 extern int file_lock();
105 static void notify_others();
111 #define NEWIO 1 /* Use the tlibio.c functions */
114 #define NEWIO 0 /* specifies to use original iowrite.c */
115 /* functions instead of tlibio.c functions */
116 /* Once it is proven tlibio.c functions work properly, */
117 /* only tlibio.c functions will be used */
123 #define PATH_MAX 1023
128 #define DEF_FILE "gf"
135 int io_type = 0; /* I/O type -sync */
136 int open_flags = O_RDWR|O_CREAT; /* open flags */
138 #define MAX_FC_READ 196608 /* 4096 * 48 - 48 blocks */
140 #define PATTERN_ASCII 1 /* repeating alphabet letter pattern */
141 /* allows multiple writers and to be checked */
142 #define PATTERN_PID 2 /* <pid><words byte offset><pid> */
143 /* Assumes 64 bit word. Only allows single */
144 /* process to write and check */
146 * 1234567890123456789012345678901234567890123456789012345678901234
147 * ________________________________________________________________
148 * < pid >< offset in file of this word >< pid >
151 #define PATTERN_OFFSET 3 /* Like PATTERN_PID but has a fixed number */
152 /* (STATIC_NUM) instead of pid. */
153 /* Allows multiple processes to write/read */
154 #define PATTERN_ALT 4 /* alternating bit pattern (i.e. 0x5555555...) */
155 #define PATTERN_CHKER 5 /* checkerboard pattern (i.e. 0xff00ff00ff00...) */
156 #define PATTERN_CNTING 6 /* counting pattern (i.e. 0 - 07, 0 - 07, ...) */
157 #define PATTERN_ONES 7 /* all bits set (i.e. 0xffffffffffffff...) */
158 #define PATTERN_ZEROS 8 /* all bits cleared (i.e. 0x000000000...) */
159 #define PATTERN_RANDOM 9 /* random integers - can not be checked */
160 #define STATIC_NUM 221849 /* used instead of pid when PATTERN_OFFSET */
162 #define MODE_RAND_SIZE 1 /* random write and trunc */
163 #define MODE_RAND_LSEEK 2 /* random lseek before write */
164 #define MODE_GROW_BY_LSEEK 4 /* lseek beyond end of file then write a byte */
165 #define RANDOM_OPEN 999876 /* if Open_flags set to this value, open flags */
166 /* will be randomly choosen from Open_flags[] */
167 #define MODE_FIFO S_IFIFO /* defined in stat.h 0010000 */
169 int num_files = 0; /* num_auto_files + cmd line files */
170 char *filenames; /* pointer to space containing filenames */
171 int remove_files = 0; /* if set, cleanup default is not to cleanup */
172 int bytes_consumed = 0; /* total bytes consumed, all files */
173 int bytes_to_consume = 0; /* non-zero if -B was specified, total bytes */
174 int Maxerrs = 100; /* Max number errors before forced exit */
175 int Errors = 0; /* number of encountered errors */
176 int Upanic_on_error = 0; /* call upanic if error and this variable set */
178 /* The *_size variables are only used when random iosize option (-r) is used */
180 int min_size=1; /* also set in option parsing */
181 int mult_size=1; /* when random iosz, iosz must be mult of mult_size */
182 /* the *_lseek variables are only used when radon lseek option (-R) is used */
183 int min_lseek=0; /* also set in option parsing */
184 int max_lseek=-1; /* -1 means size of file */
186 int Pattern=PATTERN_OFFSET; /* This pattern is 64 bit word based */
188 int Pattern=PATTERN_ASCII;
190 int Seed=-1; /* random number seed, < 0 == uninitialized */
191 int Nseeds=0; /* Number of seed specified by the user */
192 int *Seeds; /* malloc'ed arrary of ints holding user spec seeds */
194 int using_random=0; /* flag indicating randomization is being used */
195 float delaysecs=0.0; /* delay between iterations (in seconds) */
196 int delaytime; /* delay between iterations in clocks/uses */
197 int lockfile=0; /* if set, do file locking */
198 /* 1 = do file locking around write, trunc */
200 /* 2 = write lock around all file operations */
202 int Woffset=0; /* offset before last write */
203 int Grow_incr=4096; /* sz of last write */
204 int Mode=0; /* bitmask of write/trunc mode */
205 /* also knows if dealing with fifo */
206 char *Buffer = NULL; /* buffer used by write and write check */
207 int Alignment=0; /* if non word multiple, io will not be word aligned */
208 int Opid=0; /* original pid */
210 int Sync_with_others = 0; /* Flag indicating to stop other if we stop before DONE */
211 int Iter_cnt = 0; /* contains current iteration count value */
212 char TagName[40]; /* name of this growfiles (see Monster) */
222 * Define open flags that will be used when '-o random' option is used.
223 * Note: If there is more than one growfiles doing its thing to the same
224 * file, O_TRUNC will cause data mismatches. How you ask?
225 * timing of events, example:
226 * Process one Process two
227 * --------------- -------------
233 * write with wrong pattern
234 * because offset is wrong
236 * The second process truncated the file after the pattern was
237 * determined, thus the pattern is wrong for the file location.
239 * There can also be a timing problem with open flag O_APPEND if
240 * file locks are not being used (-l option). Things could happen
241 * between the fstat and the write. Thus, writing the wrong pattern.
242 * If all processes observe the file locks, O_APPEND should be ok
248 O_RDWR|O_CREAT|O_RAW,
249 O_RDWR|O_CREAT|O_BIG,
250 O_RDWR|O_CREAT|O_APPEND,
251 O_RDWR|O_CREAT|O_NDELAY,
252 O_RDWR|O_CREAT|O_PLACE,
253 O_RDWR|O_CREAT|O_SYNC,
254 O_RDWR|O_CREAT|O_RAW|O_SYNC,
255 O_RDWR|O_CREAT|O_NDELAY|O_SYNC,
256 O_RDWR|O_CREAT|O_NDELAY|O_SYNC|O_BIG,
257 O_RDWR|O_CREAT|O_RAW,
258 O_RDWR|O_CREAT|O_RAW|O_APPEND,
259 O_RDWR|O_CREAT|O_RAW|O_BIG,
260 O_RDWR|O_CREAT|O_RAW|O_APPEND|O_BIG,
262 * O_WELLFORMED makes -o random require well formed i/o
264 #if ALLOW_O_WELLFORMED
266 O_RDWR|O_CREAT|O_PARALLEL|O_WELLFORMED|O_RAW,
267 O_RDWR|O_CREAT|O_PARALLEL|O_WELLFORMED|O_RAW|O_TRUNC,
268 #endif /* O_PARALLEL */
273 O_RDWR|O_CREAT|O_APPEND,
274 O_RDWR|O_CREAT|O_NDELAY,
275 O_RDWR|O_CREAT|O_SYNC,
276 O_RDWR|O_CREAT|O_SYNC|O_NDELAY,
277 O_RDWR|O_CREAT|O_APPEND|O_NDELAY,
282 #define REXEC_INIT 0 /* don't do re-exec of childern */
283 #define REXEC_DOIT 1 /* Do re-exec of childern */
284 #define REXEC_DONE 2 /* We've already been re-exec'ed */
294 #define USECS_PER_SEC 1000000 /* microseconds per second */
297 * Define marcos used when dealing with file locks.
299 #define LKLVL0 1 /* file lock around write/read/trunc */
300 #define LKLVL1 2 /* file lock after open to before close */
303 * Define special max lseek values
305 #define LSK_EOF -1 /* set fptr up to EOF */
306 #define LSK_EOFPLUSGROW -2 /* set fptr up to EOF + grow - leave whole */
307 #define LSK_EOFMINUSGROW -3 /* set fptr up to EOF-grow - no grow */
310 /***********************************************************************
312 ***********************************************************************/
318 extern char *optarg; /* used by getopt */
323 int first_file_ind = 0;
324 int num_auto_files = 0; /* files created by tool */
325 int seq_auto_files = 0; /* auto files created by tool created by tool */
326 char *auto_dir = DEF_DIR;
327 char *auto_file = DEF_FILE;
328 int grow_incr = 4096;
329 int trunc_incr = 4096;
330 int trunc_inter = 0; /* 0 means none, */
331 int unlink_inter = 0; /* 0 means none, 1 means always unlink */
332 int unlink_inter_ran = -1; /* -1 -use unlink_inter, otherwise randomly choose */
333 /* between unlink_inter and unlink_inter_ran */
334 int file_check_inter = 0; /* 0 means never, 1 means always */
335 int write_check_inter = 1; /* 0 means never, 1 means always */
336 int iterations = 1; /* number of increments to be added */
337 int no_file_check = 0; /* if set, no whole file checking will be done */
339 int fd; /* file descriptor */
340 int stop = 0; /* loop stopper if set */
344 int pre_alloc_space = 0;
346 int total_grow_value = 0; /* used in pre-allocations */
348 int backgrnd = 1; /* return control to user */
350 int time_iterval = -1;
351 time_t start_time = 0;
352 char reason[40]; /* reason for loop termination */
355 int reexec=REXEC_INIT; /* reexec info */
356 char *exec_path=NULL;
360 char *filename; /* name of file specified by user */
361 char *cptr; /* temp char pointer */
362 extern int Forker_npids; /* num of forked pid, defined in forker.c */
365 if ( argv[0][0] == '-' )
368 * Determine name of file used to invoke this program
370 if ((Progname=strrchr(argv[0], '/')) != NULL)
380 while ((ind=getopt(argc, argv,
381 "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) {
389 switch (sscanf(optarg, "%i%c",
390 &bytes_to_consume, &chr)) {
396 bytes_to_consume *= BSIZE;
399 "%s%s: --B option arg invalid\n",
407 fprintf(stderr, "%s%s: --B option arg invalid\n",
417 prt_examples(stdout);
420 case 'b' : /* batch */
425 if (sscanf(optarg, "%i", &write_check_inter) != 1 ) {
426 fprintf(stderr, "%s%s: --c option arg invalid\n",
434 if (sscanf(optarg, "%i", &file_check_inter) != 1 ) {
435 fprintf(stderr, "%s%s: --c option arg invalid\n",
446 unsetenv("TMPDIR"); /* force the use of auto_dir */
448 if ( stat(auto_dir, &statbuf) == -1 ) {
449 if ( mkdir(auto_dir, 0777) == -1 ) {
450 if ( errno != EEXIST ) {
452 "%s%s: Unable to make dir %s\n",
453 Progname, TagName, auto_dir);
459 if ( ! (statbuf.st_mode & S_IFDIR) ) {
461 "%s%s: %s already exists and is not a directory\n",
462 Progname, TagName, auto_dir);
469 if (sscanf(optarg, "%i", &Debug) != 1 ) {
470 fprintf(stderr, "%s%s: --D option arg invalid\n",
478 if (sscanf(optarg, "%i", &Maxerrs) != 1 ) {
479 fprintf(stderr, "%s%s: --e option arg invalid\n",
491 if ((ret=sscanf(optarg, "%i%c", &grow_incr, &chr)) < 1 ||
494 fprintf(stderr, "%s%s: --g option arg invalid\n",
500 if ( chr == 'b' || chr == 'B' )
504 "%s%s: --g option arg invalid\n",
513 if (sscanf(optarg, "%f", &delaysecs) != 1 || delaysecs < 0 ) {
515 fprintf(stderr, "%s%s: --H option arg invalid\n",
523 if (sscanf(optarg, "%i", &iterations) != 1 ||
526 fprintf(stderr, "%s%s: --i option arg invalid\n",
535 if((io_type=lio_parse_io_arg1(optarg)) == -1 ) {
537 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
541 if( io_type & LIO_RANDOM )
544 if((io_type=parse_io_arg(optarg)) == -1 ) {
546 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
550 if( io_type == 99 ) /* hold-over until tlibio.h */
558 lockfile=2; /* lockfile can only be 1 or 2 */
562 if (sscanf(optarg, "%i", &time_iterval) != 1 ||
564 fprintf(stderr, "%s%s: --L option arg invalid\n",
572 if (sscanf(optarg, "%i:%i", &num_procs, &forker_mode) < 1 ||
575 fprintf(stderr, "%s%s: --n option arg invalid\n",
584 if (sscanf(optarg, "%i", &num_auto_files) != 1 ||
585 num_auto_files < 0 ) {
587 fprintf(stderr, "%s%s: --N option arg invalid\n",
595 if (sscanf(optarg, "%i", &Alignment) != 1 ||
596 num_auto_files < 0 ) {
598 fprintf(stderr, "%s%s: --O option arg invalid\n",
606 if ( strcmp(optarg, "random") == 0 ){
607 open_flags=RANDOM_OPEN;
610 } else if ((open_flags=parse_open_flags(optarg, NULL)) == -1 ) {
611 fprintf(stderr, "%s%s: --o arg contains invalid flag\n",
618 case 'p' : /* pre allocate space */
620 printf("%s%s: --p is illegal option on this system\n",
630 if (strcmp(optarg, "PANIC") != 0 ) {
631 fprintf(stderr, "%s%s: --P arg must be PANIC\n", Progname, TagName);
635 printf("%s: Will call upanic after writes\n");
637 printf("%s%s: --P is illegal option on non-cray system\n",
643 case 'q': /* file content or pattern */
646 Pattern = PATTERN_ALT;
649 Pattern = PATTERN_ASCII;
652 Pattern = PATTERN_PID;
655 Pattern = PATTERN_OFFSET;
658 Pattern = PATTERN_CHKER;
661 Pattern = PATTERN_CNTING;
664 Pattern = PATTERN_RANDOM;
668 Pattern = PATTERN_ZEROS;
671 Pattern = PATTERN_ONES;
675 "%s%s: --C option arg invalid, A, a, p, o, c, C, r, z, or 0\n",
682 case 'R': /* random lseek before write arg: [min-]max*/
683 if (sscanf(optarg, "%i-%i", &min_lseek, &max_lseek) != 2 ) {
684 min_lseek=1; /* same as default in define */
685 if (sscanf(optarg, "%i%c", &max_lseek, &chr) != 1 ) {
686 fprintf(stderr, "%s%s: --R option arg invalid: [min-]max\n",
691 if ( max_lseek < LSK_EOFMINUSGROW ) {
692 fprintf(stderr, "%s%s: --R option, max_lseek is invalid\n",
696 Mode |= MODE_RAND_LSEEK;
700 case 'r': /* random io size arg: [min-]max[:mult] */
702 /* min-max:mult format */
703 if (sscanf(optarg, "%i-%i:%i%c", &min_size, &max_size,
704 &mult_size, &chr) != 3 ) {
706 /* max:mult format */
707 if (sscanf(optarg, "%i:%i%c", &max_size,
708 &mult_size, &chr) != 2 ) {
710 if (sscanf(optarg, "%i-%i%c", &min_size,
711 &max_size, &chr) != 2 ) {
713 if (sscanf(optarg, "%i%c", &max_size, &chr) != 1 ) {
715 "%s%s: --r option arg invalid: [min-]max[:mult]\n",
723 if ( max_size < 0 ) {
724 fprintf(stderr, "%s%s: --r option, max_size is invalid\n",
729 * If min and max are the same, no randomness
731 if ( min_size != max_size ) {
732 Mode |= MODE_RAND_SIZE;
738 if (sscanf(optarg, "%i", &seq_auto_files) != 1 ||
739 seq_auto_files < 0 ) {
741 fprintf(stderr, "%s%s: --S option arg invalid\n",
748 case 's': /* format: seed[,seed...] */
750 /* count the number of seeds */
752 for(Nseeds=1; *cptr ; Nseeds++) {
753 if ( (filename=strchr(cptr, ',')) == NULL )
758 Seeds=(int *)malloc(Nseeds*sizeof(int));
761 * check that each seed is valid and put them in
762 * the newly malloc'ed Seeds arrary.
764 filename=cptr=optarg;
765 for(Nseeds=0; *cptr; Nseeds++) {
766 if ( (filename=strchr(cptr, ',')) == NULL ) {
767 if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
768 fprintf(stderr, "%s%s: --s option arg %s invalid\n",
769 Progname, TagName, cptr);
778 if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
779 fprintf(stderr, "%s%s: --s option arg %s invalid\n",
780 Progname, TagName, cptr);
784 *filename=','; /* restore string */
791 if ((ret=sscanf(optarg, "%i%c", &trunc_incr, &chr)) < 1 ||
794 fprintf(stderr, "%s%s: --t option arg invalid\n",
800 if ( chr == 'b' || chr == 'B' )
804 "%s%s: --t option arg invalid\n",
812 case 'T': /* truncate interval */
813 if (sscanf(optarg, "%i%c", &trunc_inter, &chr) != 1 ||
816 fprintf(stderr, "%s%s: --T option arg invalid\n",
827 case 'U': /* how often to unlink file */
830 * A-B - randomly pick interval between A and B
831 * X - unlink file every X iteration
833 if (sscanf(optarg, "%i-%i", &unlink_inter,
834 &unlink_inter_ran) == 2 ) {
836 if ( unlink_inter < 0 || unlink_inter_ran < 0 ) {
837 fprintf(stderr, "%s%s: --U option arg invalid\n",
842 /* ensure unlink_inter contains smaller value */
843 if ( unlink_inter > unlink_inter_ran ) {
844 tmp=unlink_inter_ran;
845 unlink_inter_ran=unlink_inter;
850 } else if (sscanf(optarg, "%i%c", &unlink_inter, &chr) != 1 ||
853 fprintf(stderr, "%s%s: --U option arg invalid\n",
861 if ( reexec != REXEC_DONE )
866 Mode |= MODE_GROW_BY_LSEEK;
870 sprintf( TagName, "(%.39s)", optarg );
885 cptr = getenv("TOUTPUT");
886 if( (cptr != NULL) && (strcmp( cptr, "NOPASS" ) == 0) ){
891 if ( Pattern == PATTERN_RANDOM ) {
893 if ( write_check_inter || file_check_inter )
894 printf("%s%s: %d Using random pattern - no data checking will be performed!\n",
895 Progname, TagName, (int)getpid());
897 else if ( max_lseek == LSK_EOFPLUSGROW || Mode & MODE_GROW_BY_LSEEK ) {
900 if ( file_check_inter )
901 printf("%s%s: %d Using random lseek beyond EOF or lseek grow,\n\
902 no whole file checking will be performed!\n", Progname, TagName, (int)getpid());
906 if ( Mode & MODE_RAND_SIZE )
916 printf("%s: %d DEBUG2 forking, returning control to the user\n",
918 background(Progname); /* give user their prompt back */
922 if ( Sync_with_others )
928 lio_set_debug(Debug-3);
930 set_iowrite_debug(Debug-3);
935 * Print some program information here if debug is turned on to
941 if ( Mode & MODE_GROW_BY_LSEEK )
942 printf("%s: %d DEBUG lseeking past end of file, writting a \"w\"\n",
944 else if ( Pattern == PATTERN_OFFSET )
945 printf("%s: %d DEBUG3 %d<byteoffset>%d per word pattern multi-writers.\n",
946 Progname, Pid, STATIC_NUM, STATIC_NUM);
947 else if ( Pattern == PATTERN_PID )
948 printf("%s: %d DEBUG3 <pid><byteoffset><pid> per word pattern - 1 writer\n",
950 else if ( Pattern == PATTERN_ASCII )
951 printf("%s: %d DEBUG3 ascii pattern (vi'able)- allows multiple writers\n",
953 else if ( Pattern == PATTERN_ALT )
954 printf("%s: %d DEBUG3 alt bit pattern - allows multiple writers\n",
956 else if ( Pattern == PATTERN_CHKER )
957 printf("%s: %d DEBUG3 checkerboard pattern - allows multiple writers\n",
959 else if ( Pattern == PATTERN_CNTING )
960 printf("%s: %d DEBUG3 counting pattern - allows multiple writers\n",
962 else if ( Pattern == PATTERN_RANDOM )
963 printf("%s: %d DEBUG3 random integer pattern - no write/file checking\n",
965 else if ( Pattern == PATTERN_ONES )
966 printf("%s: %d DEBUG3 all ones pattern - allows multiple writers\n",
968 else if ( Pattern == PATTERN_ZEROS )
969 printf("%s: %d DEBUG3 all zeros pattern - allows multiple writers\n",
973 printf("%s: %d DEBUG3 unknown pattern\n",
975 if ( bytes_to_consume )
976 printf("%s: %d DEBUG3 bytes_to_consume = %d\n",
977 Progname, Pid, bytes_to_consume);
978 printf("%s: %d DEBUG3 Maxerrs = %d, pre_alloc_space = %d, filelocking = %d\n",
979 Progname, Pid, Maxerrs, pre_alloc_space, lockfile);
981 printf("%s: %d DEBUG3 Debug = %d, remove files in cleanup : %d\n",
982 Progname, Pid, Debug, remove_files);
984 printf("%s: %d DEBUG3 Mode = %#o\n", Progname, Pid, Mode);
986 if ( open_flags == RANDOM_OPEN )
987 printf("%s: %d DEBUG3 open_flags = (random), io_type = %#o\n", Progname,
990 printf("%s: %d DEBUG3 open_flags = %#o, io_type = %#o\n", Progname,
991 Pid, open_flags, io_type);
993 if ( Mode & MODE_RAND_SIZE ) {
994 printf("%s: %d DEBUG3 random write/trunc: min=%d, max=%d, mult = %d\n",
995 Progname, Pid, min_size, max_size, mult_size);
998 printf("%s: %d DEBUG3 grow_incr = %d\n",
999 Progname, Pid, grow_incr);
1001 if ( Mode & MODE_RAND_LSEEK ) {
1002 if ( max_lseek == LSK_EOF )
1003 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile>\n",
1004 Progname, Pid, min_lseek);
1005 else if ( max_lseek == LSK_EOFPLUSGROW )
1006 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile+iosize>\n",
1007 Progname, Pid, min_lseek);
1008 else if ( max_lseek == LSK_EOFMINUSGROW )
1009 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile-iosize>\n",
1010 Progname, Pid, min_lseek);
1012 printf("%s: %d DEBUG3 random lseek: min=%d, max=%d\n",
1013 Progname, Pid, min_lseek, max_lseek);
1016 printf("%s: %d DEBUG3 check write interval = %d, check file interval = %d\n",
1017 Progname, Pid, write_check_inter, file_check_inter);
1019 printf("%s: %d DEBUG3 trunc interval = %d, trunc_incr = %d\n",
1020 Progname, Pid, trunc_inter, trunc_incr);
1022 if ( no_file_check )
1023 printf("%s: %d DEBUG3 no whole file checking will be done\n",
1026 if ( unlink_inter_ran == -1 ) {
1027 printf("%s: %d DEBUG3 unlink_inter = %d\n",
1028 Progname, Pid, unlink_inter);
1030 printf("%s: %d DEBUG3 unlink_inter = %d, unlink_inter_ran = %d\n",
1031 Progname, Pid, unlink_inter, unlink_inter_ran);
1035 num=sizeof(Open_flags)/sizeof(int);
1036 printf("%s: %d DEBUG9 random open flags values:\n", Progname, Pid);
1037 for(ind=0; ind<num; ind++) {
1038 printf("\t%#o\n", Open_flags[ind]);
1041 } /* end of DEBUG > 2 */
1043 if ( Debug > 1 && num_procs > 1 ) {
1044 printf("%s: %d DEBUG2 about to fork %d more copies\n", Progname,
1048 fflush(stdout); /* ensure pending i/o is flushed before forking */
1051 forker(num_procs, forker_mode, Progname);
1053 Pid=getpid(); /* reset after the forks */
1055 * If user specified random seed(s), get that random seed value.
1056 * get random seed if it was not specified by the user.
1057 * This is done after the forks, because pid is used to get the seed.
1059 if ( Nseeds == 1 ) {
1061 * If only one seed specified, all processes will get that seed.
1064 } else if ( Nseeds > 1 ) {
1066 * More than one seed was specified.
1067 * The original process gets the first seed. Each
1068 * process will be get the next seed in the specified list.
1070 if ( Opid == Pid ) {
1074 * If user didn't specify enough seeds, use default method.
1076 if ( Forker_npids >= Nseeds )
1077 Seed=time(0) + Pid; /* default random seed */
1079 Seed=Seeds[Forker_npids];
1084 * Generate a random seed based on time and pid.
1085 * It has a good chance of being unique for each pid.
1087 Seed=time(0) + Pid; /* default random seed */
1090 random_range_seed(Seed);
1092 if ( using_random && Debug > 0 )
1093 printf("%s%s: %d DEBUG1 Using random seed of %d\n",
1094 Progname, TagName, Pid, Seed);
1096 if ( unlink_inter_ran > 0 ) {
1098 * Find unlinking file interval. This must be done after
1099 * the seed was set. This allows multiple copies to
1100 * get different intervals.
1103 unlink_inter=random_range(tmp, unlink_inter_ran, 1, NULL);
1106 printf("%s: %d DEBUG3 Unlink interval is %d (random %d - %d)\n",
1107 Progname, Pid, unlink_inter, tmp, unlink_inter_ran);
1111 * re-exec all childern if reexec is set to REXEC_DOIT.
1112 * This is useful on MPP systems to get the
1113 * child process on another PE.
1115 if ( reexec == REXEC_DOIT && Opid != Pid ) {
1116 if ( exec_path == NULL ) {
1117 exec_path = argv[0];
1118 /* Get space for cmd (2 extra, 1 for - and 1 fro NULL */
1119 argv[0] = (char *)malloc(strlen(exec_path) + 2);
1120 sprintf(argv[0], "-%s", exec_path);
1124 printf("%s: %d DEBUG3 %s/%d: execvp(%s, argv)\n",
1125 Progname, Pid, __FILE__, __LINE__, argv[0]);
1127 execvp(argv[0], argv);
1130 /*** begin filename stuff here *****/
1132 * Determine the number of files to be dealt with
1134 if ( optind == argc ) {
1136 * no cmd line files, therfore, set
1137 * the default number of auto created files
1139 if ( ! num_auto_files && ! seq_auto_files )
1143 first_file_ind=optind;
1144 num_files += argc-optind;
1147 if ( num_auto_files ) {
1148 num_files += num_auto_files;
1151 if ( seq_auto_files ) {
1152 num_files += seq_auto_files;
1156 * get space for file names
1158 if ((filenames=(char *)malloc(num_files*PATH_MAX)) == NULL) {
1159 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1160 Progname, TagName, Pid, __FILE__, __LINE__, num_files*PATH_MAX,
1166 * fill in filename cmd files then auto files.
1170 if ( first_file_ind ) {
1171 for(ind=first_file_ind; ind<argc; ind++, num++) {
1172 strcpy((char *)filenames+(num*PATH_MAX), argv[ind]);
1177 * construct auto filename and insert them into filenames space
1180 for(ind=0;ind<num_auto_files; ind++, num++) {
1181 sprintf((char *)filenames+(num*PATH_MAX), "%s.%d",
1182 tempnam(auto_dir, auto_file), ind );
1186 * construct auto seq filenames
1188 for(ind=1; ind<=seq_auto_files; ind++, num++) {
1189 sprintf((char *)filenames+(num*PATH_MAX), "%s/%s%d",
1190 auto_dir, auto_file, ind);
1193 /**** end filename stuff ****/
1195 if ( time_iterval > 0 )
1199 * get space for I/O buffer
1202 if ((Buffer=(char *)malloc(grow_incr+Alignment)) == NULL) {
1203 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1204 Progname, TagName, Pid, __FILE__, __LINE__, grow_incr, strerror(errno));
1208 Buffer = Buffer + Alignment;
1213 printf("%s: %d DEBUG3 num_files = %d\n",
1214 Progname, Pid, num_files);
1218 if ( pre_alloc_space ) {
1219 if ( iterations == 0 ) {
1220 fprintf(stderr, "%s%s: %d %s/%d: can NOT pre-alloc and grow forever\n",
1221 Progname, TagName, Pid, __FILE__, __LINE__);
1224 if ( Mode & MODE_RAND_SIZE ) {
1226 "%s%s: %d %s/%d: can NOT pre-alloc and do random io size\n",
1227 Progname, TagName, Pid, __FILE__, __LINE__);
1231 total_grow_value=grow_incr * iterations;
1236 if ( bytes_to_consume && bytes_to_consume < total_grow_value ) {
1237 total_grow_value=bytes_to_consume;
1243 * If delaying between iterations, get amount time to
1244 * delaysecs in clocks or usecs.
1245 * If on the CRAY, delaytime is in clocks since
1246 * _rtc() will be used, which does not have the overhead
1247 * of gettimeofday(2).
1252 hz=sysconf(_SC_CLK_TCK);
1253 delaytime=(int)((float)hz * delaysecs);
1255 delaytime=(int)((float)USECS_PER_SEC * delaysecs);
1260 * This is the main iteration loop.
1261 * Each iteration, all files can be opened, written to,
1262 * read to check the write, check the whole file,
1263 * truncated, and closed.
1265 for(Iter_cnt=1; ! stop ; Iter_cnt++) {
1267 if ( iterations && Iter_cnt >= iterations+1 ) {
1268 strcpy(reason, "Hit iteration value");
1273 if ( (time_iterval > 0) && (start_time + time_iterval < time(0)) ) {
1274 sprintf(reason, "Hit time value of %d", time_iterval);
1279 if ( bytes_to_consume && bytes_consumed >= bytes_to_consume) {
1280 sprintf(reason, "Hit bytes consumed value of %d", bytes_to_consume);
1286 * This loop will loop through all files.
1287 * Each iteration, a single file can be opened, written to,
1288 * read to check the write, check the whole file,
1289 * truncated, and closed.
1291 for(ind=0; ind<num_files; ind++) {
1296 filename=(char *)filenames+(ind*PATH_MAX);
1297 Fileinfo.filename=(char *)filenames+(ind*PATH_MAX);
1300 if ( open_flags == RANDOM_OPEN ) {
1301 ret=Open_flags[random_range(0, sizeof(Open_flags)/sizeof(int)-1, 1, NULL)];
1307 Fileinfo.openflags=ret;
1310 printf("%s: %d DEBUG3 %s/%d: %d Open filename = %s, open flags = %#o %s\n",
1311 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, ret,
1312 openflags2symbols(ret, ",", NULL));
1313 } else if ( Debug > 2 ) {
1314 printf("%s: %d DEBUG3 %s/%d: %d filename = %s, open flags = %#o\n",
1315 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, ret);
1319 * open file with desired flags.
1321 if ( (fd=open(filename, ret, 0777)) == -1 ) {
1323 "%s%s: %d %s/%d: open(%s, %#o, 0777) returned -1, errno:%d %s\n",
1324 Progname, TagName, Pid, __FILE__, __LINE__, filename, ret, errno, strerror(errno));
1331 lkfile(fd, LOCK_EX, LKLVL1); /* lock if lockfile is LKLVL1 */
1335 * preallocation is only done once, if specified.
1337 if ( pre_alloc_space ) {
1338 if (pre_alloc(filename, fd, total_grow_value) != 0 ) {
1343 printf("%s: %d DEBUG2 %s/%d: pre_allocated %d for file %s\n",
1344 Progname, Pid, __FILE__, __LINE__, total_grow_value, filename);
1346 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1348 Iter_cnt=0; /* reset outside loop to restart from one */
1354 * grow file by desired amount.
1355 * growfile() will set the Grow_incr variable and
1356 * possiblly update the Mode variable indicating
1357 * if we are dealing with a FIFO file.
1360 if (growfile(fd, filename, grow_incr, Buffer) != 0 ) {
1362 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1368 * check if last write is not corrupted
1370 if ( check_write(fd, write_check_inter, filename,
1376 * Check that whole file is not corrupted.
1378 if ( check_file(fd, file_check_inter, filename,
1379 no_file_check) != 0 ) {
1384 * shrink file by desired amount if it is time
1387 if ( shrinkfile(fd, filename, trunc_incr, trunc_inter, Mode) != 0 ) {
1391 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1394 printf("%s: %d DEBUG5 %s/%d: %d Closing file %s fd:%d \n",
1395 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, fd);
1399 * Unlink the file if that is desired
1401 if ( unlink_inter && (Iter_cnt % unlink_inter == 0) ) {
1404 printf("%s: %d DEBUG5 %s/%d: %d Unlinking file %s\n",
1405 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename);
1411 * delay while staying active for "delaysecs" seconds.
1419 while ( ct < end ) {
1423 struct timeval curtime;
1424 gettimeofday(&curtime, NULL);
1425 ct=curtime.tv_sec*USECS_PER_SEC + curtime.tv_usec;
1427 while ( ct < end ) {
1429 gettimeofday(&curtime, NULL);
1430 ct=curtime.tv_sec*USECS_PER_SEC + curtime.tv_usec;
1437 * if Iter_cnt == 0, then we pre allocated space to all files
1438 * and we are starting outside loop over. Set pre_alloc_space
1439 * to zero otherwise we get in infinite loop
1441 if ( Iter_cnt == 0 ) {
1447 } /* end iteration for loop */
1451 printf("%s%s: %d %s/%d: DONE %d iterations to %d files. %s\n",
1452 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, num_files, reason);
1461 printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1462 Progname, TagName, Pid, Errors);
1463 printf("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", Progname, TagName, Pid, __FILE__, __LINE__);
1468 printf("%s%s: %d DEBUG3 %s/%d: no errors, exiting with value of 0\n", Progname, TagName, Pid, __FILE__, __LINE__);
1472 /***********************************************************************
1474 ***********************************************************************/
1482 * now loop through all signals and set the handlers
1485 for (sig = 1; sig < NSIG; sig++) {
1496 #endif /* SIGCKPT */
1499 #endif /* SIGRESTART */
1505 sigset( sig, sig_handler );
1507 /* linux and cray */
1508 signal(sig, sig_handler);
1518 /***********************************************************************
1520 ***********************************************************************/
1527 if ( sig == SIGUSR2 ) {
1528 fprintf(stdout, "%s%s: %d %s/%d: received SIGUSR2 (%d) - stopping.\n",
1529 Progname, TagName, Pid, __FILE__, __LINE__, sig);
1531 signal(sig, sig_handler); /* allow us to get this signal more than once */
1534 } else if( sig == SIGINT ){
1535 /* The user has told us to cleanup, don't pretend it's an error. */
1538 fprintf(stderr, "%s%s: %d %s/%d: received unexpected signal: %d\n", Progname, TagName,
1539 Pid, __FILE__, __LINE__, sig);
1542 fprintf(stderr, "%s%s: %d %s/%d: received unexpected signal: %d\n", Progname, TagName,
1543 Pid, __FILE__, __LINE__, sig);
1549 printf("%s%s: %d DEBUG3 %s/%d: Exiting with a value of %d\n",
1550 Progname, TagName, Pid, __FILE__, __LINE__, exit_stat);
1555 /***********************************************************************
1556 * this function attempts to send SIGUSR2 to other growfiles processes
1557 * telling them to stop.
1559 ***********************************************************************/
1563 static int send_signals = 0;
1565 extern int Forker_pids[];
1566 extern int Forker_npids;
1568 if ( Sync_with_others && send_signals == 0 ) {
1571 send_signals=1; /* only send signals once */
1573 printf("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pgrp\n",
1574 Progname, TagName, Pid, __FILE__, __LINE__);
1575 killm(C_PGRP, getpgrp(), SIGUSR2);
1577 send_signals=1; /* only send signals once */
1579 for (ind=0; ind< Forker_npids; ind++) {
1580 if ( Forker_pids[ind] != Pid )
1582 printf("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pid %d\n",
1583 Progname, TagName, Pid, __FILE__, __LINE__, Forker_pids[ind]);
1584 kill(Forker_pids[ind], SIGUSR2);
1591 /***********************************************************************
1592 * this function will count the number of errors encountered.
1593 * This function will call upanic if wanted or cleanup and
1594 * and exit is Maxerrs were encountered.
1595 ***********************************************************************/
1602 if ( Errors & Upanic_on_error ) {
1607 if ( Maxerrs && Errors >= Maxerrs ) {
1608 printf("%s%s: %d %s/%d: %d Hit max errors value of %d\n",
1609 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, Maxerrs);
1614 printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1615 Progname, TagName, Pid, Errors);
1616 printf("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", Progname, TagName, Pid, __FILE__, __LINE__);
1625 /***********************************************************************
1627 ***********************************************************************/
1633 if ( remove_files ) {
1635 printf("%s: %d DEBUG3 Removing all %d files\n",
1636 Progname, Pid, num_files);
1637 for(ind=0; ind<=num_files; ind++) {
1638 unlink(filenames+(ind*PATH_MAX));
1641 if ( using_random && Debug > 1 )
1642 printf("%s%s: %d DEBUG2 Used random seed: %d\n",
1643 Progname, TagName, Pid, Seed);
1647 /***********************************************************************
1649 ***********************************************************************/
1654 "Usage: %s%s [-bhEluy][[-g grow_incr][-i num][-t trunc_incr][-T trunc_inter]\n",
1655 Progname, TagName );
1657 "[-d auto_dir][-e maxerrs][-f auto_file][-N num_files][-w][-c chk_inter][-D debug]\n");
1659 "[-s seed][-S seq_auto_files][-p][-P PANIC][-I io_type][-o open_flags][-B maxbytes]\n");
1661 "[-r iosizes][-R lseeks][-U unlk_inter][-W tagname] [files]\n");
1665 } /* end of usage */
1667 /***********************************************************************
1669 ***********************************************************************/
1676 -h Specfied to print this help and exit.\n\
1677 -b Specfied to execute in sync mode.(def async mode)\n\
1678 -B maxbytes Max bytes to consume by all files. growfiles exits when more\n\
1679 than maxbytes have been consumed. (def no chk) If maxbytes ends\n\
1680 with the letter 'b', maxbytes is multiplied by BSIZE\n\
1681 -C write_chk Specifies how often to check the last write (default 1)\n\
1682 -c file_chk Specifies how often to check whole file (default 0)\n\
1683 -d auto_dir Specifies the directory to auto created files. (default .)\n\
1684 -D debug_lvl Specifies the debug level (default 1)\n\
1685 -E Print examples and exit\n\
1686 -e errs The number errors that will terminate this program (def 100)\n\
1687 -f auto_file Specifies the base filename files created. (default \"gf\")\n\
1688 -g grow_incr Specfied to grow by incr for each num. (default 4096)\n\
1689 grow_incr may end in b for blocks\n\
1690 If -r option is used, this option is ignored and size is random\n\
1691 -H delay Amount of time to delay between each file (default 0.0)\n\
1692 -I io_type Specifies io type: s - sync, p - polled async, a - async (def s)\n\
1693 l - listio sync, L - listio async, r - random\n\
1694 -i iteration Specfied to grow each file num times. 0 means forever (default 1)\n\
1695 -l Specfied to do file locking around write/read/trunc\n\
1696 If specified twice, file locking after open to just before close\n\
1697 -L time Specfied to exit after time secs, must be used with -i.\n\
1698 -N num_files Specifies the number of files to be created.\n\
1699 The default is zero if cmd line files.\n\
1700 The default is one if no cmd line files.\n\
1701 -n num_procs Specifies the number of copies of this cmd.\n\
1702 -o op_type Specifies open flages: (def O_RDWR,O_CREAT) op_type can be 'random'\n\
1703 -O offset adjust i/o buffer alignment by offset bytes\n\
1704 -P PANIC Specifies to call upanic on error.\n\
1705 -p Specifies to pre-allocate space\n\
1706 -q pattern pattern can be a - ascii, p - pid with boff, o boff (def)\n\
1707 A - Alternating bits, r - random, O - all ones, z - all zeros,\n\
1708 c - checkboard, C - counting\n\
1709 -R [min-]max random lseek before write and trunc, max of -1 means filesz,\n\
1710 -2 means filesz+grow, -3 filesz-grow. (min def is 0)\n\
1711 -r [min-]max random io write size (min def is 1)\n\
1712 -S seq_auto_files Specifies the number of seqental auto files (default 0)\n\
1713 -s seed[,seed...] Specifies the random number seed (default time(0)+pid)\n\
1714 -t trunc_incr Specfied the amount to shrink file. (default 4096)\n\
1715 trunc_inter may end in b for blocks\n\
1716 If -R option is used, this option is ignored and trunc is random\n\
1717 -T trunc_inter Specfied the how many grows happen before shrink. (default 0)\n\
1718 -u unlink files before exit\n\
1719 -U ui[-ui2] Unlink files each ui iteration (def 0)\n\
1720 -w Specfied to grow via lseek instead of writes.\n\
1721 -W tag-name Who-am-i. My Monster tag name. (used by Monster).\n\
1722 -x Re-exec children before continuing - useful on MPP systems\n\
1723 -y Attempt to sync copies - if one fails it will send sigusr2 to others\n\
1724 Action to each file every iteration is open, write, write check\n\
1725 file check, trunc and closed.\n");
1730 /***********************************************************************
1732 ***********************************************************************/
1734 prt_examples(FILE *stream)
1736 /* This example creates 200 files in directory dir1. It writes */
1737 /* 4090 bytes 100 times then truncates 408990 bytes off the file */
1738 /* The file contents are checked every 1000 grow. */
1740 "# run forever: writes of 4090 bytes then on every 100 iterval\n\
1741 # truncate file by 408990 bytes. Done to 200 files in dir1.\n\
1742 %s -i 0 -g 4090 -T 100 -t 408990 -l -C 10 -c 1000 -d dir1 -S 200\n\n", Progname);
1744 /* same as above with 5000 byte grow and a 499990 byte tuncate */
1746 "# same as above with writes of 5000 bytes and truncs of 499990\n\
1747 %s -i 0 -g 5000 -T 100 -t 499990 -l -C 10 -c 1000 -d dir2 -S 200\n\n", Progname);
1749 /* This example beats on opens and closes */
1751 "# runs forever: beats on opens and closes of file ocfile - no io\n\
1752 %s -i 0 -g 0 -c 0 -C 0 ocfile\n\n", Progname);
1755 "# writes 4096 to files until 50 blocks are written\n\
1756 %s -i 0 -g 4096 -B 50b file1 file2\n\n", Progname);
1759 "# write one byte to 750 files in gdir then unlinks them\n\
1760 %s -g 1 -C 0 -d gdir -u -S 750\n\n", Progname);
1763 "# run 30 secs: random iosize, random lseek up to eof\n\
1764 %s -r 1-5000 -R 0--1 -i 0 -L 30 -C 1 g_rand1 g_rand2\n\n", Progname);
1767 "# run 30 secs: grow by lseek then write single byte, trunc every 10 itervals\n\
1768 %s -g 5000 -wlu -i 0 -L 30 -C 1 -T 10 g_sleek1 g_lseek2\n\n", Progname);
1771 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1772 # rand io types doing a trunc every 5 iterations, with unlinks.\n\
1773 %s -i0 -r 1-50000 -R 0--2 -I r -C1 -l -n5 -u -U 100-200 gf_rana gf_ranb\n\n",
1777 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1778 # random open flags, rand io types doing a trunc every 10 iterations.\n\
1779 %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",
1786 /***********************************************************************
1788 * The file descriptor current offset is assumed to be the end of the
1790 * Woffset will be set to the offset before the write.
1791 * Grow_incr will be set to the size of the write or lseek write.
1792 ***********************************************************************/
1794 growfile(fd, file, grow_incr, buf)
1805 int fsize; /* current size of file */
1806 int size_grew; /* size the file grew */
1811 * Do a stat on the open file.
1812 * If the file is a fifo, set the bit in Mode variable.
1813 * This fifo check must be done prior to growfile() returning.
1814 * Also get the current size of the file.
1816 if ( fstat(fd, &stbuf) != -1 ) {
1817 if ( S_ISFIFO(stbuf.st_mode) ) {
1818 Fileinfo.mode |= MODE_FIFO;
1821 printf("%s: %d DEBUG4 %s/%d: file is a fifo - no lseek or truncs,\n",
1822 Progname, Pid, __FILE__, __LINE__);
1824 fsize = stbuf.st_size;
1827 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1828 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
1834 if ( grow_incr <= 0 ) { /* don't attempt i/o if grow_incr <= 0 */
1836 Grow_incr=grow_incr;
1838 printf("%s: %d DEBUG3 %s/%d: Not attempting to grow, growsize == %d\n",
1839 Progname, Pid, __FILE__, __LINE__, grow_incr);
1843 if ( Mode & MODE_RAND_SIZE ) {
1844 grow_incr=random_range(min_size, max_size, mult_size, &errmsg);
1845 if (errmsg != NULL) {
1846 fprintf(stderr, "%s%s: %d %s/%d: random_range() failed - %s\n", Progname, TagName, Pid, __FILE__, __LINE__, errmsg);
1849 Grow_incr=grow_incr;
1852 Grow_incr=grow_incr;
1854 if ( ! (Mode & MODE_FIFO) ) {
1855 if ((cur_offset=lseek(fd,0,SEEK_CUR)) == -1 ) {
1856 fprintf(stderr, "%s%s: %d %s/%d: tell failed: %s\n",
1857 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
1862 if ( Mode & MODE_GROW_BY_LSEEK ) {
1865 printf("%s: %d DEBUG3 %s/%d: Current size of file is %d\n", Progname,
1866 Pid, __FILE__, __LINE__, Woffset);
1867 printf("%s: %d DEBUG3 %s/%d: lseeking to %d byte with SEEK_END\n", Progname,
1868 Pid, __FILE__, __LINE__, grow_incr-1);
1871 if ((noffset=lseek(fd, grow_incr-1, SEEK_END)) == -1 ) {
1872 fprintf(stderr, "%s%s: %s/%d: lseek(fd, %d, SEEK_END) failed: %s\n",
1873 Progname, TagName, __FILE__, __LINE__, grow_incr-1, strerror(errno));
1877 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1880 ret=lio_write_buffer(fd, io_type, "w", 1, SIGUSR1, &errmsg,0);
1882 ret=write_buffer(fd, io_type, "w", 1, 0, &errmsg);
1886 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
1887 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
1888 if ( ret == -ENOSPC ) {
1897 lkfile(fd, LOCK_UN, LKLVL0);
1900 printf("%s: %d DEBUG3 %s/%d: %d wrote 1 byte to file\n",
1901 Progname, Pid, __FILE__, __LINE__, Iter_cnt);
1903 } else { /* end of grow by lseek */
1905 if ( Fileinfo.openflags & O_APPEND ) {
1907 * Deal with special case of the open flag containing O_APPEND.
1908 * If it does, the current offset does not matter since the write
1909 * will be done end of the file.
1912 printf("%s: %d DEBUG5 %s/%d: dealing with O_APPEND condition\n",
1913 Progname, Pid, __FILE__, __LINE__ );
1914 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1917 * do fstat again to get size of the file.
1918 * This is done inside a file lock (if locks are being used).
1920 if ( fstat(fd, &stbuf) != -1 ) {
1921 Woffset = stbuf.st_size;
1923 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1924 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
1926 lkfile(fd, LOCK_UN, LKLVL0); /* release lock */
1930 printf("%s: %d DEBUG3 %s/%d: dealing with O_APPEND condition (offset:fsz:%d)\n",
1931 Progname, Pid, __FILE__, __LINE__, (int)stbuf.st_size);
1934 } else if ( Mode & MODE_RAND_LSEEK ) {
1935 if ( max_lseek == LSK_EOF ) { /* within file size */
1936 noffset=random_range(min_lseek, fsize, 1, NULL);
1938 else if ( max_lseek == LSK_EOFPLUSGROW ) {
1939 /* max to beyond file size */
1940 noffset=random_range(min_lseek, fsize+grow_incr, 1, NULL);
1942 else if ( max_lseek == LSK_EOFMINUSGROW ) {
1944 * Attempt to not grow the file.
1945 * If the i/o will fit from min_lseek to EOF,
1946 * pick offset to allow it to fit.
1947 * Otherwise, pick the min_lseek offset and grow
1948 * file by smallest amount.
1949 * If min_lseek is != 0, there will be a problem
1950 * with whole file checking if file is ever smaller
1953 if ( fsize <= min_lseek + grow_incr )
1954 noffset=min_lseek; /* file will still grow */
1956 noffset=random_range(min_lseek, fsize-grow_incr, 1, NULL);
1959 noffset=random_range(min_lseek, max_lseek, 1, NULL);
1962 if ((Woffset=lseek(fd, noffset, SEEK_SET)) == -1 ) {
1963 fprintf(stderr, "%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l2 failed: %s\n",
1964 Progname, TagName, Pid, __FILE__, __LINE__, fd, noffset, strerror(errno));
1967 else if ( Debug > 2 )
1968 printf("%s: %d DEBUG3 %s/%d: lseeked to random offset %d (fsz:%d)\n",
1969 Progname, Pid, __FILE__, __LINE__, Woffset,
1970 (int)stbuf.st_size);
1975 * lseek to end of file only if not fifo
1977 else if ( ! (Mode & MODE_FIFO) ) {
1978 if ((Woffset=lseek(fd, 0, SEEK_END)) == -1 ) {
1979 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, 0, SEEK_END) failed: %s\n",
1980 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
1983 else if ( Debug > 2 )
1984 printf("%s: %d DEBUG3 %s/%d: lseeked to end of file, offset %d\n",
1985 Progname, Pid, __FILE__, __LINE__, Woffset);
1988 if ( Pattern == PATTERN_OFFSET )
1989 datapidgen(STATIC_NUM, buf, grow_incr, Woffset);
1990 else if ( Pattern == PATTERN_PID )
1991 datapidgen(Pid, buf, grow_incr, Woffset);
1992 else if ( Pattern == PATTERN_ASCII )
1993 dataasciigen(NULL, (char *)buf, grow_incr, Woffset);
1994 else if ( Pattern == PATTERN_RANDOM )
1995 databingen('r', buf, grow_incr, Woffset);
1996 else if ( Pattern == PATTERN_ALT )
1997 databingen('a', buf, grow_incr, Woffset);
1998 else if ( Pattern == PATTERN_CHKER )
1999 databingen('c', buf, grow_incr, Woffset);
2000 else if ( Pattern == PATTERN_CNTING )
2001 databingen('C', buf, grow_incr, Woffset);
2002 else if ( Pattern == PATTERN_ZEROS )
2003 databingen('z', buf, grow_incr, Woffset);
2004 else if ( Pattern == PATTERN_ONES )
2005 databingen('o', buf, grow_incr, Woffset);
2007 dataasciigen(NULL, (char *)buf, grow_incr, Woffset);
2010 printf("%s: %d DEBUG3 %s/%d: attempting to write %d bytes\n",
2011 Progname, Pid, __FILE__, __LINE__, grow_incr);
2013 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
2016 ret=write(fd, buf, grow_incr);
2020 lkfile(fd, LOCK_UN, LKLVL0);
2022 if ( ret != grow_incr) {
2023 fprintf(stderr, "%s: %s/%d: write failed: %s\n",
2024 Progname, __FILE__, __LINE__, strerror(errno));
2030 ret=lio_write_buffer(fd, io_type, (char *)buf, grow_incr,
2031 SIGUSR1, &errmsg,0);
2033 ret=write_buffer(fd, io_type, buf, grow_incr, 0, &errmsg);
2036 if( Mode & MODE_FIFO ){
2037 /* If it is a fifo then just pretend the file
2038 * offset is where we think it should be.
2040 tmp = Woffset + grow_incr;
2043 if( (tmp=lseek(fd,0,SEEK_CUR)) < 0 ){ /* get offset after the write */
2044 fprintf(stderr, "%s%s: %s/%d: tell(2) failed: %d %s\n",
2045 Progname, TagName, __FILE__, __LINE__, errno, strerror(errno) );
2050 /* If this is POSIX I/O and it is via aio_{read,write}
2051 * or lio_listio then after completion of the I/O the
2052 * value of the file offset for the file is
2053 * unspecified--which means we cannot trust what
2054 * tell() told us. Fudge it here.
2056 if( (io_type & LIO_IO_ASYNC_TYPES) || (io_type & LIO_RANDOM) ){
2057 if( tmp != Woffset + grow_incr ){
2059 printf("%s: %d DEBUG6 %s/%d: posix fudge, forcing tmp (%d) to match Woffset+grow_incr (%d)\n",
2060 Progname, Pid, __FILE__, __LINE__, tmp, Woffset+grow_incr);
2062 tmp = Woffset + grow_incr;
2069 lkfile(fd, LOCK_UN, LKLVL0);
2071 if ( ret != grow_incr ) {
2072 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
2073 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2074 if ( ret == -ENOSPC ) {
2082 * Check for a condition where the file was truncated just before
2085 if ( tmp != Woffset + grow_incr) {
2087 * The offset after the write was not as expected.
2088 * This could be caused by the following:
2089 * - file truncated after the lseek and before the write.
2090 * - the file was written to after fstat and before the write
2091 * and the file was opened with O_APPEND.
2093 * The pattern written to the file will be considered corrupted.
2095 if ( Debug > 0 && lockfile ) {
2096 printf("%s%s: %d DEBUG1 %s/%d: offset after write(%d) not as exp(%d+%d=%d)\n",
2097 Progname, TagName, Pid, __FILE__, __LINE__, tmp, Woffset, grow_incr, Woffset+grow_incr);
2098 printf("%s%s: %d DEBUG1 %s/%d: %d Assuming file changed by another process, resetting offset:%d (expect pattern mismatch)\n",
2099 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, tmp-grow_incr);
2102 printf("%s: %d DEBUG5 %s/%d: about to chop Woffset. tmp=%d, grow_incr=%d, Woffset was %d\n",
2103 Progname, Pid, __FILE__, __LINE__, tmp, grow_incr, Woffset);
2105 Woffset=tmp-grow_incr;
2110 } /* end of grow by write */
2114 * Woffset - holds start of grow (start of write expect in grow by lseek)
2115 * Grow_incr - holds size of grow (write).
2116 * fsize - holds size of file before write
2118 size_grew=(Woffset + Grow_incr) - fsize;
2120 if ( Mode & MODE_FIFO ) {
2121 printf("%s: %d DEBUG2 %s/%d: file is fifo, %d wrote %d bytes\n",
2122 Progname, Pid, __FILE__, __LINE__, Grow_incr, Iter_cnt);
2125 else if ( size_grew > 0 )
2126 printf("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%d), grew file by %d bytes\n",
2127 Progname, Pid, __FILE__, __LINE__, Iter_cnt, Grow_incr, Woffset, size_grew);
2129 printf("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%d), did not grow file\n",
2130 Progname, Pid, __FILE__, __LINE__, Iter_cnt, Grow_incr, Woffset);
2133 bytes_consumed += size_grew;
2136 } /* end of growfile */
2138 /***********************************************************************
2139 * shrinkfile file by trunc_incr. file can not be made smaller than
2140 * size zero. Therefore, if trunc_incr is larger than file size,
2141 * file will be truncated to zero.
2142 * The file descriptor current offset is assumed to be the end of the
2145 ***********************************************************************/
2147 shrinkfile(fd, filename, trunc_incr, trunc_inter, just_trunc)
2151 int trunc_inter; /* interval */
2152 int just_trunc; /* lseek has already been done for you */
2154 static int shrink_cnt = 0;
2164 if ( trunc_inter == 0 || (shrink_cnt % trunc_inter != 0)) {
2166 printf("%s: %d DEBUG4 %s/%d: Not shrinking file - not time, iter=%d, cnt=%d\n",
2167 Progname, Pid, __FILE__, __LINE__, trunc_inter, shrink_cnt);
2168 return 0; /* not this time */
2171 if ( Mode & MODE_FIFO ) {
2173 printf("%s: %d DEBUG5 %s/%d: Not attempting to shrink a FIFO\n",
2174 Progname, Pid, __FILE__, __LINE__);
2175 return 0; /* can not truncate fifo */
2178 lkfile(fd, LOCK_EX, LKLVL0);
2180 if ((cur_offset=lseek(fd,0,SEEK_CUR)) == -1 ) {
2181 fprintf(stderr, "%s%s: %d %s/%d: tell(%d) failed: %s\n",
2182 Progname, TagName, Pid, __FILE__, __LINE__, fd, strerror(errno));
2183 lkfile(fd, LOCK_UN, LKLVL0);
2187 if ( Mode & MODE_RAND_LSEEK ) {
2188 if ( max_lseek <= -1 ) {
2189 if ( (new_offset=file_size(fd)) == -1 ) {
2190 lkfile(fd, LOCK_UN, LKLVL0);
2194 if ( new_offset < min_lseek )
2195 new_offset=min_lseek;
2197 new_offset=random_range(min_lseek, new_offset, 1, NULL);
2200 new_offset=random_range(min_lseek, max_lseek, 1, NULL);
2204 if ((offset=lseek(fd, new_offset, SEEK_SET)) == -1 ) {
2205 fprintf(stderr, "%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l3 failed: %s\n",
2206 Progname, TagName, Pid, __FILE__, __LINE__, fd, new_offset, strerror(errno));
2207 lkfile(fd, LOCK_UN, LKLVL0);
2210 else if ( Debug > 3 )
2211 printf("%s: %d DEBUG4 %s/%d: lseeked to random offset %d\n",
2212 Progname, Pid, __FILE__, __LINE__, offset);
2217 else { /* remove trunc_incr from file */
2219 new_offset = cur_offset-trunc_incr;
2221 if ( new_offset < 0 )
2225 if ( lseek(fd, new_offset, SEEK_SET) == -1 ) {
2226 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, %d, SEEK_SET) l4 failed: %s\n",
2227 Progname, TagName, Pid, __FILE__, __LINE__, new_offset, strerror(errno));
2228 lkfile(fd, LOCK_UN, LKLVL0);
2231 else if ( Debug > 3 )
2232 printf("%s: %d DEBUG4 %s/%d: lseeked to offset %d, %d bytes from end\n",
2233 Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr);
2241 ret=ftruncate(fd, new_offset );
2242 if( (ret == 0) && (Debug > 3) ){
2243 printf("%s: %d DEBUG4 %s/%d: ftruncated to offset %d, %d bytes from end\n",
2244 Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr);
2248 lkfile(fd, LOCK_UN, LKLVL0);
2252 fprintf(stderr, "%s%s: %d %s/%d: trunc failed: %s\n",
2253 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
2255 fprintf(stderr, "%s%s: %d %s/%d: ftruncate failed: %s\n",
2256 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
2262 printf("%s: %d DEBUG2 %s/%d: trunc file by %d bytes, to size of = %d bytes\n",
2263 Progname, Pid, __FILE__, __LINE__, cur_offset-new_offset, new_offset);
2267 bytes_consumed -= (cur_offset - new_offset);
2270 } /* end of shrinkfile */
2272 /***********************************************************************
2274 ***********************************************************************/
2276 check_write(fd, cf_inter, filename, mode)
2278 int cf_inter; /* check file interval */
2279 char *filename; /* needed for error messages */
2280 int mode; /* write mode */
2283 static int cf_count = 0;
2291 if ( cf_inter == 0 || (cf_count % cf_inter != 0)) {
2293 printf("%s: %d DEBUG5 %s/%d: no write check, not time iter=%d, cnt=%d\n",
2294 Progname, Pid, __FILE__, __LINE__, cf_inter, cf_count);
2295 return 0; /* no check done */
2298 if ( Grow_incr <= 0 ) {
2300 printf("%s: %d DEBUG4 %s/%d: No write validation, Grow_incr = %d, offset = %d\n",
2301 Progname, Pid, __FILE__, __LINE__, Grow_incr, Woffset);
2302 return 0; /* no check */
2308 * Get the shared file lock. We need to hold the lock from before
2309 * we do the stat until after the read.
2311 lkfile(fd, LOCK_SH, LKLVL0);
2313 if ((fsize=file_size(fd)) == -1 ) {
2314 lkfile(fd, LOCK_UN, LKLVL0);
2317 } else if ( fsize <= Woffset ) {
2319 * The file was truncated between write and now.
2320 * The contents of our last write is totally gone, no check.
2323 printf("%s%s: %d DEBUG2 %s/%d: %d File size (%d) smaller than where last wrote (%d)- no write validation\n",
2324 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, fsize, Woffset);
2325 lkfile(fd, LOCK_UN, LKLVL0);
2326 return 0; /* no validation, but not an error */
2328 } else if ( fsize < (Woffset + Grow_incr)) {
2330 * The file was truncated between write and now.
2331 * Part of our last write has been truncated, adjust our Grow_incr
2336 Grow_incr=fsize-Woffset;
2340 printf("%s%s: %d DEBUG2 %s/%d: %d fsz:%d, lost(%d)of wrt(off:%d, sz:%d), adj=%d\n",
2341 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, fsize, tmp-Grow_incr, Woffset, tmp, Grow_incr);
2347 printf("%s: %d DEBUG3 %s/%d: about to do write validation, offset = %d, size = %d\n",
2348 Progname, Pid, __FILE__, __LINE__, Woffset, Grow_incr);
2350 if ( ! (mode & MODE_FIFO) ) {
2352 if ( lseek(fd, Woffset, 0) == -1 ) {
2353 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, %d, 0) failed: %s\n",
2354 Progname, TagName, Pid, __FILE__, __LINE__, Woffset, strerror(errno));
2357 printf("%s: %d DEBUG4 %s/%d: lseeked to offset:%d\n",
2358 Progname, Pid, __FILE__, __LINE__, Woffset);
2362 * Read last writes data
2365 ret=lio_read_buffer(fd, io_type, Buffer, Grow_incr, SIGUSR1, &errmsg,0);
2367 ret=read_buffer(fd, io_type, Buffer, Grow_incr, 0, &errmsg);
2371 * report the error and debug information before releasing
2374 if ( ret != Grow_incr ) {
2375 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s\n", Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2380 printf("%s%s: %d DEBUG3 %s/%d: fd:%d, offset:%d, fsize:%d, openflags:%#o\n",
2381 Progname, TagName, Pid, __FILE__, __LINE__, fd,
2382 (int)lseek(fd,SEEK_CUR,0), /* FIXME: 64bit/LFS ? */
2384 Fileinfo.openflags);
2387 lkfile(fd, LOCK_UN, LKLVL0);
2392 lkfile(fd, LOCK_UN, LKLVL0);
2394 if ( Mode & MODE_GROW_BY_LSEEK ) {
2395 /* check that all zeros upto last character */
2396 for(ptr=Buffer; ptr < (Buffer+Grow_incr-1); ptr++) {
2397 if ( *ptr != '\0' ) {
2399 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2400 Progname, TagName, Pid, __FILE__, __LINE__,
2401 (int)(Woffset+(Grow_incr-(Buffer-ptr))),
2407 /* check that the last char is a 'w' */
2408 if ( *ptr != 'w' ) {
2410 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2411 Progname, TagName, Pid, __FILE__, __LINE__,
2412 (int)(Woffset+(Grow_incr-(Buffer-ptr))), 'w',
2417 return 0; /* all is well */
2420 else if ( Pattern == PATTERN_OFFSET )
2421 ret=datapidchk(STATIC_NUM, Buffer, Grow_incr, Woffset, &errmsg);
2422 else if ( Pattern == PATTERN_PID )
2423 ret=datapidchk(Pid, Buffer, Grow_incr, Woffset, &errmsg);
2424 else if ( Pattern == PATTERN_ASCII )
2425 ret=dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2426 else if ( Pattern == PATTERN_RANDOM )
2427 ; /* no check for random */
2428 else if ( Pattern == PATTERN_ALT )
2429 ret=databinchk('a', Buffer, Grow_incr, Woffset, &errmsg);
2430 else if ( Pattern == PATTERN_CHKER )
2431 ret=databinchk('c', Buffer, Grow_incr, Woffset, &errmsg);
2432 else if ( Pattern == PATTERN_CNTING )
2433 ret=databinchk('C', Buffer, Grow_incr, Woffset, &errmsg);
2434 else if ( Pattern == PATTERN_ZEROS )
2435 ret=databinchk('z', Buffer, Grow_incr, Woffset, &errmsg);
2436 else if ( Pattern == PATTERN_ONES )
2437 ret=databinchk('o', Buffer, Grow_incr, Woffset, &errmsg);
2439 ret=dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2442 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s in file %s\n",
2443 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2446 printf("%s%s: %d DEBUG1 %s/%d: **fd:%d, lk:%d, offset:%d, sz:%d open flags:%#o %s\n",
2447 Progname, TagName, Pid, __FILE__, __LINE__, fd, lockfile,
2448 Woffset, Grow_incr, Fileinfo.openflags, openflags2symbols(Fileinfo.openflags, ",", NULL));
2455 printf("%s: %d DEBUG7 %s/%d: No corruption detected on write validation , offset = %d, size = %d\n",
2456 Progname, Pid, __FILE__, __LINE__, Woffset, Grow_incr);
2458 return 0; /* all is well */
2463 /***********************************************************************
2465 ***********************************************************************/
2467 check_file(fd, cf_inter, filename, no_file_check)
2469 int cf_inter; /* check file interval */
2470 char *filename; /* needed for error messages */
2471 int no_file_check; /* if set, do not do file content check */
2474 static int cf_count = 0;
2484 if ( cf_inter == 0 || (cf_count % cf_inter != 0)) {
2486 printf("%s: %d DEBUG5 %s/%d: No file check - not time, iter=%d, cnt=%d\n",
2487 Progname, Pid, __FILE__, __LINE__, cf_inter, cf_count);
2488 return 0; /* no check done */
2492 * if we can't determine file content, don't bother checking
2494 if ( no_file_check ) {
2496 printf("%s: %d DEBUG5 %s/%d: No file check, lseek grow or random lseeks\n",
2497 Progname, Pid, __FILE__, __LINE__);
2502 * Lock the file. We need to have the file lock before
2503 * the stat and until after the last read to prevent
2504 * a trunc/truncate from "corrupting" our data.
2506 lkfile(fd, LOCK_SH, LKLVL0);
2508 if ((fsize=file_size(fd)) == -1 ) {
2509 lkfile(fd, LOCK_UN, LKLVL0);
2515 printf("%s: %d DEBUG3 %s/%d: No file validation, file size == 0\n",
2516 Progname, Pid, __FILE__, __LINE__);
2518 lkfile(fd, LOCK_UN, LKLVL0);
2523 printf("%s: %d DEBUG3 %s/%d: about to do file validation\n",
2524 Progname, Pid, __FILE__, __LINE__);
2526 if ( fsize > MAX_FC_READ ) {
2528 * read the file in MAX_FC_READ chuncks.
2531 if ((buf=(char *)malloc(MAX_FC_READ)) == NULL ) {
2532 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", Progname, TagName,
2533 __FILE__, __LINE__, MAX_FC_READ, strerror(errno));
2534 lkfile(fd, LOCK_UN, LKLVL0);
2538 lseek(fd, 0, SEEK_SET);
2540 lkfile(fd, LOCK_SH, LKLVL0); /* get lock on file before getting file size */
2543 while (rd_cnt < fsize ) {
2544 if ( fsize - rd_cnt > MAX_FC_READ )
2545 rd_size=MAX_FC_READ;
2547 rd_size=fsize - rd_cnt;
2550 ret=lio_read_buffer(fd, io_type, buf, rd_size,
2551 SIGUSR1, &errmsg,0);
2553 ret=read_buffer(fd, io_type, buf, rd_size, 0, &errmsg);
2556 if (ret != rd_size ) {
2557 fprintf(stderr, "%s%s: %d %s/%d: %d CFa %s\n",
2558 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2560 lkfile(fd, LOCK_UN, LKLVL0);
2564 read(fd, buf, rd_size);
2567 if ( Pattern == PATTERN_OFFSET )
2568 ret=datapidchk(STATIC_NUM, buf, rd_size, rd_cnt, &errmsg);
2569 else if ( Pattern == PATTERN_PID )
2570 ret=datapidchk(Pid, buf, rd_size, rd_cnt, &errmsg);
2571 else if ( Pattern == PATTERN_ASCII )
2572 ret=dataasciichk(NULL, buf, rd_size, rd_cnt, &errmsg);
2573 else if ( Pattern == PATTERN_RANDOM )
2574 ; /* no checks for random */
2575 else if ( Pattern == PATTERN_ALT )
2576 ret=databinchk('a', buf, rd_size, rd_cnt, &errmsg);
2577 else if ( Pattern == PATTERN_CHKER )
2578 ret=databinchk('c', buf, rd_size, rd_cnt, &errmsg);
2579 else if ( Pattern == PATTERN_CNTING )
2580 ret=databinchk('C', buf, rd_size, rd_cnt, &errmsg);
2581 else if ( Pattern == PATTERN_ZEROS )
2582 ret=databinchk('z', buf, rd_size, rd_cnt, &errmsg);
2583 else if ( Pattern == PATTERN_ONES )
2584 ret=databinchk('o', buf, rd_size, rd_cnt, &errmsg);
2586 ret=dataasciichk(NULL, buf, rd_size, rd_cnt, &errmsg);
2591 "%s%s: %d %s/%d: %d CFp %s in file %s\n",
2592 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2595 lkfile(fd, LOCK_UN, LKLVL0);
2601 lkfile(fd, LOCK_UN, LKLVL0);
2608 * Read the whole file in a single read
2610 if((buf=(char *)malloc(fsize)) == NULL ) {
2611 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", Progname, TagName,
2612 __FILE__, __LINE__, fsize, strerror(errno));
2617 lseek(fd, 0, SEEK_SET);
2620 read(fd, buf, fsize);
2623 ret=lio_read_buffer(fd, io_type, buf, fsize, SIGUSR1, &errmsg,0);
2625 ret=read_buffer(fd, io_type, buf, fsize, 0, &errmsg);
2628 /* unlock the file as soon as we can */
2629 lkfile(fd, LOCK_UN, LKLVL0);
2632 if ( ret != fsize ) {
2633 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s\n",
2634 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2638 if ( Pattern == PATTERN_OFFSET )
2639 ret=datapidchk(STATIC_NUM, buf, fsize, 0, &errmsg);
2640 else if ( Pattern == PATTERN_PID )
2641 ret=datapidchk(Pid, buf, fsize, 0, &errmsg);
2642 else if ( Pattern == PATTERN_ASCII )
2643 ret=dataasciichk(NULL, buf, fsize, 0, &errmsg);
2644 else if ( Pattern == PATTERN_RANDOM )
2645 ; /* no check for random */
2646 else if ( Pattern == PATTERN_ALT )
2647 ret=databinchk('a', buf, fsize, 0, &errmsg);
2648 else if ( Pattern == PATTERN_CHKER )
2649 ret=databinchk('c', buf, fsize, 0, &errmsg);
2650 else if ( Pattern == PATTERN_CNTING )
2651 ret=databinchk('C', buf, fsize, 0, &errmsg);
2652 else if ( Pattern == PATTERN_ZEROS )
2653 ret=databinchk('z', buf, fsize, 0, &errmsg);
2654 else if ( Pattern == PATTERN_ONES )
2655 ret=databinchk('o', buf, fsize, 0, &errmsg);
2657 ret=dataasciichk(NULL, buf, fsize, 0, &errmsg);
2660 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s in file %s\n",
2661 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2671 } /* end of check_file */
2673 /***********************************************************************
2675 ***********************************************************************/
2681 if (fstat(fd, &sb) < 0) {
2682 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
2683 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
2691 /***********************************************************************
2692 * do file lock/unlock action.
2693 ***********************************************************************/
2695 lkfile(int fd, int operation, int lklevel)
2700 if ( lockfile == lklevel) {
2703 switch (operation) {
2705 printf("%s: %d DEBUG6 %s/%d: Attempting to release lock on fd %d\n",
2706 Progname, Pid, __FILE__, __LINE__, fd);
2710 printf("%s: %d DEBUG6 %s/%d: Attempting to get read/shared lock on fd %d\n",
2711 Progname, Pid, __FILE__, __LINE__, fd);
2715 printf("%s: %d DEBUG6 %s/%d: Attempting to get write/exclusive lock on fd %d\n",
2716 Progname, Pid, __FILE__, __LINE__, fd);
2722 * Attempt to get/release desired lock.
2723 * file_lock will attempt to do action over and over again until
2724 * either an unretryable error or the action is completed.
2727 if ( file_lock(fd, operation, &errmsg) != 0 ) {
2728 printf("%s%s: %d %s/%d: Unable to perform lock operation. %s\n",
2729 Progname, TagName, Pid, __FILE__, __LINE__, errmsg);
2731 /* do we count this as an error? handle_error(); */
2736 switch (operation) {
2738 printf("%s: %d DEBUG3 %s/%d: Released lock on fd %d\n",
2739 Progname, Pid, __FILE__, __LINE__, fd);
2743 printf("%s: %d DEBUG3 %s/%d: Got read/shared lock on fd %d\n",
2744 Progname, Pid, __FILE__, __LINE__, fd);
2748 printf("%s: %d DEBUG3 %s/%d: Got write/exclusive lock on fd %d\n",
2749 Progname, Pid, __FILE__, __LINE__, fd);
2753 printf("%s: %d DEBUG3 %s/%d: Completed action %d on fd %d\n",
2754 Progname, Pid, __FILE__, __LINE__, operation, fd);
2764 /***********************************************************************
2766 ***********************************************************************/
2768 pre_alloc(file, fd, size)
2777 if ( ialloc(fd, size, IA_CONT, &avl) == -1 ) {
2778 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: ialloc failed: %d %s\n",
2780 __FILE__, __LINE__, errno, strerror(errno));
2786 #ifdef XFS_IOC_RESVSP
2787 struct xfs_flock64 f;
2793 /* non-zeroing reservation */
2794 if( xfsctl( file, fd, XFS_IOC_RESVSP, &f ) == -1 ){
2795 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: xfsctl(XFS_IOC_RESVSP) failed: %d %s\n",
2797 __FILE__, __LINE__, errno, strerror(errno));
2807 /* non-zeroing reservation */
2808 if( fcntl( fd, F_RESVSP64, &f ) == -1 ){
2809 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: fcntl(F_RESVSP) failed: %d %s\n",
2811 __FILE__, __LINE__, errno, strerror(errno));