Cleanup profile support
This is closer to where it needs to end up. No ext_options, just
include profile options in the general option table (and mark them
private for that profile).
Profile options are only available after loading a specific profile,
so there should be less confusion.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/fio.c b/fio.c
index 778749d..c33f786 100644
--- a/fio.c
+++ b/fio.c
@@ -40,6 +40,7 @@
#include "verify.h"
#include "diskutil.h"
#include "cgroup.h"
+#include "profile.h"
unsigned long page_mask;
unsigned long page_size;
@@ -1653,6 +1654,9 @@
if (parse_options(argc, argv))
return 1;
+ if (exec_profile && load_profile(exec_profile))
+ return 1;
+
if (!thread_number)
return 0;
diff --git a/fio.h b/fio.h
index 91a28b4..23e007b 100644
--- a/fio.h
+++ b/fio.h
@@ -29,6 +29,7 @@
#include "ioengine.h"
#include "iolog.h"
#include "helpers.h"
+#include "options.h"
#ifdef FIO_HAVE_GUASI
#include <guasi.h>
@@ -539,7 +540,7 @@
extern void td_fill_rand_seeds(struct thread_data *);
extern void add_job_opts(const char **);
#define FIO_GETOPT_JOB 0x89988998
-#define FIO_NR_OPTIONS 512
+#define FIO_NR_OPTIONS (FIO_MAX_OPTS + 128)
/*
* ETA/status stuff
diff --git a/init.c b/init.c
index c0ce431..acebb7d 100644
--- a/init.c
+++ b/init.c
@@ -39,6 +39,7 @@
FILE *f_out = NULL;
FILE *f_err = NULL;
char *job_section = NULL;
+char *exec_profile = NULL;
int write_bw_log = 0;
int read_only = 0;
@@ -1114,8 +1115,7 @@
job_section = strdup(optarg);
break;
case 'p':
- if (load_profile(optarg))
- do_exit++;
+ exec_profile = strdup(optarg);
break;
case FIO_GETOPT_JOB: {
const char *opt = l_opts[lidx].name;
@@ -1204,6 +1204,8 @@
if (!thread_number) {
if (dump_cmdline)
return 0;
+ if (exec_profile)
+ return 0;
log_err("No jobs defined(s)\n\n");
usage(argv[0]);
diff --git a/options.c b/options.c
index 6cfd80d..da9d0be 100644
--- a/options.c
+++ b/options.c
@@ -16,8 +16,6 @@
#include "lib/fls.h"
#include "options.h"
-static FLIST_HEAD(ext_opt_list);
-
/*
* Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
*/
@@ -736,7 +734,7 @@
/*
* Map of job/command line options
*/
-static struct fio_option options[] = {
+static struct fio_option options[FIO_MAX_OPTS] = {
{
.name = "description",
.type = FIO_OPT_STR_STORE,
@@ -1774,8 +1772,6 @@
void fio_options_dup_and_init(struct option *long_options)
{
struct fio_option *o;
- struct ext_option *eo;
- struct flist_head *n;
unsigned int i;
options_init(options);
@@ -1792,13 +1788,6 @@
o++;
assert(i < FIO_NR_OPTIONS);
}
-
- flist_for_each(n, &ext_opt_list) {
- eo = flist_entry(n, struct ext_option, list);
- add_to_lopt(&long_options[i], &eo->o);
- i++;
- assert(i < FIO_NR_OPTIONS);
- }
}
struct fio_keyword {
@@ -1955,7 +1944,7 @@
for (ret = 0, i = 0; i < num_opts; i++) {
opts[i] = fio_keyword_replace(opts[i]);
- ret |= parse_option(opts[i], options, &ext_opt_list, td);
+ ret |= parse_option(opts[i], options, td);
}
return ret;
@@ -1963,7 +1952,7 @@
int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
{
- return parse_cmd_option(opt, val, options, &ext_opt_list, td);
+ return parse_cmd_option(opt, val, options, td);
}
void fio_fill_default_options(struct thread_data *td)
@@ -1973,7 +1962,7 @@
int fio_show_option_help(const char *opt)
{
- return show_cmd_help(options, &ext_opt_list, opt);
+ return show_cmd_help(options, opt);
}
static void __options_mem(struct thread_data *td, int alloc)
@@ -2027,23 +2016,31 @@
return kb_base;
}
-void register_ext_option(struct ext_option *eopt)
+int add_option(struct fio_option *o)
{
- dprint(FD_PARSE, "register option '%s'\n", eopt->o.name);
- option_init(&eopt->o);
- flist_add_tail(&eopt->list, &ext_opt_list);
+ struct fio_option *__o;
+ int opt_index = 0;
+
+ __o = options;
+ while (__o->name) {
+ opt_index++;
+ __o++;
+ }
+
+ memcpy(&options[opt_index], o, sizeof(*o));
+ return 0;
}
-void prune_profile_options(const char *prof_name)
+void invalidate_profile_options(const char *prof_name)
{
- struct ext_option *eo;
- struct flist_head *n, *tmp;
+ struct fio_option *o;
- flist_for_each_safe(n, tmp, &ext_opt_list) {
- eo = flist_entry(n, struct ext_option, list);
- if (strcmp(eo->prof_name, prof_name))
- continue;
- flist_del(&eo->list);
- free(eo);
+ o = options;
+ while (o->name) {
+ if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
+ o->type = FIO_OPT_INVALID;
+ o->prof_name = NULL;
+ }
+ o++;
}
}
diff --git a/options.h b/options.h
index 96c81a1..cf823fc 100644
--- a/options.h
+++ b/options.h
@@ -1,18 +1,15 @@
#ifndef FIO_OPTION_H
#define FIO_OPTION_H
+#define FIO_MAX_OPTS 512
+
#include "parse.h"
#include "flist.h"
#define td_var_offset(var) ((size_t) &((struct thread_options *)0)->var)
-struct ext_option {
- struct flist_head list;
- const char *prof_name;
- struct fio_option o;
-};
-
-void register_ext_option(struct ext_option *);
-void prune_profile_options(const char *);
+int add_option(struct fio_option *);
+void invalidate_profile_options(const char *);
+extern char *exec_profile;
#endif
diff --git a/parse.c b/parse.c
index 9c0965f..98e623a 100644
--- a/parse.c
+++ b/parse.c
@@ -78,6 +78,7 @@
static void show_option_help(struct fio_option *o, FILE *out)
{
const char *typehelp[] = {
+ "invalid",
"string (opt=bla)",
"string with possible k/m/g postfix (opt=4k)",
"string with time postfix (opt=10s)",
@@ -86,6 +87,7 @@
"integer value (opt=100)",
"boolean value (opt=1)",
"no argument (opt)",
+ "deprecated",
};
if (o->alias)
@@ -93,6 +95,8 @@
fprintf(out, "%20s: %s\n", "type", typehelp[o->type]);
fprintf(out, "%20s: %s\n", "default", o->def ? o->def : "no default");
+ if (o->prof_name)
+ fprintf(out, "%20s: only for profile '%s'\n", "valid", o->prof_name);
show_option_range(o, stdout);
show_option_values(o);
}
@@ -265,26 +269,14 @@
}
static struct fio_option *find_option(struct fio_option *options,
- struct flist_head *eops, const char *opt)
+ const char *opt)
{
- struct flist_head *n;
struct fio_option *o;
for (o = &options[0]; o->name; o++)
if (o_match(o, opt))
return o;
- if (!eops)
- return NULL;
-
- flist_for_each(n, eops) {
- struct ext_option *eopt;
-
- eopt = flist_entry(n, struct ext_option, list);
- if (o_match(&eopt->o, opt))
- return &eopt->o;
- }
-
return NULL;
}
@@ -604,8 +596,7 @@
}
static struct fio_option *get_option(const char *opt,
- struct fio_option *options,
- struct flist_head *eops, char **post)
+ struct fio_option *options, char **post)
{
struct fio_option *o;
char *ret;
@@ -617,9 +608,9 @@
ret = (char *) opt;
(*post)++;
strip_blank_end(ret);
- o = find_option(options, eops, ret);
+ o = find_option(options, ret);
} else {
- o = find_option(options, eops, opt);
+ o = find_option(options, opt);
*post = NULL;
}
@@ -635,8 +626,8 @@
s1 = strdup(*((char **) p1));
s2 = strdup(*((char **) p2));
- o1 = get_option(s1, fio_options, NULL, &foo);
- o2 = get_option(s2, fio_options, NULL, &foo);
+ o1 = get_option(s1, fio_options, &foo);
+ o2 = get_option(s2, fio_options, &foo);
prio1 = prio2 = 0;
if (o1)
@@ -657,12 +648,11 @@
}
int parse_cmd_option(const char *opt, const char *val,
- struct fio_option *options, struct flist_head *eops,
- void *data)
+ struct fio_option *options, void *data)
{
struct fio_option *o;
- o = find_option(options, eops, opt);
+ o = find_option(options, opt);
if (!o) {
fprintf(stderr, "Bad option <%s>\n", opt);
return 1;
@@ -729,8 +719,7 @@
return strdup(out);
}
-int parse_option(const char *opt, struct fio_option *options,
- struct flist_head *ext_opt_list, void *data)
+int parse_option(const char *opt, struct fio_option *options, void *data)
{
struct fio_option *o;
char *post, *tmp;
@@ -739,7 +728,7 @@
if (!tmp)
return 1;
- o = get_option(tmp, options, ext_opt_list, &post);
+ o = get_option(tmp, options, &post);
if (!o) {
fprintf(stderr, "Bad option <%s>\n", tmp);
free(tmp);
@@ -852,11 +841,8 @@
} while (printed);
}
-int show_cmd_help(struct fio_option *options, struct flist_head *ext_opts,
- const char *name)
+int show_cmd_help(struct fio_option *options, const char *name)
{
- struct flist_head *n;
- struct ext_option *eo;
struct fio_option *o, *closest;
unsigned int best_dist;
int found = 0;
@@ -872,6 +858,8 @@
if (o->type == FIO_OPT_DEPRECATED)
continue;
+ if (!exec_profile && o->prof_name)
+ continue;
if (name) {
if (!strcmp(name, o->name) ||
@@ -891,7 +879,7 @@
if (show_all || match) {
found = 1;
if (match)
- printf("%24s: %s\n", o->name, o->help);
+ printf("%20s: %s\n", o->name, o->help);
if (show_all) {
if (!o->parent)
print_option(o);
@@ -908,18 +896,6 @@
if (found)
return 0;
- flist_for_each(n, ext_opts) {
- eo = flist_entry(n, struct ext_option, list);
- o = &eo->o;
- if (!strcmp(name, o->name) ||
- (o->alias && !strcmp(name, o->alias))) {
- printf("%20s: %s\n", o->name, o->help);
- show_option_help(o, stdout);
- printf("%20s: External, valid for '%s'\n", "Restriction", eo->prof_name);
- return 0;
- }
- }
-
printf("No such command: %s", name);
if (closest) {
printf(" - showing closest match\n");
diff --git a/parse.h b/parse.h
index 5f602a3..8f7982a 100644
--- a/parse.h
+++ b/parse.h
@@ -7,7 +7,8 @@
* Option types
*/
enum fio_opt_type {
- FIO_OPT_STR = 0,
+ FIO_OPT_INVALID = 0,
+ FIO_OPT_STR,
FIO_OPT_STR_VAL,
FIO_OPT_STR_VAL_TIME,
FIO_OPT_STR_STORE,
@@ -52,14 +53,15 @@
const struct value_pair posval[PARSE_MAX_VP];/* possible values */
const char *parent; /* parent option */
int (*verify)(struct fio_option *, void *);
+ const char *prof_name; /* only valid for specific profile */
};
typedef int (str_cb_fn)(void *, char *);
-extern int parse_option(const char *, struct fio_option *, struct flist_head *, void *);
+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 *, struct flist_head *, void *);
-extern int show_cmd_help(struct fio_option *, struct flist_head *, const char *);
+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 *);
extern void option_init(struct fio_option *);
extern void options_init(struct fio_option *);
diff --git a/profile.c b/profile.c
index 44e6269..354b06d 100644
--- a/profile.c
+++ b/profile.c
@@ -31,34 +31,40 @@
return 1;
}
-static void add_profile_options(struct profile_ops *ops)
+static int add_profile_options(struct profile_ops *ops)
{
- struct fio_option *fo;
- struct ext_option *eo;
+ struct fio_option *o;
if (!ops->options)
- return;
+ return 0;
- fo = ops->options;
- while (fo->name) {
- eo = malloc(sizeof(*eo));
- eo->prof_name = ops->name;
- memcpy(&eo->o, fo, sizeof(*fo));
- register_ext_option(eo);
- fo++;
+ o = ops->options;
+ while (o->name) {
+ o->prof_name = ops->name;
+ if (add_option(o))
+ return 1;
+ o++;
}
+
+ return 0;
}
-void register_profile(struct profile_ops *ops)
+int register_profile(struct profile_ops *ops)
{
+ int ret;
+
dprint(FD_PROFILE, "register profile '%s'\n", ops->name);
flist_add_tail(&ops->list, &profile_list);
- add_profile_options(ops);
+ ret = add_profile_options(ops);
+ if (ret)
+ invalidate_profile_options(ops->name);
+
+ return ret;
}
void unregister_profile(struct profile_ops *ops)
{
dprint(FD_PROFILE, "unregister profile '%s'\n", ops->name);
flist_del(&ops->list);
- prune_profile_options(ops->name);
+ invalidate_profile_options(ops->name);
}
diff --git a/profile.h b/profile.h
index 8ea77d9..dbfb9c2 100644
--- a/profile.h
+++ b/profile.h
@@ -24,7 +24,7 @@
const char **cmdline;
};
-void register_profile(struct profile_ops *);
+int register_profile(struct profile_ops *);
void unregister_profile(struct profile_ops *);
int load_profile(const char *);
diff --git a/profiles/tiobench.c b/profiles/tiobench.c
index 4bdcfa2..aba0785 100644
--- a/profiles/tiobench.c
+++ b/profiles/tiobench.c
@@ -92,7 +92,8 @@
static void fio_init tiobench_register(void)
{
- register_profile(&tiobench_profile);
+ if (register_profile(&tiobench_profile))
+ log_err("fio: failed to register profile 'tiobench'\n");
}
static void fio_exit tiobench_unregister(void)