#define td_var_offset(var) ((size_t) &((struct thread_data *)0)->var)
-static int str_rw_cb(void *, const char *);
static int str_ioengine_cb(void *, const char *);
static int str_mem_cb(void *, const char *);
-static int str_verify_cb(void *, const char *);
static int str_lockmem_cb(void *, unsigned long *);
#ifdef FIO_HAVE_IOPRIO
static int str_prio_cb(void *, unsigned int *);
#endif
static int str_exitall_cb(void);
static int str_cpumask_cb(void *, unsigned int *);
-static int str_file_service_cb(void *, const char *);
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
{
.name = "rw",
.type = FIO_OPT_STR,
- .cb = str_rw_cb,
+ .off1 = td_var_offset(td_ddir),
.help = "IO direction",
.def = "read",
- .posval = { "read", "write", "randwrite", "randread", "rw",
- "randrw", },
+ .posval = {
+ { .ival = "read", .oval = TD_DDIR_READ },
+ { .ival = "write", .oval = TD_DDIR_WRITE },
+ { .ival = "randread", .oval = TD_DDIR_RANDREAD },
+ { .ival = "randwrite", .oval = TD_DDIR_RANDWRITE },
+ { .ival = "rw", .oval = TD_DDIR_RW },
+ { .ival = "randrw", .oval = TD_DDIR_RANDRW },
+ },
},
{
.name = "ioengine",
.cb = str_ioengine_cb,
.help = "IO engine to use",
.def = "sync",
- .posval = { "sync", "libaio", "posixaio", "mmap", "splice",
- "sg", "null", "net", "syslet-rw" },
+ .posval = {
+ { .ival = "sync", }, { .ival = "libaio", },
+ { .ival = "posixaio", }, { .ival = "mmap", },
+ { .ival = "splice", }, { .ival = "sg", },
+ { .ival = "null", }, { .ival = "net", },
+ { .ival = "syslet-rw", },
+ },
},
{
.name = "iodepth",
{
.name = "file_service_type",
.type = FIO_OPT_STR,
- .cb = str_file_service_cb,
+ .off1 = td_var_offset(file_service_type),
.help = "How to select which file to service next",
.def = "roundrobin",
- .posval = { "random", "roundrobin" },
+ .posval = {
+ { .ival = "random", .oval = FIO_FSERVICE_RANDOM },
+ { .ival = "roundrobin", .oval = FIO_FSERVICE_RR },
+ },
},
{
.name = "fsync",
.name = "mem",
.type = FIO_OPT_STR,
.cb = str_mem_cb,
+ .off1 = td_var_offset(mem_type),
.help = "Backing type for IO buffers",
.def = "malloc",
- .posval = { "malloc", "shm", "shmhuge", "mmap", "mmaphuge", },
+ .posval = {
+ { .ival = "malloc", .oval = MEM_MALLOC },
+ { .ival = "shm", .oval = MEM_SHM },
+#ifdef FIO_HAVE_HUGETLB
+ { .ival = "shmhuge", .oval = MEM_SHMHUGE },
+#endif
+ { .ival = "mmap", .oval = MEM_MMAP },
+#ifdef FIO_HAVE_HUGETLB
+ { .ival = "mmaphuge", .oval = MEM_MMAPHUGE },
+#endif
+ },
},
{
.name = "verify",
.type = FIO_OPT_STR,
- .cb = str_verify_cb,
+ .off1 = td_var_offset(verify),
.help = "Verify sum function",
.def = "0",
- .posval = { "crc32", "md5", },
+ .posval = {
+ { .ival = "0", .oval = VERIFY_NONE },
+ { .ival = "crc32", .oval = VERIFY_CRC32 },
+ { .ival = "md5", .oval = VERIFY_MD5 },
+ },
},
{
.name = "write_iolog",
return 1;
}
-static int str_rw_cb(void *data, const char *mem)
-{
- struct thread_data *td = data;
-
- if (!strncmp(mem, "read", 4) || !strncmp(mem, "0", 1)) {
- td->td_ddir = TD_DDIR_READ;
- return 0;
- } else if (!strncmp(mem, "randread", 8)) {
- td->td_ddir = TD_DDIR_READ | TD_DDIR_RAND;
- return 0;
- } else if (!strncmp(mem, "write", 5) || !strncmp(mem, "1", 1)) {
- td->td_ddir = TD_DDIR_WRITE;
- return 0;
- } else if (!strncmp(mem, "randwrite", 9)) {
- td->td_ddir = TD_DDIR_WRITE | TD_DDIR_RAND;
- return 0;
- } else if (!strncmp(mem, "rw", 2)) {
- td->td_ddir = TD_DDIR_RW;
- return 0;
- } else if (!strncmp(mem, "randrw", 6)) {
- td->td_ddir = TD_DDIR_RW | TD_DDIR_RAND;
- return 0;
- }
-
- log_err("fio: data direction: read, write, randread, randwrite, rw, randrw\n");
- return 1;
-}
-
-static int str_verify_cb(void *data, const char *mem)
-{
- struct thread_data *td = data;
-
- if (!strncmp(mem, "0", 1)) {
- td->verify = VERIFY_NONE;
- return 0;
- } else if (!strncmp(mem, "md5", 3) || !strncmp(mem, "1", 1)) {
- td->verify = VERIFY_MD5;
- return 0;
- } else if (!strncmp(mem, "crc32", 5)) {
- td->verify = VERIFY_CRC32;
- return 0;
- }
-
- log_err("fio: verify types: md5, crc32\n");
- return 1;
-}
-
/*
* Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
*/
{
struct thread_data *td = data;
- if (!strncmp(mem, "malloc", 6)) {
- td->mem_type = MEM_MALLOC;
- return 0;
- } else if (!strncmp(mem, "mmaphuge", 8)) {
-#ifdef FIO_HAVE_HUGETLB
- /*
- * mmaphuge must be appended with the actual file
- */
+ if (td->mem_type == MEM_MMAPHUGE || td->mem_type == MEM_MMAP) {
td->mmapfile = get_mmap_file(mem);
- if (!td->mmapfile) {
+ if (td->mem_type == MEM_MMAPHUGE && !td->mmapfile) {
log_err("fio: mmaphuge:/path/to/file\n");
return 1;
}
-
- td->mem_type = MEM_MMAPHUGE;
- return 0;
-#else
- log_err("fio: mmaphuge not available\n");
- return 1;
-#endif
- } else if (!strncmp(mem, "mmap", 4)) {
- /*
- * Check if the user wants file backed memory. It's ok
- * if there's no file given, we'll just use anon mamp then.
- */
- td->mmapfile = get_mmap_file(mem);
- td->mem_type = MEM_MMAP;
- return 0;
- } else if (!strncmp(mem, "shmhuge", 7)) {
-#ifdef FIO_HAVE_HUGETLB
- td->mem_type = MEM_SHMHUGE;
- return 0;
-#else
- log_err("fio: shmhuge not available\n");
- return 1;
-#endif
- } else if (!strncmp(mem, "shm", 3)) {
- td->mem_type = MEM_SHM;
- return 0;
}
- log_err("fio: mem type: malloc, shm, shmhuge, mmap, mmaphuge\n");
- return 1;
+ return 0;
}
static int str_ioengine_cb(void *data, const char *str)
return 0;
}
-static int str_file_service_cb(void *data, const char *str)
-{
- struct thread_data *td = data;
-
- if (!strncmp(str, "random", 6)) {
- td->file_service_type = FIO_FSERVICE_RANDOM;
- return 0;
- } else if (!strncmp(str, "roundrobin", 10)) {
- td->file_service_type = FIO_FSERVICE_RR;
- return 0;
- }
-
- log_err("fio: file_service= random, roundrobin\n");
- return 1;
-}
-
/*
* This is our [ini] type file parser.
*/
static int parse_cmd_line(int argc, char *argv[])
{
struct thread_data *td = NULL;
- int c, ini_idx = 0, lidx, ret;
+ int c, ini_idx = 0, lidx, ret, dont_add_job = 0;
while ((c = getopt_long(argc, argv, "", long_options, &lidx)) != -1) {
switch (c) {
ret = parse_cmd_option(opt, val, options, td);
if (ret) {
+ dont_add_job = 1;
log_err("fio: job dropped\n");
- put_job(td);
- td = NULL;
}
break;
}
}
if (td) {
- ret = add_job(td, td->name ?: "fio", 0);
- if (ret)
+ if (dont_add_job)
put_job(td);
+ else {
+ ret = add_job(td, td->name ?: "fio", 0);
+ if (ret)
+ put_job(td);
+ }
}
while (optind < argc) {
#include "parse.h"
+static void show_option_range(struct fio_option *o)
+{
+ if (!o->minval && !o->maxval)
+ return;
+
+ printf("%16s: min=%d, max=%d\n", "range", o->minval, o->maxval);
+}
+
+static void show_option_values(struct fio_option *o)
+{
+ const char *msg;
+ int i = 0;
+
+ do {
+ msg = o->posval[i].ival;
+ if (!msg)
+ break;
+
+ if (!i)
+ printf("%16s: ", "valid values");
+
+ printf("%s,", msg);
+ i++;
+ } while (i < PARSE_MAX_VP);
+
+ if (i)
+ printf("\n");
+}
+
static unsigned long get_mult_time(char c)
{
switch (c) {
switch (o->type) {
case FIO_OPT_STR: {
fio_opt_str_fn *fn = o->cb;
+ const struct value_pair *vp;
+ int i;
+
+ ret = 1;
+ for (i = 0; i < PARSE_MAX_VP; i++) {
+ vp = &o->posval[i];
+ if (!vp->ival || vp->ival[0] == '\0')
+ break;
+ if (!strncmp(vp->ival, ptr, strlen(vp->ival))) {
+ ret = 0;
+ if (!o->off1)
+ break;
+ val_store(ilp, vp->oval, o->off1, data);
+ break;
+ }
+ }
- ret = fn(data, ptr);
+ if (ret)
+ show_option_values(o);
+ else if (fn)
+ ret = fn(data, ptr);
break;
}
case FIO_OPT_STR_VAL_TIME:
return 1;
}
-static void show_option_range(struct fio_option *o)
-{
- if (!o->minval && !o->maxval)
- return;
-
- printf("%16s: min=%d, max=%d\n", "range", o->minval, o->maxval);
-}
-
-static void show_option_values(struct fio_option *o)
-{
- const char *msg;
- int i = 0;
-
- if (!o->posval)
- return;
-
- do {
- msg = o->posval[i];
- if (!msg)
- break;
-
- if (!i)
- printf("%16s: ", "valid values");
-
- printf("%s,", msg);
- i++;
- } while (1);
-
- if (i)
- printf("\n");
-}
-
int show_cmd_help(struct fio_option *options, const char *name)
{
int show_all = !strcmp(name, "all");
o->minval = 0;
o->maxval = 1;
}
+ if (!o->cb && !o->off1)
+ fprintf(stderr, "Option %s: neither cb nor offset given\n", o->name);
+ if (o->type == FIO_OPT_STR)
+ continue;
if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4))
fprintf(stderr, "Option %s: both cb and offset given\n", o->name);
}