X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=options.c;h=76146a71e09a824b8fc326765c61d57fb26e8764;hp=e3c9c87b8ef4e3fb44b5695ebac982e607e300fd;hb=b01af66b13f0594617602b61d31b1495292e5fd2;hpb=2f2e6c23e26888acb7ad2f2a2e4bd8fa5b250c0f diff --git a/options.c b/options.c index e3c9c87b..76146a71 100644 --- a/options.c +++ b/options.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "fio.h" #include "verify.h" @@ -17,6 +18,8 @@ #include "crc/crc32c.h" +char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 }; + /* * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that. */ @@ -443,9 +446,9 @@ static int str_cpumask_cb(void *data, unsigned long long *val) for (i = 0; i < sizeof(int) * 8; i++) { if ((1 << i) & *val) { - if (i > max_cpu) { + if (i >= max_cpu) { log_err("fio: CPU %d too large (max=%ld)\n", i, - max_cpu); + max_cpu - 1); return 1; } dprint(FD_PARSE, "set cpu allowed %d\n", i); @@ -503,9 +506,9 @@ static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask, ret = 1; break; } - if (icpu > max_cpu) { + if (icpu >= max_cpu) { log_err("fio: CPU %d too large (max=%ld)\n", - icpu, max_cpu); + icpu, max_cpu - 1); ret = 1; break; } @@ -715,9 +718,11 @@ 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 if (td->o.random_distribution == FIO_RAND_DIST_GAUSS) + val = 0.0; else return 0; @@ -736,12 +741,18 @@ static int str_random_distribution_cb(void *data, const char *str) return 1; } td->o.zipf_theta.u.f = val; - } else { + } else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) { if (val <= 0.00 || val >= 1.00) { log_err("fio: pareto input out of range (0 < input < 1.0)\n"); return 1; } td->o.pareto_h.u.f = val; + } else { + if (val <= 0.00 || val >= 100.0) { + log_err("fio: normal deviation out of range (0 < input < 100.0)\n"); + return 1; + } + td->o.gauss_dev.u.f = val; } return 0; @@ -812,7 +823,7 @@ static int get_max_name_idx(char *input) * Returns the directory at the index, indexes > entires will be * assigned via modulo division of the index */ -int set_name_idx(char *target, char *input, int index) +int set_name_idx(char *target, size_t tlen, char *input, int index) { unsigned int cur_idx; int len; @@ -824,7 +835,13 @@ int set_name_idx(char *target, char *input, int index) for (cur_idx = 0; cur_idx <= index; cur_idx++) fname = get_next_name(&str); - len = sprintf(target, "%s/", fname); + if (client_sockaddr_str[0]) { + len = snprintf(target, tlen, "%s/%s.", fname, + client_sockaddr_str); + } else + len = snprintf(target, tlen, "%s/", fname); + + target[tlen - 1] = '\0'; free(p); return len; @@ -884,18 +901,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; @@ -912,7 +917,7 @@ static int str_opendir_cb(void *data, const char fio_unused *str) static int pattern_cb(char *pattern, unsigned int max_size, const char *input, unsigned int *pattern_bytes) { - long off; + long off = 0; int i = 0, j = 0, len, k, base = 10; uint32_t pattern_length; char *loc1, *loc2; @@ -978,6 +983,8 @@ static int pattern_cb(char *pattern, unsigned int max_size, */ fill: pattern_length = i; + if (!i && !off) + i = 1; while (i > 1 && i * 2 <= max_size) { memcpy(&pattern[i], &pattern[0], i); i *= 2; @@ -1057,7 +1064,7 @@ static int str_verify_pattern_cb(void *data, const char *input) /* * VERIFY_META could already be set */ - if (!ret && td->o.verify == VERIFY_NONE) + if (!ret && !fio_option_is_set(&td->o, verify)) td->o.verify = VERIFY_PATTERN; return ret; @@ -1269,6 +1276,10 @@ static struct opt_group fio_opt_cat_groups[] = { .name = "Tiobench profile", .mask = FIO_OPT_G_TIOBENCH, }, + { + .name = "MTD", + .mask = FIO_OPT_G_MTD, + }, { .name = NULL, @@ -1343,7 +1354,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 = { @@ -1421,6 +1431,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = TD_DDIR_RANDRW, .help = "Random read and write mix" }, + { .ival = "trimwrite", + .oval = TD_DDIR_TRIMWRITE, + .help = "Trim and write mix, trims preceding writes" + }, }, }, { @@ -1619,6 +1633,26 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_BASIC, }, + { + .name = "io_submit_mode", + .lname = "IO submit mode", + .type = FIO_OPT_STR, + .off1 = td_var_offset(io_submit_mode), + .help = "How IO submissions and completions are done", + .def = "inline", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IO_BASIC, + .posval = { + { .ival = "inline", + .oval = IO_MODE_INLINE, + .help = "Submit and complete IO inline", + }, + { .ival = "offload", + .oval = IO_MODE_OFFLOAD, + .help = "Offload submit and complete to threads", + }, + }, + }, { .name = "size", .lname = "Size", @@ -1813,6 +1847,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .type = FIO_OPT_STR_VAL, .off1 = td_var_offset(rand_seed), .help = "Set the random generator seed value", + .def = "0x89", .parent = "rw", .category = FIO_OPT_C_IO, .group = FIO_OPT_G_RANDOM, @@ -1864,6 +1899,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = FIO_RAND_GEN_LFSR, .help = "Variable length LFSR", }, + { + .ival = "tausworthe64", + .oval = FIO_RAND_GEN_TAUSWORTHE64, + .help = "64-bit Tausworthe variant", + }, }, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_RANDOM, @@ -1888,6 +1928,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = FIO_RAND_DIST_PARETO, .help = "Pareto distribution", }, + { .ival = "normal", + .oval = FIO_RAND_DIST_GAUSS, + .help = "Normal (gaussian) distribution", + }, }, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_RANDOM, @@ -2018,6 +2062,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_FILE, .group = FIO_OPT_G_INVALID, }, +#ifdef FIO_HAVE_STREAMID + { + .name = "fadvise_stream", + .lname = "Fadvise stream", + .type = FIO_OPT_INT, + .off1 = td_var_offset(fadvise_stream), + .help = "Use fadvise() to set stream ID", + .category = FIO_OPT_C_FILE, + .group = FIO_OPT_G_INVALID, + }, +#endif { .name = "fsync", .lname = "Fsync", @@ -2347,6 +2402,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = VERIFY_META, .help = "Use io information", }, + { .ival = "pattern", + .oval = VERIFY_PATTERN_NO_HDR, + .help = "Verify strict pattern", + }, { .ival = "null", .oval = VERIFY_NULL, @@ -2623,6 +2682,28 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IOLOG, }, + { + .name = "replay_scale", + .lname = "Replace offset scale factor", + .type = FIO_OPT_INT, + .off1 = td_var_offset(replay_scale), + .parent = "read_iolog", + .def = "1", + .help = "Align offsets to this blocksize", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IOLOG, + }, + { + .name = "replay_align", + .lname = "Replace alignment", + .type = FIO_OPT_INT, + .off1 = td_var_offset(replay_align), + .parent = "read_iolog", + .help = "Scale offset down by this factor", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IOLOG, + .pow2 = 1, + }, { .name = "exec_prerun", .lname = "Pre-execute runnable", @@ -2969,6 +3050,26 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_FILE, .def = "0", }, + { + .name = "allow_file_create", + .lname = "Allow file create", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(allow_create), + .help = "Permit fio to create files, if they don't exist", + .def = "1", + .category = FIO_OPT_C_FILE, + .group = FIO_OPT_G_FILENAME, + }, + { + .name = "allow_mounted_write", + .lname = "Allow mounted write", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(allow_mounted_write), + .help = "Allow writes to a mounted partition", + .def = "0", + .category = FIO_OPT_C_FILE, + .group = FIO_OPT_G_FILENAME, + }, { .name = "pre_read", .lname = "Pre-read files", @@ -3113,6 +3214,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_PROCESS, }, + { + .name = "per_job_logs", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(per_job_logs), + .help = "Include job number in generated log files or not", + .def = "1", + .category = FIO_OPT_C_LOG, + .group = FIO_OPT_G_INVALID, + }, { .name = "write_bw_log", .lname = "Write bandwidth log", @@ -3182,6 +3292,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .group = FIO_OPT_G_INVALID, }, #endif + { + .name = "block_error_percentiles", + .lname = "Block error percentiles", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(block_error_hist), + .help = "Record trim block errors and make a histogram", + .def = "0", + .category = FIO_OPT_C_LOG, + .group = FIO_OPT_G_INVALID, + }, { .name = "bwavgtime", .lname = "Bandwidth average time", @@ -3306,11 +3426,12 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { }, { .name = "percentile_list", - .lname = "Completion latency percentile list", + .lname = "Percentile list", .type = FIO_OPT_FLOAT_LIST, .off1 = td_var_offset(percentile_list), .off2 = td_var_offset(percentile_precision), - .help = "Specify a custom list of percentiles to report", + .help = "Specify a custom list of percentiles to report for " + "completion latency and block errors", .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99", .maxlen = FIO_IO_U_LIST_MAX_LEN, .minfp = 0.0, @@ -3636,6 +3757,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_FLOW, }, + { + .name = "skip_bad", + .lname = "Skip operations against bad blocks", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(skip_bad), + .help = "Skip operations against known bad blocks.", + .hide = 1, + .def = "0", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_MTD, + }, { .name = NULL, }, @@ -3731,6 +3863,18 @@ static struct fio_keyword fio_keywords[] = { }, }; +void fio_keywords_exit(void) +{ + struct fio_keyword *kw; + + kw = &fio_keywords[0]; + while (kw->word) { + free(kw->replace); + kw->replace = NULL; + kw++; + } +} + void fio_keywords_init(void) { unsigned long long mb_memory; @@ -4191,21 +4335,32 @@ 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) +static struct fio_option *find_next_opt(struct thread_options *o, + struct fio_option *from, + unsigned int off1) { - unsigned int opt_off, index, offset; - struct fio_option *opt = NULL; - int i; + struct fio_option *opt; + + if (!from) + from = &fio_options[0]; + else + from++; - for (i = 0; fio_options[i].name; i++) { - if (off1 == fio_options[i].off1) { - opt = &fio_options[i]; + opt = NULL; + do { + if (off1 == from->off1) { + opt = from; break; } - } + from++; + } while (from->name); - if (!opt) - return -1; + 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)); @@ -4213,6 +4368,21 @@ int __fio_option_is_set(struct thread_options *o, unsigned int off1) 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;