The following changes since commit 4ceb30d4b44957e252a75f7ee4170f36109934c3: Use log_info() more consistently (2010-02-24 09:19:14 +0100) are available in the git repository at: git://git.kernel.dk/fio.git master Jens Axboe (9): Add check for OPT_LEN_MAX being too small Quote profile name Add support for registrering external options Merge branch 'master' of ssh://router/data/git/fio Add support for loadable profiles Add parser support for out-of-td option storage Add initial support for profile specific options More progress on per-profile options support Make sure profile options get added to long_options[] Zhang, Yanmin (1): Increase OPT_LEN_MAX Makefile | 4 +- debug.h | 1 + fio.h | 6 +- flist.h | 2 + init.c | 110 +++++++++---------------- options.c | 64 +++++++++++---- options.h | 18 ++++ parse.c | 220 +++++++++++++++++++++++++++++++++++++-------------- parse.h | 12 ++- profile.c | 64 +++++++++++++++ profile.h | 31 +++++++ profiles.h | 10 --- profiles/tiobench.c | 101 +++++++++++++++++++++++ 13 files changed, 476 insertions(+), 167 deletions(-) create mode 100644 options.h create mode 100644 profile.c create mode 100644 profile.h delete mode 100644 profiles.h create mode 100644 profiles/tiobench.c --- Diff of recent changes: diff --git a/Makefile b/Makefile index ce63cfc..ce2374b 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SCRIPTS = fio_generate_plots OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \ eta.o verify.o memory.o io_u.o parse.o mutex.o options.o \ rbtree.o diskutil.o fifo.o blktrace.o smalloc.o filehash.o helpers.o \ - cgroup.o + cgroup.o profile.o OBJS += crc/crc7.o OBJS += crc/crc16.o @@ -32,6 +32,8 @@ OBJS += engines/net.o OBJS += engines/syslet-rw.o OBJS += engines/guasi.o +OBJS += profiles/tiobench.o + ifneq ($(findstring $(MAKEFLAGS),s),s) ifndef V QUIET_CC = @echo ' ' CC $@; diff --git a/debug.h b/debug.h index 1a2b79a..71b346d 100644 --- a/debug.h +++ b/debug.h @@ -16,6 +16,7 @@ enum { FD_DISKUTIL, FD_JOB, FD_MUTEX, + FD_PROFILE, FD_DEBUG_MAX, }; diff --git a/fio.h b/fio.h index bdc1708..91a28b4 100644 --- a/fio.h +++ b/fio.h @@ -28,7 +28,6 @@ #include "io_ddir.h" #include "ioengine.h" #include "iolog.h" -#include "profiles.h" #include "helpers.h" #ifdef FIO_HAVE_GUASI @@ -271,7 +270,7 @@ struct thread_options { /* * Benchmark profile type */ - unsigned int profile; + char *profile; /* * blkio cgroup support @@ -538,8 +537,9 @@ extern void fio_options_dup_and_init(struct option *); extern void options_mem_dupe(struct thread_data *); extern void options_mem_free(struct thread_data *); 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 128 +#define FIO_NR_OPTIONS 512 /* * ETA/status stuff diff --git a/flist.h b/flist.h index 95023c7..7aca973 100644 --- a/flist.h +++ b/flist.h @@ -1,6 +1,8 @@ #ifndef _LINUX_FLIST_H #define _LINUX_FLIST_H +#include <stdlib.h> + #undef offsetof #ifdef __compiler_offsetof #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) diff --git a/init.c b/init.c index 19c6340..c0ce431 100644 --- a/init.c +++ b/init.c @@ -19,6 +19,7 @@ #include "smalloc.h" #include "filehash.h" #include "verify.h" +#include "profile.h" static char fio_version_string[] = "fio 1.37"; @@ -136,26 +137,6 @@ static struct option l_opts[FIO_NR_OPTIONS] = { }, }; -static const char *tiobench_opts[] = { - "buffered=0", "size=4*1024*$mb_memory", "bs=4k", "timeout=600", - "numjobs=4", "group_reporting", "thread", "overwrite=1", - "filename=.fio.tio.1:.fio.tio.2:.fio.tio.3:.fio.tio.4", - "name=seqwrite", "rw=write", "end_fsync=1", - "name=randwrite", "stonewall", "rw=randwrite", "end_fsync=1", - "name=seqread", "stonewall", "rw=read", - "name=randread", "stonewall", "rw=randread", NULL, -}; - -static const char **fio_prof_strings[PROFILE_END] = { - NULL, - tiobench_opts, -}; - -static const char *profiles[PROFILE_END] = { - "none", - "tiobench", -}; - FILE *get_f_out() { return f_out; @@ -655,6 +636,43 @@ err: return -1; } +/* + * Parse as if 'o' was a command line + */ +void add_job_opts(const char **o) +{ + struct thread_data *td, *td_parent; + int i, in_global = 1; + char jobname[32]; + + i = 0; + td_parent = td = NULL; + while (o[i]) { + if (!strncmp(o[i], "name", 4)) { + in_global = 0; + if (td) + add_job(td, jobname, 0); + td = NULL; + sprintf(jobname, "%s", o[i] + 5); + } + if (in_global && !td_parent) + td_parent = get_new_job(1, &def_thread); + else if (!in_global && !td) { + if (!td_parent) + td_parent = &def_thread; + td = get_new_job(0, td_parent); + } + if (in_global) + fio_options_parse(td_parent, (char **) &o[i], 1); + else + fio_options_parse(td, (char **) &o[i], 1); + i++; + } + + if (td) + add_job(td, jobname, 0); +} + static int skip_this_section(const char *name) { if (!job_section) @@ -961,6 +979,7 @@ struct debug_level debug_levels[] = { { .name = "diskutil", .shift = FD_DISKUTIL }, { .name = "job", .shift = FD_JOB }, { .name = "mutex", .shift = FD_MUTEX }, + { .name = "profile", .shift = FD_PROFILE }, { .name = NULL, }, }; @@ -1028,57 +1047,6 @@ static int set_debug(const char *string) } #endif -static int load_profile(const char *profile) -{ - struct thread_data *td, *td_parent; - const char **o; - int i, in_global = 1; - char jobname[32]; - - dprint(FD_PARSE, "loading profile %s\n", profile); - - for (i = 0; i < PROFILE_END; i++) { - if (!strcmp(profile, profiles[i])) - break; - } - - if (i == PROFILE_END) { - log_err("fio: unknown profile %s\n", profile); - return 1; - } - - o = fio_prof_strings[i]; - if (!o) - return 0; - - i = 0; - td_parent = td = NULL; - while (o[i]) { - if (!strncmp(o[i], "name", 4)) { - in_global = 0; - if (td) - add_job(td, jobname, 0); - td = NULL; - sprintf(jobname, "%s", o[i] + 5); - } - if (in_global && !td_parent) - td_parent = get_new_job(1, &def_thread); - else if (!in_global && !td) { - if (!td_parent) - td_parent = &def_thread; - td = get_new_job(0, td_parent); - } - if (in_global) - fio_options_parse(td_parent, (char **) &o[i], 1); - else - fio_options_parse(td, (char **) &o[i], 1); - i++; - } - if (td) - add_job(td, jobname, 0); - return 0; -} - static int parse_cmd_line(int argc, char *argv[]) { struct thread_data *td = NULL; diff --git a/options.c b/options.c index 1c07982..6cfd80d 100644 --- a/options.c +++ b/options.c @@ -14,8 +14,9 @@ #include "verify.h" #include "parse.h" #include "lib/fls.h" +#include "options.h" -#define td_var_offset(var) ((size_t) &((struct thread_options *)0)->var) +static FLIST_HEAD(ext_opt_list); /* * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that. @@ -1725,14 +1726,8 @@ static struct fio_option options[] = { }, { .name = "profile", - .type = FIO_OPT_STR, + .type = FIO_OPT_STR_STORE, .off1 = td_var_offset(profile), - .posval = { - { .ival = "tiobench", - .oval = PROFILE_TIOBENCH, - .help = "Perform tiobench like test", - }, - }, .help = "Select a specific builtin performance test", }, { @@ -1766,9 +1761,21 @@ static struct fio_option options[] = { }, }; +static void add_to_lopt(struct option *lopt, struct fio_option *o) +{ + lopt->name = (char *) o->name; + lopt->val = FIO_GETOPT_JOB; + if (o->type == FIO_OPT_STR_SET) + lopt->has_arg = no_argument; + else + lopt->has_arg = required_argument; +} + 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); @@ -1779,17 +1786,19 @@ void fio_options_dup_and_init(struct option *long_options) o = &options[0]; while (o->name) { - long_options[i].name = (char *) o->name; - long_options[i].val = FIO_GETOPT_JOB; - if (o->type == FIO_OPT_STR_SET) - long_options[i].has_arg = no_argument; - else - long_options[i].has_arg = required_argument; + add_to_lopt(&long_options[i], o); i++; 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 { @@ -1946,7 +1955,7 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts) for (ret = 0, i = 0; i < num_opts; i++) { opts[i] = fio_keyword_replace(opts[i]); - ret |= parse_option(opts[i], options, td); + ret |= parse_option(opts[i], options, &ext_opt_list, td); } return ret; @@ -1954,7 +1963,7 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts) 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, options, &ext_opt_list, td); } void fio_fill_default_options(struct thread_data *td) @@ -1964,7 +1973,7 @@ void fio_fill_default_options(struct thread_data *td) int fio_show_option_help(const char *opt) { - return show_cmd_help(options, opt); + return show_cmd_help(options, &ext_opt_list, opt); } static void __options_mem(struct thread_data *td, int alloc) @@ -2017,3 +2026,24 @@ unsigned int fio_get_kb_base(void *data) return kb_base; } + +void register_ext_option(struct ext_option *eopt) +{ + dprint(FD_PARSE, "register option '%s'\n", eopt->o.name); + option_init(&eopt->o); + flist_add_tail(&eopt->list, &ext_opt_list); +} + +void prune_profile_options(const char *prof_name) +{ + struct ext_option *eo; + struct flist_head *n, *tmp; + + 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); + } +} diff --git a/options.h b/options.h new file mode 100644 index 0000000..96c81a1 --- /dev/null +++ b/options.h @@ -0,0 +1,18 @@ +#ifndef FIO_OPTION_H +#define FIO_OPTION_H + +#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 *); + +#endif diff --git a/parse.c b/parse.c index a55e52b..9c0965f 100644 --- a/parse.c +++ b/parse.c @@ -12,6 +12,7 @@ #include "parse.h" #include "debug.h" +#include "options.h" static struct fio_option *fio_options; extern unsigned int fio_get_kb_base(void *); @@ -253,16 +254,35 @@ static int check_int(const char *p, int *val) return 1; } +static inline int o_match(struct fio_option *o, const char *opt) +{ + if (!strcmp(o->name, opt)) + return 1; + else if (o->alias && !strcmp(o->alias, opt)) + return 1; + + return 0; +} + static struct fio_option *find_option(struct fio_option *options, - const char *opt) + struct flist_head *eops, const char *opt) { + struct flist_head *n; struct fio_option *o; - for (o = &options[0]; o->name; o++) { - if (!strcmp(o->name, opt)) - return o; - else if (o->alias && !strcmp(o->alias, opt)) + 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; @@ -307,9 +327,13 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, ret = 1; if (!strncmp(vp->ival, ptr, strlen(vp->ival))) { ret = 0; - if (!o->off1) - break; - val_store(ilp, vp->oval, o->off1, data); + if (o->roff1) + *(unsigned int *) o->roff1 = vp->oval; + else { + if (!o->off1) + break; + val_store(ilp, vp->oval, o->off1, data); + } break; } } @@ -349,15 +373,31 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, ret = fn(data, &ull); else { if (o->type == FIO_OPT_INT) { - if (first) - val_store(ilp, ull, o->off1, data); - if (!more && o->off2) - val_store(ilp, ull, o->off2, data); + if (first) { + if (o->roff1) + *(unsigned long long *) o->roff1 = ull; + else + val_store(ilp, ull, o->off1, data); + } + if (!more) { + if (o->roff2) + *(unsigned long long *) o->roff2 = ull; + else if (o->off2) + val_store(ilp, ull, o->off2, data); + } } else { - if (first) - val_store(ullp, ull, o->off1, data); - if (!more && o->off2) - val_store(ullp, ull, o->off2, data); + if (first) { + if (o->roff1) + *(unsigned long long *) o->roff1 = ull; + else + val_store(ullp, ull, o->off1, data); + } + if (!more) { + if (o->roff2) + *(unsigned long long *) o->roff2 = ull; + else if (o->off2) + val_store(ullp, ull, o->off2, data); + } } } break; @@ -365,7 +405,11 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, case FIO_OPT_STR_STORE: { fio_opt_str_fn *fn = o->cb; - cp = td_var(data, o->off1); + if (o->roff1) + cp = (char **) o->roff1; + else + cp = td_var(data, o->off1); + *cp = strdup(ptr); if (fn) { ret = fn(data, ptr); @@ -407,10 +451,19 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, } if (first) { - val_store(ilp, ul1, o->off1, data); - val_store(ilp, ul2, o->off2, data); + if (o->roff1) + *(unsigned long *) o->roff1 = ul1; + else + val_store(ilp, ul1, o->off1, data); + if (o->roff2) + *(unsigned long *) o->roff2 = ul2; + else + val_store(ilp, ul2, o->off2, data); } - if (o->off3 && o->off4) { + if (o->roff3 && o->roff4) { + *(unsigned long *) o->roff3 = ul1; + *(unsigned long *) o->roff4 = ul2; + } else if (o->off3 && o->off4) { val_store(ilp, ul1, o->off3, data); val_store(ilp, ul2, o->off4, data); } @@ -442,10 +495,18 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, if (fn) ret = fn(data, &il); else { - if (first) - val_store(ilp, il, o->off1, data); - if (!more && o->off2) - val_store(ilp, il, o->off2, data); + if (first) { + if (o->roff1) + *(unsigned int *)o->roff1 = il; + else + val_store(ilp, il, o->off1, data); + } + if (!more) { + if (o->roff2) + *(unsigned int *) o->roff2 = il; + else if (o->off2) + val_store(ilp, il, o->off2, data); + } } break; } @@ -455,10 +516,18 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, if (fn) ret = fn(data); else { - if (first) - val_store(ilp, 1, o->off1, data); - if (!more && o->off2) - val_store(ilp, 1, o->off2, data); + if (first) { + if (o->roff1) + *(unsigned int *) o->roff1 = 1; + else + val_store(ilp, 1, o->off1, data); + } + if (!more) { + if (o->roff2) + *(unsigned int *) o->roff2 = 1; + else if (o->off2) + val_store(ilp, 1, o->off2, data); + } } break; } @@ -535,7 +604,8 @@ static int handle_option(struct fio_option *o, const char *__ptr, void *data) } static struct fio_option *get_option(const char *opt, - struct fio_option *options, char **post) + struct fio_option *options, + struct flist_head *eops, char **post) { struct fio_option *o; char *ret; @@ -547,9 +617,9 @@ static struct fio_option *get_option(const char *opt, ret = (char *) opt; (*post)++; strip_blank_end(ret); - o = find_option(options, ret); + o = find_option(options, eops, ret); } else { - o = find_option(options, opt); + o = find_option(options, eops, opt); *post = NULL; } @@ -565,8 +635,8 @@ static int opt_cmp(const void *p1, const void *p2) s1 = strdup(*((char **) p1)); s2 = strdup(*((char **) p2)); - o1 = get_option(s1, fio_options, &foo); - o2 = get_option(s2, fio_options, &foo); + o1 = get_option(s1, fio_options, NULL, &foo); + o2 = get_option(s2, fio_options, NULL, &foo); prio1 = prio2 = 0; if (o1) @@ -587,11 +657,12 @@ void sort_options(char **opts, struct fio_option *options, int num_opts) } int parse_cmd_option(const char *opt, const char *val, - struct fio_option *options, void *data) + struct fio_option *options, struct flist_head *eops, + void *data) { struct fio_option *o; - o = find_option(options, opt); + o = find_option(options, eops, opt); if (!o) { fprintf(stderr, "Bad option <%s>\n", opt); return 1; @@ -620,6 +691,11 @@ static char *option_dup_subs(const char *opt) ssize_t nchr = OPT_LEN_MAX; size_t envlen; + if (strlen(in) + 1 > OPT_LEN_MAX) { + fprintf(stderr, "OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX); + return NULL; + } + in[OPT_LEN_MAX] = '\0'; strncpy(in, opt, OPT_LEN_MAX); @@ -653,14 +729,17 @@ static char *option_dup_subs(const char *opt) return strdup(out); } -int parse_option(const char *opt, struct fio_option *options, void *data) +int parse_option(const char *opt, struct fio_option *options, + struct flist_head *ext_opt_list, void *data) { struct fio_option *o; char *post, *tmp; tmp = option_dup_subs(opt); + if (!tmp) + return 1; - o = get_option(tmp, options, &post); + o = get_option(tmp, options, ext_opt_list, &post); if (!o) { fprintf(stderr, "Bad option <%s>\n", tmp); free(tmp); @@ -773,8 +852,11 @@ static void print_option(struct fio_option *o) } while (printed); } -int show_cmd_help(struct fio_option *options, const char *name) +int show_cmd_help(struct fio_option *options, struct flist_head *ext_opts, + const char *name) { + struct flist_head *n; + struct ext_option *eo; struct fio_option *o, *closest; unsigned int best_dist; int found = 0; @@ -826,6 +908,18 @@ int show_cmd_help(struct fio_option *options, const char *name) 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"); @@ -851,6 +945,31 @@ void fill_default_options(void *data, struct fio_option *options) handle_option(o, o->def, data); } +void option_init(struct fio_option *o) +{ + if (o->type == FIO_OPT_DEPRECATED) + return; + if (o->type == FIO_OPT_BOOL) { + o->minval = 0; + o->maxval = 1; + } + if (o->type == FIO_OPT_STR_SET && o->def) { + fprintf(stderr, "Option %s: string set option with" + " default will always be true\n", o->name); + } + if (!o->cb && (!o->off1 && !o->roff1)) { + fprintf(stderr, "Option %s: neither cb nor offset given\n", + o->name); + } + if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE) + return; + if (o->cb && ((o->off1 || o->off2 || o->off3 || o->off4) || + (o->roff1 || o->roff2 || o->roff3 || o->roff4))) { + fprintf(stderr, "Option %s: both cb and offset given\n", + o->name); + } +} + /* * Sanitize the options structure. For now it just sets min/max for bool * values and whether both callback and offsets are given. @@ -861,27 +980,6 @@ void options_init(struct fio_option *options) dprint(FD_PARSE, "init options\n"); - for (o = &options[0]; o->name; o++) { - if (o->type == FIO_OPT_DEPRECATED) - continue; - if (o->type == FIO_OPT_BOOL) { - o->minval = 0; - o->maxval = 1; - } - if (o->type == FIO_OPT_STR_SET && o->def) { - fprintf(stderr, "Option %s: string set option with" - " default will always be true\n", - o->name); - } - if (!o->cb && !o->off1) { - fprintf(stderr, "Option %s: neither cb nor offset" - " given\n", o->name); - } - if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE) - continue; - if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4)) { - fprintf(stderr, "Option %s: both cb and offset given\n", - o->name); - } - } + for (o = &options[0]; o->name; o++) + option_init(o); } diff --git a/parse.h b/parse.h index 5b1a53d..5f602a3 100644 --- a/parse.h +++ b/parse.h @@ -1,6 +1,8 @@ #ifndef FIO_PARSE_H #define FIO_PARSE_H +#include "flist.h" + /* * Option types */ @@ -25,7 +27,7 @@ struct value_pair { const char *help; /* help text for sub option */ }; -#define OPT_LEN_MAX 1024 +#define OPT_LEN_MAX 4096 #define PARSE_MAX_VP 16 /* @@ -39,6 +41,7 @@ struct fio_option { unsigned int off2; unsigned int off3; unsigned int off4; + void *roff1, *roff2, *roff3, *roff4; unsigned int maxval; /* max and min value */ int minval; int neg; /* negate value stored */ @@ -53,11 +56,12 @@ struct fio_option { typedef int (str_cb_fn)(void *, char *); -extern int parse_option(const char *, struct fio_option *, void *); +extern int parse_option(const char *, struct fio_option *, struct flist_head *, 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 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 void fill_default_options(void *, struct fio_option *); +extern void option_init(struct fio_option *); extern void options_init(struct fio_option *); extern void strip_blank_front(char **); diff --git a/profile.c b/profile.c new file mode 100644 index 0000000..44e6269 --- /dev/null +++ b/profile.c @@ -0,0 +1,64 @@ +#include "fio.h" +#include "profile.h" +#include "debug.h" +#include "flist.h" +#include "options.h" + +static FLIST_HEAD(profile_list); + +int load_profile(const char *profile) +{ + struct profile_ops *ops; + struct flist_head *n; + + dprint(FD_PROFILE, "loading profile '%s'\n", profile); + + flist_for_each(n, &profile_list) { + ops = flist_entry(n, struct profile_ops, list); + if (!strcmp(profile, ops->name)) + break; + + ops = NULL; + } + + if (ops) { + ops->prep_cmd(); + add_job_opts(ops->cmdline); + return 0; + } + + log_err("fio: profile '%s' not found\n", profile); + return 1; +} + +static void add_profile_options(struct profile_ops *ops) +{ + struct fio_option *fo; + struct ext_option *eo; + + if (!ops->options) + return; + + 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++; + } +} + +void register_profile(struct profile_ops *ops) +{ + dprint(FD_PROFILE, "register profile '%s'\n", ops->name); + flist_add_tail(&ops->list, &profile_list); + add_profile_options(ops); +} + +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); +} diff --git a/profile.h b/profile.h new file mode 100644 index 0000000..8ea77d9 --- /dev/null +++ b/profile.h @@ -0,0 +1,31 @@ +#ifndef FIO_PROFILE_H +#define FIO_PROFILE_H + +#include "flist.h" + +struct profile_ops { + struct flist_head list; + char name[32]; + int flags; + + /* + * Profile specific options + */ + struct fio_option *options; + + /* + * Called after parsing options, to prepare 'cmdline' + */ + void (*prep_cmd)(void); + + /* + * The complete command line + */ + const char **cmdline; +}; + +void register_profile(struct profile_ops *); +void unregister_profile(struct profile_ops *); +int load_profile(const char *); + +#endif diff --git a/profiles.h b/profiles.h deleted file mode 100644 index 8203a46..0000000 --- a/profiles.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef FIO_PROFILE_H -#define FIO_PROFILE_H - -enum { - PROFILE_NONE = 0, - PROFILE_TIOBENCH = 1, - PROFILE_END = 2, -}; - -#endif diff --git a/profiles/tiobench.c b/profiles/tiobench.c new file mode 100644 index 0000000..4bdcfa2 --- /dev/null +++ b/profiles/tiobench.c @@ -0,0 +1,101 @@ +#include "../fio.h" +#include "../profile.h" +#include "../parse.h" + +static unsigned long long size; +static unsigned int loops = 1; +static unsigned int bs = 4096; +static unsigned int nthreads = 1; +static char *dir; + +char sz_idx[80], bs_idx[80], loop_idx[80], dir_idx[80], t_idx[80]; + +static const char *tb_opts[] = { + "buffered=0", sz_idx, bs_idx, loop_idx, dir_idx, t_idx, + "timeout=600", "group_reporting", "thread", "overwrite=1", + "filename=.fio.tio.1:.fio.tio.2:.fio.tio.3:.fio.tio.4", + "name=seqwrite", "rw=write", "end_fsync=1", + "name=randwrite", "stonewall", "rw=randwrite", "end_fsync=1", + "name=seqread", "stonewall", "rw=read", + "name=randread", "stonewall", "rw=randread", NULL, +}; + +static struct fio_option options[] = { + { + .name = "size", + .type = FIO_OPT_STR_VAL, + .roff1 = &size, + .help = "Size in MB", + }, + { + .name = "block", + .type = FIO_OPT_INT, + .roff1 = &bs, + .help = "Block size in bytes", + .def = "4k", + }, + { + .name = "numruns", + .type = FIO_OPT_INT, + .roff1 = &loops, + .help = "Number of runs", + }, + { + .name = "dir", + .type = FIO_OPT_STR_STORE, + .roff1 = &dir, + .help = "Test directory", + }, + { + .name = "threads", + .type = FIO_OPT_INT, + .roff1 = &nthreads, + .help = "Number of Threads", + }, + { + .name = NULL, + }, +}; + +/* + * Fill our private options into the command line + */ +static void tb_prep_cmdline(void) +{ + + /* + * tiobench uses size as MB, so multiply up + */ + size *= 1024 * 1024ULL; + if (size) + sprintf(sz_idx, "size=%llu", size); + else + strcpy(sz_idx, "size=4*1024*$mb_memory"); + + sprintf(bs_idx, "bs=%u", bs); + sprintf(loop_idx, "loops=%u", loops); + + if (dir) + sprintf(dir_idx, "directory=%s", dir); + else + sprintf(dir_idx, "directory=./"); + + sprintf(t_idx, "numjobs=%u", nthreads); +} + +static struct profile_ops tiobench_profile = { + .name = "tiobench", + .options = options, + .prep_cmd = tb_prep_cmdline, + .cmdline = tb_opts, +}; + +static void fio_init tiobench_register(void) +{ + register_profile(&tiobench_profile); +} + +static void fio_exit tiobench_unregister(void) +{ + unregister_profile(&tiobench_profile); +} -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html