From 3b8b7135602a4d3a7132fee10da9c1203ab643ad Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 10 Jun 2008 19:46:23 +0200 Subject: [PATCH 1/1] Add option priorities For instance, filename= must come after directory= or things will go wrong. So add a priority value to each option, so that the parser will take that into account. Signed-off-by: Jens Axboe --- fio.h | 2 +- init.c | 40 ++++++++++++++++++++++++-------- options.c | 12 ++++++++-- parse.c | 68 +++++++++++++++++++++++++++++++++++++++++++------------ parse.h | 2 ++ 5 files changed, 97 insertions(+), 27 deletions(-) diff --git a/fio.h b/fio.h index 207b2ecd..ff4668e8 100644 --- a/fio.h +++ b/fio.h @@ -820,7 +820,7 @@ extern void set_genesis_time(void); * Init/option functions */ extern int __must_check parse_options(int, char **); -extern int fio_option_parse(struct thread_data *, const char *); +extern int fio_options_parse(struct thread_data *, char **, int); extern int fio_cmd_option_parse(struct thread_data *, const char *, char *); extern void fio_fill_default_options(struct thread_data *); extern int fio_show_option_help(const char *); diff --git a/init.c b/init.c index a13e8b3c..b192e587 100644 --- a/init.c +++ b/init.c @@ -614,6 +614,8 @@ static int parse_jobs_ini(char *file, int stonewall_flag) int first_sect = 1; int skip_fgets = 0; int inside_skip = 0; + char **opts; + int i, alloc_opts, num_opts; if (!strcmp(file, "-")) f = stdin; @@ -633,6 +635,9 @@ static int parse_jobs_ini(char *file, int stonewall_flag) name = malloc(280); memset(name, 0, 280); + alloc_opts = 8; + opts = malloc(sizeof(char *) * alloc_opts); + stonewall = stonewall_flag; do { /* @@ -691,6 +696,9 @@ static int parse_jobs_ini(char *file, int stonewall_flag) stonewall = 0; } + num_opts = 0; + memset(opts, 0, alloc_opts * sizeof(char *)); + while ((p = fgets(string, 4096, f)) != NULL) { if (is_empty_or_comment(p)) continue; @@ -708,27 +716,39 @@ static int parse_jobs_ini(char *file, int stonewall_flag) strip_blank_end(p); - /* - * Don't break here, continue parsing options so we - * dump all the bad ones. Makes trial/error fixups - * easier on the user. - */ - ret |= fio_option_parse(td, p); - if (!ret && dump_cmdline) - log_info("--%s ", p); + if (num_opts == alloc_opts) { + alloc_opts <<= 1; + opts = realloc(opts, + alloc_opts * sizeof(char *)); + } + + opts[num_opts] = strdup(p); + num_opts++; } - if (!ret) + ret = fio_options_parse(td, opts, num_opts); + if (!ret) { + if (dump_cmdline) + for (i = 0; i < num_opts; i++) + log_info("--%s ", opts[i]); + ret = add_job(td, name, 0); - else { + } else { log_err("fio: job %s dropped\n", name); put_job(td); } + + for (i = 0; i < num_opts; i++) + free(opts[i]); + num_opts = 0; } while (!ret); if (dump_cmdline) log_info("\n"); + for (i = 0; i < num_opts; i++) + free(opts[i]); + free(string); free(name); if (f != stdin) diff --git a/options.c b/options.c index a7225eab..07e93045 100644 --- a/options.c +++ b/options.c @@ -463,6 +463,7 @@ static struct fio_option options[] = { .type = FIO_OPT_STR_STORE, .off1 = td_var_offset(filename), .cb = str_filename_cb, + .prio = 1, /* must come before "directory" */ .help = "File(s) to use for the workload", }, { @@ -1306,9 +1307,16 @@ void fio_options_dup_and_init(struct option *long_options) } } -int fio_option_parse(struct thread_data *td, const char *opt) +int fio_options_parse(struct thread_data *td, char **opts, int num_opts) { - return parse_option(opt, options, td); + int i, ret; + + sort_options(opts, options, num_opts); + + for (ret = 0, i = 0; i < num_opts; i++) + ret |= parse_option(opts[i], options, td); + + return ret; } int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val) diff --git a/parse.c b/parse.c index ca78f904..b9466901 100644 --- a/parse.c +++ b/parse.c @@ -12,6 +12,8 @@ #include "parse.h" #include "debug.h" +static struct fio_option *fio_options; + static int vp_cmp(const void *p1, const void *p2) { const struct value_pair *vp1 = p1; @@ -459,6 +461,56 @@ static int handle_option(struct fio_option *o, const char *ptr, void *data) return r1 && r2; } +static struct fio_option *get_option(const char *opt, + struct fio_option *options, char **post) +{ + struct fio_option *o; + char *ret; + + ret = strchr(opt, '='); + if (ret) { + *post = ret; + *ret = '\0'; + ret = (char *) opt; + (*post)++; + o = find_option(options, ret); + } else { + o = find_option(options, opt); + *post = NULL; + } + + return o; +} + +static int opt_cmp(const void *p1, const void *p2) +{ + struct fio_option *o1, *o2; + char *s1, *s2, *foo; + int ret; + + s1 = strdup(*((char **) p1)); + s2 = strdup(*((char **) p2)); + + o1 = get_option(s1, fio_options, &foo); + o2 = get_option(s2, fio_options, &foo); + + if ((!o1 && o2) || (o1 && !o2)) + ret = 0; + else + ret = o2->prio - o1->prio; + + free(s1); + free(s2); + return ret; +} + +void sort_options(char **opts, struct fio_option *options, int num_opts) +{ + fio_options = options; + qsort(opts, num_opts, sizeof(char *), opt_cmp); + fio_options = NULL; +} + int parse_cmd_option(const char *opt, const char *val, struct fio_option *options, void *data) { @@ -480,23 +532,11 @@ int parse_cmd_option(const char *opt, const char *val, int parse_option(const char *opt, struct fio_option *options, void *data) { struct fio_option *o; - char *pre, *post; - char *tmp; + char *post, *tmp; tmp = strdup(opt); - pre = strchr(tmp, '='); - if (pre) { - post = pre; - *pre = '\0'; - pre = tmp; - post++; - o = find_option(options, pre); - } else { - o = find_option(options, tmp); - post = NULL; - } - + o = get_option(tmp, options, &post); if (!o) { fprintf(stderr, "Bad option %s\n", tmp); free(tmp); diff --git a/parse.h b/parse.h index 4e8124f8..4f3f94d0 100644 --- a/parse.h +++ b/parse.h @@ -42,6 +42,7 @@ struct fio_option { unsigned int maxval; /* max and min value */ int minval; int neg; /* negate value stored */ + int prio; void *cb; /* callback */ const char *help; /* help text for option */ const char *def; /* default setting */ @@ -52,6 +53,7 @@ struct fio_option { typedef int (str_cb_fn)(void *, char *); extern int parse_option(const char *, struct fio_option *, void *); +extern void sort_options(char **, struct fio_option *, int); extern int parse_cmd_option(const char *t, const char *l, struct fio_option *, void *); extern int show_cmd_help(struct fio_option *, const char *); extern void fill_default_options(void *, struct fio_option *); -- 2.25.1