From: Jens Axboe Date: Tue, 9 Dec 2014 19:58:15 +0000 (-0700) Subject: options: add support for checking if an option has been set X-Git-Tag: fio-2.2.0~30 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=a8523a6ae6ce7beafcfa75c4f0b9226e2ab17139 options: add support for checking if an option has been set We often just do a non-zero check, but an option can be set and be set to zero, so we can't currently detect that. For complicated options, we add a second variable to mark if it has been set or not. This allows us to directly check if a given option was set by the user or not. Signed-off-by: Jens Axboe --- diff --git a/cconv.c b/cconv.c index d0a124ec..a4d50035 100644 --- a/cconv.c +++ b/cconv.c @@ -49,6 +49,7 @@ void convert_thread_options_to_cpu(struct thread_options *o, { int i, j; + memcpy(o->set_options, top->set_options, NR_OPTS_SZ * sizeof(uint64_t)); string_to_cpu(&o->description, top->description); string_to_cpu(&o->name, top->name); string_to_cpu(&o->directory, top->directory); @@ -258,6 +259,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top, { int i, j; + memcpy(top->set_options, o->set_options, NR_OPTS_SZ * sizeof(uint64_t)); string_to_net(top->description, o->description); string_to_net(top->name, o->name); string_to_net(top->directory, o->directory); diff --git a/options.c b/options.c index 2c703fdb..ac561bc9 100644 --- a/options.c +++ b/options.c @@ -1650,6 +1650,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Size", .type = FIO_OPT_STR_VAL, .cb = str_size_cb, + .off1 = td_var_offset(size), .help = "Total size of device or files", .interval = 1024 * 1024, .category = FIO_OPT_C_IO, @@ -1789,6 +1790,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Block size split", .type = FIO_OPT_STR, .cb = str_bssplit_cb, + .off1 = td_var_offset(bssplit), .help = "Set a specific mix of block sizes", .parent = "rw", .hide = 1, @@ -2443,6 +2445,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Verify pattern", .type = FIO_OPT_STR, .cb = str_verify_pattern_cb, + .off1 = td_var_offset(verify_pattern), .help = "Fill pattern for IO buffers", .parent = "verify", .hide = 1, @@ -2513,6 +2516,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Async verify CPUs", .type = FIO_OPT_STR, .cb = str_verify_cpus_allowed_cb, + .off1 = td_var_offset(verify_cpumask), .help = "Set CPUs allowed for async verify threads", .parent = "verify_async", .hide = 1, @@ -2722,6 +2726,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Read/write mix read", .type = FIO_OPT_INT, .cb = str_rwmix_read_cb, + .off1 = td_var_offset(rwmix[DDIR_READ]), .maxval = 100, .help = "Percentage of mixed workload that is reads", .def = "50", @@ -2735,6 +2740,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Read/write mix write", .type = FIO_OPT_INT, .cb = str_rwmix_write_cb, + .off1 = td_var_offset(rwmix[DDIR_WRITE]), .maxval = 100, .help = "Percentage of mixed workload that is writes", .def = "50", @@ -3004,6 +3010,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "CPU mask", .type = FIO_OPT_INT, .cb = str_cpumask_cb, + .off1 = td_var_offset(cpumask), .help = "CPU affinity mask", .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_CRED, @@ -3013,6 +3020,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "CPUs allowed", .type = FIO_OPT_STR, .cb = str_cpus_allowed_cb, + .off1 = td_var_offset(cpumask), .help = "Set CPUs allowed", .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_CRED, @@ -3266,6 +3274,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Buffer pattern", .type = FIO_OPT_STR, .cb = str_buffer_pattern_cb, + .off1 = td_var_offset(buffer_pattern), .help = "Fill pattern for IO buffers", .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_BUF, @@ -3275,6 +3284,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Buffer compression percentage", .type = FIO_OPT_INT, .cb = str_buffer_compress_cb, + .off1 = td_var_offset(compress_percentage), .maxval = 100, .minval = 0, .help = "How compressible the buffer is (approximately)", @@ -3299,6 +3309,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Dedupe percentage", .type = FIO_OPT_INT, .cb = str_dedupe_cb, + .off1 = td_var_offset(dedupe_percentage), .maxval = 100, .minval = 0, .help = "Percentage of buffers that are dedupable", @@ -3469,6 +3480,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .name = "ignore_error", .type = FIO_OPT_STR, .cb = str_ignore_error_cb, + .off1 = td_var_offset(ignore_error_nr), .help = "Set a specific list of errors to ignore", .parent = "rw", .category = FIO_OPT_C_GENERAL, @@ -3980,6 +3992,9 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts, int newret = parse_option(opts_copy[i], opts[i], fio_options, &o, td, dump_cmdline); + if (!newret && o) + fio_option_mark_set(&td->o, o); + if (opts_copy[i]) { if (newret && !o) { unknown++; @@ -4026,7 +4041,18 @@ 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, fio_options, td); + int ret; + + ret = parse_cmd_option(opt, val, fio_options, td); + if (!ret) { + struct fio_option *o; + + o = find_option(fio_options, opt); + if (o) + fio_option_mark_set(&td->o, o); + } + + return ret; } int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt, @@ -4188,3 +4214,36 @@ struct fio_option *fio_option_find(const char *name) return find_option(fio_options, name); } +int __fio_option_is_set(struct thread_options *o, unsigned int off1) +{ + unsigned int opt_off, index, offset; + struct fio_option *opt = NULL; + int i; + + for (i = 0; fio_options[i].name; i++) { + if (off1 == fio_options[i].off1) { + opt = &fio_options[i]; + break; + } + } + + if (!opt) { + log_err("fio: no option found at offset %u\n", off1); + return 0; + } + + opt_off = opt - &fio_options[0]; + index = opt_off / (8 * sizeof(uint64_t)); + offset = opt_off & ((8 * sizeof(uint64_t)) - 1); + return (o->set_options[index] & (1UL << offset)) != 0; +} + +void fio_option_mark_set(struct thread_options *o, struct fio_option *opt) +{ + unsigned int opt_off, index, offset; + + opt_off = opt - &fio_options[0]; + index = opt_off / (8 * sizeof(uint64_t)); + offset = opt_off & ((8 * sizeof(uint64_t)) - 1); + o->set_options[index] |= 1UL << offset; +} diff --git a/options.h b/options.h index b2e2c0c8..fa015c39 100644 --- a/options.h +++ b/options.h @@ -22,6 +22,13 @@ int set_name_idx(char *, char *, int); extern struct fio_option fio_options[FIO_MAX_OPTS]; +extern int __fio_option_is_set(struct thread_options *, unsigned int off); + +#define fio_option_is_set(__td, name) \ + __fio_option_is_set((__td), td_var_offset(name)) + +extern void fio_option_mark_set(struct thread_options *, struct fio_option *); + static inline int o_match(struct fio_option *o, const char *opt) { if (!strcmp(o->name, opt)) diff --git a/parse.c b/parse.c index 141f4b28..ae87b1ed 100644 --- a/parse.c +++ b/parse.c @@ -1279,8 +1279,6 @@ void option_init(struct fio_option *o) if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE || o->type == FIO_OPT_STR_MULTI) return; - if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4)) - log_err("Option %s: both cb and offset given\n", o->name); } /* diff --git a/thread_options.h b/thread_options.h index f311e2c6..f0c6325b 100644 --- a/thread_options.h +++ b/thread_options.h @@ -3,6 +3,7 @@ #include "arch/arch.h" #include "os/os.h" +#include "options.h" #include "stat.h" #include "gettime.h" #include "lib/ieee754.h" @@ -28,10 +29,13 @@ struct bssplit { uint32_t perc; }; +#define NR_OPTS_SZ (FIO_MAX_OPTS / (8 * sizeof(uint64_t))) + #define OPT_MAGIC 0x4f50544e struct thread_options { int magic; + uint64_t set_options[NR_OPTS_SZ]; char *description; char *name; char *directory; @@ -265,6 +269,7 @@ struct thread_options { #define FIO_TOP_STR_MAX 256 struct thread_options_pack { + uint64_t set_options[NR_OPTS_SZ]; uint8_t description[FIO_TOP_STR_MAX]; uint8_t name[FIO_TOP_STR_MAX]; uint8_t directory[FIO_TOP_STR_MAX];