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"
65 #include "open_flags.h"
67 #include "file_lock.h"
69 extern int datapidgen(int pid, unsigned char *buffer, int bsize, int offset);
70 extern void databingen(int mode, unsigned char *buffer, int bsize, int offset);
71 extern int datapidchk(int pid, char *buffer, int bsize, int offset, char **errmsg);
72 extern int databinchk(int mode, char *buffer, int bsize, int offset, char **errmsg);
74 int file_size(int fd);
75 int check_write(int fd, int cf_inter, char *filename, int mode);
76 int shrinkfile(int fd, char *filename, int trunc_incr, int trunc_inter, int just_trunc);
77 int check_file(int fd, int cf_inter, char *filename, int no_file_check);
78 int growfile(int fd, char *file, int grow_incr, unsigned char *buf);
81 int lkfile(int fd, int operation, int lklevel);
84 void prt_examples(FILE *stream);
87 static void notify_others();
88 int pre_alloc(char *file, int fd, int size);
91 #define NEWIO 1 /* Use the tlibio.c functions */
94 #define NEWIO 0 /* specifies to use original iowrite.c */
95 /* functions instead of tlibio.c functions */
96 /* Once it is proven tlibio.c functions work properly, */
97 /* only tlibio.c functions will be used */
103 #define PATH_MAX 1023
108 #define DEF_FILE "gf"
115 int io_type = 0; /* I/O type -sync */
116 int open_flags = O_RDWR|O_CREAT; /* open flags */
118 #define MAX_FC_READ 196608 /* 4096 * 48 - 48 blocks */
120 #define PATTERN_ASCII 1 /* repeating alphabet letter pattern */
121 /* allows multiple writers and to be checked */
122 #define PATTERN_PID 2 /* <pid><words byte offset><pid> */
123 /* Assumes 64 bit word. Only allows single */
124 /* process to write and check */
126 * 1234567890123456789012345678901234567890123456789012345678901234
127 * ________________________________________________________________
128 * < pid >< offset in file of this word >< pid >
131 #define PATTERN_OFFSET 3 /* Like PATTERN_PID but has a fixed number */
132 /* (STATIC_NUM) instead of pid. */
133 /* Allows multiple processes to write/read */
134 #define PATTERN_ALT 4 /* alternating bit pattern (i.e. 0x5555555...) */
135 #define PATTERN_CHKER 5 /* checkerboard pattern (i.e. 0xff00ff00ff00...) */
136 #define PATTERN_CNTING 6 /* counting pattern (i.e. 0 - 07, 0 - 07, ...) */
137 #define PATTERN_ONES 7 /* all bits set (i.e. 0xffffffffffffff...) */
138 #define PATTERN_ZEROS 8 /* all bits cleared (i.e. 0x000000000...) */
139 #define PATTERN_RANDOM 9 /* random integers - can not be checked */
140 #define STATIC_NUM 221849 /* used instead of pid when PATTERN_OFFSET */
142 #define MODE_RAND_SIZE 1 /* random write and trunc */
143 #define MODE_RAND_LSEEK 2 /* random lseek before write */
144 #define MODE_GROW_BY_LSEEK 4 /* lseek beyond end of file then write a byte */
145 #define RANDOM_OPEN 999876 /* if Open_flags set to this value, open flags */
146 /* will be randomly choosen from Open_flags[] */
147 #define MODE_FIFO S_IFIFO /* defined in stat.h 0010000 */
149 int num_files = 0; /* num_auto_files + cmd line files */
150 char *filenames; /* pointer to space containing filenames */
151 int remove_files = 0; /* if set, cleanup default is not to cleanup */
152 int bytes_consumed = 0; /* total bytes consumed, all files */
153 int bytes_to_consume = 0; /* non-zero if -B was specified, total bytes */
154 int Maxerrs = 100; /* Max number errors before forced exit */
155 int Errors = 0; /* number of encountered errors */
156 int Upanic_on_error = 0; /* call upanic if error and this variable set */
158 /* The *_size variables are only used when random iosize option (-r) is used */
160 int min_size=1; /* also set in option parsing */
161 int mult_size=1; /* when random iosz, iosz must be mult of mult_size */
162 /* the *_lseek variables are only used when radon lseek option (-R) is used */
163 int min_lseek=0; /* also set in option parsing */
164 int max_lseek=-1; /* -1 means size of file */
165 int Pattern=PATTERN_ASCII;
166 int Seed=-1; /* random number seed, < 0 == uninitialized */
167 int Nseeds=0; /* Number of seed specified by the user */
168 int *Seeds; /* malloc'ed arrary of ints holding user spec seeds */
170 int using_random=0; /* flag indicating randomization is being used */
171 float delaysecs=0.0; /* delay between iterations (in seconds) */
172 int delaytime; /* delay between iterations in clocks/uses */
173 int lockfile=0; /* if set, do file locking */
174 /* 1 = do file locking around write, trunc */
176 /* 2 = write lock around all file operations */
178 int Woffset=0; /* offset before last write */
179 int Grow_incr=4096; /* sz of last write */
180 int Mode=0; /* bitmask of write/trunc mode */
181 /* also knows if dealing with fifo */
182 char *Buffer = NULL; /* buffer used by write and write check */
183 int Alignment=0; /* if non word multiple, io will not be word aligned */
184 int Opid=0; /* original pid */
186 int Sync_with_others = 0; /* Flag indicating to stop other if we stop before DONE */
187 int Iter_cnt = 0; /* contains current iteration count value */
188 char TagName[40]; /* name of this growfiles (see Monster) */
198 * Define open flags that will be used when '-o random' option is used.
199 * Note: If there is more than one growfiles doing its thing to the same
200 * file, O_TRUNC will cause data mismatches. How you ask?
201 * timing of events, example:
202 * Process one Process two
203 * --------------- -------------
209 * write with wrong pattern
210 * because offset is wrong
212 * The second process truncated the file after the pattern was
213 * determined, thus the pattern is wrong for the file location.
215 * There can also be a timing problem with open flag O_APPEND if
216 * file locks are not being used (-l option). Things could happen
217 * between the fstat and the write. Thus, writing the wrong pattern.
218 * If all processes observe the file locks, O_APPEND should be ok
223 O_RDWR|O_CREAT|O_APPEND,
224 O_RDWR|O_CREAT|O_NDELAY,
225 O_RDWR|O_CREAT|O_SYNC,
226 O_RDWR|O_CREAT|O_SYNC|O_NDELAY,
227 O_RDWR|O_CREAT|O_APPEND|O_NDELAY,
231 #define REXEC_INIT 0 /* don't do re-exec of childern */
232 #define REXEC_DOIT 1 /* Do re-exec of childern */
233 #define REXEC_DONE 2 /* We've already been re-exec'ed */
239 #define USECS_PER_SEC 1000000 /* microseconds per second */
242 * Define marcos used when dealing with file locks.
244 #define LKLVL0 1 /* file lock around write/read/trunc */
245 #define LKLVL1 2 /* file lock after open to before close */
248 * Define special max lseek values
250 #define LSK_EOF -1 /* set fptr up to EOF */
251 #define LSK_EOFPLUSGROW -2 /* set fptr up to EOF + grow - leave whole */
252 #define LSK_EOFMINUSGROW -3 /* set fptr up to EOF-grow - no grow */
255 /***********************************************************************
257 ***********************************************************************/
263 extern char *optarg; /* used by getopt */
268 int first_file_ind = 0;
269 int num_auto_files = 0; /* files created by tool */
270 int seq_auto_files = 0; /* auto files created by tool created by tool */
271 char *auto_dir = DEF_DIR;
272 char *auto_file = DEF_FILE;
273 int grow_incr = 4096;
274 int trunc_incr = 4096;
275 int trunc_inter = 0; /* 0 means none, */
276 int unlink_inter = 0; /* 0 means none, 1 means always unlink */
277 int unlink_inter_ran = -1; /* -1 -use unlink_inter, otherwise randomly choose */
278 /* between unlink_inter and unlink_inter_ran */
279 int file_check_inter = 0; /* 0 means never, 1 means always */
280 int write_check_inter = 1; /* 0 means never, 1 means always */
281 int iterations = 1; /* number of increments to be added */
282 int no_file_check = 0; /* if set, no whole file checking will be done */
284 int fd; /* file descriptor */
285 int stop = 0; /* loop stopper if set */
289 int pre_alloc_space = 0;
290 int total_grow_value = 0; /* used in pre-allocations */
291 int backgrnd = 1; /* return control to user */
293 int time_iterval = -1;
294 time_t start_time = 0;
295 char reason[40]; /* reason for loop termination */
298 int reexec=REXEC_INIT; /* reexec info */
299 char *exec_path=NULL;
303 char *filename; /* name of file specified by user */
304 char *cptr; /* temp char pointer */
305 extern int Forker_npids; /* num of forked pid, defined in forker.c */
308 if ( argv[0][0] == '-' )
311 * Determine name of file used to invoke this program
313 if ((Progname=strrchr(argv[0], '/')) != NULL)
323 while ((ind=getopt(argc, argv,
324 "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) {
332 switch (sscanf(optarg, "%i%c",
333 &bytes_to_consume, &chr)) {
339 bytes_to_consume *= BSIZE;
342 "%s%s: --B option arg invalid\n",
350 fprintf(stderr, "%s%s: --B option arg invalid\n",
360 prt_examples(stdout);
363 case 'b' : /* batch */
368 if (sscanf(optarg, "%i", &write_check_inter) != 1 ) {
369 fprintf(stderr, "%s%s: --c option arg invalid\n",
377 if (sscanf(optarg, "%i", &file_check_inter) != 1 ) {
378 fprintf(stderr, "%s%s: --c option arg invalid\n",
388 if ( stat(auto_dir, &statbuf) == -1 ) {
389 if ( mkdir(auto_dir, 0777) == -1 ) {
390 if ( errno != EEXIST ) {
392 "%s%s: Unable to make dir %s\n",
393 Progname, TagName, auto_dir);
399 if ( ! (statbuf.st_mode & S_IFDIR) ) {
401 "%s%s: %s already exists and is not a directory\n",
402 Progname, TagName, auto_dir);
409 if (sscanf(optarg, "%i", &Debug) != 1 ) {
410 fprintf(stderr, "%s%s: --D option arg invalid\n",
418 if (sscanf(optarg, "%i", &Maxerrs) != 1 ) {
419 fprintf(stderr, "%s%s: --e option arg invalid\n",
431 if ((ret=sscanf(optarg, "%i%c", &grow_incr, &chr)) < 1 ||
434 fprintf(stderr, "%s%s: --g option arg invalid\n",
440 if ( chr == 'b' || chr == 'B' )
444 "%s%s: --g option arg invalid\n",
453 if (sscanf(optarg, "%f", &delaysecs) != 1 || delaysecs < 0 ) {
455 fprintf(stderr, "%s%s: --H option arg invalid\n",
463 if (sscanf(optarg, "%i", &iterations) != 1 ||
466 fprintf(stderr, "%s%s: --i option arg invalid\n",
475 if((io_type=lio_parse_io_arg1(optarg)) == -1 ) {
477 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
481 if( io_type & LIO_RANDOM )
484 if((io_type=parse_io_arg(optarg)) == -1 ) {
486 "%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
490 if( io_type == 99 ) /* hold-over until tlibio.h */
498 lockfile=2; /* lockfile can only be 1 or 2 */
502 if (sscanf(optarg, "%i", &time_iterval) != 1 ||
504 fprintf(stderr, "%s%s: --L option arg invalid\n",
512 if (sscanf(optarg, "%i:%i", &num_procs, &forker_mode) < 1 ||
515 fprintf(stderr, "%s%s: --n option arg invalid\n",
524 if (sscanf(optarg, "%i", &num_auto_files) != 1 ||
525 num_auto_files < 0 ) {
527 fprintf(stderr, "%s%s: --N option arg invalid\n",
535 if (sscanf(optarg, "%i", &Alignment) != 1 ||
536 num_auto_files < 0 ) {
538 fprintf(stderr, "%s%s: --O option arg invalid\n",
546 if ( strcmp(optarg, "random") == 0 ){
547 open_flags=RANDOM_OPEN;
550 } else if ((open_flags=parse_open_flags(optarg, NULL)) == -1 ) {
551 fprintf(stderr, "%s%s: --o arg contains invalid flag\n",
558 case 'p' : /* pre allocate space */
559 printf("%s%s: --p is illegal option on this system\n",
565 printf("%s%s: --P is illegal option on non-cray system\n",
570 case 'q': /* file content or pattern */
573 Pattern = PATTERN_ALT;
576 Pattern = PATTERN_ASCII;
579 Pattern = PATTERN_PID;
582 Pattern = PATTERN_OFFSET;
585 Pattern = PATTERN_CHKER;
588 Pattern = PATTERN_CNTING;
591 Pattern = PATTERN_RANDOM;
595 Pattern = PATTERN_ZEROS;
598 Pattern = PATTERN_ONES;
602 "%s%s: --C option arg invalid, A, a, p, o, c, C, r, z, or 0\n",
609 case 'R': /* random lseek before write arg: [min-]max*/
610 if (sscanf(optarg, "%i-%i", &min_lseek, &max_lseek) != 2 ) {
611 min_lseek=1; /* same as default in define */
612 if (sscanf(optarg, "%i%c", &max_lseek, &chr) != 1 ) {
613 fprintf(stderr, "%s%s: --R option arg invalid: [min-]max\n",
618 if ( max_lseek < LSK_EOFMINUSGROW ) {
619 fprintf(stderr, "%s%s: --R option, max_lseek is invalid\n",
623 Mode |= MODE_RAND_LSEEK;
627 case 'r': /* random io size arg: [min-]max[:mult] */
629 /* min-max:mult format */
630 if (sscanf(optarg, "%i-%i:%i%c", &min_size, &max_size,
631 &mult_size, &chr) != 3 ) {
633 /* max:mult format */
634 if (sscanf(optarg, "%i:%i%c", &max_size,
635 &mult_size, &chr) != 2 ) {
637 if (sscanf(optarg, "%i-%i%c", &min_size,
638 &max_size, &chr) != 2 ) {
640 if (sscanf(optarg, "%i%c", &max_size, &chr) != 1 ) {
642 "%s%s: --r option arg invalid: [min-]max[:mult]\n",
650 if ( max_size < 0 ) {
651 fprintf(stderr, "%s%s: --r option, max_size is invalid\n",
656 * If min and max are the same, no randomness
658 if ( min_size != max_size ) {
659 Mode |= MODE_RAND_SIZE;
665 if (sscanf(optarg, "%i", &seq_auto_files) != 1 ||
666 seq_auto_files < 0 ) {
668 fprintf(stderr, "%s%s: --S option arg invalid\n",
675 case 's': /* format: seed[,seed...] */
677 /* count the number of seeds */
679 for(Nseeds=1; *cptr ; Nseeds++) {
680 if ( (filename=strchr(cptr, ',')) == NULL )
685 Seeds=(int *)malloc(Nseeds*sizeof(int));
688 * check that each seed is valid and put them in
689 * the newly malloc'ed Seeds arrary.
691 filename=cptr=optarg;
692 for(Nseeds=0; *cptr; Nseeds++) {
693 if ( (filename=strchr(cptr, ',')) == NULL ) {
694 if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
695 fprintf(stderr, "%s%s: --s option arg %s invalid\n",
696 Progname, TagName, cptr);
705 if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
706 fprintf(stderr, "%s%s: --s option arg %s invalid\n",
707 Progname, TagName, cptr);
711 *filename=','; /* restore string */
718 if ((ret=sscanf(optarg, "%i%c", &trunc_incr, &chr)) < 1 ||
721 fprintf(stderr, "%s%s: --t option arg invalid\n",
727 if ( chr == 'b' || chr == 'B' )
731 "%s%s: --t option arg invalid\n",
739 case 'T': /* truncate interval */
740 if (sscanf(optarg, "%i%c", &trunc_inter, &chr) != 1 ||
743 fprintf(stderr, "%s%s: --T option arg invalid\n",
754 case 'U': /* how often to unlink file */
757 * A-B - randomly pick interval between A and B
758 * X - unlink file every X iteration
760 if (sscanf(optarg, "%i-%i", &unlink_inter,
761 &unlink_inter_ran) == 2 ) {
763 if ( unlink_inter < 0 || unlink_inter_ran < 0 ) {
764 fprintf(stderr, "%s%s: --U option arg invalid\n",
769 /* ensure unlink_inter contains smaller value */
770 if ( unlink_inter > unlink_inter_ran ) {
771 tmp=unlink_inter_ran;
772 unlink_inter_ran=unlink_inter;
777 } else if (sscanf(optarg, "%i%c", &unlink_inter, &chr) != 1 ||
780 fprintf(stderr, "%s%s: --U option arg invalid\n",
788 if ( reexec != REXEC_DONE )
793 Mode |= MODE_GROW_BY_LSEEK;
797 sprintf( TagName, "(%.37s)", optarg );
812 cptr = getenv("TOUTPUT");
813 if( (cptr != NULL) && (strcmp( cptr, "NOPASS" ) == 0) ){
818 if ( Pattern == PATTERN_RANDOM ) {
820 if ( write_check_inter || file_check_inter )
821 printf("%s%s: %d Using random pattern - no data checking will be performed!\n",
822 Progname, TagName, (int)getpid());
824 else if ( max_lseek == LSK_EOFPLUSGROW || Mode & MODE_GROW_BY_LSEEK ) {
827 if ( file_check_inter )
828 printf("%s%s: %d Using random lseek beyond EOF or lseek grow,\n\
829 no whole file checking will be performed!\n", Progname, TagName, (int)getpid());
833 if ( Mode & MODE_RAND_SIZE )
843 printf("%s: %d DEBUG2 forking, returning control to the user\n",
845 background(Progname); /* give user their prompt back */
850 lio_set_debug(Debug-3);
852 set_iowrite_debug(Debug-3);
857 * Print some program information here if debug is turned on to
863 if ( Mode & MODE_GROW_BY_LSEEK )
864 printf("%s: %d DEBUG lseeking past end of file, writting a \"w\"\n",
866 else if ( Pattern == PATTERN_OFFSET )
867 printf("%s: %d DEBUG3 %d<byteoffset>%d per word pattern multi-writers.\n",
868 Progname, Pid, STATIC_NUM, STATIC_NUM);
869 else if ( Pattern == PATTERN_PID )
870 printf("%s: %d DEBUG3 <pid><byteoffset><pid> per word pattern - 1 writer\n",
872 else if ( Pattern == PATTERN_ASCII )
873 printf("%s: %d DEBUG3 ascii pattern (vi'able)- allows multiple writers\n",
875 else if ( Pattern == PATTERN_ALT )
876 printf("%s: %d DEBUG3 alt bit pattern - allows multiple writers\n",
878 else if ( Pattern == PATTERN_CHKER )
879 printf("%s: %d DEBUG3 checkerboard pattern - allows multiple writers\n",
881 else if ( Pattern == PATTERN_CNTING )
882 printf("%s: %d DEBUG3 counting pattern - allows multiple writers\n",
884 else if ( Pattern == PATTERN_RANDOM )
885 printf("%s: %d DEBUG3 random integer pattern - no write/file checking\n",
887 else if ( Pattern == PATTERN_ONES )
888 printf("%s: %d DEBUG3 all ones pattern - allows multiple writers\n",
890 else if ( Pattern == PATTERN_ZEROS )
891 printf("%s: %d DEBUG3 all zeros pattern - allows multiple writers\n",
895 printf("%s: %d DEBUG3 unknown pattern\n",
897 if ( bytes_to_consume )
898 printf("%s: %d DEBUG3 bytes_to_consume = %d\n",
899 Progname, Pid, bytes_to_consume);
900 printf("%s: %d DEBUG3 Maxerrs = %d, pre_alloc_space = %d, filelocking = %d\n",
901 Progname, Pid, Maxerrs, pre_alloc_space, lockfile);
903 printf("%s: %d DEBUG3 Debug = %d, remove files in cleanup : %d\n",
904 Progname, Pid, Debug, remove_files);
906 printf("%s: %d DEBUG3 Mode = %#o\n", Progname, Pid, Mode);
908 if ( open_flags == RANDOM_OPEN )
909 printf("%s: %d DEBUG3 open_flags = (random), io_type = %#o\n", Progname,
912 printf("%s: %d DEBUG3 open_flags = %#o, io_type = %#o\n", Progname,
913 Pid, open_flags, io_type);
915 if ( Mode & MODE_RAND_SIZE ) {
916 printf("%s: %d DEBUG3 random write/trunc: min=%d, max=%d, mult = %d\n",
917 Progname, Pid, min_size, max_size, mult_size);
920 printf("%s: %d DEBUG3 grow_incr = %d\n",
921 Progname, Pid, grow_incr);
923 if ( Mode & MODE_RAND_LSEEK ) {
924 if ( max_lseek == LSK_EOF )
925 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile>\n",
926 Progname, Pid, min_lseek);
927 else if ( max_lseek == LSK_EOFPLUSGROW )
928 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile+iosize>\n",
929 Progname, Pid, min_lseek);
930 else if ( max_lseek == LSK_EOFMINUSGROW )
931 printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile-iosize>\n",
932 Progname, Pid, min_lseek);
934 printf("%s: %d DEBUG3 random lseek: min=%d, max=%d\n",
935 Progname, Pid, min_lseek, max_lseek);
938 printf("%s: %d DEBUG3 check write interval = %d, check file interval = %d\n",
939 Progname, Pid, write_check_inter, file_check_inter);
941 printf("%s: %d DEBUG3 trunc interval = %d, trunc_incr = %d\n",
942 Progname, Pid, trunc_inter, trunc_incr);
945 printf("%s: %d DEBUG3 no whole file checking will be done\n",
948 if ( unlink_inter_ran == -1 ) {
949 printf("%s: %d DEBUG3 unlink_inter = %d\n",
950 Progname, Pid, unlink_inter);
952 printf("%s: %d DEBUG3 unlink_inter = %d, unlink_inter_ran = %d\n",
953 Progname, Pid, unlink_inter, unlink_inter_ran);
957 num=sizeof(Open_flags)/sizeof(int);
958 printf("%s: %d DEBUG9 random open flags values:\n", Progname, Pid);
959 for(ind=0; ind<num; ind++) {
960 printf("\t%#o\n", Open_flags[ind]);
963 } /* end of DEBUG > 2 */
965 if ( Debug > 1 && num_procs > 1 ) {
966 printf("%s: %d DEBUG2 about to fork %d more copies\n", Progname,
970 fflush(stdout); /* ensure pending i/o is flushed before forking */
973 forker(num_procs, forker_mode, Progname);
975 Pid=getpid(); /* reset after the forks */
977 * If user specified random seed(s), get that random seed value.
978 * get random seed if it was not specified by the user.
979 * This is done after the forks, because pid is used to get the seed.
983 * If only one seed specified, all processes will get that seed.
986 } else if ( Nseeds > 1 ) {
988 * More than one seed was specified.
989 * The original process gets the first seed. Each
990 * process will be get the next seed in the specified list.
996 * If user didn't specify enough seeds, use default method.
998 if ( Forker_npids >= Nseeds )
999 Seed=time(0) + Pid; /* default random seed */
1001 Seed=Seeds[Forker_npids];
1006 * Generate a random seed based on time and pid.
1007 * It has a good chance of being unique for each pid.
1009 Seed=time(0) + Pid; /* default random seed */
1012 random_range_seed(Seed);
1014 if ( using_random && Debug > 0 )
1015 printf("%s%s: %d DEBUG1 Using random seed of %d\n",
1016 Progname, TagName, Pid, Seed);
1018 if ( unlink_inter_ran > 0 ) {
1020 * Find unlinking file interval. This must be done after
1021 * the seed was set. This allows multiple copies to
1022 * get different intervals.
1025 unlink_inter=random_range(tmp, unlink_inter_ran, 1, NULL);
1028 printf("%s: %d DEBUG3 Unlink interval is %d (random %d - %d)\n",
1029 Progname, Pid, unlink_inter, tmp, unlink_inter_ran);
1033 * re-exec all childern if reexec is set to REXEC_DOIT.
1034 * This is useful on MPP systems to get the
1035 * child process on another PE.
1037 if ( reexec == REXEC_DOIT && Opid != Pid ) {
1038 if ( exec_path == NULL ) {
1039 exec_path = argv[0];
1040 /* Get space for cmd (2 extra, 1 for - and 1 fro NULL */
1041 argv[0] = (char *)malloc(strlen(exec_path) + 2);
1042 sprintf(argv[0], "-%s", exec_path);
1046 printf("%s: %d DEBUG3 %s/%d: execvp(%s, argv)\n",
1047 Progname, Pid, __FILE__, __LINE__, argv[0]);
1049 execvp(argv[0], argv);
1052 /*** begin filename stuff here *****/
1054 * Determine the number of files to be dealt with
1056 if ( optind == argc ) {
1058 * no cmd line files, therfore, set
1059 * the default number of auto created files
1061 if ( ! num_auto_files && ! seq_auto_files )
1065 first_file_ind=optind;
1066 num_files += argc-optind;
1069 if ( num_auto_files ) {
1070 num_files += num_auto_files;
1073 if ( seq_auto_files ) {
1074 num_files += seq_auto_files;
1078 * get space for file names
1080 if ((filenames=(char *)malloc(num_files*PATH_MAX)) == NULL) {
1081 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1082 Progname, TagName, Pid, __FILE__, __LINE__, num_files*PATH_MAX,
1088 * fill in filename cmd files then auto files.
1092 if ( first_file_ind ) {
1093 for(ind=first_file_ind; ind<argc; ind++, num++) {
1094 strcpy((char *)filenames+(num*PATH_MAX), argv[ind]);
1099 * construct auto filename and insert them into filenames space
1101 for(ind=0;ind<num_auto_files; ind++, num++) {
1102 sprintf((char *)filenames+(num*PATH_MAX), "%s/%s.%d",
1103 auto_dir, auto_file, ind);
1107 * construct auto seq filenames
1109 for(ind=1; ind<=seq_auto_files; ind++, num++) {
1110 sprintf((char *)filenames+(num*PATH_MAX), "%s/%s%d",
1111 auto_dir, auto_file, ind);
1114 /**** end filename stuff ****/
1116 if ( time_iterval > 0 )
1120 * get space for I/O buffer
1123 if ((Buffer=(char *)malloc(grow_incr+Alignment)) == NULL) {
1124 fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1125 Progname, TagName, Pid, __FILE__, __LINE__, grow_incr, strerror(errno));
1129 Buffer = Buffer + Alignment;
1134 printf("%s: %d DEBUG3 num_files = %d\n",
1135 Progname, Pid, num_files);
1138 if ( pre_alloc_space ) {
1139 if ( iterations == 0 ) {
1140 fprintf(stderr, "%s%s: %d %s/%d: can NOT pre-alloc and grow forever\n",
1141 Progname, TagName, Pid, __FILE__, __LINE__);
1144 if ( Mode & MODE_RAND_SIZE ) {
1146 "%s%s: %d %s/%d: can NOT pre-alloc and do random io size\n",
1147 Progname, TagName, Pid, __FILE__, __LINE__);
1151 total_grow_value=grow_incr * iterations;
1156 if ( bytes_to_consume && bytes_to_consume < total_grow_value ) {
1157 total_grow_value=bytes_to_consume;
1162 * If delaying between iterations, get amount time to
1163 * delaysecs in clocks or usecs.
1166 delaytime=(int)((float)USECS_PER_SEC * delaysecs);
1170 * This is the main iteration loop.
1171 * Each iteration, all files can be opened, written to,
1172 * read to check the write, check the whole file,
1173 * truncated, and closed.
1175 for(Iter_cnt=1; ! stop ; Iter_cnt++) {
1177 if ( iterations && Iter_cnt >= iterations+1 ) {
1178 strcpy(reason, "Hit iteration value");
1183 if ( (time_iterval > 0) && (start_time + time_iterval < time(0)) ) {
1184 sprintf(reason, "Hit time value of %d", time_iterval);
1189 if ( bytes_to_consume && bytes_consumed >= bytes_to_consume) {
1190 sprintf(reason, "Hit bytes consumed value of %d", bytes_to_consume);
1196 * This loop will loop through all files.
1197 * Each iteration, a single file can be opened, written to,
1198 * read to check the write, check the whole file,
1199 * truncated, and closed.
1201 for(ind=0; ind<num_files; ind++) {
1206 filename=(char *)filenames+(ind*PATH_MAX);
1207 Fileinfo.filename=(char *)filenames+(ind*PATH_MAX);
1210 if ( open_flags == RANDOM_OPEN ) {
1211 ret=Open_flags[random_range(0, sizeof(Open_flags)/sizeof(int)-1, 1, NULL)];
1217 Fileinfo.openflags=ret;
1220 printf("%s: %d DEBUG3 %s/%d: %d Open filename = %s, open flags = %#o %s\n",
1221 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, ret,
1222 openflags2symbols(ret, ",", 0));
1223 } else if ( Debug > 2 ) {
1224 printf("%s: %d DEBUG3 %s/%d: %d filename = %s, open flags = %#o\n",
1225 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, ret);
1229 * open file with desired flags.
1231 if ( (fd=open(filename, ret, 0777)) == -1 ) {
1233 "%s%s: %d %s/%d: open(%s, %#o, 0777) returned -1, errno:%d %s\n",
1234 Progname, TagName, Pid, __FILE__, __LINE__, filename, ret, errno, strerror(errno));
1241 lkfile(fd, LOCK_EX, LKLVL1); /* lock if lockfile is LKLVL1 */
1244 * preallocation is only done once, if specified.
1246 if ( pre_alloc_space ) {
1247 if (pre_alloc(filename, fd, total_grow_value) != 0 ) {
1252 printf("%s: %d DEBUG2 %s/%d: pre_allocated %d for file %s\n",
1253 Progname, Pid, __FILE__, __LINE__, total_grow_value, filename);
1255 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1257 Iter_cnt=0; /* reset outside loop to restart from one */
1262 * grow file by desired amount.
1263 * growfile() will set the Grow_incr variable and
1264 * possiblly update the Mode variable indicating
1265 * if we are dealing with a FIFO file.
1268 if (growfile(fd, filename, grow_incr, (unsigned char *)Buffer) != 0 ) {
1270 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1276 * check if last write is not corrupted
1278 if ( check_write(fd, write_check_inter, filename,
1284 * Check that whole file is not corrupted.
1286 if ( check_file(fd, file_check_inter, filename,
1287 no_file_check) != 0 ) {
1292 * shrink file by desired amount if it is time
1295 if ( shrinkfile(fd, filename, trunc_incr, trunc_inter, Mode) != 0 ) {
1299 lkfile(fd, LOCK_UN, LKLVL1); /* release lock */
1302 printf("%s: %d DEBUG5 %s/%d: %d Closing file %s fd:%d \n",
1303 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename, fd);
1307 * Unlink the file if that is desired
1309 if ( unlink_inter && (Iter_cnt % unlink_inter == 0) ) {
1312 printf("%s: %d DEBUG5 %s/%d: %d Unlinking file %s\n",
1313 Progname, Pid, __FILE__, __LINE__, Iter_cnt, filename);
1319 * delay while staying active for "delaysecs" seconds.
1324 struct timeval curtime;
1325 gettimeofday(&curtime, NULL);
1326 ct=curtime.tv_sec*USECS_PER_SEC + curtime.tv_usec;
1328 while ( ct < end ) {
1330 gettimeofday(&curtime, NULL);
1331 ct=curtime.tv_sec*USECS_PER_SEC + curtime.tv_usec;
1336 * if Iter_cnt == 0, then we pre allocated space to all files
1337 * and we are starting outside loop over. Set pre_alloc_space
1338 * to zero otherwise we get in infinite loop
1340 if ( Iter_cnt == 0 ) {
1343 } /* end iteration for loop */
1347 printf("%s%s: %d %s/%d: DONE %d iterations to %d files. %s\n",
1348 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, num_files, reason);
1357 printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1358 Progname, TagName, Pid, Errors);
1359 printf("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", Progname, TagName, Pid, __FILE__, __LINE__);
1364 printf("%s%s: %d DEBUG3 %s/%d: no errors, exiting with value of 0\n", Progname, TagName, Pid, __FILE__, __LINE__);
1368 /***********************************************************************
1370 ***********************************************************************/
1378 * now loop through all signals and set the handlers
1381 for (sig = 1; sig < NSIG; sig++) {
1388 #endif /* SIGCKPT */
1391 #endif /* SIGRESTART */
1396 signal(sig, sig_handler);
1405 /***********************************************************************
1407 ***********************************************************************/
1414 if ( sig == SIGUSR2 ) {
1415 fprintf(stdout, "%s%s: %d %s/%d: received SIGUSR2 (%d) - stopping.\n",
1416 Progname, TagName, Pid, __FILE__, __LINE__, sig);
1417 signal(sig, sig_handler); /* allow us to get this signal more than once */
1419 } else if( sig == SIGINT ){
1420 /* The user has told us to cleanup, don't pretend it's an error. */
1423 fprintf(stderr, "%s%s: %d %s/%d: received unexpected signal: %d\n", Progname, TagName,
1424 Pid, __FILE__, __LINE__, sig);
1427 fprintf(stderr, "%s%s: %d %s/%d: received unexpected signal: %d\n", Progname, TagName,
1428 Pid, __FILE__, __LINE__, sig);
1434 printf("%s%s: %d DEBUG3 %s/%d: Exiting with a value of %d\n",
1435 Progname, TagName, Pid, __FILE__, __LINE__, exit_stat);
1440 /***********************************************************************
1441 * this function attempts to send SIGUSR2 to other growfiles processes
1442 * telling them to stop.
1444 ***********************************************************************/
1448 static int send_signals = 0;
1450 extern int Forker_pids[];
1451 extern int Forker_npids;
1453 if ( Sync_with_others && send_signals == 0 ) {
1455 send_signals=1; /* only send signals once */
1457 for (ind=0; ind< Forker_npids; ind++) {
1458 if ( Forker_pids[ind] != Pid ) {
1460 printf("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pid %d\n",
1461 Progname, TagName, Pid, __FILE__, __LINE__, Forker_pids[ind]);
1462 kill(Forker_pids[ind], SIGUSR2);
1469 /***********************************************************************
1470 * this function will count the number of errors encountered.
1471 * This function will call upanic if wanted or cleanup and
1472 * and exit is Maxerrs were encountered.
1473 ***********************************************************************/
1479 if ( Maxerrs && Errors >= Maxerrs ) {
1480 printf("%s%s: %d %s/%d: %d Hit max errors value of %d\n",
1481 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, Maxerrs);
1486 printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1487 Progname, TagName, Pid, Errors);
1488 printf("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n", Progname, TagName, Pid, __FILE__, __LINE__);
1497 /***********************************************************************
1499 ***********************************************************************/
1505 if ( remove_files ) {
1507 printf("%s: %d DEBUG3 Removing all %d files\n",
1508 Progname, Pid, num_files);
1509 for(ind=0; ind<=num_files; ind++) {
1510 unlink(filenames+(ind*PATH_MAX));
1513 if ( using_random && Debug > 1 )
1514 printf("%s%s: %d DEBUG2 Used random seed: %d\n",
1515 Progname, TagName, Pid, Seed);
1519 /***********************************************************************
1521 ***********************************************************************/
1526 "Usage: %s%s [-bhEluy][[-g grow_incr][-i num][-t trunc_incr][-T trunc_inter]\n",
1527 Progname, TagName );
1529 "[-d auto_dir][-e maxerrs][-f auto_file][-N num_files][-w][-c chk_inter][-D debug]\n");
1531 "[-s seed][-S seq_auto_files][-p][-P PANIC][-I io_type][-o open_flags][-B maxbytes]\n");
1533 "[-r iosizes][-R lseeks][-U unlk_inter][-W tagname] [files]\n");
1537 } /* end of usage */
1539 /***********************************************************************
1541 ***********************************************************************/
1548 -h Specfied to print this help and exit.\n\
1549 -b Specfied to execute in sync mode.(def async mode)\n\
1550 -B maxbytes Max bytes to consume by all files. growfiles exits when more\n\
1551 than maxbytes have been consumed. (def no chk) If maxbytes ends\n\
1552 with the letter 'b', maxbytes is multiplied by BSIZE\n\
1553 -C write_chk Specifies how often to check the last write (default 1)\n\
1554 -c file_chk Specifies how often to check whole file (default 0)\n\
1555 -d auto_dir Specifies the directory to auto created files. (default .)\n\
1556 -D debug_lvl Specifies the debug level (default 1)\n\
1557 -E Print examples and exit\n\
1558 -e errs The number errors that will terminate this program (def 100)\n\
1559 -f auto_file Specifies the base filename files created. (default \"gf\")\n\
1560 -g grow_incr Specfied to grow by incr for each num. (default 4096)\n\
1561 grow_incr may end in b for blocks\n\
1562 If -r option is used, this option is ignored and size is random\n\
1563 -H delay Amount of time to delay between each file (default 0.0)\n\
1564 -I io_type Specifies io type: s - sync, p - polled async, a - async (def s)\n\
1565 l - listio sync, L - listio async, r - random\n\
1566 -i iteration Specfied to grow each file num times. 0 means forever (default 1)\n\
1567 -l Specfied to do file locking around write/read/trunc\n\
1568 If specified twice, file locking after open to just before close\n\
1569 -L time Specfied to exit after time secs, must be used with -i.\n\
1570 -N num_files Specifies the number of files to be created.\n\
1571 The default is zero if cmd line files.\n\
1572 The default is one if no cmd line files.\n\
1573 -n num_procs Specifies the number of copies of this cmd.\n\
1574 -o op_type Specifies open flages: (def O_RDWR,O_CREAT) op_type can be 'random'\n\
1575 -O offset adjust i/o buffer alignment by offset bytes\n\
1576 -P PANIC Specifies to call upanic on error.\n\
1577 -p Specifies to pre-allocate space\n\
1578 -q pattern pattern can be a - ascii, p - pid with boff, o boff (def)\n\
1579 A - Alternating bits, r - random, O - all ones, z - all zeros,\n\
1580 c - checkboard, C - counting\n\
1581 -R [min-]max random lseek before write and trunc, max of -1 means filesz,\n\
1582 -2 means filesz+grow, -3 filesz-grow. (min def is 0)\n\
1583 -r [min-]max random io write size (min def is 1)\n\
1584 -S seq_auto_files Specifies the number of seqental auto files (default 0)\n\
1585 -s seed[,seed...] Specifies the random number seed (default time(0)+pid)\n\
1586 -t trunc_incr Specfied the amount to shrink file. (default 4096)\n\
1587 trunc_inter may end in b for blocks\n\
1588 If -R option is used, this option is ignored and trunc is random\n\
1589 -T trunc_inter Specfied the how many grows happen before shrink. (default 0)\n\
1590 -u unlink files before exit\n\
1591 -U ui[-ui2] Unlink files each ui iteration (def 0)\n\
1592 -w Specfied to grow via lseek instead of writes.\n\
1593 -W tag-name Who-am-i. My Monster tag name. (used by Monster).\n\
1594 -x Re-exec children before continuing - useful on MPP systems\n\
1595 -y Attempt to sync copies - if one fails it will send sigusr2 to others\n\
1596 Action to each file every iteration is open, write, write check\n\
1597 file check, trunc and closed.\n");
1602 /***********************************************************************
1604 ***********************************************************************/
1606 prt_examples(FILE *stream)
1608 /* This example creates 200 files in directory dir1. It writes */
1609 /* 4090 bytes 100 times then truncates 408990 bytes off the file */
1610 /* The file contents are checked every 1000 grow. */
1612 "# run forever: writes of 4090 bytes then on every 100 iterval\n\
1613 # truncate file by 408990 bytes. Done to 200 files in dir1.\n\
1614 %s -i 0 -g 4090 -T 100 -t 408990 -l -C 10 -c 1000 -d dir1 -S 200\n\n", Progname);
1616 /* same as above with 5000 byte grow and a 499990 byte tuncate */
1618 "# same as above with writes of 5000 bytes and truncs of 499990\n\
1619 %s -i 0 -g 5000 -T 100 -t 499990 -l -C 10 -c 1000 -d dir2 -S 200\n\n", Progname);
1621 /* This example beats on opens and closes */
1623 "# runs forever: beats on opens and closes of file ocfile - no io\n\
1624 %s -i 0 -g 0 -c 0 -C 0 ocfile\n\n", Progname);
1627 "# writes 4096 to files until 50 blocks are written\n\
1628 %s -i 0 -g 4096 -B 50b file1 file2\n\n", Progname);
1631 "# write one byte to 750 files in gdir then unlinks them\n\
1632 %s -g 1 -C 0 -d gdir -u -S 750\n\n", Progname);
1635 "# run 30 secs: random iosize, random lseek up to eof\n\
1636 %s -r 1-5000 -R 0--1 -i 0 -L 30 -C 1 g_rand1 g_rand2\n\n", Progname);
1639 "# run 30 secs: grow by lseek then write single byte, trunc every 10 itervals\n\
1640 %s -g 5000 -wlu -i 0 -L 30 -C 1 -T 10 g_sleek1 g_lseek2\n\n", Progname);
1643 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1644 # rand io types doing a trunc every 5 iterations, with unlinks.\n\
1645 %s -i0 -r 1-50000 -R 0--2 -I r -C1 -l -n5 -u -U 100-200 gf_rana gf_ranb\n\n",
1649 "# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1650 # random open flags, rand io types doing a trunc every 10 iterations.\n\
1651 %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",
1658 /***********************************************************************
1660 * The file descriptor current offset is assumed to be the end of the
1662 * Woffset will be set to the offset before the write.
1663 * Grow_incr will be set to the size of the write or lseek write.
1664 ***********************************************************************/
1666 growfile(fd, file, grow_incr, buf)
1677 int fsize; /* current size of file */
1678 int size_grew; /* size the file grew */
1683 * Do a stat on the open file.
1684 * If the file is a fifo, set the bit in Mode variable.
1685 * This fifo check must be done prior to growfile() returning.
1686 * Also get the current size of the file.
1688 if ( fstat(fd, &stbuf) != -1 ) {
1689 if ( S_ISFIFO(stbuf.st_mode) ) {
1690 Fileinfo.mode |= MODE_FIFO;
1693 printf("%s: %d DEBUG4 %s/%d: file is a fifo - no lseek or truncs,\n",
1694 Progname, Pid, __FILE__, __LINE__);
1696 fsize = stbuf.st_size;
1699 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1700 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
1706 if ( grow_incr <= 0 ) { /* don't attempt i/o if grow_incr <= 0 */
1708 Grow_incr=grow_incr;
1710 printf("%s: %d DEBUG3 %s/%d: Not attempting to grow, growsize == %d\n",
1711 Progname, Pid, __FILE__, __LINE__, grow_incr);
1715 if ( Mode & MODE_RAND_SIZE ) {
1716 grow_incr=random_range(min_size, max_size, mult_size, &errmsg);
1717 if (errmsg != NULL) {
1718 fprintf(stderr, "%s%s: %d %s/%d: random_range() failed - %s\n", Progname, TagName, Pid, __FILE__, __LINE__, errmsg);
1721 Grow_incr=grow_incr;
1724 Grow_incr=grow_incr;
1726 if ( ! (Mode & MODE_FIFO) ) {
1727 if ((cur_offset=lseek(fd,0,SEEK_CUR)) == -1 ) {
1728 fprintf(stderr, "%s%s: %d %s/%d: tell failed: %s\n",
1729 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
1734 if ( Mode & MODE_GROW_BY_LSEEK ) {
1737 printf("%s: %d DEBUG3 %s/%d: Current size of file is %d\n", Progname,
1738 Pid, __FILE__, __LINE__, Woffset);
1739 printf("%s: %d DEBUG3 %s/%d: lseeking to %d byte with SEEK_END\n", Progname,
1740 Pid, __FILE__, __LINE__, grow_incr-1);
1743 if ((noffset=lseek(fd, grow_incr-1, SEEK_END)) == -1 ) {
1744 fprintf(stderr, "%s%s: %s/%d: lseek(fd, %d, SEEK_END) failed: %s\n",
1745 Progname, TagName, __FILE__, __LINE__, grow_incr-1, strerror(errno));
1749 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1752 ret=lio_write_buffer(fd, io_type, "w", 1, SIGUSR1, &errmsg,0);
1754 ret=write_buffer(fd, io_type, "w", 1, 0, &errmsg);
1758 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
1759 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
1760 if ( ret == -ENOSPC ) {
1769 lkfile(fd, LOCK_UN, LKLVL0);
1772 printf("%s: %d DEBUG3 %s/%d: %d wrote 1 byte to file\n",
1773 Progname, Pid, __FILE__, __LINE__, Iter_cnt);
1775 } else { /* end of grow by lseek */
1777 if ( Fileinfo.openflags & O_APPEND ) {
1779 * Deal with special case of the open flag containing O_APPEND.
1780 * If it does, the current offset does not matter since the write
1781 * will be done end of the file.
1784 printf("%s: %d DEBUG5 %s/%d: dealing with O_APPEND condition\n",
1785 Progname, Pid, __FILE__, __LINE__ );
1786 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1789 * do fstat again to get size of the file.
1790 * This is done inside a file lock (if locks are being used).
1792 if ( fstat(fd, &stbuf) != -1 ) {
1793 Woffset = stbuf.st_size;
1795 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1796 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
1798 lkfile(fd, LOCK_UN, LKLVL0); /* release lock */
1802 printf("%s: %d DEBUG3 %s/%d: dealing with O_APPEND condition (offset:fsz:%d)\n",
1803 Progname, Pid, __FILE__, __LINE__, (int)stbuf.st_size);
1806 } else if ( Mode & MODE_RAND_LSEEK ) {
1807 if ( max_lseek == LSK_EOF ) { /* within file size */
1808 noffset=random_range(min_lseek, fsize, 1, NULL);
1810 else if ( max_lseek == LSK_EOFPLUSGROW ) {
1811 /* max to beyond file size */
1812 noffset=random_range(min_lseek, fsize+grow_incr, 1, NULL);
1814 else if ( max_lseek == LSK_EOFMINUSGROW ) {
1816 * Attempt to not grow the file.
1817 * If the i/o will fit from min_lseek to EOF,
1818 * pick offset to allow it to fit.
1819 * Otherwise, pick the min_lseek offset and grow
1820 * file by smallest amount.
1821 * If min_lseek is != 0, there will be a problem
1822 * with whole file checking if file is ever smaller
1825 if ( fsize <= min_lseek + grow_incr )
1826 noffset=min_lseek; /* file will still grow */
1828 noffset=random_range(min_lseek, fsize-grow_incr, 1, NULL);
1831 noffset=random_range(min_lseek, max_lseek, 1, NULL);
1834 if ((Woffset=lseek(fd, noffset, SEEK_SET)) == -1 ) {
1835 fprintf(stderr, "%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l2 failed: %s\n",
1836 Progname, TagName, Pid, __FILE__, __LINE__, fd, noffset, strerror(errno));
1839 else if ( Debug > 2 )
1840 printf("%s: %d DEBUG3 %s/%d: lseeked to random offset %d (fsz:%d)\n",
1841 Progname, Pid, __FILE__, __LINE__, Woffset,
1842 (int)stbuf.st_size);
1847 * lseek to end of file only if not fifo
1849 else if ( ! (Mode & MODE_FIFO) ) {
1850 if ((Woffset=lseek(fd, 0, SEEK_END)) == -1 ) {
1851 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, 0, SEEK_END) failed: %s\n",
1852 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
1855 else if ( Debug > 2 )
1856 printf("%s: %d DEBUG3 %s/%d: lseeked to end of file, offset %d\n",
1857 Progname, Pid, __FILE__, __LINE__, Woffset);
1860 if ( Pattern == PATTERN_OFFSET )
1861 datapidgen(STATIC_NUM, buf, grow_incr, Woffset);
1862 else if ( Pattern == PATTERN_PID )
1863 datapidgen(Pid, buf, grow_incr, Woffset);
1864 else if ( Pattern == PATTERN_ASCII )
1865 dataasciigen(NULL, (char *)buf, grow_incr, Woffset);
1866 else if ( Pattern == PATTERN_RANDOM )
1867 databingen('r', buf, grow_incr, Woffset);
1868 else if ( Pattern == PATTERN_ALT )
1869 databingen('a', buf, grow_incr, Woffset);
1870 else if ( Pattern == PATTERN_CHKER )
1871 databingen('c', buf, grow_incr, Woffset);
1872 else if ( Pattern == PATTERN_CNTING )
1873 databingen('C', buf, grow_incr, Woffset);
1874 else if ( Pattern == PATTERN_ZEROS )
1875 databingen('z', buf, grow_incr, Woffset);
1876 else if ( Pattern == PATTERN_ONES )
1877 databingen('o', buf, grow_incr, Woffset);
1879 dataasciigen(NULL, (char *)buf, grow_incr, Woffset);
1882 printf("%s: %d DEBUG3 %s/%d: attempting to write %d bytes\n",
1883 Progname, Pid, __FILE__, __LINE__, grow_incr);
1885 lkfile(fd, LOCK_EX, LKLVL0); /* get exclusive lock */
1888 ret=write(fd, buf, grow_incr);
1892 lkfile(fd, LOCK_UN, LKLVL0);
1894 if ( ret != grow_incr) {
1895 fprintf(stderr, "%s: %s/%d: write failed: %s\n",
1896 Progname, __FILE__, __LINE__, strerror(errno));
1902 ret=lio_write_buffer(fd, io_type, (char *)buf, grow_incr,
1903 SIGUSR1, &errmsg,0);
1905 ret=write_buffer(fd, io_type, buf, grow_incr, 0, &errmsg);
1908 if( Mode & MODE_FIFO ){
1909 /* If it is a fifo then just pretend the file
1910 * offset is where we think it should be.
1912 tmp = Woffset + grow_incr;
1915 if( (tmp=lseek(fd,0,SEEK_CUR)) < 0 ){ /* get offset after the write */
1916 fprintf(stderr, "%s%s: %s/%d: tell(2) failed: %d %s\n",
1917 Progname, TagName, __FILE__, __LINE__, errno, strerror(errno) );
1922 lkfile(fd, LOCK_UN, LKLVL0);
1924 if ( ret != grow_incr ) {
1925 fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
1926 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
1927 if ( ret == -ENOSPC ) {
1935 * Check for a condition where the file was truncated just before
1938 if ( tmp != Woffset + grow_incr) {
1940 * The offset after the write was not as expected.
1941 * This could be caused by the following:
1942 * - file truncated after the lseek and before the write.
1943 * - the file was written to after fstat and before the write
1944 * and the file was opened with O_APPEND.
1946 * The pattern written to the file will be considered corrupted.
1948 if ( Debug > 0 && lockfile ) {
1949 printf("%s%s: %d DEBUG1 %s/%d: offset after write(%d) not as exp(%d+%d=%d)\n",
1950 Progname, TagName, Pid, __FILE__, __LINE__, tmp, Woffset, grow_incr, Woffset+grow_incr);
1951 printf("%s%s: %d DEBUG1 %s/%d: %d Assuming file changed by another process, resetting offset:%d (expect pattern mismatch)\n",
1952 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, tmp-grow_incr);
1955 printf("%s: %d DEBUG5 %s/%d: about to chop Woffset. tmp=%d, grow_incr=%d, Woffset was %d\n",
1956 Progname, Pid, __FILE__, __LINE__, tmp, grow_incr, Woffset);
1958 Woffset=tmp-grow_incr;
1963 } /* end of grow by write */
1967 * Woffset - holds start of grow (start of write expect in grow by lseek)
1968 * Grow_incr - holds size of grow (write).
1969 * fsize - holds size of file before write
1971 size_grew=(Woffset + Grow_incr) - fsize;
1973 if ( Mode & MODE_FIFO ) {
1974 printf("%s: %d DEBUG2 %s/%d: file is fifo, %d wrote %d bytes\n",
1975 Progname, Pid, __FILE__, __LINE__, Grow_incr, Iter_cnt);
1978 else if ( size_grew > 0 )
1979 printf("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%d), grew file by %d bytes\n",
1980 Progname, Pid, __FILE__, __LINE__, Iter_cnt, Grow_incr, Woffset, size_grew);
1982 printf("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%d), did not grow file\n",
1983 Progname, Pid, __FILE__, __LINE__, Iter_cnt, Grow_incr, Woffset);
1986 bytes_consumed += size_grew;
1989 } /* end of growfile */
1991 /***********************************************************************
1992 * shrinkfile file by trunc_incr. file can not be made smaller than
1993 * size zero. Therefore, if trunc_incr is larger than file size,
1994 * file will be truncated to zero.
1995 * The file descriptor current offset is assumed to be the end of the
1998 ***********************************************************************/
2000 shrinkfile(fd, filename, trunc_incr, trunc_inter, just_trunc)
2004 int trunc_inter; /* interval */
2005 int just_trunc; /* lseek has already been done for you */
2007 static int shrink_cnt = 0;
2014 if ( trunc_inter == 0 || (shrink_cnt % trunc_inter != 0)) {
2016 printf("%s: %d DEBUG4 %s/%d: Not shrinking file - not time, iter=%d, cnt=%d\n",
2017 Progname, Pid, __FILE__, __LINE__, trunc_inter, shrink_cnt);
2018 return 0; /* not this time */
2021 if ( Mode & MODE_FIFO ) {
2023 printf("%s: %d DEBUG5 %s/%d: Not attempting to shrink a FIFO\n",
2024 Progname, Pid, __FILE__, __LINE__);
2025 return 0; /* can not truncate fifo */
2028 lkfile(fd, LOCK_EX, LKLVL0);
2030 if ((cur_offset=lseek(fd,0,SEEK_CUR)) == -1 ) {
2031 fprintf(stderr, "%s%s: %d %s/%d: tell(%d) failed: %s\n",
2032 Progname, TagName, Pid, __FILE__, __LINE__, fd, strerror(errno));
2033 lkfile(fd, LOCK_UN, LKLVL0);
2037 if ( Mode & MODE_RAND_LSEEK ) {
2038 if ( max_lseek <= -1 ) {
2039 if ( (new_offset=file_size(fd)) == -1 ) {
2040 lkfile(fd, LOCK_UN, LKLVL0);
2044 if ( new_offset < min_lseek )
2045 new_offset=min_lseek;
2047 new_offset=random_range(min_lseek, new_offset, 1, NULL);
2050 new_offset=random_range(min_lseek, max_lseek, 1, NULL);
2054 else { /* remove trunc_incr from file */
2056 new_offset = cur_offset-trunc_incr;
2058 if ( new_offset < 0 )
2062 ret=ftruncate(fd, new_offset );
2063 if( (ret == 0) && (Debug > 3) ){
2064 printf("%s: %d DEBUG4 %s/%d: ftruncated to offset %d, %d bytes from end\n",
2065 Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr);
2068 lkfile(fd, LOCK_UN, LKLVL0);
2071 fprintf(stderr, "%s%s: %d %s/%d: ftruncate failed: %s\n",
2072 Progname, TagName, Pid, __FILE__, __LINE__, strerror(errno));
2077 printf("%s: %d DEBUG2 %s/%d: trunc file by %d bytes, to size of = %d bytes\n",
2078 Progname, Pid, __FILE__, __LINE__, cur_offset-new_offset, new_offset);
2082 bytes_consumed -= (cur_offset - new_offset);
2085 } /* end of shrinkfile */
2087 /***********************************************************************
2089 ***********************************************************************/
2091 check_write(fd, cf_inter, filename, mode)
2093 int cf_inter; /* check file interval */
2094 char *filename; /* needed for error messages */
2095 int mode; /* write mode */
2098 static int cf_count = 0;
2106 if ( cf_inter == 0 || (cf_count % cf_inter != 0)) {
2108 printf("%s: %d DEBUG5 %s/%d: no write check, not time iter=%d, cnt=%d\n",
2109 Progname, Pid, __FILE__, __LINE__, cf_inter, cf_count);
2110 return 0; /* no check done */
2113 if ( Grow_incr <= 0 ) {
2115 printf("%s: %d DEBUG4 %s/%d: No write validation, Grow_incr = %d, offset = %d\n",
2116 Progname, Pid, __FILE__, __LINE__, Grow_incr, Woffset);
2117 return 0; /* no check */
2123 * Get the shared file lock. We need to hold the lock from before
2124 * we do the stat until after the read.
2126 lkfile(fd, LOCK_SH, LKLVL0);
2128 if ((fsize=file_size(fd)) == -1 ) {
2129 lkfile(fd, LOCK_UN, LKLVL0);
2132 } else if ( fsize <= Woffset ) {
2134 * The file was truncated between write and now.
2135 * The contents of our last write is totally gone, no check.
2138 printf("%s%s: %d DEBUG2 %s/%d: %d File size (%d) smaller than where last wrote (%d)- no write validation\n",
2139 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, fsize, Woffset);
2140 lkfile(fd, LOCK_UN, LKLVL0);
2141 return 0; /* no validation, but not an error */
2143 } else if ( fsize < (Woffset + Grow_incr)) {
2145 * The file was truncated between write and now.
2146 * Part of our last write has been truncated, adjust our Grow_incr
2151 Grow_incr=fsize-Woffset;
2155 printf("%s%s: %d DEBUG2 %s/%d: %d fsz:%d, lost(%d)of wrt(off:%d, sz:%d), adj=%d\n",
2156 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, fsize, tmp-Grow_incr, Woffset, tmp, Grow_incr);
2162 printf("%s: %d DEBUG3 %s/%d: about to do write validation, offset = %d, size = %d\n",
2163 Progname, Pid, __FILE__, __LINE__, Woffset, Grow_incr);
2165 if ( ! (mode & MODE_FIFO) ) {
2167 if ( lseek(fd, Woffset, 0) == -1 ) {
2168 fprintf(stderr, "%s%s: %d %s/%d: lseek(fd, %d, 0) failed: %s\n",
2169 Progname, TagName, Pid, __FILE__, __LINE__, Woffset, strerror(errno));
2172 printf("%s: %d DEBUG4 %s/%d: lseeked to offset:%d\n",
2173 Progname, Pid, __FILE__, __LINE__, Woffset);
2177 * Read last writes data
2180 ret=lio_read_buffer(fd, io_type, Buffer, Grow_incr, SIGUSR1, &errmsg,0);
2182 ret=read_buffer(fd, io_type, Buffer, Grow_incr, 0, &errmsg);
2186 * report the error and debug information before releasing
2189 if ( ret != Grow_incr ) {
2190 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s\n", Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2195 printf("%s%s: %d DEBUG3 %s/%d: fd:%d, offset:%d, fsize:%d, openflags:%#o\n",
2196 Progname, TagName, Pid, __FILE__, __LINE__, fd,
2197 (int)lseek(fd,SEEK_CUR,0), /* FIXME: 64bit/LFS ? */
2199 Fileinfo.openflags);
2202 lkfile(fd, LOCK_UN, LKLVL0);
2207 lkfile(fd, LOCK_UN, LKLVL0);
2209 if ( Mode & MODE_GROW_BY_LSEEK ) {
2210 /* check that all zeros upto last character */
2211 for(ptr=Buffer; ptr < (Buffer+Grow_incr-1); ptr++) {
2212 if ( *ptr != '\0' ) {
2214 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2215 Progname, TagName, Pid, __FILE__, __LINE__,
2216 (int)(Woffset+(Grow_incr-(Buffer-ptr))),
2222 /* check that the last char is a 'w' */
2223 if ( *ptr != 'w' ) {
2225 "%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2226 Progname, TagName, Pid, __FILE__, __LINE__,
2227 (int)(Woffset+(Grow_incr-(Buffer-ptr))), 'w',
2232 return 0; /* all is well */
2235 else if ( Pattern == PATTERN_OFFSET )
2236 ret=datapidchk(STATIC_NUM, Buffer, Grow_incr, Woffset, &errmsg);
2237 else if ( Pattern == PATTERN_PID )
2238 ret=datapidchk(Pid, Buffer, Grow_incr, Woffset, &errmsg);
2239 else if ( Pattern == PATTERN_ASCII )
2240 ret=dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2241 else if ( Pattern == PATTERN_RANDOM )
2242 ; /* no check for random */
2243 else if ( Pattern == PATTERN_ALT )
2244 ret=databinchk('a', Buffer, Grow_incr, Woffset, &errmsg);
2245 else if ( Pattern == PATTERN_CHKER )
2246 ret=databinchk('c', Buffer, Grow_incr, Woffset, &errmsg);
2247 else if ( Pattern == PATTERN_CNTING )
2248 ret=databinchk('C', Buffer, Grow_incr, Woffset, &errmsg);
2249 else if ( Pattern == PATTERN_ZEROS )
2250 ret=databinchk('z', Buffer, Grow_incr, Woffset, &errmsg);
2251 else if ( Pattern == PATTERN_ONES )
2252 ret=databinchk('o', Buffer, Grow_incr, Woffset, &errmsg);
2254 ret=dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2257 fprintf(stderr, "%s%s: %d %s/%d: %d CW %s in file %s\n",
2258 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2261 printf("%s%s: %d DEBUG1 %s/%d: **fd:%d, lk:%d, offset:%d, sz:%d open flags:%#o %s\n",
2262 Progname, TagName, Pid, __FILE__, __LINE__, fd, lockfile,
2263 Woffset, Grow_incr, Fileinfo.openflags, openflags2symbols(Fileinfo.openflags, ",", 0));
2270 printf("%s: %d DEBUG7 %s/%d: No corruption detected on write validation , offset = %d, size = %d\n",
2271 Progname, Pid, __FILE__, __LINE__, Woffset, Grow_incr);
2273 return 0; /* all is well */
2278 /***********************************************************************
2280 ***********************************************************************/
2282 check_file(fd, cf_inter, filename, no_file_check)
2284 int cf_inter; /* check file interval */
2285 char *filename; /* needed for error messages */
2286 int no_file_check; /* if set, do not do file content check */
2289 static int cf_count = 0;
2299 if ( cf_inter == 0 || (cf_count % cf_inter != 0)) {
2301 printf("%s: %d DEBUG5 %s/%d: No file check - not time, iter=%d, cnt=%d\n",
2302 Progname, Pid, __FILE__, __LINE__, cf_inter, cf_count);
2303 return 0; /* no check done */
2307 * if we can't determine file content, don't bother checking
2309 if ( no_file_check ) {
2311 printf("%s: %d DEBUG5 %s/%d: No file check, lseek grow or random lseeks\n",
2312 Progname, Pid, __FILE__, __LINE__);
2317 * Lock the file. We need to have the file lock before
2318 * the stat and until after the last read to prevent
2319 * a trunc/truncate from "corrupting" our data.
2321 lkfile(fd, LOCK_SH, LKLVL0);
2323 if ((fsize=file_size(fd)) == -1 ) {
2324 lkfile(fd, LOCK_UN, LKLVL0);
2330 printf("%s: %d DEBUG3 %s/%d: No file validation, file size == 0\n",
2331 Progname, Pid, __FILE__, __LINE__);
2333 lkfile(fd, LOCK_UN, LKLVL0);
2338 printf("%s: %d DEBUG3 %s/%d: about to do file validation\n",
2339 Progname, Pid, __FILE__, __LINE__);
2341 if ( fsize > MAX_FC_READ ) {
2343 * read the file in MAX_FC_READ chuncks.
2346 if ((buf=(char *)malloc(MAX_FC_READ)) == NULL ) {
2347 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", Progname, TagName,
2348 __FILE__, __LINE__, MAX_FC_READ, strerror(errno));
2349 lkfile(fd, LOCK_UN, LKLVL0);
2353 lseek(fd, 0, SEEK_SET);
2355 lkfile(fd, LOCK_SH, LKLVL0); /* get lock on file before getting file size */
2358 while (rd_cnt < fsize ) {
2359 if ( fsize - rd_cnt > MAX_FC_READ )
2360 rd_size=MAX_FC_READ;
2362 rd_size=fsize - rd_cnt;
2365 ret=lio_read_buffer(fd, io_type, buf, rd_size,
2366 SIGUSR1, &errmsg,0);
2368 ret=read_buffer(fd, io_type, buf, rd_size, 0, &errmsg);
2371 if (ret != rd_size ) {
2372 fprintf(stderr, "%s%s: %d %s/%d: %d CFa %s\n",
2373 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2375 lkfile(fd, LOCK_UN, LKLVL0);
2379 read(fd, buf, rd_size);
2382 if ( Pattern == PATTERN_OFFSET )
2383 ret=datapidchk(STATIC_NUM, buf, rd_size, rd_cnt, &errmsg);
2384 else if ( Pattern == PATTERN_PID )
2385 ret=datapidchk(Pid, buf, rd_size, rd_cnt, &errmsg);
2386 else if ( Pattern == PATTERN_ASCII )
2387 ret=dataasciichk(NULL, buf, rd_size, rd_cnt, &errmsg);
2388 else if ( Pattern == PATTERN_RANDOM )
2389 ; /* no checks for random */
2390 else if ( Pattern == PATTERN_ALT )
2391 ret=databinchk('a', buf, rd_size, rd_cnt, &errmsg);
2392 else if ( Pattern == PATTERN_CHKER )
2393 ret=databinchk('c', buf, rd_size, rd_cnt, &errmsg);
2394 else if ( Pattern == PATTERN_CNTING )
2395 ret=databinchk('C', buf, rd_size, rd_cnt, &errmsg);
2396 else if ( Pattern == PATTERN_ZEROS )
2397 ret=databinchk('z', buf, rd_size, rd_cnt, &errmsg);
2398 else if ( Pattern == PATTERN_ONES )
2399 ret=databinchk('o', buf, rd_size, rd_cnt, &errmsg);
2401 ret=dataasciichk(NULL, buf, rd_size, rd_cnt, &errmsg);
2406 "%s%s: %d %s/%d: %d CFp %s in file %s\n",
2407 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2410 lkfile(fd, LOCK_UN, LKLVL0);
2416 lkfile(fd, LOCK_UN, LKLVL0);
2423 * Read the whole file in a single read
2425 if((buf=(char *)malloc(fsize)) == NULL ) {
2426 fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n", Progname, TagName,
2427 __FILE__, __LINE__, fsize, strerror(errno));
2432 lseek(fd, 0, SEEK_SET);
2435 read(fd, buf, fsize);
2438 ret=lio_read_buffer(fd, io_type, buf, fsize, SIGUSR1, &errmsg,0);
2440 ret=read_buffer(fd, io_type, buf, fsize, 0, &errmsg);
2443 /* unlock the file as soon as we can */
2444 lkfile(fd, LOCK_UN, LKLVL0);
2447 if ( ret != fsize ) {
2448 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s\n",
2449 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2453 if ( Pattern == PATTERN_OFFSET )
2454 ret=datapidchk(STATIC_NUM, buf, fsize, 0, &errmsg);
2455 else if ( Pattern == PATTERN_PID )
2456 ret=datapidchk(Pid, buf, fsize, 0, &errmsg);
2457 else if ( Pattern == PATTERN_ASCII )
2458 ret=dataasciichk(NULL, buf, fsize, 0, &errmsg);
2459 else if ( Pattern == PATTERN_RANDOM )
2460 ; /* no check for random */
2461 else if ( Pattern == PATTERN_ALT )
2462 ret=databinchk('a', buf, fsize, 0, &errmsg);
2463 else if ( Pattern == PATTERN_CHKER )
2464 ret=databinchk('c', buf, fsize, 0, &errmsg);
2465 else if ( Pattern == PATTERN_CNTING )
2466 ret=databinchk('C', buf, fsize, 0, &errmsg);
2467 else if ( Pattern == PATTERN_ZEROS )
2468 ret=databinchk('z', buf, fsize, 0, &errmsg);
2469 else if ( Pattern == PATTERN_ONES )
2470 ret=databinchk('o', buf, fsize, 0, &errmsg);
2472 ret=dataasciichk(NULL, buf, fsize, 0, &errmsg);
2475 fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s in file %s\n",
2476 Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt, errmsg, filename);
2486 } /* end of check_file */
2488 /***********************************************************************
2490 ***********************************************************************/
2496 if (fstat(fd, &sb) < 0) {
2497 fprintf(stderr, "%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
2498 Progname, TagName, Pid, __FILE__, __LINE__, fd, errno, strerror(errno));
2506 /***********************************************************************
2507 * do file lock/unlock action.
2508 ***********************************************************************/
2510 lkfile(int fd, int operation, int lklevel)
2515 if ( lockfile == lklevel) {
2518 switch (operation) {
2520 printf("%s: %d DEBUG6 %s/%d: Attempting to release lock on fd %d\n",
2521 Progname, Pid, __FILE__, __LINE__, fd);
2525 printf("%s: %d DEBUG6 %s/%d: Attempting to get read/shared lock on fd %d\n",
2526 Progname, Pid, __FILE__, __LINE__, fd);
2530 printf("%s: %d DEBUG6 %s/%d: Attempting to get write/exclusive lock on fd %d\n",
2531 Progname, Pid, __FILE__, __LINE__, fd);
2537 * Attempt to get/release desired lock.
2538 * file_lock will attempt to do action over and over again until
2539 * either an unretryable error or the action is completed.
2542 if ( file_lock(fd, operation, &errmsg) != 0 ) {
2543 printf("%s%s: %d %s/%d: Unable to perform lock operation. %s\n",
2544 Progname, TagName, Pid, __FILE__, __LINE__, errmsg);
2546 /* do we count this as an error? handle_error(); */
2551 switch (operation) {
2553 printf("%s: %d DEBUG3 %s/%d: Released lock on fd %d\n",
2554 Progname, Pid, __FILE__, __LINE__, fd);
2558 printf("%s: %d DEBUG3 %s/%d: Got read/shared lock on fd %d\n",
2559 Progname, Pid, __FILE__, __LINE__, fd);
2563 printf("%s: %d DEBUG3 %s/%d: Got write/exclusive lock on fd %d\n",
2564 Progname, Pid, __FILE__, __LINE__, fd);
2568 printf("%s: %d DEBUG3 %s/%d: Completed action %d on fd %d\n",
2569 Progname, Pid, __FILE__, __LINE__, operation, fd);
2578 /***********************************************************************
2580 ***********************************************************************/
2582 pre_alloc(file, fd, size)
2588 #ifdef XFS_IOC_RESVSP
2589 struct xfs_flock64 f;
2595 /* non-zeroing reservation */
2596 if( xfsctl( file, fd, XFS_IOC_RESVSP, &f ) == -1 ){
2597 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: xfsctl(XFS_IOC_RESVSP) failed: %d %s\n",
2599 __FILE__, __LINE__, errno, strerror(errno));
2609 /* non-zeroing reservation */
2610 if( fcntl( fd, F_RESVSP64, &f ) == -1 ){
2611 fprintf(stderr, "%s%s %s/%d: Unable to pre-alloc space: fcntl(F_RESVSP) failed: %d %s\n",
2613 __FILE__, __LINE__, errno, strerror(errno));