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 * iogen - a tool for generating file/sds io for a doio process
45 #include <sys/param.h>
46 #include <sys/types.h>
48 #include <sys/sysmacros.h>
52 #include <sys/listio.h>
55 #include <sys/statvfs.h>
56 #include <sys/fs/xfs_itable.h>
60 #include <xfs/libxfs.h>
68 #include "str_to_bytes.h"
69 #include "string_to_tokens.h"
70 #include "open_flags.h"
71 #include "random_range.h"
77 #define RAW_IO(_flags_) ((_flags_) & (O_RAW | O_SSD))
79 #define SYSERR strerror(errno)
82 * Structure for retaining test file information
86 char f_path[MAX_FNAME_LENGTH+1]; /* file name (full path) */
87 int f_length; /* length in bytes */
88 int f_iou; /* file iounit */
89 int f_riou; /* file raw iounit (for O_RAW/O_SSD) */
90 int f_dalign; /* direct I/O alignment */
91 int f_nextoff; /* offset of end of last io operation */
92 int f_type; /* file type S_IFREG, etc... */
93 int f_lastoffset; /* offset of last io operation */
94 int f_lastlength; /* length of last io operation */
98 * Simple structure for associating strings with values - useful for converting
99 * cmdline args to internal values, as well as printing internal values in
100 * a human readable form.
110 * Declare cmdline option flags/variables initialized in parse_cmdline()
113 #define OPTS "a:dhf:i:L:m:op:qr:s:t:T:O:N:"
115 int a_opt = 0; /* async io comp. types supplied */
116 int o_opt = 0; /* form overlapping requests */
117 int f_opt = 0; /* test flags */
118 int i_opt = 0; /* iterations - 0 implies infinite */
119 int L_opt = 0; /* listio min-max nstrides & nents */
120 int m_opt = 0; /* offset mode */
121 int O_opt = 0; /* file creation Open flags */
122 int p_opt = 0; /* output pipe - default is stdout */
123 int r_opt = 0; /* specify raw io multiple instead of */
124 /* getting it from the mounted on device. */
125 /* Only applies to regular files. */
126 int s_opt = 0; /* syscalls */
127 int t_opt = 0; /* min transfer size (bytes) */
128 int T_opt = 0; /* max transfer size (bytes) */
129 int q_opt = 0; /* quiet operation on startup */
130 char TagName[40]; /* name of this iogen (see Monster) */
131 struct strmap *Offset_Mode; /* M_SEQUENTIAL, M_RANDOM, etc. */
132 int Iterations; /* # requests to generate (0 --> infinite) */
133 int Time_Mode = 0; /* non-zero if Iterations is in seconds */
134 /* (ie. -i arg was suffixed with 's') */
135 char *Outpipe; /* Pipe to write output to if p_opt */
136 int Mintrans; /* min io transfer size */
137 int Maxtrans; /* max io transfer size */
138 int Rawmult; /* raw/ssd io multiple (from -r) */
139 int Minstrides; /* min # of listio strides per request */
140 int Maxstrides; /* max # of listio strides per request */
141 int Oflags; /* open(2) flags for creating files */
142 int Ocbits; /* open(2) cbits for creating files */
143 int Ocblks; /* open(2) cblks for creating files */
144 int Orealtime=0; /* flag set for -O REALTIME */
145 int Oextsize=0; /* real-time extent size */
146 int Oreserve=1; /* flag for -O [no]reserve */
147 int Oallocate=0; /* flag for -O allocate */
148 int Owrite=1; /* flag for -O nowrite */
150 int Nfiles = 0; /* # files on cmdline */
151 struct file_info *File_List; /* info about each file */
152 int Nflags = 0; /* # flags on cmdline */
153 struct strmap *Flag_List[128]; /* flags selected from cmdline */
154 int Nsyscalls = 0; /* # syscalls on cmdline */
155 struct strmap *Syscall_List[128]; /* syscalls selected on cmdline */
156 int Fileio = 0; /* flag indicating that a file */
157 /* io syscall has been chosen. */
158 int Naio_Strat_Types = 0; /* # async io completion types */
159 struct strmap *Aio_Strat_List[128]; /* Async io completion types */
164 * Map async io completion modes (-a args) names to values. Macros are
168 struct strmap Aio_Strat_Map[] = {
171 { "signal", A_SIGNAL },
176 #if _UMK || RELEASE_LEVEL >= 8000
177 { "recall", A_RECALL },
181 { "recalla", A_RECALLA },
183 { "recalls", A_RECALLS },
187 { "suspend", A_SUSPEND },
188 { "callback", A_CALLBACK },
194 * Offset_Mode #defines
198 #define M_SEQUENTIAL 2
202 * Map offset mode (-m args) names to values
205 struct strmap Omode_Map[] = {
206 { "random", M_RANDOM },
207 { "sequential", M_SEQUENTIAL },
208 { "reverse", M_REVERSE },
213 * Map syscall names (-s args) to values - macros are defined in doio.h.
215 #define SY_ASYNC 00001
216 #define SY_WRITE 00002
218 #define SY_LISTIO 00020
219 #define SY_NENT 00100 /* multi entry vs multi stride >>> */
221 struct strmap Syscall_Map[] = {
223 { "write", WRITE, SY_WRITE },
225 { "reada", READA, SY_ASYNC },
226 { "writea", WRITEA, SY_WRITE|SY_ASYNC },
228 { "ssread", SSREAD, SY_SDS },
229 { "sswrite", SSWRITE, SY_WRITE|SY_SDS },
231 { "listio", LISTIO, SY_ASYNC },
233 /* listio as 4 system calls */
234 { "lread", LREAD, 0 },
235 { "lreada", LREADA, SY_ASYNC },
236 { "lwrite", LWRITE, SY_WRITE },
237 { "lwritea", LWRITEA, SY_WRITE|SY_ASYNC },
239 /* listio with nstrides > 1 */
240 { "lsread", LSREAD, 0 },
241 { "lsreada", LSREADA, SY_ASYNC },
242 { "lswrite", LSWRITE, SY_WRITE },
243 { "lswritea", LSWRITEA, SY_WRITE|SY_ASYNC },
245 /* listio with nents > 1 */
246 { "leread", LEREAD, 0|SY_NENT },
247 { "lereada", LEREADA, SY_ASYNC|SY_NENT },
248 { "lewrite", LEWRITE, SY_WRITE|SY_NENT },
249 { "lewritea", LEWRITEA, SY_WRITE|SY_ASYNC|SY_NENT },
251 /* listio with nents > 1 & nstrides > 1 */
253 /* all listio system calls under one name */
254 { "listio+", LREAD, 0 },
255 { "listio+", LREADA, SY_ASYNC },
256 { "listio+", LWRITE, SY_WRITE },
257 { "listio+", LWRITEA, SY_WRITE|SY_ASYNC },
258 { "listio+", LSREAD, 0 },
259 { "listio+", LSREADA, SY_ASYNC },
260 { "listio+", LSWRITE, SY_WRITE },
261 { "listio+", LSWRITEA, SY_WRITE|SY_ASYNC },
262 { "listio+", LEREAD, 0|SY_NENT },
263 { "listio+", LEREADA, SY_ASYNC|SY_NENT },
264 { "listio+", LEWRITE, SY_WRITE|SY_NENT },
265 { "listio+", LEWRITEA, SY_WRITE|SY_ASYNC|SY_NENT },
269 { "pwrite", PWRITE, SY_WRITE },
271 { "aread", AREAD, SY_ASYNC },
272 { "awrite", AWRITE, SY_WRITE|SY_ASYNC },
274 /* not written yet */
275 { "llread", LLREAD, 0 },
276 { "llaread", LLAREAD, SY_ASYNC },
277 { "llwrite", LLWRITE, 0 },
278 { "llawrite", LLAWRITE, SY_ASYNC },
280 { "ffsync", DFFSYNC, SY_WRITE },
283 { "resvsp", RESVSP, SY_WRITE },
284 { "unresvsp", UNRESVSP, SY_WRITE },
285 { "reserve", RESVSP, SY_WRITE },
286 { "unreserve", UNRESVSP, SY_WRITE },
291 { "writev", WRITEV, SY_WRITE },
293 { "mmwrite", MMAPW, SY_WRITE },
294 { "fsync2", FSYNC2, SY_WRITE },
295 { "fdatasync", FDATASYNC, SY_WRITE },
302 * Map open flags (-f args) to values
304 #define FLG_RAW 00001
306 struct strmap Flag_Map[] = {
307 { "buffered", 0, 0 },
308 { "sync", O_SYNC, 0 },
310 { "raw", O_RAW, FLG_RAW },
311 { "raw+wf", O_RAW | O_WELLFORMED, FLG_RAW },
312 { "raw+wf+ldraw", O_RAW | O_WELLFORMED | O_LDRAW, FLG_RAW },
313 { "raw+wf+ldraw+sync", O_RAW | O_WELLFORMED | O_LDRAW | O_SYNC, FLG_RAW },
315 { "ssd", O_SSD, FLG_RAW },
318 { "ldraw", O_LDRAW, 0 },
321 { "parallel", O_PARALLEL | O_RAW | O_WELLFORMED,
323 { "parallel+sync", O_PARALLEL | O_RAW | O_WELLFORMED | O_SYNC,
325 { "parallel+ldraw", O_PARALLEL | O_RAW | O_WELLFORMED | O_LDRAW,
327 { "parallel+ldraw+sync",
328 O_PARALLEL | O_RAW | O_WELLFORMED | O_LDRAW | O_SYNC,
333 { "direct", O_DIRECT, FLG_RAW },
335 { "dsync", O_DSYNC }, /* affects writes */
336 { "rsync", O_RSYNC }, /* affects reads */
337 { "rsync+dsync", O_RSYNC|O_DSYNC },
343 * Map file types to strings
346 struct strmap Ftype_Map[] = {
347 { "regular", S_IFREG },
348 { "blk-spec", S_IFBLK },
349 { "chr-spec", S_IFCHR },
359 char Byte_Patterns[26] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
360 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
361 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
365 int form_iorequest(struct io_req *);
367 int parse_cmdline(int argc, char **argv, char *opts);
368 int help(FILE *stream);
369 int usage(FILE *stream);
377 int rseed, outfd, infinite;
384 Sds_Avail = sysconf(_SC_CRAY_SDS);
390 parse_cmdline(argc, argv, OPTS);
393 * Initialize output descriptor.
398 outfd = init_output();
402 random_range_seed(rseed); /* initialize random number generator */
405 * Print out startup information, unless we're running in quiet mode
408 startup_info(stderr, rseed);
410 start_time = time(0);
413 * While iterations (or forever if Iterations == 0) - compute an
414 * io request, and write the structure to the output descriptor
417 infinite = !Iterations;
420 (! Time_Mode && Iterations--) ||
421 (Time_Mode && time(0) - start_time <= Iterations)) {
423 memset(&req, 0, sizeof(struct io_req));
424 if (form_iorequest(&req) == -1) {
425 fprintf(stderr, "iogen%s: form_iorequest() failed\n", TagName);
429 req.r_magic = DOIO_MAGIC;
430 write(outfd, (char *)&req, sizeof(req));
438 startup_info(FILE *stream, int seed)
440 char *value_to_string(), *type;
443 fprintf(stream, "\n");
444 fprintf(stream, "iogen%s starting up with the following:\n", TagName);
445 fprintf(stream, "\n");
447 fprintf(stream, "Out-pipe: %s\n",
448 p_opt ? Outpipe : "stdout");
451 fprintf(stream, "Iterations: %d", Iterations);
453 fprintf(stream, " seconds");
455 fprintf(stream, "\n");
457 fprintf(stream, "Iterations: Infinite\n");
464 "Offset-Mode: %s\n", Offset_Mode->m_string);
466 fprintf(stream, "Overlap Flag: %s\n",
467 o_opt ? "on" : "off");
470 "Mintrans: %-11d (%d blocks)\n",
471 Mintrans, (Mintrans+BSIZE-1)/BSIZE);
474 "Maxtrans: %-11d (%d blocks)\n",
475 Maxtrans, (Maxtrans+BSIZE-1)/BSIZE);
479 "O_RAW/O_SSD Multiple: (Determined by device)\n");
482 "O_RAW/O_SSD Multiple: %-11d (%d blocks)\n",
483 Rawmult, (Rawmult+BSIZE-1)/BSIZE);
485 fprintf(stream, "Syscalls: ");
486 for (i = 0; i < Nsyscalls; i++)
488 "%s ", Syscall_List[i]->m_string);
489 fprintf(stream, "\n");
491 fprintf(stream, "Aio completion types: ");
492 for (i = 0; i < Naio_Strat_Types; i++)
494 "%s ", Aio_Strat_List[i]->m_string);
495 fprintf(stream, "\n");
498 fprintf(stream, "Flags: ");
499 for (i = 0; i < Nflags; i++)
501 "%s ", Flag_List[i]->m_string);
503 fprintf(stream, "\n");
504 fprintf(stream, "\n");
505 fprintf(stream, "Test Files: \n");
506 fprintf(stream, "\n");
508 "Path Length iou raw iou file\n");
510 " (bytes) (bytes) (bytes) type\n");
512 "-----------------------------------------------------------------------------\n");
514 for (i = 0; i < Nfiles; i++) {
515 type = value_to_string(Ftype_Map, File_List[i].f_type);
516 fprintf(stream, "%-40s %12d %7d %7d %s\n",
517 File_List[i].f_path, File_List[i].f_length,
518 File_List[i].f_iou, File_List[i].f_riou, type);
524 * Initialize output descriptor. If going to stdout, its easy,
525 * otherwise, attempt to create a FIFO on path Outpipe. Exit with an
526 * error code if this cannot be done.
534 if (stat(Outpipe, &sbuf) == -1) {
535 if (errno == ENOENT) {
536 if (mkfifo(Outpipe, 0666) == -1) {
537 fprintf(stderr, "iogen%s: Could not mkfifo %s: %s\n",
538 TagName, Outpipe, SYSERR);
542 fprintf(stderr, "iogen%s: Could not stat outpipe %s: %s\n",
543 TagName, Outpipe, SYSERR);
547 if (! S_ISFIFO(sbuf.st_mode)) {
549 "iogen%s: Output file %s exists, but is not a FIFO\n",
555 if ((outfd = open(Outpipe, O_RDWR)) == -1) {
557 "iogen%s: Couldn't open outpipe %s with flags O_RDWR: %s\n",
558 TagName, Outpipe, SYSERR);
567 * Main io generation function. form_iorequest() selects a system call to
568 * do based on cmdline arguments, and proceeds to select parameters for that
571 * Returns 0 if req is filled in with a complete doio request, otherwise
579 int mult, offset = 0, length = 0, slength;
580 int minlength, maxlength, laststart, lastend;
581 int minoffset, maxoffset;
582 int maxstride, nstrides;
584 struct strmap *flags, *sc, *aio_strat;
585 struct file_info *fptr;
591 * Choose system call, flags, and file
594 sc = Syscall_List[random_range(0, Nsyscalls-1, 1, NULL)];
595 req->r_type = sc->m_value;
598 if (sc->m_value == LISTIO ) {
599 opcode = random_range(0, 1, 1, NULL) ? LO_READ : LO_WRITE;
600 cmd = random_range(0, 1, 1, NULL) ? LC_START : LC_WAIT;
604 if( sc->m_flags & SY_WRITE )
605 pattern = Byte_Patterns[random_range(0, sizeof(Byte_Patterns) - 1, 1, NULL)];
611 * If sds io, simply choose a length (possibly pattern) and return
614 if (sc->m_flags & SY_SDS ) {
615 req->r_data.ssread.r_nbytes = random_range(Mintrans, Maxtrans, BSIZE, NULL);
616 if (sc->m_flags & SY_WRITE)
617 req->r_data.sswrite.r_pattern = pattern;
624 * otherwise, we're doing file io. Choose starting offset, length,
625 * open flags, and possibly a pattern (for write/writea).
628 fptr = &File_List[random_range(0, Nfiles-1, 1, NULL)];
629 flags = Flag_List[random_range(0, Nflags-1, 1, NULL)];
632 * Choose offset/length multiple. IO going to a device, or regular
633 * IO that is O_RAW or O_SSD must be aligned on the file r_iou. Otherwise
634 * it must be aligned on the regular iou (normally 1).
637 if ( fptr->f_type == S_IFREG && (flags->m_flags & FLG_RAW) )
643 * Choose offset and length. Both must be a multiple of mult
647 * Choose length first - it must be a multiple of mult
650 laststart = fptr->f_lastoffset;
651 lastend = fptr->f_lastoffset + fptr->f_lastlength - 1;
653 minlength = (Mintrans > mult) ? Mintrans : mult;
655 switch (Offset_Mode->m_value) {
657 if (o_opt && lastend > laststart)
658 offset = random_range(laststart, lastend, 1, NULL);
660 offset = lastend + 1;
661 if (offset && (offset%mult))
662 offset += mult - (offset % mult);
664 if (minlength > fptr->f_length - offset)
667 maxlength = fptr->f_length - offset;
668 if (maxlength > Maxtrans)
669 maxlength = Maxtrans;
671 length = random_range(minlength, maxlength, mult, &errp);
673 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
674 TagName, minlength, maxlength, mult);
681 maxlength = laststart;
683 if (maxlength > Maxtrans)
684 maxlength = Maxtrans;
686 if (minlength > maxlength) {
687 laststart = fptr->f_length;
688 lastend = fptr->f_length;
689 maxlength = Maxtrans;
692 length = random_range(minlength, maxlength, mult, &errp);
694 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
695 TagName, minlength, maxlength, mult);
699 offset = laststart - length;
701 if (o_opt && lastend > laststart)
702 offset += random_range(1, lastend - laststart, 1, NULL);
704 if (offset && (offset%mult))
705 offset -= offset % mult;
710 length = random_range(Mintrans, Maxtrans, mult, NULL);
712 if (o_opt && lastend > laststart) {
713 minoffset = laststart - length + 1;
718 if (lastend + length > fptr->f_length) {
719 maxoffset = fptr->f_length - length;
725 maxoffset = fptr->f_length - length;
731 offset = random_range(minoffset, maxoffset, mult, &errp);
733 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
734 TagName, minoffset, maxoffset, mult);
739 fptr->f_lastoffset = offset;
740 fptr->f_lastlength = length;
743 * Choose an async io completion strategy if necessary
745 if( sc->m_flags & SY_ASYNC )
746 aio_strat = Aio_Strat_List[random_range(0, Naio_Strat_Types - 1,
752 * fill in specific syscall record data
754 switch (sc->m_value) {
757 strcpy(req->r_data.read.r_file, fptr->f_path);
758 req->r_data.read.r_oflags = O_RDONLY | flags->m_value;
759 req->r_data.read.r_offset = offset;
760 req->r_data.read.r_nbytes = length;
761 req->r_data.read.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
762 req->r_data.read.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
763 req->r_data.read.r_nstrides = 1;
764 req->r_data.read.r_nent = 1;
769 strcpy(req->r_data.write.r_file, fptr->f_path);
770 req->r_data.write.r_oflags = O_WRONLY | flags->m_value;
771 req->r_data.write.r_offset = offset;
772 req->r_data.write.r_nbytes = length;
773 req->r_data.write.r_pattern = pattern;
774 req->r_data.write.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
775 req->r_data.write.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
776 req->r_data.write.r_nstrides = 1;
777 req->r_data.write.r_nent = 1;
797 strcpy(req->r_data.io.r_file, fptr->f_path);
798 req->r_data.io.r_oflags = ((sc->m_flags & SY_WRITE) ? O_WRONLY : O_RDONLY) | flags->m_value;
799 req->r_data.io.r_offset = offset;
800 req->r_data.io.r_nbytes = length;
801 req->r_data.io.r_pattern = pattern;
802 req->r_data.io.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
803 req->r_data.io.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
804 req->r_data.io.r_nstrides = 1;
805 req->r_data.io.r_nent = 1;
810 strcpy(req->r_data.io.r_file, fptr->f_path);
811 /* a subtle "feature" of mmap: a write-map requires
812 the file open read/write */
813 req->r_data.io.r_oflags = ((sc->m_flags & SY_WRITE) ? O_RDWR : O_RDONLY) | flags->m_value;
814 req->r_data.io.r_offset = offset;
815 req->r_data.io.r_nbytes = length;
816 req->r_data.io.r_pattern = pattern;
817 req->r_data.io.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
818 req->r_data.io.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
819 req->r_data.io.r_nstrides = 1;
820 req->r_data.io.r_nent = 1;
832 strcpy(req->r_data.io.r_file, fptr->f_path);
833 req->r_data.io.r_oflags = ((sc->m_flags & SY_WRITE) ? O_WRONLY : O_RDONLY) | flags->m_value;
834 req->r_data.io.r_offset = offset;
835 req->r_data.io.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
836 req->r_data.io.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
837 req->r_data.io.r_pattern = pattern;
839 /* multi-strided request...
840 * random number of strides (1...MaxStrides)
841 * length of stride must be > minlength
842 * length of stride must be % mult
844 * maxstrides = min(length / mult, overall.max#strides)
845 * nstrides = random #
846 * while( length / nstrides < minlength )
847 * nstrides = new random #
849 maxstride = length / mult;
850 if(maxstride > Maxstrides)
851 maxstride = Maxstrides;
855 nstrides = random_range(Minstrides, maxstride, 1, &errp);
857 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
858 TagName, Minstrides, maxstride, 1);
862 slength = length / nstrides;
863 if(slength % mult != 0) {
864 if( mult > slength) {
867 slength -= slength % mult;
869 nstrides = length / slength;
870 if(nstrides > Maxstrides)
871 nstrides = Maxstrides;
874 req->r_data.io.r_nbytes = slength;
875 if( sc->m_flags & SY_NENT ) {
876 req->r_data.io.r_nstrides = 1;
877 req->r_data.io.r_nent = nstrides;
879 req->r_data.io.r_nstrides = nstrides;
880 req->r_data.io.r_nent = 1;
886 strcpy(req->r_data.listio.r_file, fptr->f_path);
887 req->r_data.listio.r_offset = offset;
888 req->r_data.listio.r_cmd = cmd;
889 req->r_data.listio.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
890 req->r_data.listio.r_filestride = 0;
891 req->r_data.listio.r_memstride = 0;
892 req->r_data.listio.r_opcode = opcode;
893 req->r_data.listio.r_nstrides = 1;
894 req->r_data.listio.r_nbytes = length;
895 req->r_data.listio.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
897 if (opcode == LO_WRITE) {
898 req->r_data.listio.r_pattern = pattern;
899 req->r_data.listio.r_oflags = O_WRONLY | flags->m_value;
901 req->r_data.listio.r_oflags = O_RDONLY | flags->m_value;
911 * Get information about a file that iogen uses to choose io length and
912 * offset. Information gathered is file length, iounit, and raw iounit.
913 * For regurlar files, iounit is 1, and raw iounit is the iounit of the
914 * device on which the file resides. For block/character special files
915 * the iounit and raw iounit are both the iounit of the device.
917 * Note: buffered and osync io must be iounit aligned
918 * raw and ossd io must be raw iounit aligned
923 struct file_info *rec;
927 struct lk_device_info dinfo;
931 struct dioattr finfo;
935 * Figure out if the files is regular, block or character special. Any
936 * other type is an error.
939 if (stat(rec->f_path, &sbuf) == -1) {
940 fprintf(stderr, "iogen%s: get_file_info(): Could not stat() %s: %s\n",
941 TagName, rec->f_path, SYSERR);
946 if ((! S_ISREG(sbuf.st_mode)) || strncmp(rec->f_path, "/dev/", 5) == 0) {
947 fprintf(stderr, "iogen%s: device level io not supported on cray2\n", TagName);
952 rec->f_type = sbuf.st_mode & S_IFMT;
955 * If regular, iou is 1, and we must figure out the device on
956 * which the file resides. riou is the iou (logical sector size) of
960 if (S_ISREG(sbuf.st_mode)) {
962 rec->f_length = sbuf.st_size;
965 * If -r used, take Rawmult as the raw/ssd io multiple. Otherwise
966 * attempt to determine it by looking at the device the file
971 rec->f_riou = Rawmult;
977 if (lk_rawdev(rec->f_path, dinfo.path, sizeof(dinfo.path), 0) == -1)
980 if (lk_devinfo(&dinfo, 0) == -1) {
981 /* can't get raw I/O unit -- use stat to fudge it */
982 rec->f_riou = sbuf.st_blksize;
984 rec->f_riou = ctob(dinfo.iou);
988 if( (fd = open(rec->f_path, O_RDWR|O_DIRECT, 0)) != -1 ) {
989 if(xfsctl(rec->f_path, fd, XFS_IOC_DIOINFO, &finfo) != -1) {
990 rec->f_riou = finfo.d_miniosz;
993 "iogen%s: Error %s (%d) getting direct I/O info of file %s\n",
994 TagName, strerror(errno), errno, rec->f_path);
998 rec->f_riou = BBSIZE;
1006 * Otherwise, file is a device. Use lk_devinfo() to get its logical
1007 * sector size. This is the iou and riou
1010 strcpy(dinfo.path, rec->f_path);
1012 if (lk_devinfo(&dinfo, 0) == -1) {
1013 fprintf(stderr, "iogen%s: %s: %s\n", TagName, Lk_err_func, Lk_err_mesg);
1017 rec->f_iou = ctob(dinfo.iou);
1018 rec->f_riou = ctob(dinfo.iou);
1019 rec->f_length = ctob(dinfo.length);
1022 rec->f_riou = BBSIZE;
1023 rec->f_length = BBSIZE;
1025 rec->f_riou = BSIZE;
1026 rec->f_length = BSIZE;
1035 * Create file path as nbytes long. If path exists, the file will either be
1036 * extended or truncated to be nbytes long. Returns final size of file,
1037 * or -1 if there was a failure.
1041 create_file(path, nbytes)
1050 struct xfs_flock64 f;
1051 struct fsxattr xattr;
1052 struct dioattr finfo;
1057 rval = stat(path, &sbuf);
1060 if (errno == ENOENT) {
1063 fprintf(stderr, "iogen%s: Could not stat file %s: %s (%d)\n",
1064 TagName, path, SYSERR, errno);
1068 if (! S_ISREG(sbuf.st_mode)) {
1070 "iogen%s: file %s exists, but is not a regular file - cannot modify length\n",
1076 if (sbuf.st_size == nbytes)
1079 Oflags |= O_CREAT | O_WRONLY;
1081 if ((fd = open(path, Oflags, 0666, Ocbits, Ocblks)) == -1) {
1082 fprintf(stderr, "iogen%s: Could not create/open file %s: %s (%d)\n",
1083 TagName, path, SYSERR, errno);
1088 * Truncate file if it is longer than nbytes, otherwise attempt to
1089 * pre-allocate file blocks.
1092 if (sbuf.st_size > nbytes) {
1093 if (ftruncate(fd, nbytes) == -1) {
1095 "iogen%s: Could not ftruncate() %s to %d bytes: %s (%d)\n",
1096 TagName, path, nbytes, SYSERR, errno);
1104 * The file must be designated as Real-Time before any data
1105 * is allocated to it.
1108 if(Orealtime != 0) {
1109 bzero(&xattr, sizeof(xattr));
1110 xattr.fsx_xflags = XFS_XFLAG_REALTIME;
1111 /*fprintf(stderr, "set: fsx_xflags = 0x%x\n", xattr.fsx_xflags);*/
1112 if( xfsctl(path, fd, XFS_IOC_FSSETXATTR, &xattr) == -1 ) {
1113 fprintf(stderr, "iogen%s: Error %s (%d) setting XFS XATTR->Realtime on file %s\n",
1114 TagName, SYSERR, errno, path);
1120 if( xfsctl(path, fd, XFS_IOC_FSGETXATTR, &xattr) == -1 ) {
1121 fprintf(stderr, "iogen%s: Error getting realtime flag %s (%d)\n",
1122 TagName, SYSERR, errno);
1126 fprintf(stderr, "get: fsx_xflags = 0x%x\n",
1135 * Failure is ignored since XFS_IOC_RESVSP only works on XFS and the
1136 * filesystem could be on some otehr filesystem.
1139 f.l_whence = SEEK_SET;
1144 "create_file: xfsctl(%d, RESVSP, { %d, %lld, %lld })\n",
1145 fd, f.l_whence, (long long)f.l_start, (long long)f.l_len);*/
1147 /* non-zeroing reservation */
1148 if( xfsctl( path, fd, XFS_IOC_RESVSP, &f ) == -1) {
1150 "iogen%s: Could not xfsctl(XFS_IOC_RESVSP) %d bytes in file %s: %s (%d)\n",
1151 TagName, nbytes, path, SYSERR, errno);
1158 /* XFS_IOC_ALLOCSP allocates from the file start to l_start */
1159 f.l_whence = SEEK_SET;
1163 "create_file: xfsctl(%d, XFS_IOC_ALLOCSP, { %d, %lld, %lld })\n",
1164 fd, f.l_whence, (long long)f.l_start,
1165 (long long)f.l_len);*/
1167 /* zeroing reservation */
1168 if( xfsctl( path, fd, XFS_IOC_ALLOCSP, &f ) == -1) {
1170 "iogen%s: Could not xfsctl(XFS_IOC_ALLOCSP) %d bytes in file %s: %s (%d)\n",
1171 TagName, nbytes, path, SYSERR, errno);
1179 * Write a byte at the end of file so that stat() sets the right
1186 if( (fd = open(path, O_CREAT|O_RDWR|O_DIRECT, 0)) != -1 ) {
1187 if(xfsctl(path, fd, XFS_IOC_DIOINFO, &finfo) == -1) {
1189 "iogen%s: Error %s (%d) getting direct I/O info for file %s\n",
1190 TagName, SYSERR, errno, path);
1193 /*fprintf(stderr, "%s: miniosz=%d\n",
1194 path, finfo.d_miniosz);*/
1197 fprintf(stderr, "iogen%s: Error %s (%d) opening file %s with flags O_CREAT|O_RDWR|O_DIRECT\n",
1198 TagName, SYSERR, errno, path);
1203 * nb is nbytes adjusted down by an even d_miniosz block
1205 * Note: the first adjustment can cause iogen to print a warning
1206 * about not being able to create a file of <nbytes> length,
1207 * since the file will be shorter.
1209 nb = nbytes-finfo.d_miniosz;
1210 nb = nb-nb%finfo.d_miniosz;
1213 "create_file_ow2: lseek(%d, %d {%d %d}, SEEK_SET)\n",
1214 fd, nb, nbytes, finfo.d_miniosz);*/
1216 if (lseek(fd, nb, SEEK_SET) == -1) {
1218 "iogen%s: Could not lseek() to EOF of file %s: %s (%d)\n\tactual offset %d file size goal %d miniosz %lld\n",
1219 TagName, path, SYSERR, errno,
1220 nb, nbytes, (long long)finfo.d_miniosz);
1225 b = buf = (char *)malloc(finfo.d_miniosz+finfo.d_mem);
1227 if( ((long)buf % finfo.d_mem != 0) ) {
1228 buf += finfo.d_mem - ((long)buf % finfo.d_mem);
1231 memset(buf, 0, finfo.d_miniosz);
1233 if ( (rval=write(fd, buf, finfo.d_miniosz)) != finfo.d_miniosz) {
1235 "iogen%s: Could not write %d byte length file %s: %s (%d)\n",
1236 TagName, nb, path, SYSERR, errno);
1238 "\twrite(%d, 0x%lx, %d) = %d\n",
1239 fd, (long)buf, finfo.d_miniosz, rval);
1241 "\toffset %d file size goal %d, miniosz=%d\n",
1242 nb, nbytes, finfo.d_miniosz);
1251 "create_file_Owrite: lseek(%d, %d {%d}, SEEK_SET)\n",
1252 fd, nbytes-1, nbytes);*/
1254 if (lseek(fd, nbytes-1, SEEK_SET) == -1) {
1256 "iogen%s: Could not lseek() to EOF in file %s: %s (%d)\n\toffset goal %d\n",
1257 TagName, path, SYSERR, errno,
1263 if ( (rval=write(fd, &c, 1)) != 1) {
1265 "iogen%s: Could not create a %d byte length file %s: %s (%d)\n",
1266 TagName, nbytes, path, SYSERR, errno);
1268 "\twrite(%d, 0x%lx, %d) = %d\n",
1269 fd, (long)&c, 1, rval);
1271 "\toffset %d file size goal %d\n",
1282 return sbuf.st_size;
1286 * Function to convert a string to its corresponding value in a strmap array.
1287 * If the string is not found in the array, the value corresponding to the
1288 * NULL string (the last element in the array) is returned.
1292 str_to_value(map, str)
1298 for (mp = map; mp->m_string != NULL; mp++)
1299 if (strcmp(mp->m_string, str) == 0)
1306 * Function to convert a string to its corresponding entry in a strmap array.
1307 * If the string is not found in the array, a NULL is returned.
1311 str_lookup(map, str)
1317 for (mp = map; mp->m_string != NULL; mp++)
1318 if (strcmp(mp->m_string, str) == 0)
1321 return((mp->m_string == NULL) ? NULL : mp);
1326 * Function to convert a value to its corresponding string in a strmap array.
1327 * If the value is not found in the array, NULL is returned.
1331 value_to_string(map, val)
1337 for (mp = map; mp->m_string != NULL; mp++)
1338 if (mp->m_value == val)
1341 return mp->m_string;
1345 * Interpret cmdline options/arguments. Exit with 1 if something on the
1346 * cmdline isn't kosher.
1350 parse_cmdline(argc, argv, opts)
1355 int o, len, nb, format_error;
1356 struct strmap *flgs, *sc;
1357 char *file, *cp, ch;
1359 struct file_info *fptr;
1361 char *openargs[5]; /* Flags, cbits, cblks */
1365 struct strmap *type;
1368 while ((o = getopt(argc, argv, opts)) != EOF) {
1373 fprintf(stderr, "iogen%s: Unrecognized option -a on this platform\n", TagName);
1376 cp = strtok(optarg, ",");
1377 while (cp != NULL) {
1378 if ((type = str_lookup(Aio_Strat_Map, cp)) == NULL) {
1379 fprintf(stderr, "iogen%s: Unrecognized aio completion strategy: %s\n", TagName, cp);
1383 Aio_Strat_List[Naio_Strat_Types++] = type;
1384 cp = strtok(NULL, ",");
1391 cp = strtok(optarg, ",");
1392 while (cp != NULL) {
1393 if( (flgs = str_lookup(Flag_Map, cp)) == NULL ) {
1394 fprintf(stderr, "iogen%s: Unrecognized flags: %s\n", TagName, cp);
1398 cp = strtok(NULL, ",");
1401 if (flgs->m_value & O_SSD && ! Sds_Avail) {
1402 fprintf(stderr, "iogen%s: Warning - no sds available, ignoring ssd flag\n", TagName);
1407 Flag_List[Nflags++] = flgs;
1420 switch (sscanf(optarg, "%i%c", &Iterations, &ch)) {
1440 fprintf(stderr, "iogen%s: Illegal -i arg (%s): Must be of the format: number[s]\n", TagName, optarg);
1441 fprintf(stderr, " where 'number' is >= 0\n");
1450 fprintf(stderr, "iogen%s: Unrecognized option -L on this platform\n", TagName);
1453 if( parse_ranges(optarg, 1, 255, 1, NULL, &ranges,
1455 fprintf(stderr, "iogen%s: error parsing listio range '%s': %s\n",
1456 TagName, optarg, errmsg);
1460 Minstrides = range_min(ranges, 0);
1461 Maxstrides = range_max(ranges, 0);
1469 if ((Offset_Mode = str_lookup(Omode_Map, optarg)) == NULL) {
1470 fprintf(stderr, "iogen%s: Illegal -m arg (%s)\n", TagName, optarg);
1478 sprintf( TagName, "(%.39s)", optarg );
1487 nopenargs = string_to_tokens(optarg, openargs, 4, ":/");
1491 sscanf(openargs[1],"%i", &Ocbits);
1493 sscanf(openargs[2],"%i", &Ocblks);
1495 Oflags = parse_open_flags(openargs[0], &errmsg);
1497 fprintf(stderr, "iogen%s: -O %s error: %s\n", TagName, optarg, errmsg);
1502 if(!strcmp(openargs[0], "realtime")) {
1504 * -O realtime:extsize
1508 sscanf(openargs[1],"%i", &Oextsize);
1511 } else if( !strcmp(openargs[0], "allocate") ||
1512 !strcmp(openargs[0], "allocsp")) {
1518 } else if(!strcmp(openargs[0], "reserve")) {
1524 } else if(!strcmp(openargs[0], "noreserve")) {
1525 /* Oreserve=1 by default; this clears that default */
1527 } else if(!strcmp(openargs[0], "nowrite")) {
1528 /* Owrite=1 by default; this clears that default */
1530 } else if(!strcmp(openargs[0], "direct")) {
1531 /* this means "use direct i/o to preallocate file" */
1534 fprintf(stderr, "iogen%s: Error: -O %s error: unrecognized option\n",
1535 TagName, openargs[0]);
1539 Oflags = parse_open_flags(openargs[0], &errmsg);
1541 fprintf(stderr, "iogen%s: -O %s error: %s\n", TagName, optarg, errmsg);
1555 if ((Rawmult = str_to_bytes(optarg)) == -1 ||
1556 Rawmult < 11 || Rawmult % BSIZE) {
1557 fprintf(stderr, "iogen%s: Illegal -r arg (%s). Must be > 0 and multipe of BSIZE (%d)\n",
1558 TagName, optarg, BSIZE);
1566 cp = strtok(optarg, ",");
1567 while (cp != NULL) {
1568 if ((sc = str_lookup(Syscall_Map, cp)) == NULL) {
1569 fprintf(stderr, "iogen%s: Unrecognized syscall: %s\n", TagName, cp);
1574 /* >>> sc->m_flags & FLG_SDS */
1575 if (sc->m_value != SSREAD && sc->m_value != SSWRITE)
1578 Syscall_List[Nsyscalls++] = sc;
1579 } while ( (sc = str_lookup(++sc, cp)) != NULL);
1581 cp = strtok(NULL, ",");
1587 if ((Mintrans = str_to_bytes(optarg)) == -1) {
1588 fprintf(stderr, "iogen%s: Illegal -t arg (%s): Must have the form num[bkm]\n", TagName, optarg);
1595 if ((Maxtrans = str_to_bytes(optarg)) == -1) {
1596 fprintf(stderr, "iogen%s: Illegal -T arg (%s): Must have the form num[bkm]\n", TagName, optarg);
1622 Offset_Mode = str_lookup(Omode_Map, "sequential");
1631 Maxtrans = 256 * BSIZE;
1634 Oflags = Ocbits = Ocblks = 0;
1637 * Supply default async io completion strategy types.
1641 for (mp = Aio_Strat_Map; mp->m_string != NULL; mp++) {
1642 Aio_Strat_List[Naio_Strat_Types++] = mp;
1647 * Supply default syscalls. Default is read,write,reada,writea,listio.
1652 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "read");
1653 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "write");
1655 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "reada");
1656 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "writea");
1657 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lread");
1658 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lreada");
1659 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lwrite");
1660 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lwritea");
1663 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "pread");
1664 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "pwrite");
1666 /*Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "aread");*/
1667 /*Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "awrite");*/
1671 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "readv");
1672 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "writev");
1673 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "mmread");
1674 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "mmwrite");
1680 if (Fileio && (argc - optind < 1)) {
1681 fprintf(stderr, "iogen%s: No files specified on the cmdline\n", TagName);
1686 * Supply default file io flags - defaut is 'buffered,raw,sync,ldraw'.
1689 if (! f_opt && Fileio) {
1691 Flag_List[Nflags++] = str_lookup(Flag_Map, "buffered");
1692 Flag_List[Nflags++] = str_lookup(Flag_Map, "sync");
1694 Flag_List[Nflags++] = str_lookup(Flag_Map, "raw+wf");
1695 Flag_List[Nflags++] = str_lookup(Flag_Map, "ldraw");
1699 /* Warning: cannot mix direct i/o with others! */
1700 Flag_List[Nflags++] = str_lookup(Flag_Map, "dsync");
1701 Flag_List[Nflags++] = str_lookup(Flag_Map, "rsync");
1702 /* Flag_List[Nflags++] = str_lookup(Flag_Map, "rsync+sync");*/
1703 /* Flag_List[Nflags++] = str_lookup(Flag_Map, "rsync+dsync");*/
1708 if (optind >= argc) {
1709 fprintf(stderr, "iogen%s: No files listed on the cmdline\n", TagName);
1714 * Initialize File_List[] - only necessary if doing file io. First
1715 * space for the File_List array, then fill it in.
1718 File_List = (struct file_info *)
1719 malloc((argc-optind) * sizeof(struct file_info));
1721 if (File_List == NULL) {
1722 fprintf(stderr, "iogen%s: Could not malloc space for %d file_info structures\n", TagName, argc-optind);
1726 memset(File_List, 0, (argc-optind) * sizeof(struct file_info));
1729 while (optind < argc) {
1733 * Pick off leading len: if it's there and create/extend/trunc
1734 * the file to the desired length. Otherwise, just make sure
1735 * the file is accessable.
1738 if ((cp = strchr(argv[optind], ':')) != NULL) {
1740 if ((len = str_to_bytes(argv[optind])) == -1) {
1742 "iogen%s: illegal file length (%s) for file %s\n",
1743 TagName, argv[optind], cp+1);
1749 if (strlen(file) > MAX_FNAME_LENGTH) {
1750 fprintf(stderr, "iogen%s: Max fname length is %d chars - ignoring file %s\n",
1751 TagName, MAX_FNAME_LENGTH, file);
1756 nb = create_file(file, len);
1760 "iogen%s warning: Couldn't create file %s of %d bytes\n",
1761 TagName, file, len);
1769 file = argv[optind];
1770 if (access(file, R_OK | W_OK) == -1) {
1771 fprintf(stderr, "iogen%s: file %s cannot be accessed for reading and/or writing: %s (%d)\n",
1772 TagName, file, SYSERR, errno);
1778 * get per-file information
1781 fptr = &File_List[Nfiles];
1783 if (file[0] == '/') {
1784 strcpy(fptr->f_path, file);
1786 getcwd(fptr->f_path,
1787 sizeof(fptr->f_path)-1);
1788 strcat(fptr->f_path, "/");
1789 strcat(fptr->f_path, file);
1792 if (get_file_info(fptr) == -1) {
1793 fprintf(stderr, "iogen%s warning: Error getting file info for %s\n", TagName, file);
1797 * If the file length is smaller than our min transfer size,
1801 if (fptr->f_length < Mintrans) {
1802 fprintf(stderr, "iogen%s warning: Ignoring file %s\n",
1803 TagName, fptr->f_path);
1804 fprintf(stderr, " length (%d) is < min transfer size (%d)\n",
1805 fptr->f_length, Mintrans);
1811 * If the file length is smaller than our max transfer size,
1815 if (fptr->f_length < Maxtrans) {
1816 fprintf(stderr, "iogen%s warning: Ignoring file %s\n",
1817 TagName, fptr->f_path);
1818 fprintf(stderr, " length (%d) is < max transfer size (%d)\n",
1819 fptr->f_length, Maxtrans);
1824 if (fptr->f_length > 0) {
1825 switch (Offset_Mode->m_value) {
1827 fptr->f_lastoffset = 0;
1828 fptr->f_lastlength = 0;
1832 fptr->f_lastoffset = fptr->f_length;
1833 fptr->f_lastlength = 0;
1837 fptr->f_lastoffset = fptr->f_length / 2;
1838 fptr->f_lastlength = 0;
1850 fprintf(stderr, "iogen%s: Could not create, or gather info for any test files\n", TagName);
1863 fprintf(stream, "\n");
1865 fprintf(stream, "\t-a aio_type,... Async io completion types to choose. Supported types\n");
1867 #if _UMK || RELEASE_LEVEL >= 8000
1868 fprintf(stream, "\t are: poll, signal, recall, recalla, and recalls.\n");
1870 fprintf(stream, "\t are: poll, signal, recalla, and recalls.\n");
1873 fprintf(stream, "\t are: poll, signal, suspend, and callback.\n");
1875 fprintf(stream, "\t Default is all of the above.\n");
1877 fprintf(stream, "\t-a (Not used on Linux).\n");
1879 fprintf(stream, "\t-f flag,... Flags to use for file IO. Supported flags are\n");
1881 fprintf(stream, "\t raw, ssd, buffered, ldraw, sync,\n");
1882 fprintf(stream, "\t raw+wf, raw+wf+ldraw, raw+wf+ldraw+sync,\n");
1883 fprintf(stream, "\t and parallel (unicos/mk on MPP only).\n");
1884 fprintf(stream, "\t Default is 'raw,ldraw,sync,buffered'.\n");
1887 fprintf(stream, "\t buffered, direct, sync.\n");
1888 fprintf(stream, "\t Default is 'buffered,sync'.\n");
1890 fprintf(stream, "\t buffered, sync.\n");
1891 fprintf(stream, "\t Default is 'buffered,sync'.\n");
1894 fprintf(stream, "\t-h This help.\n");
1895 fprintf(stream, "\t-i iterations[s] # of requests to generate. 0 means causes iogen\n");
1896 fprintf(stream, "\t to run until it's killed. If iterations is suffixed\n");
1897 fprintf(stream, "\t with 's', then iterations is the number of seconds\n");
1898 fprintf(stream, "\t that iogen should run for. Default is '0'.\n");
1900 fprintf(stream, "\t-L min:max listio nstrides / nrequests range\n");
1902 fprintf(stream, "\t-L (Not used on this platform).\n");
1904 fprintf(stream, "\t-m offset-mode The mode by which iogen chooses the offset for\n");
1905 fprintf(stream, "\t consectutive transfers within a given file.\n");
1906 fprintf(stream, "\t Allowed values are 'random', 'sequential',\n");
1907 fprintf(stream, "\t and 'reverse'.\n");
1908 fprintf(stream, "\t sequential is the default.\n");
1909 fprintf(stream, "\t-N tagname Tag name, for Monster.\n");
1910 fprintf(stream, "\t-o Form overlapping consecutive requests.\n");
1911 fprintf(stream, "\t-O Open flags for creating files\n");
1913 fprintf(stream, "\t {O_PLACE,O_BIG,etc}[:CBITS[:CBLKS]]\n");
1916 fprintf(stream, "\t realtime:extsize - put file on real-time volume\n");
1917 fprintf(stream, "\t allocate - allocate space with F_ALLOCSP\n");
1918 fprintf(stream, "\t reserve - reserve space with F_RESVSP (default)\n");
1919 fprintf(stream, "\t noreserve - do not reserve with F_RESVSP\n");
1920 fprintf(stream, "\t direct - use O_DIRECT I/O to write to the file\n");
1922 fprintf(stream, "\t {O_SYNC,etc}\n");
1924 fprintf(stream, "\t-p Output pipe. Default is stdout.\n");
1925 fprintf(stream, "\t-q Quiet mode. Normally iogen spits out info\n");
1926 fprintf(stream, "\t about test files, options, etc. before starting.\n");
1927 fprintf(stream, "\t-s syscall,... Syscalls to do. Supported syscalls are\n");
1929 fprintf(stream, "\t read, write, pread, pwrite, readv, writev\n");
1930 fprintf(stream, "\t aread, awrite, resvsp, unresvsp, ffsync,\n");
1931 fprintf(stream, "\t mmread, mmwrite, fsync2, fdatasync,\n");
1932 fprintf(stream, "\t Default is 'read,write,pread,pwrite,readv,writev,mmread,mmwrite'.\n");
1935 fprintf(stream, "\t read, write, reada, writea, listio,\n");
1936 fprintf(stream, "\t ssread (PVP only), and sswrite (PVP only).\n");
1937 fprintf(stream, "\t Default is 'read,write,reada,writea,listio'.\n");
1940 fprintf(stream, "\t read, write, pread, pwrite, readv, writev,\n");
1941 fprintf(stream, "\t mmread, mmwrite, fsync2, fdatasync,\n");
1942 fprintf(stream, "\t Default is 'read,write,readv,writev,mmread,mmwrite'.\n");
1944 fprintf(stream, "\t-t mintrans Min transfer length\n");
1945 fprintf(stream, "\t-T maxtrans Max transfer length\n");
1946 fprintf(stream, "\n");
1947 fprintf(stream, "\t[len:]file,... Test files to do IO against (note ssread/sswrite\n");
1948 fprintf(stream, "\t don't need a test file). The len: syntax\n");
1949 fprintf(stream, "\t informs iogen to first create/expand/truncate the\n");
1950 fprintf(stream, "\t to the desired length.\n");
1951 fprintf(stream, "\n");
1952 fprintf(stream, "\tNote: The ssd flag causes sds transfers to also be done.\n");
1953 fprintf(stream, "\t To totally eliminate sds transfers, you must eleminate sds\n");
1954 fprintf(stream, "\t from the flags (-f) and ssread,ssrite from the syscalls (-s)\n");
1955 fprintf(stream, "\tThe mintrans, maxtrans, and len: parameters are numbers of the\n");
1956 fprintf(stream, "\tform [0-9]+[bkm]. The optional trailing b, k, or m multiplies\n");
1957 fprintf(stream, "\tthe number by blocks, kilobytes, or megabytes. If no trailing\n");
1958 fprintf(stream, "\tmultiplier is present, the number is interpreted as bytes\n");
1964 * Obvious - usage clause
1971 fprintf(stream, "usage%s: iogen [-hoq] [-a aio_type,...] [-f flag[,flag...]] [-i iterations] [-p outpipe] [-m offset-mode] [-s syscall[,syscall...]] [-t mintrans] [-T maxtrans] [ -O file-create-flags ] [[len:]file ...]\n", TagName);