X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=options.c;h=ab6e399db5208d81689c0ec9752fa0a7e4adeda1;hp=918de8e8e34b2cd29409871c3d7ae5604826532a;hb=67a176fc7fa918cc91880530fac07cc3aa864c71;hpb=86d59660ca54dd2e3e2457f3683198afc2b2701c diff --git a/options.c b/options.c index 918de8e8..ab6e399d 100644 --- a/options.c +++ b/options.c @@ -102,7 +102,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str) } else perc = -1U; - if (str_to_decimal(fname, &val, 1, o, 0)) { + if (str_to_decimal(fname, &val, 1, o, 0, 0)) { log_err("fio: bssplit conversion failed\n"); free(bssplit); return 1; @@ -342,7 +342,7 @@ static int str_rw_cb(void *data, const char *str) else { long long val; - if (str_to_decimal(nr, &val, 1, o, 0)) { + if (str_to_decimal(nr, &val, 1, o, 0, 0)) { log_err("fio: rw postfix parsing failed\n"); free(nr); return 1; @@ -453,7 +453,6 @@ static int str_cpumask_cb(void *data, unsigned long long *val) } } - td->o.cpumask_set = 1; return 0; } @@ -520,36 +519,24 @@ static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask, } free(p); - if (!ret) - td->o.cpumask_set = 1; return ret; } static int str_cpus_allowed_cb(void *data, const char *input) { struct thread_data *td = data; - int ret; if (parse_dryrun()) return 0; - ret = set_cpus_allowed(td, &td->o.cpumask, input); - if (!ret) - td->o.cpumask_set = 1; - - return ret; + return set_cpus_allowed(td, &td->o.cpumask, input); } static int str_verify_cpus_allowed_cb(void *data, const char *input) { struct thread_data *td = data; - int ret; - - ret = set_cpus_allowed(td, &td->o.verify_cpumask, input); - if (!ret) - td->o.verify_cpumask_set = 1; - return ret; + return set_cpus_allowed(td, &td->o.verify_cpumask, input); } #endif @@ -576,7 +563,6 @@ static int str_numa_cpunodes_cb(void *data, char *input) numa_free_nodemask(verify_bitmask); td->o.numa_cpunodes = strdup(input); - td->o.numa_cpumask_set = 1; return 0; } @@ -683,9 +669,7 @@ static int str_numa_mpol_cb(void *data, char *input) break; } - td->o.numa_memmask_set = 1; return 0; - out: return 1; } @@ -731,14 +715,14 @@ static int str_random_distribution_cb(void *data, const char *str) return 0; if (td->o.random_distribution == FIO_RAND_DIST_ZIPF) - val = 1.1; + val = FIO_DEF_ZIPF; else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) - val = 0.2; + val = FIO_DEF_PARETO; else return 0; nr = get_opt_postfix(str); - if (nr && !str_to_float(nr, &val)) { + if (nr && !str_to_float(nr, &val, 0)) { log_err("fio: random postfix parsing failed\n"); free(nr); return 1; @@ -900,18 +884,6 @@ out: return ret; } -static int str_lockfile_cb(void *data, const char fio_unused *str) -{ - struct thread_data *td = data; - - if (td->files_index) { - log_err("fio: lockfile= option must precede filename=\n"); - return 1; - } - - return 0; -} - static int str_opendir_cb(void *data, const char fio_unused *str) { struct thread_data *td = data; @@ -1031,7 +1003,8 @@ static int str_buffer_pattern_cb(void *data, const char *input) &td->o.buffer_pattern_bytes); if (!ret && td->o.buffer_pattern_bytes) { - td->o.refill_buffers = 0; + if (!td->o.compress_percentage) + td->o.refill_buffers = 0; td->o.scramble_buffers = 0; td->o.zero_buffers = 0; } else { @@ -1094,16 +1067,6 @@ static int str_gtod_reduce_cb(void *data, int *il) return 0; } -static int str_gtod_cpu_cb(void *data, long long *il) -{ - struct thread_data *td = data; - int val = *il; - - td->o.gtod_cpu = val; - td->o.gtod_offload = 1; - return 0; -} - static int str_size_cb(void *data, unsigned long long *__val) { struct thread_data *td = data; @@ -1368,7 +1331,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .parent = "filename", .hide = 0, .def = "none", - .cb = str_lockfile_cb, .category = FIO_OPT_C_FILE, .group = FIO_OPT_G_FILENAME, .posval = { @@ -1649,14 +1611,16 @@ 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, .group = FIO_OPT_G_INVALID, }, { - .name = "io_limit", - .lname = "IO Limit", + .name = "io_size", + .alias = "io_limit", + .lname = "IO Size", .type = FIO_OPT_STR_VAL, .off1 = td_var_offset(io_limit), .interval = 1024 * 1024, @@ -1788,6 +1752,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, @@ -1842,12 +1807,8 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .name = "use_os_rand", .lname = "Use OS random", - .type = FIO_OPT_BOOL, - .off1 = td_var_offset(use_os_rand), - .help = "Set to use OS random generator", - .def = "0", - .parent = "rw", - .hide = 1, + .type = FIO_OPT_DEPRECATED, + .off1 = td_var_offset(dep_use_os_rand), .category = FIO_OPT_C_IO, .group = FIO_OPT_G_RANDOM, }, @@ -2181,6 +2142,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "Only start job when this period has passed", .def = "0", .is_seconds = 1, + .is_time = 1, .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_RUNTIME, }, @@ -2193,6 +2155,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "Stop workload when this amount of time has passed", .def = "0", .is_seconds = 1, + .is_time = 1, .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_RUNTIME, }, @@ -2221,6 +2184,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .off1 = td_var_offset(ramp_time), .help = "Ramp up time before measuring performance", .is_seconds = 1, + .is_time = 1, .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_RUNTIME, }, @@ -2443,6 +2407,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 +2478,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, @@ -2525,6 +2491,28 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .off1 = td_var_offset(experimental_verify), .type = FIO_OPT_BOOL, .help = "Enable experimental verification", + .parent = "verify", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_VERIFY, + }, + { + .name = "verify_state_load", + .lname = "Load verify state", + .off1 = td_var_offset(verify_state), + .type = FIO_OPT_BOOL, + .help = "Load verify termination state", + .parent = "verify", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_VERIFY, + }, + { + .name = "verify_state_save", + .lname = "Save verify state", + .off1 = td_var_offset(verify_state_save), + .type = FIO_OPT_BOOL, + .def = "1", + .help = "Save verify state on termination", + .parent = "verify", .category = FIO_OPT_C_IO, .group = FIO_OPT_G_VERIFY, }, @@ -2700,6 +2688,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", @@ -2713,6 +2702,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", @@ -2774,6 +2764,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .off1 = td_var_offset(thinktime), .help = "Idle time between IO buffers (usec)", .def = "0", + .is_time = 1, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_THINKTIME, }, @@ -2784,6 +2775,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .off1 = td_var_offset(thinktime_spin), .help = "Start think time by spinning this amount (usec)", .def = "0", + .is_time = 1, .parent = "thinktime", .hide = 1, .category = FIO_OPT_C_IO, @@ -2867,6 +2859,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .type = FIO_OPT_INT, .off1 = td_var_offset(max_latency), .help = "Maximum tolerated IO latency (usec)", + .is_time = 1, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_LATPROF, }, @@ -2876,6 +2869,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .type = FIO_OPT_STR_VAL_TIME, .off1 = td_var_offset(latency_target), .help = "Ramp to max queue depth supporting this latency", + .is_time = 1, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_LATPROF, }, @@ -2885,6 +2879,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .type = FIO_OPT_STR_VAL_TIME, .off1 = td_var_offset(latency_window), .help = "Time to sustain latency_target", + .is_time = 1, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_LATPROF, }, @@ -2977,6 +2972,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, @@ -2986,6 +2982,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, @@ -3017,6 +3014,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .name = "numa_cpu_nodes", .type = FIO_OPT_STR, .cb = str_numa_cpunodes_cb, + .off1 = td_var_offset(numa_cpunodes), .help = "NUMA CPU nodes bind", .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_INVALID, @@ -3025,6 +3023,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .name = "numa_mem_policy", .type = FIO_OPT_STR, .cb = str_numa_mpol_cb, + .off1 = td_var_offset(numa_memnodes), .help = "NUMA memory policy setup", .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_INVALID, @@ -3239,6 +3238,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, @@ -3248,6 +3248,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)", @@ -3272,6 +3273,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", @@ -3379,7 +3381,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .name = "gtod_cpu", .lname = "Dedicated gettimeofday() CPU", .type = FIO_OPT_INT, - .cb = str_gtod_cpu_cb, + .off1 = td_var_offset(gtod_cpu), .help = "Set up dedicated gettimeofday() thread on this CPU", .verify = gtod_cpu_verify, .category = FIO_OPT_C_GENERAL, @@ -3442,6 +3444,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, @@ -3906,6 +3909,39 @@ static char **dup_and_sub_options(char **opts, int num_opts) return opts_copy; } +static void show_closest_option(const char *opt) +{ + int best_option, best_distance; + int i, distance; + char *name; + + if (!strlen(opt)) + return; + + name = strdup(opt); + i = 0; + while (name[i] != '\0' && name[i] != '=') + i++; + name[i] = '\0'; + + best_option = -1; + best_distance = INT_MAX; + i = 0; + while (fio_options[i].name) { + distance = string_distance(name, fio_options[i].name); + if (distance < best_distance) { + best_distance = distance; + best_option = i; + } + i++; + } + + if (best_option != -1) + log_err("Did you mean %s?\n", fio_options[best_option].name); + + free(name); +} + int fio_options_parse(struct thread_data *td, char **opts, int num_opts, int dump_cmdline) { @@ -3920,6 +3956,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++; @@ -3941,6 +3980,7 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts, for (i = 0; i < num_opts; i++) { struct fio_option *o = NULL; int newret = 1; + if (!opts_copy[i]) continue; @@ -3950,9 +3990,10 @@ int fio_options_parse(struct thread_data *td, char **opts, int num_opts, td->eo, dump_cmdline); ret |= newret; - if (!o) + if (!o) { log_err("Bad option <%s>\n", opts[i]); - + show_closest_option(opts[i]); + } free(opts_copy[i]); opts_copy[i] = NULL; } @@ -3964,7 +4005,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, @@ -4126,3 +4178,60 @@ struct fio_option *fio_option_find(const char *name) return find_option(fio_options, name); } +static struct fio_option *find_next_opt(struct thread_options *o, + struct fio_option *from, + unsigned int off1) +{ + struct fio_option *opt; + + if (!from) + from = &fio_options[0]; + else + from++; + + opt = NULL; + do { + if (off1 == from->off1) { + opt = from; + break; + } + from++; + } while (from->name); + + return opt; +} + +static int opt_is_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); + return (o->set_options[index] & (1UL << offset)) != 0; +} + +int __fio_option_is_set(struct thread_options *o, unsigned int off1) +{ + struct fio_option *opt, *next; + + next = NULL; + while ((opt = find_next_opt(o, next, off1)) != NULL) { + if (opt_is_set(o, opt)) + return 1; + + next = opt; + } + + return 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; +}