Move handling of possible values into the option parser
authorJens Axboe <jens.axboe@oracle.com>
Fri, 23 Feb 2007 09:29:16 +0000 (10:29 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 23 Feb 2007 09:29:16 +0000 (10:29 +0100)
Eliminates the need for a callback for any FIO_OPT_STR type
option, unless it needs to do something there other than just
setting the variable.

The possible options are not in an array of value pairs, so we
can easily match an string option with an integer output value.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fio.h
init.c
parse.c
parse.h

diff --git a/fio.h b/fio.h
index 8880ea61e7a518c02bc33840f9b0f8571a0c6b76..6abbd79e2dfd7e737f57ffdfca83a5c2e9b9bf8b 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -29,10 +29,13 @@ enum fio_ddir {
 };
 
 enum td_ddir {
 };
 
 enum td_ddir {
-       TD_DDIR_READ    = 1 << 0,
-       TD_DDIR_WRITE   = 1 << 1,
-       TD_DDIR_RAND    = 1 << 2,
-       TD_DDIR_RW      = TD_DDIR_READ | TD_DDIR_WRITE,
+       TD_DDIR_READ            = 1 << 0,
+       TD_DDIR_WRITE           = 1 << 1,
+       TD_DDIR_RAND            = 1 << 2,
+       TD_DDIR_RW              = TD_DDIR_READ | TD_DDIR_WRITE,
+       TD_DDIR_RANDREAD        = TD_DDIR_READ | TD_DDIR_RAND,
+       TD_DDIR_RANDWRITE       = TD_DDIR_WRITE | TD_DDIR_READ,
+       TD_DDIR_RANDRW          = TD_DDIR_RW | TD_DDIR_RAND,
 };
 
 /*
 };
 
 /*
@@ -274,6 +277,7 @@ struct thread_stat {
  * This describes a single thread/process executing a fio job.
  */
 struct thread_data {
  * This describes a single thread/process executing a fio job.
  */
 struct thread_data {
+       int pad;
        char *description;
        char *name;
        char *directory;
        char *description;
        char *name;
        char *directory;
diff --git a/init.c b/init.c
index 9ed99d797feace5c46cba7e2141450633174bbe0..557382b6a1b8c2e25c4ff42aaf1ab85a1c0ff0fa 100644 (file)
--- a/init.c
+++ b/init.c
 
 #define td_var_offset(var)     ((size_t) &((struct thread_data *)0)->var)
 
 
 #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_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 *);
 static int str_lockmem_cb(void *, unsigned long *);
 #ifdef FIO_HAVE_IOPRIO
 static int str_prio_cb(void *, unsigned int *);
@@ -33,7 +31,6 @@ static int str_prioclass_cb(void *, unsigned int *);
 #endif
 static int str_exitall_cb(void);
 static int str_cpumask_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)
 
 #define __stringify_1(x)       #x
 #define __stringify(x)         __stringify_1(x)
@@ -69,11 +66,17 @@ static struct fio_option options[] = {
        {
                .name   = "rw",
                .type   = FIO_OPT_STR,
        {
                .name   = "rw",
                .type   = FIO_OPT_STR,
-               .cb     = str_rw_cb,
+               .off1   = td_var_offset(td_ddir),
                .help   = "IO direction",
                .def    = "read",
                .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",
        },
        {
                .name   = "ioengine",
@@ -81,8 +84,13 @@ static struct fio_option options[] = {
                .cb     = str_ioengine_cb,
                .help   = "IO engine to use",
                .def    = "sync",
                .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   = "iodepth",
@@ -156,10 +164,13 @@ static struct fio_option options[] = {
        {
                .name   = "file_service_type",
                .type   = FIO_OPT_STR,
        {
                .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",
                .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   = "fsync",
@@ -223,17 +234,32 @@ static struct fio_option options[] = {
                .name   = "mem",
                .type   = FIO_OPT_STR,
                .cb     = str_mem_cb,
                .name   = "mem",
                .type   = FIO_OPT_STR,
                .cb     = str_mem_cb,
+               .off1   = td_var_offset(mem_type),
                .help   = "Backing type for IO buffers",
                .def    = "malloc",
                .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,
        },
        {
                .name   = "verify",
                .type   = FIO_OPT_STR,
-               .cb     = str_verify_cb,
+               .off1   = td_var_offset(verify),
                .help   = "Verify sum function",
                .def    = "0",
                .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",
        },
        {
                .name   = "write_iolog",
@@ -926,53 +952,6 @@ static int is_empty_or_comment(char *line)
        return 1;
 }
 
        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.
  */
 /*
  * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
  */
@@ -993,49 +972,15 @@ static int str_mem_cb(void *data, const char *mem)
 {
        struct thread_data *td = data;
 
 {
        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);
                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;
                }
                        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)
 }
 
 static int str_ioengine_cb(void *data, const char *str)
@@ -1089,22 +1034,6 @@ static int str_cpumask_cb(void *data, unsigned int *val)
        return 0;
 }
 
        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.
  */
 /*
  * This is our [ini] type file parser.
  */
@@ -1234,7 +1163,7 @@ static void usage(void)
 static int parse_cmd_line(int argc, char *argv[])
 {
        struct thread_data *td = NULL;
 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) {
 
        while ((c = getopt_long(argc, argv, "", long_options, &lidx)) != -1) {
                switch (c) {
@@ -1289,9 +1218,8 @@ static int parse_cmd_line(int argc, char *argv[])
 
                        ret = parse_cmd_option(opt, val, options, td);
                        if (ret) {
 
                        ret = parse_cmd_option(opt, val, options, td);
                        if (ret) {
+                               dont_add_job = 1;
                                log_err("fio: job dropped\n");
                                log_err("fio: job dropped\n");
-                               put_job(td);
-                               td = NULL;
                        }
                        break;
                }
                        }
                        break;
                }
@@ -1301,9 +1229,13 @@ static int parse_cmd_line(int argc, char *argv[])
        }
 
        if (td) {
        }
 
        if (td) {
-               ret = add_job(td, td->name ?: "fio", 0);
-               if (ret)
+               if (dont_add_job)
                        put_job(td);
                        put_job(td);
+               else {
+                       ret = add_job(td, td->name ?: "fio", 0);
+                       if (ret)
+                               put_job(td);
+               }
        }
 
        while (optind < argc) {
        }
 
        while (optind < argc) {
diff --git a/parse.c b/parse.c
index 7fb2bb6399cc564b038f6889a5f2fb3f603b5719..d300a219dbef9fcb8a2be1aa643429027916d6ae 100644 (file)
--- a/parse.c
+++ b/parse.c
 
 #include "parse.h"
 
 
 #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) {
 static unsigned long get_mult_time(char c)
 {
        switch (c) {
@@ -165,8 +194,27 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data,
        switch (o->type) {
        case FIO_OPT_STR: {
                fio_opt_str_fn *fn = o->cb;
        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:
                break;
        }
        case FIO_OPT_STR_VAL_TIME:
@@ -387,38 +435,6 @@ int parse_option(const char *opt, struct fio_option *options, void *data)
        return 1;
 }
 
        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");
 int show_cmd_help(struct fio_option *options, const char *name)
 {
        int show_all = !strcmp(name, "all");
@@ -487,6 +503,10 @@ void options_init(struct fio_option *options)
                        o->minval = 0;
                        o->maxval = 1;
                }
                        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);
        }
                if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4))
                        fprintf(stderr, "Option %s: both cb and offset given\n", o->name);
        }
diff --git a/parse.h b/parse.h
index 7374c258ab95a339cff8853707a567df2ad68422..214e56b4769d9c5a5faa3b2589e6b85f5e81b3ad 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -16,6 +16,16 @@ enum fio_opt_type {
        FIO_OPT_STR_SET,
 };
 
        FIO_OPT_STR_SET,
 };
 
+/*
+ * Match a possible value string with the integer option.
+ */
+struct value_pair {
+       const char *ival;               /* string option */
+       unsigned int oval;              /* output value */
+};
+
+#define PARSE_MAX_VP   16
+
 /*
  * Option define
  */
 /*
  * Option define
  */
@@ -33,7 +43,7 @@ struct fio_option {
        void *cb;                       /* callback */
        const char *help;               /* help text for option */
        const char *def;                /* default setting */
        void *cb;                       /* callback */
        const char *help;               /* help text for option */
        const char *def;                /* default setting */
-       const char *posval[16];         /* possible values */
+       const struct value_pair posval[PARSE_MAX_VP];/* possible values */
 };
 
 typedef int (str_cb_fn)(void *, char *);
 };
 
 typedef int (str_cb_fn)(void *, char *);