return 0;
}
+/*
+ * Option grouping
+ */
+static struct opt_group fio_opt_groups[] = {
+ {
+ .name = "Description",
+ .mask = FIO_OPT_G_DESC,
+ },
+ {
+ .name = "File",
+ .mask = FIO_OPT_G_FILE,
+ },
+ {
+ .name = "Misc",
+ .mask = FIO_OPT_G_MISC,
+ },
+ {
+ .name = "IO (main)",
+ .mask = FIO_OPT_G_IO,
+ },
+ {
+ .name = "IO direction",
+ .mask = FIO_OPT_G_IO_DDIR,
+ },
+ {
+ .name = "IO buffer",
+ .mask = FIO_OPT_G_IO_BUF,
+ },
+ {
+ .name = "IO engine",
+ .mask = FIO_OPT_G_IO_ENG,
+ },
+ {
+ .name = "Random",
+ .mask = FIO_OPT_G_RAND,
+ },
+ {
+ .name = "OS",
+ .mask = FIO_OPT_G_OS,
+ },
+ {
+ .name = "Memory",
+ .mask = FIO_OPT_G_MEM,
+ },
+ {
+ .name = "Verify",
+ .mask = FIO_OPT_G_VERIFY,
+ },
+ {
+ .name = "CPU",
+ .mask = FIO_OPT_G_CPU,
+ },
+ {
+ .name = "Log",
+ .mask = FIO_OPT_G_LOG,
+ },
+ {
+ .name = "Zone",
+ .mask = FIO_OPT_G_ZONE,
+ },
+ {
+ .name = "Cache",
+ .mask = FIO_OPT_G_CACHE,
+ },
+ {
+ .name = "Stat",
+ .mask = FIO_OPT_G_STAT,
+ },
+ {
+ .name = "Error",
+ .mask = FIO_OPT_G_ERR,
+ },
+ {
+ .name = "Job",
+ .mask = FIO_OPT_G_JOB,
+ },
+ {
+ .name = NULL,
+ },
+};
+
+struct opt_group *opt_group_from_mask(unsigned int *mask)
+{
+ struct opt_group *og;
+ int i;
+
+ if (*mask == FIO_OPT_G_INVALID)
+ return NULL;
+
+ for (i = 0; fio_opt_groups[i].name; i++) {
+ og = &fio_opt_groups[i];
+
+ if (*mask & og->mask) {
+ *mask &= ~(og->mask);
+ return og;
+ }
+ }
+
+ return NULL;
+}
+
/*
* Map of job/command line options
*/
-static struct fio_option options[FIO_MAX_OPTS] = {
+struct fio_option fio_options[FIO_MAX_OPTS] = {
{
.name = "description",
.type = FIO_OPT_STR_STORE,
.off1 = td_var_offset(file_lock_mode),
.help = "Lock file when doing IO to it",
.parent = "filename",
+ .hide = 0,
.def = "none",
.category = FIO_OPT_G_FILE,
.posval = {
.off1 = td_var_offset(iodepth),
.help = "Number of IO buffers to keep in flight",
.minval = 1,
+ .interval = 1,
.def = "1",
.category = FIO_OPT_G_IO,
},
.off1 = td_var_offset(iodepth_batch),
.help = "Number of IO buffers to submit in one go",
.parent = "iodepth",
+ .hide = 1,
.minval = 1,
+ .interval = 1,
.def = "1",
.category = FIO_OPT_G_IO,
},
.off1 = td_var_offset(iodepth_batch_complete),
.help = "Number of IO buffers to retrieve in one go",
.parent = "iodepth",
+ .hide = 1,
.minval = 0,
+ .interval = 1,
.def = "1",
.category = FIO_OPT_G_IO,
},
.off1 = td_var_offset(iodepth_low),
.help = "Low water mark for queuing depth",
.parent = "iodepth",
+ .hide = 1,
+ .interval = 1,
.category = FIO_OPT_G_IO,
},
{
.type = FIO_OPT_STR_VAL,
.cb = str_size_cb,
.help = "Total size of device or files",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_IO,
},
{
.off2 = td_var_offset(file_size_high),
.minval = 1,
.help = "Size of individual files",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_IO | FIO_OPT_G_FILE,
},
{
.off1 = td_var_offset(start_offset),
.help = "Start IO from this offset",
.def = "0",
+ .interval = 1024 * 1024,
+ .category = FIO_OPT_G_IO,
+ },
+ {
+ .name = "offset_increment",
+ .type = FIO_OPT_STR_VAL,
+ .off1 = td_var_offset(offset_increment),
+ .help = "What is the increment from one offset to the next",
+ .parent = "offset",
+ .hide = 1,
+ .def = "0",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_IO,
},
{
.help = "Block size unit",
.def = "4k",
.parent = "rw",
+ .hide = 1,
+ .interval = 512,
.category = FIO_OPT_G_IO,
},
{
.minval = 1,
.help = "IO block offset alignment",
.parent = "rw",
+ .hide = 1,
+ .interval = 512,
.category = FIO_OPT_G_IO | FIO_OPT_G_IO_BUF,
},
{
.minval = 1,
.help = "Set block size range (in more detail than bs)",
.parent = "rw",
+ .hide = 1,
+ .interval = 4096,
.category = FIO_OPT_G_IO,
},
{
.cb = str_bssplit_cb,
.help = "Set a specific mix of block sizes",
.parent = "rw",
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.off1 = td_var_offset(bs_unaligned),
.help = "Don't sector align IO buffer sizes",
.parent = "rw",
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.help = "Use repeatable random IO pattern",
.def = "1",
.parent = "rw",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_RAND,
},
{
.help = "Set to use OS random generator",
.def = "0",
.parent = "rw",
+ .hide = 1,
.category = FIO_OPT_G_RAND,
},
{
.off1 = td_var_offset(norandommap),
.help = "Accept potential duplicate random blocks",
.parent = "rw",
+ .hide = 1,
.category = FIO_OPT_G_RAND,
},
{
.off1 = td_var_offset(softrandommap),
.help = "Set norandommap if randommap allocation fails",
.parent = "norandommap",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_RAND,
},
.off1 = td_var_offset(nr_files),
.help = "Split job workload between this number of files",
.def = "1",
+ .interval = 1,
.category = FIO_OPT_G_FILE,
},
{
},
},
.parent = "nrfiles",
+ .hide = 1,
},
#ifdef FIO_HAVE_FALLOCATE
{
.off1 = td_var_offset(fsync_blocks),
.help = "Issue fsync for writes every given number of blocks",
.def = "0",
+ .interval = 1,
.category = FIO_OPT_G_FILE,
},
{
.off1 = td_var_offset(fdatasync_blocks),
.help = "Issue fdatasync for writes every given number of blocks",
.def = "0",
+ .interval = 1,
.category = FIO_OPT_G_FILE,
},
{
.off1 = td_var_offset(barrier_blocks),
.help = "Make every Nth write a barrier write",
.def = "0",
+ .interval = 1,
.category = FIO_OPT_G_IO,
},
#ifdef FIO_HAVE_SYNC_FILE_RANGE
.off1 = td_var_offset(loops),
.help = "Number of times to run the job",
.def = "1",
+ .interval = 1,
.category = FIO_OPT_G_MISC,
},
{
.off1 = td_var_offset(numjobs),
.help = "Duplicate this job this many times",
.def = "1",
+ .interval = 1,
.category = FIO_OPT_G_MISC,
},
{
.help = "IO memory buffer offset alignment",
.def = "0",
.parent = "iomem",
+ .hide = 1,
.category = FIO_OPT_G_IO_BUF | FIO_OPT_G_MEM,
},
{
.help = "Run verification stage after write",
.def = "1",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.help = "Sort written verify blocks for read back",
.def = "1",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.minval = 2 * sizeof(struct verify_header),
.help = "Store verify buffer header every N bytes",
.parent = "verify",
+ .hide = 1,
+ .interval = 2 * sizeof(struct verify_header),
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.def = "0",
.cb = str_verify_offset_cb,
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.cb = str_verify_pattern_cb,
.help = "Fill pattern for IO buffers",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.def = "0",
.help = "Exit on a single verify failure, don't continue",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY | FIO_OPT_G_ERR,
},
{
.def = "0",
.help = "Dump contents of good and bad blocks on failure",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY | FIO_OPT_G_ERR,
},
{
.def = "0",
.help = "Number of async verifier threads to use",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.off1 = td_var_offset(verify_backlog),
.help = "Verify after this number of blocks are written",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
{
.off1 = td_var_offset(verify_batch),
.help = "Verify this number of IO blocks",
.parent = "verify",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_VERIFY,
},
#ifdef FIO_HAVE_CPU_AFFINITY
.cb = str_verify_cpus_allowed_cb,
.help = "Set CPUs allowed for async verify threads",
.parent = "verify_async",
+ .hide = 1,
.category = FIO_OPT_G_OS | FIO_OPT_G_CPU | FIO_OPT_G_VERIFY,
},
#endif
.name = "trim_percentage",
.type = FIO_OPT_INT,
.cb = str_verify_trim_cb,
+ .minval = 0,
.maxval = 100,
.help = "Number of verify blocks to discard/trim",
.parent = "verify",
.def = "0",
+ .interval = 1,
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.name = "trim_verify_zero",
- .type = FIO_OPT_INT,
+ .type = FIO_OPT_BOOL,
.help = "Verify that trim/discarded blocks are returned as zeroes",
.off1 = td_var_offset(trim_zero),
.parent = "trim_percentage",
+ .hide = 1,
.def = "1",
.category = FIO_OPT_G_IO,
},
.off1 = td_var_offset(trim_backlog),
.help = "Trim after this number of blocks are written",
.parent = "trim_percentage",
+ .hide = 1,
+ .interval = 1,
.category = FIO_OPT_G_IO,
},
{
.off1 = td_var_offset(trim_batch),
.help = "Trim this number of IO blocks",
.parent = "trim_percentage",
+ .hide = 1,
+ .interval = 1,
.category = FIO_OPT_G_IO,
},
#endif
},
{
.name = "replay_no_stall",
- .type = FIO_OPT_INT,
+ .type = FIO_OPT_BOOL,
.off1 = td_var_offset(no_stall),
.def = "0",
.parent = "read_iolog",
+ .hide = 1,
.help = "Playback IO pattern file as fast as possible without stalls",
.category = FIO_OPT_G_IO | FIO_OPT_G_LOG,
},
.type = FIO_OPT_STR_STORE,
.off1 = td_var_offset(replay_redirect),
.parent = "read_iolog",
+ .hide = 1,
.help = "Replay all I/O onto this device, regardless of trace device",
.category = FIO_OPT_G_IO | FIO_OPT_G_LOG,
},
.off1 = td_var_offset(zone_size),
.help = "Amount of data to read per zone",
.def = "0",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_IO | FIO_OPT_G_ZONE,
},
{
.off1 = td_var_offset(zone_range),
.help = "Give size of an IO zone",
.def = "0",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_IO | FIO_OPT_G_ZONE,
},
{
.off1 = td_var_offset(zone_skip),
.help = "Space between IO zones",
.def = "0",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_IO | FIO_OPT_G_ZONE,
},
{
.cb = str_lockmem_cb,
.help = "Lock down this amount of memory",
.def = "0",
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_OS | FIO_OPT_G_MEM,
},
{
.maxval = 100,
.help = "Percentage of mixed workload that is reads",
.def = "50",
+ .interval = 5,
.category = FIO_OPT_G_IO,
},
{
.maxval = 100,
.help = "Percentage of mixed workload that is writes",
.def = "50",
+ .interval = 5,
.category = FIO_OPT_G_IO,
},
{
.minval = -19,
.maxval = 20,
.def = "0",
+ .interval = 1,
.category = FIO_OPT_G_OS | FIO_OPT_G_CPU,
},
#ifdef FIO_HAVE_IOPRIO
.help = "Set job IO priority value",
.minval = 0,
.maxval = 7,
+ .interval = 1,
.category = FIO_OPT_G_OS | FIO_OPT_G_CPU,
},
{
.help = "Set job IO priority class",
.minval = 0,
.maxval = 3,
+ .interval = 1,
.category = FIO_OPT_G_OS | FIO_OPT_G_CPU,
},
#endif
.help = "Start think time by spinning this amount (usec)",
.def = "0",
.parent = "thinktime",
+ .hide = 1,
.category = FIO_OPT_G_MISC,
},
{
.help = "IO buffer period between 'thinktime'",
.def = "1",
.parent = "thinktime",
+ .hide = 1,
.category = FIO_OPT_G_MISC,
},
{
.off2 = td_var_offset(ratemin[1]),
.help = "Job must meet this rate or it will be shutdown",
.parent = "rate",
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.off1 = td_var_offset(rate_iops[0]),
.off2 = td_var_offset(rate_iops[1]),
.help = "Limit IO used to this number of IO operations/sec",
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.off2 = td_var_offset(rate_iops_min[1]),
.help = "Job must meet this rate or it will be shut down",
.parent = "rate_iops",
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.help = "Window average for rate limits (msec)",
.def = "1000",
.parent = "rate",
+ .hide = 1,
.category = FIO_OPT_G_IO,
},
{
.help = "Use O_SYNC for buffered writes",
.def = "0",
.parent = "buffered",
+ .hide = 1,
.category = FIO_OPT_G_IO | FIO_OPT_G_FILE,
},
{
" (msec)",
.def = "500",
.parent = "write_bw_log",
+ .hide = 1,
+ .interval = 100,
.category = FIO_OPT_G_LOG | FIO_OPT_G_STAT,
},
{
.help = "Time window over which to calculate IOPS (msec)",
.def = "500",
.parent = "write_iops_log",
+ .hide = 1,
+ .interval = 100,
.category = FIO_OPT_G_LOG | FIO_OPT_G_STAT,
},
{
.help = "Length of the CPU burn cycles (usecs)",
.def = "50000",
.parent = "cpuload",
+ .hide = 1,
.category = FIO_OPT_G_CPU,
},
#ifdef FIO_HAVE_CPU_AFFINITY
.name = "thread",
.type = FIO_OPT_STR_SET,
.off1 = td_var_offset(use_thread),
- .help = "Use threads instead of forks",
+ .help = "Use threads instead of processes",
.category = FIO_OPT_G_MISC | FIO_OPT_G_OS | FIO_OPT_G_JOB,
},
{
.off1 = td_var_offset(hugepage_size),
.help = "When using hugepages, specify size of each page",
.def = __fio_stringify(FIO_HUGE_PAGE),
+ .interval = 1024 * 1024,
.category = FIO_OPT_G_OS | FIO_OPT_G_MEM,
},
{
.maxval = 100,
.minval = 1,
.help = "How compressible the buffer is (approximately)",
+ .interval = 5,
+ .category = FIO_OPT_G_IO_BUF,
},
{
.name = "buffer_compress_chunk",
.type = FIO_OPT_INT,
.off1 = td_var_offset(compress_chunk),
.parent = "buffer_compress_percentage",
+ .hide = 1,
.help = "Size of compressible region in buffer",
+ .interval = 256,
+ .category = FIO_OPT_G_IO_BUF,
},
{
.name = "clat_percentiles",
.off1 = td_var_offset(disable_lat),
.help = "Disable latency numbers",
.parent = "gtod_reduce",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_OS | FIO_OPT_G_MISC | FIO_OPT_G_STAT,
},
.off1 = td_var_offset(disable_clat),
.help = "Disable completion latency numbers",
.parent = "gtod_reduce",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_OS | FIO_OPT_G_MISC | FIO_OPT_G_STAT,
},
.off1 = td_var_offset(disable_slat),
.help = "Disable submission latency numbers",
.parent = "gtod_reduce",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_OS | FIO_OPT_G_MISC | FIO_OPT_G_STAT,
},
.off1 = td_var_offset(disable_bw),
.help = "Disable bandwidth logging",
.parent = "gtod_reduce",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_OS | FIO_OPT_G_MISC | FIO_OPT_G_STAT,
},
.off1 = td_var_offset(flow),
.help = "Weight for flow control of this job",
.parent = "flow_id",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_IO,
},
" should be set to the same value for all threads"
" with non-zero flow.",
.parent = "flow_id",
+ .hide = 1,
.def = "1024",
.category = FIO_OPT_G_IO,
},
.help = "How many microseconds to sleep after being held"
" back by the flow control mechanism",
.parent = "flow_id",
+ .hide = 1,
.def = "0",
.category = FIO_OPT_G_IO,
},
{
unsigned int i;
- options_init(options);
+ options_init(fio_options);
i = 0;
while (long_options[i].name)
i++;
- options_to_lopts(options, long_options, i, FIO_GETOPT_JOB);
+ options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
}
struct fio_keyword {
int i, ret, unknown;
char **opts_copy;
- sort_options(opts, options, num_opts);
+ sort_options(opts, fio_options, num_opts);
opts_copy = dup_and_sub_options(opts, num_opts);
for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
struct fio_option *o;
- int newret = parse_option(opts_copy[i], opts[i], options, &o,
- td);
+ int newret = parse_option(opts_copy[i], opts[i], fio_options,
+ &o, td);
if (opts_copy[i]) {
if (newret && !o) {
int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
{
- return parse_cmd_option(opt, val, options, td);
+ return parse_cmd_option(opt, val, fio_options, td);
}
int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
void fio_fill_default_options(struct thread_data *td)
{
- fill_default_options(td, options);
+ fill_default_options(td, fio_options);
}
int fio_show_option_help(const char *opt)
{
- return show_cmd_help(options, opt);
+ return show_cmd_help(fio_options, opt);
}
void options_mem_dupe(void *data, struct fio_option *options)
*/
void fio_options_mem_dupe(struct thread_data *td)
{
- options_mem_dupe(&td->o, options);
+ options_mem_dupe(&td->o, fio_options);
if (td->eo && td->io_ops) {
void *oldeo = td->eo;
struct fio_option *__o;
int opt_index = 0;
- __o = options;
+ __o = fio_options;
while (__o->name) {
opt_index++;
__o++;
}
- memcpy(&options[opt_index], o, sizeof(*o));
+ memcpy(&fio_options[opt_index], o, sizeof(*o));
return 0;
}
{
struct fio_option *o;
- o = options;
+ o = fio_options;
while (o->name) {
if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
o->type = FIO_OPT_INVALID;
struct fio_option *o;
unsigned int i;
- o = find_option(options, optname);
+ o = find_option(fio_options, optname);
if (!o)
return;
struct fio_option *o;
unsigned int i;
- o = find_option(options, optname);
+ o = find_option(fio_options, optname);
if (!o)
return;
void fio_options_free(struct thread_data *td)
{
- options_free(options, td);
+ options_free(fio_options, td);
if (td->eo && td->io_ops && td->io_ops->options) {
options_free(td->io_ops->options, td->eo);
free(td->eo);