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 * iogen - a tool for generating file/sds io for a doio process
24 #ifdef HAVE_SYS_SYSSGI_H
25 #include <sys/syssgi.h>
28 #ifdef HAVE_SYS_UUID_H
32 #ifdef HAVE_SYS_FS_XFS_FSOPS_H
33 #include <sys/fs/xfs_fsops.h>
36 #ifdef HAVE_SYS_FS_XFS_ITABLE_H
37 #include <sys/fs/xfs_itable.h>
42 #include "str_to_bytes.h"
43 #include "string_to_tokens.h"
44 #include "open_flags.h"
45 #include "random_range.h"
51 #define RAW_IO(_flags_) ((_flags_) & (O_RAW | O_SSD))
53 #define SYSERR strerror(errno)
56 * Structure for retaining test file information
60 char f_path[MAX_FNAME_LENGTH+1]; /* file name (full path) */
61 int f_length; /* length in bytes */
62 int f_iou; /* file iounit */
63 int f_riou; /* file raw iounit (for O_RAW/O_SSD) */
64 int f_dalign; /* direct I/O alignment */
65 int f_nextoff; /* offset of end of last io operation */
66 int f_type; /* file type S_IFREG, etc... */
67 int f_lastoffset; /* offset of last io operation */
68 int f_lastlength; /* length of last io operation */
72 * Simple structure for associating strings with values - useful for converting
73 * cmdline args to internal values, as well as printing internal values in
74 * a human readable form.
84 * Declare cmdline option flags/variables initialized in parse_cmdline()
87 #define OPTS "a:dhf:i:L:m:op:qr:s:t:T:O:N:"
89 int a_opt = 0; /* async io comp. types supplied */
90 int o_opt = 0; /* form overlapping requests */
91 int f_opt = 0; /* test flags */
92 int i_opt = 0; /* iterations - 0 implies infinite */
93 int L_opt = 0; /* listio min-max nstrides & nents */
94 int m_opt = 0; /* offset mode */
95 int O_opt = 0; /* file creation Open flags */
96 int p_opt = 0; /* output pipe - default is stdout */
97 int r_opt = 0; /* specify raw io multiple instead of */
98 /* getting it from the mounted on device. */
99 /* Only applies to regular files. */
100 int s_opt = 0; /* syscalls */
101 int t_opt = 0; /* min transfer size (bytes) */
102 int T_opt = 0; /* max transfer size (bytes) */
103 int q_opt = 0; /* quiet operation on startup */
104 char TagName[40]; /* name of this iogen (see Monster) */
105 struct strmap *Offset_Mode; /* M_SEQUENTIAL, M_RANDOM, etc. */
106 int Iterations; /* # requests to generate (0 --> infinite) */
107 int Time_Mode = 0; /* non-zero if Iterations is in seconds */
108 /* (ie. -i arg was suffixed with 's') */
109 char *Outpipe; /* Pipe to write output to if p_opt */
110 int Mintrans; /* min io transfer size */
111 int Maxtrans; /* max io transfer size */
112 int Rawmult; /* raw/ssd io multiple (from -r) */
113 int Minstrides; /* min # of listio strides per request */
114 int Maxstrides; /* max # of listio strides per request */
115 int Oflags; /* open(2) flags for creating files */
116 int Ocbits; /* open(2) cbits for creating files */
117 int Ocblks; /* open(2) cblks for creating files */
118 int Orealtime=0; /* flag set for -O REALTIME */
119 int Oextsize=0; /* real-time extent size */
120 int Oreserve=1; /* flag for -O [no]reserve */
121 int Oallocate=0; /* flag for -O allocate */
122 int Owrite=1; /* flag for -O nowrite */
124 int Nfiles = 0; /* # files on cmdline */
125 struct file_info *File_List; /* info about each file */
126 int Nflags = 0; /* # flags on cmdline */
127 struct strmap *Flag_List[128]; /* flags selected from cmdline */
128 int Nsyscalls = 0; /* # syscalls on cmdline */
129 struct strmap *Syscall_List[128]; /* syscalls selected on cmdline */
130 int Fileio = 0; /* flag indicating that a file */
131 /* io syscall has been chosen. */
132 int Naio_Strat_Types = 0; /* # async io completion types */
133 struct strmap *Aio_Strat_List[128]; /* Async io completion types */
138 * Map async io completion modes (-a args) names to values. Macros are
142 struct strmap Aio_Strat_Map[] = {
145 { "signal", A_SIGNAL },
150 #if _UMK || RELEASE_LEVEL >= 8000
151 { "recall", A_RECALL },
155 { "recalla", A_RECALLA },
157 { "recalls", A_RECALLS },
161 { "suspend", A_SUSPEND },
162 { "callback", A_CALLBACK },
168 * Offset_Mode #defines
172 #define M_SEQUENTIAL 2
176 * Map offset mode (-m args) names to values
179 struct strmap Omode_Map[] = {
180 { "random", M_RANDOM },
181 { "sequential", M_SEQUENTIAL },
182 { "reverse", M_REVERSE },
187 * Map syscall names (-s args) to values - macros are defined in doio.h.
189 #define SY_ASYNC 00001
190 #define SY_WRITE 00002
192 #define SY_LISTIO 00020
193 #define SY_NENT 00100 /* multi entry vs multi stride >>> */
195 struct strmap Syscall_Map[] = {
197 { "write", WRITE, SY_WRITE },
199 { "reada", READA, SY_ASYNC },
200 { "writea", WRITEA, SY_WRITE|SY_ASYNC },
202 { "ssread", SSREAD, SY_SDS },
203 { "sswrite", SSWRITE, SY_WRITE|SY_SDS },
205 { "listio", LISTIO, SY_ASYNC },
207 /* listio as 4 system calls */
208 { "lread", LREAD, 0 },
209 { "lreada", LREADA, SY_ASYNC },
210 { "lwrite", LWRITE, SY_WRITE },
211 { "lwritea", LWRITEA, SY_WRITE|SY_ASYNC },
213 /* listio with nstrides > 1 */
214 { "lsread", LSREAD, 0 },
215 { "lsreada", LSREADA, SY_ASYNC },
216 { "lswrite", LSWRITE, SY_WRITE },
217 { "lswritea", LSWRITEA, SY_WRITE|SY_ASYNC },
219 /* listio with nents > 1 */
220 { "leread", LEREAD, 0|SY_NENT },
221 { "lereada", LEREADA, SY_ASYNC|SY_NENT },
222 { "lewrite", LEWRITE, SY_WRITE|SY_NENT },
223 { "lewritea", LEWRITEA, SY_WRITE|SY_ASYNC|SY_NENT },
225 /* listio with nents > 1 & nstrides > 1 */
227 /* all listio system calls under one name */
228 { "listio+", LREAD, 0 },
229 { "listio+", LREADA, SY_ASYNC },
230 { "listio+", LWRITE, SY_WRITE },
231 { "listio+", LWRITEA, SY_WRITE|SY_ASYNC },
232 { "listio+", LSREAD, 0 },
233 { "listio+", LSREADA, SY_ASYNC },
234 { "listio+", LSWRITE, SY_WRITE },
235 { "listio+", LSWRITEA, SY_WRITE|SY_ASYNC },
236 { "listio+", LEREAD, 0|SY_NENT },
237 { "listio+", LEREADA, SY_ASYNC|SY_NENT },
238 { "listio+", LEWRITE, SY_WRITE|SY_NENT },
239 { "listio+", LEWRITEA, SY_WRITE|SY_ASYNC|SY_NENT },
243 { "pwrite", PWRITE, SY_WRITE },
245 { "aread", AREAD, SY_ASYNC },
246 { "awrite", AWRITE, SY_WRITE|SY_ASYNC },
248 /* not written yet */
249 { "llread", LLREAD, 0 },
250 { "llaread", LLAREAD, SY_ASYNC },
251 { "llwrite", LLWRITE, 0 },
252 { "llawrite", LLAWRITE, SY_ASYNC },
253 { "ffsync", DFFSYNC, SY_WRITE },
257 { "resvsp", RESVSP, SY_WRITE },
258 { "unresvsp", UNRESVSP, SY_WRITE },
259 { "reserve", RESVSP, SY_WRITE },
260 { "unreserve", UNRESVSP, SY_WRITE },
265 { "writev", WRITEV, SY_WRITE },
267 { "mmwrite", MMAPW, SY_WRITE },
268 { "fsync2", FSYNC2, SY_WRITE },
269 { "fdatasync", FDATASYNC, SY_WRITE },
276 * Map open flags (-f args) to values
278 #define FLG_RAW 00001
280 struct strmap Flag_Map[] = {
281 { "buffered", 0, 0 },
282 { "sync", O_SYNC, 0 },
284 { "raw", O_RAW, FLG_RAW },
285 { "raw+wf", O_RAW | O_WELLFORMED, FLG_RAW },
286 { "raw+wf+ldraw", O_RAW | O_WELLFORMED | O_LDRAW, FLG_RAW },
287 { "raw+wf+ldraw+sync", O_RAW | O_WELLFORMED | O_LDRAW | O_SYNC, FLG_RAW },
289 { "ssd", O_SSD, FLG_RAW },
292 { "ldraw", O_LDRAW, 0 },
295 { "parallel", O_PARALLEL | O_RAW | O_WELLFORMED,
297 { "parallel+sync", O_PARALLEL | O_RAW | O_WELLFORMED | O_SYNC,
299 { "parallel+ldraw", O_PARALLEL | O_RAW | O_WELLFORMED | O_LDRAW,
301 { "parallel+ldraw+sync",
302 O_PARALLEL | O_RAW | O_WELLFORMED | O_LDRAW | O_SYNC,
307 { "direct", O_DIRECT, FLG_RAW },
309 { "dsync", O_DSYNC }, /* affects writes */
310 { "rsync", O_RSYNC }, /* affects reads */
311 { "rsync+dsync", O_RSYNC|O_DSYNC },
317 * Map file types to strings
320 struct strmap Ftype_Map[] = {
321 { "regular", S_IFREG },
322 { "blk-spec", S_IFBLK },
323 { "chr-spec", S_IFCHR },
333 char Byte_Patterns[26] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
334 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
335 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
339 int form_iorequest(struct io_req *);
341 int parse_cmdline(int argc, char **argv, char *opts);
342 int help(FILE *stream);
343 int usage(FILE *stream);
351 int rseed, outfd, infinite;
358 Sds_Avail = sysconf(_SC_CRAY_SDS);
364 parse_cmdline(argc, argv, OPTS);
367 * Initialize output descriptor.
372 outfd = init_output();
376 random_range_seed(rseed); /* initialize random number generator */
379 * Print out startup information, unless we're running in quiet mode
382 startup_info(stderr, rseed);
384 start_time = time(0);
387 * While iterations (or forever if Iterations == 0) - compute an
388 * io request, and write the structure to the output descriptor
391 infinite = !Iterations;
394 (! Time_Mode && Iterations--) ||
395 (Time_Mode && time(0) - start_time <= Iterations)) {
397 memset(&req, 0, sizeof(struct io_req));
398 if (form_iorequest(&req) == -1) {
399 fprintf(stderr, "iogen%s: form_iorequest() failed\n", TagName);
403 req.r_magic = DOIO_MAGIC;
404 write(outfd, (char *)&req, sizeof(req));
412 startup_info(FILE *stream, int seed)
414 char *value_to_string(), *type;
417 fprintf(stream, "\n");
418 fprintf(stream, "iogen%s starting up with the following:\n", TagName);
419 fprintf(stream, "\n");
421 fprintf(stream, "Out-pipe: %s\n",
422 p_opt ? Outpipe : "stdout");
425 fprintf(stream, "Iterations: %d", Iterations);
427 fprintf(stream, " seconds");
429 fprintf(stream, "\n");
431 fprintf(stream, "Iterations: Infinite\n");
438 "Offset-Mode: %s\n", Offset_Mode->m_string);
440 fprintf(stream, "Overlap Flag: %s\n",
441 o_opt ? "on" : "off");
444 "Mintrans: %-11d (%d blocks)\n",
445 Mintrans, (Mintrans+BSIZE-1)/BSIZE);
448 "Maxtrans: %-11d (%d blocks)\n",
449 Maxtrans, (Maxtrans+BSIZE-1)/BSIZE);
453 "O_RAW/O_SSD Multiple: (Determined by device)\n");
456 "O_RAW/O_SSD Multiple: %-11d (%d blocks)\n",
457 Rawmult, (Rawmult+BSIZE-1)/BSIZE);
459 fprintf(stream, "Syscalls: ");
460 for (i = 0; i < Nsyscalls; i++)
462 "%s ", Syscall_List[i]->m_string);
463 fprintf(stream, "\n");
465 fprintf(stream, "Aio completion types: ");
466 for (i = 0; i < Naio_Strat_Types; i++)
468 "%s ", Aio_Strat_List[i]->m_string);
469 fprintf(stream, "\n");
472 fprintf(stream, "Flags: ");
473 for (i = 0; i < Nflags; i++)
475 "%s ", Flag_List[i]->m_string);
477 fprintf(stream, "\n");
478 fprintf(stream, "\n");
479 fprintf(stream, "Test Files: \n");
480 fprintf(stream, "\n");
482 "Path Length iou raw iou file\n");
484 " (bytes) (bytes) (bytes) type\n");
486 "-----------------------------------------------------------------------------\n");
488 for (i = 0; i < Nfiles; i++) {
489 type = value_to_string(Ftype_Map, File_List[i].f_type);
490 fprintf(stream, "%-40s %12d %7d %7d %s\n",
491 File_List[i].f_path, File_List[i].f_length,
492 File_List[i].f_iou, File_List[i].f_riou, type);
498 * Initialize output descriptor. If going to stdout, its easy,
499 * otherwise, attempt to create a FIFO on path Outpipe. Exit with an
500 * error code if this cannot be done.
508 if (stat(Outpipe, &sbuf) == -1) {
509 if (errno == ENOENT) {
510 if (mkfifo(Outpipe, 0666) == -1) {
511 fprintf(stderr, "iogen%s: Could not mkfifo %s: %s\n",
512 TagName, Outpipe, SYSERR);
516 fprintf(stderr, "iogen%s: Could not stat outpipe %s: %s\n",
517 TagName, Outpipe, SYSERR);
521 if (! S_ISFIFO(sbuf.st_mode)) {
523 "iogen%s: Output file %s exists, but is not a FIFO\n",
529 if ((outfd = open(Outpipe, O_RDWR)) == -1) {
531 "iogen%s: Couldn't open outpipe %s with flags O_RDWR: %s\n",
532 TagName, Outpipe, SYSERR);
541 * Main io generation function. form_iorequest() selects a system call to
542 * do based on cmdline arguments, and proceeds to select parameters for that
545 * Returns 0 if req is filled in with a complete doio request, otherwise
553 int mult, offset = 0, length = 0, slength;
554 int minlength, maxlength, laststart, lastend;
555 int minoffset, maxoffset;
556 int maxstride, nstrides;
558 struct strmap *flags, *sc, *aio_strat;
559 struct file_info *fptr;
565 * Choose system call, flags, and file
568 sc = Syscall_List[random_range(0, Nsyscalls-1, 1, NULL)];
569 req->r_type = sc->m_value;
572 if (sc->m_value == LISTIO ) {
573 opcode = random_range(0, 1, 1, NULL) ? LO_READ : LO_WRITE;
574 cmd = random_range(0, 1, 1, NULL) ? LC_START : LC_WAIT;
578 if( sc->m_flags & SY_WRITE )
579 pattern = Byte_Patterns[random_range(0, sizeof(Byte_Patterns) - 1, 1, NULL)];
585 * If sds io, simply choose a length (possibly pattern) and return
588 if (sc->m_flags & SY_SDS ) {
589 req->r_data.ssread.r_nbytes = random_range(Mintrans, Maxtrans, BSIZE, NULL);
590 if (sc->m_flags & SY_WRITE)
591 req->r_data.sswrite.r_pattern = pattern;
598 * otherwise, we're doing file io. Choose starting offset, length,
599 * open flags, and possibly a pattern (for write/writea).
602 fptr = &File_List[random_range(0, Nfiles-1, 1, NULL)];
603 flags = Flag_List[random_range(0, Nflags-1, 1, NULL)];
606 * Choose offset/length multiple. IO going to a device, or regular
607 * IO that is O_RAW or O_SSD must be aligned on the file r_iou. Otherwise
608 * it must be aligned on the regular iou (normally 1).
611 if ( fptr->f_type == S_IFREG && (flags->m_flags & FLG_RAW) )
617 * Choose offset and length. Both must be a multiple of mult
621 * Choose length first - it must be a multiple of mult
624 laststart = fptr->f_lastoffset;
625 lastend = fptr->f_lastoffset + fptr->f_lastlength - 1;
627 minlength = (Mintrans > mult) ? Mintrans : mult;
629 switch (Offset_Mode->m_value) {
631 if (o_opt && lastend > laststart)
632 offset = random_range(laststart, lastend, 1, NULL);
634 offset = lastend + 1;
635 if (offset && (offset%mult))
636 offset += mult - (offset % mult);
638 if (minlength > fptr->f_length - offset)
641 maxlength = fptr->f_length - offset;
642 if (maxlength > Maxtrans)
643 maxlength = Maxtrans;
645 length = random_range(minlength, maxlength, mult, &errp);
647 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
648 TagName, minlength, maxlength, mult);
655 maxlength = laststart;
657 if (maxlength > Maxtrans)
658 maxlength = Maxtrans;
660 if (minlength > maxlength) {
661 laststart = fptr->f_length;
662 lastend = fptr->f_length;
663 maxlength = Maxtrans;
666 length = random_range(minlength, maxlength, mult, &errp);
668 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
669 TagName, minlength, maxlength, mult);
673 offset = laststart - length;
675 if (o_opt && lastend > laststart)
676 offset += random_range(1, lastend - laststart, 1, NULL);
678 if (offset && (offset%mult))
679 offset -= offset % mult;
684 length = random_range(Mintrans, Maxtrans, mult, NULL);
686 if (o_opt && lastend > laststart) {
687 minoffset = laststart - length + 1;
692 if (lastend + length > fptr->f_length) {
693 maxoffset = fptr->f_length - length;
699 maxoffset = fptr->f_length - length;
705 offset = random_range(minoffset, maxoffset, mult, &errp);
707 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
708 TagName, minoffset, maxoffset, mult);
713 fptr->f_lastoffset = offset;
714 fptr->f_lastlength = length;
717 * Choose an async io completion strategy if necessary
719 if( sc->m_flags & SY_ASYNC )
720 aio_strat = Aio_Strat_List[random_range(0, Naio_Strat_Types - 1,
726 * fill in specific syscall record data
728 switch (sc->m_value) {
731 strcpy(req->r_data.read.r_file, fptr->f_path);
732 req->r_data.read.r_oflags = O_RDONLY | flags->m_value;
733 req->r_data.read.r_offset = offset;
734 req->r_data.read.r_nbytes = length;
735 req->r_data.read.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
736 req->r_data.read.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
737 req->r_data.read.r_nstrides = 1;
738 req->r_data.read.r_nent = 1;
743 strcpy(req->r_data.write.r_file, fptr->f_path);
744 req->r_data.write.r_oflags = O_WRONLY | flags->m_value;
745 req->r_data.write.r_offset = offset;
746 req->r_data.write.r_nbytes = length;
747 req->r_data.write.r_pattern = pattern;
748 req->r_data.write.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
749 req->r_data.write.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
750 req->r_data.write.r_nstrides = 1;
751 req->r_data.write.r_nent = 1;
771 strcpy(req->r_data.io.r_file, fptr->f_path);
772 req->r_data.io.r_oflags = ((sc->m_flags & SY_WRITE) ? O_WRONLY : O_RDONLY) | flags->m_value;
773 req->r_data.io.r_offset = offset;
774 req->r_data.io.r_nbytes = length;
775 req->r_data.io.r_pattern = pattern;
776 req->r_data.io.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
777 req->r_data.io.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
778 req->r_data.io.r_nstrides = 1;
779 req->r_data.io.r_nent = 1;
784 strcpy(req->r_data.io.r_file, fptr->f_path);
785 /* a subtle "feature" of mmap: a write-map requires
786 the file open read/write */
787 req->r_data.io.r_oflags = ((sc->m_flags & SY_WRITE) ? O_RDWR : O_RDONLY) | flags->m_value;
788 req->r_data.io.r_offset = offset;
789 req->r_data.io.r_nbytes = length;
790 req->r_data.io.r_pattern = pattern;
791 req->r_data.io.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
792 req->r_data.io.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
793 req->r_data.io.r_nstrides = 1;
794 req->r_data.io.r_nent = 1;
806 strcpy(req->r_data.io.r_file, fptr->f_path);
807 req->r_data.io.r_oflags = ((sc->m_flags & SY_WRITE) ? O_WRONLY : O_RDONLY) | flags->m_value;
808 req->r_data.io.r_offset = offset;
809 req->r_data.io.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
810 req->r_data.io.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
811 req->r_data.io.r_pattern = pattern;
813 /* multi-strided request...
814 * random number of strides (1...MaxStrides)
815 * length of stride must be > minlength
816 * length of stride must be % mult
818 * maxstrides = min(length / mult, overall.max#strides)
819 * nstrides = random #
820 * while( length / nstrides < minlength )
821 * nstrides = new random #
823 maxstride = length / mult;
824 if(maxstride > Maxstrides)
825 maxstride = Maxstrides;
829 nstrides = random_range(Minstrides, maxstride, 1, &errp);
831 fprintf(stderr, "iogen%s: random_range(%d, %d, %d) failed\n",
832 TagName, Minstrides, maxstride, 1);
836 slength = length / nstrides;
837 if(slength % mult != 0) {
838 if( mult > slength) {
841 slength -= slength % mult;
843 nstrides = length / slength;
844 if(nstrides > Maxstrides)
845 nstrides = Maxstrides;
848 req->r_data.io.r_nbytes = slength;
849 if( sc->m_flags & SY_NENT ) {
850 req->r_data.io.r_nstrides = 1;
851 req->r_data.io.r_nent = nstrides;
853 req->r_data.io.r_nstrides = nstrides;
854 req->r_data.io.r_nent = 1;
860 strcpy(req->r_data.listio.r_file, fptr->f_path);
861 req->r_data.listio.r_offset = offset;
862 req->r_data.listio.r_cmd = cmd;
863 req->r_data.listio.r_aio_strat = (aio_strat==NULL) ? 0 : aio_strat->m_value;
864 req->r_data.listio.r_filestride = 0;
865 req->r_data.listio.r_memstride = 0;
866 req->r_data.listio.r_opcode = opcode;
867 req->r_data.listio.r_nstrides = 1;
868 req->r_data.listio.r_nbytes = length;
869 req->r_data.listio.r_uflags = (flags->m_flags & FLG_RAW) ? F_WORD_ALIGNED : 0;
871 if (opcode == LO_WRITE) {
872 req->r_data.listio.r_pattern = pattern;
873 req->r_data.listio.r_oflags = O_WRONLY | flags->m_value;
875 req->r_data.listio.r_oflags = O_RDONLY | flags->m_value;
885 * Get information about a file that iogen uses to choose io length and
886 * offset. Information gathered is file length, iounit, and raw iounit.
887 * For regurlar files, iounit is 1, and raw iounit is the iounit of the
888 * device on which the file resides. For block/character special files
889 * the iounit and raw iounit are both the iounit of the device.
891 * Note: buffered and osync io must be iounit aligned
892 * raw and ossd io must be raw iounit aligned
897 struct file_info *rec;
901 struct lk_device_info dinfo;
905 struct dioattr finfo;
909 * Figure out if the files is regular, block or character special. Any
910 * other type is an error.
913 if (stat(rec->f_path, &sbuf) == -1) {
914 fprintf(stderr, "iogen%s: get_file_info(): Could not stat() %s: %s\n",
915 TagName, rec->f_path, SYSERR);
920 if ((! S_ISREG(sbuf.st_mode)) || strncmp(rec->f_path, "/dev/", 5) == 0) {
921 fprintf(stderr, "iogen%s: device level io not supported on cray2\n", TagName);
926 rec->f_type = sbuf.st_mode & S_IFMT;
929 * If regular, iou is 1, and we must figure out the device on
930 * which the file resides. riou is the iou (logical sector size) of
934 if (S_ISREG(sbuf.st_mode)) {
936 rec->f_length = sbuf.st_size;
939 * If -r used, take Rawmult as the raw/ssd io multiple. Otherwise
940 * attempt to determine it by looking at the device the file
945 rec->f_riou = Rawmult;
951 if (lk_rawdev(rec->f_path, dinfo.path, sizeof(dinfo.path), 0) == -1)
954 if (lk_devinfo(&dinfo, 0) == -1) {
955 /* can't get raw I/O unit -- use stat to fudge it */
956 rec->f_riou = sbuf.st_blksize;
958 rec->f_riou = ctob(dinfo.iou);
962 if( (fd = open(rec->f_path, O_RDWR|O_DIRECT, 0)) != -1 ) {
963 #ifdef XFS_IOC_DIOINFO
964 if(xfsctl(rec->f_path, fd, XFS_IOC_DIOINFO, &finfo) != -1) {
967 if(fcntl(fd, F_DIOINFO, &finfo) != -1) {
972 rec->f_riou = finfo.d_miniosz;
975 "iogen%s: Error %s (%d) getting direct I/O info of file %s\n",
976 TagName, strerror(errno), errno, rec->f_path);
980 rec->f_riou = BBSIZE;
988 * Otherwise, file is a device. Use lk_devinfo() to get its logical
989 * sector size. This is the iou and riou
992 strcpy(dinfo.path, rec->f_path);
994 if (lk_devinfo(&dinfo, 0) == -1) {
995 fprintf(stderr, "iogen%s: %s: %s\n", TagName, Lk_err_func, Lk_err_mesg);
999 rec->f_iou = ctob(dinfo.iou);
1000 rec->f_riou = ctob(dinfo.iou);
1001 rec->f_length = ctob(dinfo.length);
1004 rec->f_riou = BBSIZE;
1005 rec->f_length = BBSIZE;
1007 rec->f_riou = BSIZE;
1008 rec->f_length = BSIZE;
1017 * Create file path as nbytes long. If path exists, the file will either be
1018 * extended or truncated to be nbytes long. Returns final size of file,
1019 * or -1 if there was a failure.
1023 create_file(path, nbytes)
1033 struct fsxattr xattr;
1034 struct dioattr finfo;
1039 rval = stat(path, &sbuf);
1042 if (errno == ENOENT) {
1045 fprintf(stderr, "iogen%s: Could not stat file %s: %s (%d)\n",
1046 TagName, path, SYSERR, errno);
1050 if (! S_ISREG(sbuf.st_mode)) {
1052 "iogen%s: file %s exists, but is not a regular file - cannot modify length\n",
1058 if (sbuf.st_size == nbytes)
1061 Oflags |= O_CREAT | O_WRONLY;
1063 if ((fd = open(path, Oflags, 0666)) == -1) {
1064 fprintf(stderr, "iogen%s: Could not create/open file %s: %s (%d)\n",
1065 TagName, path, SYSERR, errno);
1070 * Truncate file if it is longer than nbytes, otherwise attempt to
1071 * pre-allocate file blocks.
1074 if (sbuf.st_size > nbytes) {
1075 if (ftruncate(fd, nbytes) == -1) {
1077 "iogen%s: Could not ftruncate() %s to %d bytes: %s (%d)\n",
1078 TagName, path, nbytes, SYSERR, errno);
1086 * The file must be designated as Real-Time before any data
1087 * is allocated to it.
1090 if(Orealtime != 0) {
1091 bzero(&xattr, sizeof(xattr));
1092 xattr.fsx_xflags = XFS_XFLAG_REALTIME;
1093 /*fprintf(stderr, "set: fsx_xflags = 0x%x\n", xattr.fsx_xflags);*/
1094 #ifdef XFS_IOC_FSSETXATTR
1095 if( xfsctl(path, fd, XFS_IOC_FSSETXATTR, &xattr) == -1 ) {
1098 if (fcntl(fd, F_FSSETXATTR, &xattr) < 0) {
1103 fprintf(stderr, "iogen%s: Error %s (%d) setting XFS XATTR->Realtime on file %s\n",
1104 TagName, SYSERR, errno, path);
1110 #ifdef XFS_IOC_FSGETXATTR
1111 if( xfsctl(path, fd, XFS_IOC_FSGETXATTR, &xattr) == -1 ) {
1114 if (fcntl(fd, F_FSGETXATTR, &xattr) < 0) {
1119 fprintf(stderr, "iogen%s: Error getting realtime flag %s (%d)\n",
1120 TagName, SYSERR, errno);
1124 fprintf(stderr, "get: fsx_xflags = 0x%x\n",
1133 * Failure is ignored since XFS_IOC_RESVSP only works on XFS and the
1134 * filesystem could be on some otehr filesystem.
1137 f.l_whence = SEEK_SET;
1142 "create_file: xfsctl(%d, RESVSP, { %d, %lld, %lld })\n",
1143 fd, f.l_whence, (long long)f.l_start, (long long)f.l_len);*/
1145 /* non-zeroing reservation */
1146 #ifdef XFS_IOC_RESVSP
1147 if( xfsctl( path, fd, XFS_IOC_RESVSP, &f ) == -1) {
1149 "iogen%s: Could not xfsctl(XFS_IOC_RESVSP) %d bytes in file %s: %s (%d)\n",
1150 TagName, nbytes, path, SYSERR, errno);
1156 if( fcntl( fd, F_RESVSP, &f ) == -1) {
1158 "iogen%s: Could not fcntl(F_RESVSP) %d bytes in file %s: %s (%d)\n",
1159 TagName, nbytes, path, SYSERR, errno);
1170 /* XFS_IOC_ALLOCSP allocates from the file start to l_start */
1171 f.l_whence = SEEK_SET;
1175 "create_file: xfsctl(%d, XFS_IOC_ALLOCSP, { %d, %lld, %lld })\n",
1176 fd, f.l_whence, (long long)f.l_start,
1177 (long long)f.l_len);*/
1179 /* zeroing reservation */
1180 #ifdef XFS_IOC_ALLOCSP
1181 if( xfsctl( path, fd, XFS_IOC_ALLOCSP, &f ) == -1) {
1183 "iogen%s: Could not xfsctl(XFS_IOC_ALLOCSP) %d bytes in file %s: %s (%d)\n",
1184 TagName, nbytes, path, SYSERR, errno);
1190 if ( fcntl(fd, F_ALLOCSP, &f) < 0) {
1192 "iogen%s: Could not fcntl(F_ALLOCSP) %d bytes in file %s: %s (%d)\n",
1193 TagName, nbytes, path, SYSERR, errno);
1205 * Write a byte at the end of file so that stat() sets the right
1212 if( (fd = open(path, O_CREAT|O_RDWR|O_DIRECT, 0)) != -1 ) {
1213 #ifdef XFS_IOC_DIOINFO
1214 if(xfsctl(path, fd, XFS_IOC_DIOINFO, &finfo) == -1) {
1217 if (fcntl(fd, F_DIOINFO, &finfo) < 0) {
1223 "iogen%s: Error %s (%d) getting direct I/O info for file %s\n",
1224 TagName, SYSERR, errno, path);
1227 /*fprintf(stderr, "%s: miniosz=%d\n",
1228 path, finfo.d_miniosz);*/
1231 fprintf(stderr, "iogen%s: Error %s (%d) opening file %s with flags O_CREAT|O_RDWR|O_DIRECT\n",
1232 TagName, SYSERR, errno, path);
1237 * nb is nbytes adjusted down by an even d_miniosz block
1239 * Note: the first adjustment can cause iogen to print a warning
1240 * about not being able to create a file of <nbytes> length,
1241 * since the file will be shorter.
1243 nb = nbytes-finfo.d_miniosz;
1244 nb = nb-nb%finfo.d_miniosz;
1247 "create_file_ow2: lseek(%d, %d {%d %d}, SEEK_SET)\n",
1248 fd, nb, nbytes, finfo.d_miniosz);*/
1250 if (lseek(fd, nb, SEEK_SET) == -1) {
1252 "iogen%s: Could not lseek() to EOF of file %s: %s (%d)\n\tactual offset %d file size goal %d miniosz %lld\n",
1253 TagName, path, SYSERR, errno,
1254 nb, nbytes, (long long)finfo.d_miniosz);
1259 b = buf = (char *)malloc(finfo.d_miniosz+finfo.d_mem);
1261 if( ((long)buf % finfo.d_mem != 0) ) {
1262 buf += finfo.d_mem - ((long)buf % finfo.d_mem);
1265 memset(buf, 0, finfo.d_miniosz);
1267 if ( (rval=write(fd, buf, finfo.d_miniosz)) != finfo.d_miniosz) {
1269 "iogen%s: Could not write %d byte length file %s: %s (%d)\n",
1270 TagName, nb, path, SYSERR, errno);
1272 "\twrite(%d, 0x%lx, %d) = %d\n",
1273 fd, (long)buf, finfo.d_miniosz, rval);
1275 "\toffset %d file size goal %d, miniosz=%d\n",
1276 nb, nbytes, finfo.d_miniosz);
1285 "create_file_Owrite: lseek(%d, %d {%d}, SEEK_SET)\n",
1286 fd, nbytes-1, nbytes);*/
1288 if (lseek(fd, nbytes-1, SEEK_SET) == -1) {
1290 "iogen%s: Could not lseek() to EOF in file %s: %s (%d)\n\toffset goal %d\n",
1291 TagName, path, SYSERR, errno,
1297 if ( (rval=write(fd, &c, 1)) != 1) {
1299 "iogen%s: Could not create a %d byte length file %s: %s (%d)\n",
1300 TagName, nbytes, path, SYSERR, errno);
1302 "\twrite(%d, 0x%lx, %d) = %d\n",
1303 fd, (long)&c, 1, rval);
1305 "\toffset %d file size goal %d\n",
1316 return sbuf.st_size;
1320 * Function to convert a string to its corresponding value in a strmap array.
1321 * If the string is not found in the array, the value corresponding to the
1322 * NULL string (the last element in the array) is returned.
1326 str_to_value(map, str)
1332 for (mp = map; mp->m_string != NULL; mp++)
1333 if (strcmp(mp->m_string, str) == 0)
1340 * Function to convert a string to its corresponding entry in a strmap array.
1341 * If the string is not found in the array, a NULL is returned.
1345 str_lookup(map, str)
1351 for (mp = map; mp->m_string != NULL; mp++)
1352 if (strcmp(mp->m_string, str) == 0)
1355 return((mp->m_string == NULL) ? NULL : mp);
1360 * Function to convert a value to its corresponding string in a strmap array.
1361 * If the value is not found in the array, NULL is returned.
1365 value_to_string(map, val)
1371 for (mp = map; mp->m_string != NULL; mp++)
1372 if (mp->m_value == val)
1375 return mp->m_string;
1379 * Interpret cmdline options/arguments. Exit with 1 if something on the
1380 * cmdline isn't kosher.
1384 parse_cmdline(argc, argv, opts)
1389 int o, len, nb, format_error;
1390 struct strmap *flgs, *sc;
1391 char *file, *cp, ch;
1393 struct file_info *fptr;
1395 char *openargs[5]; /* Flags, cbits, cblks */
1399 struct strmap *type;
1402 while ((o = getopt(argc, argv, opts)) != EOF) {
1407 fprintf(stderr, "iogen%s: Unrecognized option -a on this platform\n", TagName);
1410 cp = strtok(optarg, ",");
1411 while (cp != NULL) {
1412 if ((type = str_lookup(Aio_Strat_Map, cp)) == NULL) {
1413 fprintf(stderr, "iogen%s: Unrecognized aio completion strategy: %s\n", TagName, cp);
1417 Aio_Strat_List[Naio_Strat_Types++] = type;
1418 cp = strtok(NULL, ",");
1425 cp = strtok(optarg, ",");
1426 while (cp != NULL) {
1427 if( (flgs = str_lookup(Flag_Map, cp)) == NULL ) {
1428 fprintf(stderr, "iogen%s: Unrecognized flags: %s\n", TagName, cp);
1432 cp = strtok(NULL, ",");
1435 if (flgs->m_value & O_SSD && ! Sds_Avail) {
1436 fprintf(stderr, "iogen%s: Warning - no sds available, ignoring ssd flag\n", TagName);
1441 Flag_List[Nflags++] = flgs;
1454 switch (sscanf(optarg, "%i%c", &Iterations, &ch)) {
1474 fprintf(stderr, "iogen%s: Illegal -i arg (%s): Must be of the format: number[s]\n", TagName, optarg);
1475 fprintf(stderr, " where 'number' is >= 0\n");
1484 fprintf(stderr, "iogen%s: Unrecognized option -L on this platform\n", TagName);
1487 if( parse_ranges(optarg, 1, 255, 1, NULL, &ranges,
1489 fprintf(stderr, "iogen%s: error parsing listio range '%s': %s\n",
1490 TagName, optarg, errmsg);
1494 Minstrides = range_min(ranges, 0);
1495 Maxstrides = range_max(ranges, 0);
1503 if ((Offset_Mode = str_lookup(Omode_Map, optarg)) == NULL) {
1504 fprintf(stderr, "iogen%s: Illegal -m arg (%s)\n", TagName, optarg);
1512 sprintf( TagName, "(%.39s)", optarg );
1521 nopenargs = string_to_tokens(optarg, openargs, 4, ":/");
1525 sscanf(openargs[1],"%i", &Ocbits);
1527 sscanf(openargs[2],"%i", &Ocblks);
1529 Oflags = parse_open_flags(openargs[0], &errmsg);
1531 fprintf(stderr, "iogen%s: -O %s error: %s\n", TagName, optarg, errmsg);
1536 if(!strcmp(openargs[0], "realtime")) {
1538 * -O realtime:extsize
1542 sscanf(openargs[1],"%i", &Oextsize);
1545 } else if( !strcmp(openargs[0], "allocate") ||
1546 !strcmp(openargs[0], "allocsp")) {
1552 } else if(!strcmp(openargs[0], "reserve")) {
1558 } else if(!strcmp(openargs[0], "noreserve")) {
1559 /* Oreserve=1 by default; this clears that default */
1561 } else if(!strcmp(openargs[0], "nowrite")) {
1562 /* Owrite=1 by default; this clears that default */
1564 } else if(!strcmp(openargs[0], "direct")) {
1565 /* this means "use direct i/o to preallocate file" */
1568 fprintf(stderr, "iogen%s: Error: -O %s error: unrecognized option\n",
1569 TagName, openargs[0]);
1573 Oflags = parse_open_flags(openargs[0], &errmsg);
1575 fprintf(stderr, "iogen%s: -O %s error: %s\n", TagName, optarg, errmsg);
1589 if ((Rawmult = str_to_bytes(optarg)) == -1 ||
1590 Rawmult < 11 || Rawmult % BSIZE) {
1591 fprintf(stderr, "iogen%s: Illegal -r arg (%s). Must be > 0 and multipe of BSIZE (%d)\n",
1592 TagName, optarg, BSIZE);
1600 cp = strtok(optarg, ",");
1601 while (cp != NULL) {
1602 if ((sc = str_lookup(Syscall_Map, cp)) == NULL) {
1603 fprintf(stderr, "iogen%s: Unrecognized syscall: %s\n", TagName, cp);
1608 /* >>> sc->m_flags & FLG_SDS */
1609 if (sc->m_value != SSREAD && sc->m_value != SSWRITE)
1612 Syscall_List[Nsyscalls++] = sc;
1613 } while ( (sc = str_lookup(++sc, cp)) != NULL);
1615 cp = strtok(NULL, ",");
1621 if ((Mintrans = str_to_bytes(optarg)) == -1) {
1622 fprintf(stderr, "iogen%s: Illegal -t arg (%s): Must have the form num[bkm]\n", TagName, optarg);
1629 if ((Maxtrans = str_to_bytes(optarg)) == -1) {
1630 fprintf(stderr, "iogen%s: Illegal -T arg (%s): Must have the form num[bkm]\n", TagName, optarg);
1656 Offset_Mode = str_lookup(Omode_Map, "sequential");
1665 Maxtrans = 256 * BSIZE;
1668 Oflags = Ocbits = Ocblks = 0;
1671 * Supply default async io completion strategy types.
1675 for (mp = Aio_Strat_Map; mp->m_string != NULL; mp++) {
1676 Aio_Strat_List[Naio_Strat_Types++] = mp;
1681 * Supply default syscalls. Default is read,write,reada,writea,listio.
1686 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "read");
1687 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "write");
1689 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "reada");
1690 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "writea");
1691 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lread");
1692 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lreada");
1693 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lwrite");
1694 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "lwritea");
1697 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "pread");
1698 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "pwrite");
1700 /*Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "aread");*/
1701 /*Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "awrite");*/
1705 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "readv");
1706 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "writev");
1707 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "mmread");
1708 Syscall_List[Nsyscalls++] = str_lookup(Syscall_Map, "mmwrite");
1714 if (Fileio && (argc - optind < 1)) {
1715 fprintf(stderr, "iogen%s: No files specified on the cmdline\n", TagName);
1720 * Supply default file io flags - defaut is 'buffered,raw,sync,ldraw'.
1723 if (! f_opt && Fileio) {
1725 Flag_List[Nflags++] = str_lookup(Flag_Map, "buffered");
1726 Flag_List[Nflags++] = str_lookup(Flag_Map, "sync");
1728 Flag_List[Nflags++] = str_lookup(Flag_Map, "raw+wf");
1729 Flag_List[Nflags++] = str_lookup(Flag_Map, "ldraw");
1733 /* Warning: cannot mix direct i/o with others! */
1734 Flag_List[Nflags++] = str_lookup(Flag_Map, "dsync");
1735 Flag_List[Nflags++] = str_lookup(Flag_Map, "rsync");
1736 /* Flag_List[Nflags++] = str_lookup(Flag_Map, "rsync+sync");*/
1737 /* Flag_List[Nflags++] = str_lookup(Flag_Map, "rsync+dsync");*/
1742 if (optind >= argc) {
1743 fprintf(stderr, "iogen%s: No files listed on the cmdline\n", TagName);
1748 * Initialize File_List[] - only necessary if doing file io. First
1749 * space for the File_List array, then fill it in.
1752 File_List = (struct file_info *)
1753 malloc((argc-optind) * sizeof(struct file_info));
1755 if (File_List == NULL) {
1756 fprintf(stderr, "iogen%s: Could not malloc space for %d file_info structures\n", TagName, argc-optind);
1760 memset(File_List, 0, (argc-optind) * sizeof(struct file_info));
1763 while (optind < argc) {
1767 * Pick off leading len: if it's there and create/extend/trunc
1768 * the file to the desired length. Otherwise, just make sure
1769 * the file is accessable.
1772 if ((cp = strchr(argv[optind], ':')) != NULL) {
1774 if ((len = str_to_bytes(argv[optind])) == -1) {
1776 "iogen%s: illegal file length (%s) for file %s\n",
1777 TagName, argv[optind], cp+1);
1783 if (strlen(file) > MAX_FNAME_LENGTH) {
1784 fprintf(stderr, "iogen%s: Max fname length is %d chars - ignoring file %s\n",
1785 TagName, MAX_FNAME_LENGTH, file);
1790 nb = create_file(file, len);
1794 "iogen%s warning: Couldn't create file %s of %d bytes\n",
1795 TagName, file, len);
1803 file = argv[optind];
1804 if (access(file, R_OK | W_OK) == -1) {
1805 fprintf(stderr, "iogen%s: file %s cannot be accessed for reading and/or writing: %s (%d)\n",
1806 TagName, file, SYSERR, errno);
1812 * get per-file information
1815 fptr = &File_List[Nfiles];
1817 if (file[0] == '/') {
1818 strcpy(fptr->f_path, file);
1820 getcwd(fptr->f_path,
1821 sizeof(fptr->f_path)-1);
1822 strcat(fptr->f_path, "/");
1823 strcat(fptr->f_path, file);
1826 if (get_file_info(fptr) == -1) {
1827 fprintf(stderr, "iogen%s warning: Error getting file info for %s\n", TagName, file);
1831 * If the file length is smaller than our min transfer size,
1835 if (fptr->f_length < Mintrans) {
1836 fprintf(stderr, "iogen%s warning: Ignoring file %s\n",
1837 TagName, fptr->f_path);
1838 fprintf(stderr, " length (%d) is < min transfer size (%d)\n",
1839 fptr->f_length, Mintrans);
1845 * If the file length is smaller than our max transfer size,
1849 if (fptr->f_length < Maxtrans) {
1850 fprintf(stderr, "iogen%s warning: Ignoring file %s\n",
1851 TagName, fptr->f_path);
1852 fprintf(stderr, " length (%d) is < max transfer size (%d)\n",
1853 fptr->f_length, Maxtrans);
1858 if (fptr->f_length > 0) {
1859 switch (Offset_Mode->m_value) {
1861 fptr->f_lastoffset = 0;
1862 fptr->f_lastlength = 0;
1866 fptr->f_lastoffset = fptr->f_length;
1867 fptr->f_lastlength = 0;
1871 fptr->f_lastoffset = fptr->f_length / 2;
1872 fptr->f_lastlength = 0;
1884 fprintf(stderr, "iogen%s: Could not create, or gather info for any test files\n", TagName);
1897 fprintf(stream, "\n");
1899 fprintf(stream, "\t-a aio_type,... Async io completion types to choose. Supported types\n");
1901 #if _UMK || RELEASE_LEVEL >= 8000
1902 fprintf(stream, "\t are: poll, signal, recall, recalla, and recalls.\n");
1904 fprintf(stream, "\t are: poll, signal, recalla, and recalls.\n");
1907 fprintf(stream, "\t are: poll, signal, suspend, and callback.\n");
1909 fprintf(stream, "\t Default is all of the above.\n");
1911 fprintf(stream, "\t-a (Not used on Linux).\n");
1913 fprintf(stream, "\t-f flag,... Flags to use for file IO. Supported flags are\n");
1915 fprintf(stream, "\t raw, ssd, buffered, ldraw, sync,\n");
1916 fprintf(stream, "\t raw+wf, raw+wf+ldraw, raw+wf+ldraw+sync,\n");
1917 fprintf(stream, "\t and parallel (unicos/mk on MPP only).\n");
1918 fprintf(stream, "\t Default is 'raw,ldraw,sync,buffered'.\n");
1921 fprintf(stream, "\t buffered, direct, sync.\n");
1922 fprintf(stream, "\t Default is 'buffered,sync'.\n");
1924 fprintf(stream, "\t buffered, sync.\n");
1925 fprintf(stream, "\t Default is 'buffered,sync'.\n");
1928 fprintf(stream, "\t-h This help.\n");
1929 fprintf(stream, "\t-i iterations[s] # of requests to generate. 0 means causes iogen\n");
1930 fprintf(stream, "\t to run until it's killed. If iterations is suffixed\n");
1931 fprintf(stream, "\t with 's', then iterations is the number of seconds\n");
1932 fprintf(stream, "\t that iogen should run for. Default is '0'.\n");
1934 fprintf(stream, "\t-L min:max listio nstrides / nrequests range\n");
1936 fprintf(stream, "\t-L (Not used on this platform).\n");
1938 fprintf(stream, "\t-m offset-mode The mode by which iogen chooses the offset for\n");
1939 fprintf(stream, "\t consectutive transfers within a given file.\n");
1940 fprintf(stream, "\t Allowed values are 'random', 'sequential',\n");
1941 fprintf(stream, "\t and 'reverse'.\n");
1942 fprintf(stream, "\t sequential is the default.\n");
1943 fprintf(stream, "\t-N tagname Tag name, for Monster.\n");
1944 fprintf(stream, "\t-o Form overlapping consecutive requests.\n");
1945 fprintf(stream, "\t-O Open flags for creating files\n");
1947 fprintf(stream, "\t {O_PLACE,O_BIG,etc}[:CBITS[:CBLKS]]\n");
1950 fprintf(stream, "\t realtime:extsize - put file on real-time volume\n");
1951 fprintf(stream, "\t allocate - allocate space with F_ALLOCSP\n");
1952 fprintf(stream, "\t reserve - reserve space with F_RESVSP (default)\n");
1953 fprintf(stream, "\t noreserve - do not reserve with F_RESVSP\n");
1954 fprintf(stream, "\t direct - use O_DIRECT I/O to write to the file\n");
1956 fprintf(stream, "\t {O_SYNC,etc}\n");
1958 fprintf(stream, "\t-p Output pipe. Default is stdout.\n");
1959 fprintf(stream, "\t-q Quiet mode. Normally iogen spits out info\n");
1960 fprintf(stream, "\t about test files, options, etc. before starting.\n");
1961 fprintf(stream, "\t-s syscall,... Syscalls to do. Supported syscalls are\n");
1963 fprintf(stream, "\t read, write, pread, pwrite, readv, writev\n");
1964 fprintf(stream, "\t aread, awrite, resvsp, unresvsp, ffsync,\n");
1965 fprintf(stream, "\t mmread, mmwrite, fsync2, fdatasync,\n");
1966 fprintf(stream, "\t Default is 'read,write,pread,pwrite,readv,writev,mmread,mmwrite'.\n");
1969 fprintf(stream, "\t read, write, reada, writea, listio,\n");
1970 fprintf(stream, "\t ssread (PVP only), and sswrite (PVP only).\n");
1971 fprintf(stream, "\t Default is 'read,write,reada,writea,listio'.\n");
1974 fprintf(stream, "\t read, write, pread, pwrite, readv, writev,\n");
1975 fprintf(stream, "\t mmread, mmwrite, fsync2, fdatasync,\n");
1976 fprintf(stream, "\t Default is 'read,write,readv,writev,mmread,mmwrite'.\n");
1978 fprintf(stream, "\t-t mintrans Min transfer length\n");
1979 fprintf(stream, "\t-T maxtrans Max transfer length\n");
1980 fprintf(stream, "\n");
1981 fprintf(stream, "\t[len:]file,... Test files to do IO against (note ssread/sswrite\n");
1982 fprintf(stream, "\t don't need a test file). The len: syntax\n");
1983 fprintf(stream, "\t informs iogen to first create/expand/truncate the\n");
1984 fprintf(stream, "\t to the desired length.\n");
1985 fprintf(stream, "\n");
1986 fprintf(stream, "\tNote: The ssd flag causes sds transfers to also be done.\n");
1987 fprintf(stream, "\t To totally eliminate sds transfers, you must eleminate sds\n");
1988 fprintf(stream, "\t from the flags (-f) and ssread,ssrite from the syscalls (-s)\n");
1989 fprintf(stream, "\tThe mintrans, maxtrans, and len: parameters are numbers of the\n");
1990 fprintf(stream, "\tform [0-9]+[bkm]. The optional trailing b, k, or m multiplies\n");
1991 fprintf(stream, "\tthe number by blocks, kilobytes, or megabytes. If no trailing\n");
1992 fprintf(stream, "\tmultiplier is present, the number is interpreted as bytes\n");
1998 * Obvious - usage clause
2005 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);