X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=options.c;h=0d64e7c0581e9ad912d85315fcc85cab1cd06506;hp=20b64648004e3cf54d0c28b0939d3722ba305981;hb=2dd96cc46fa83a73acc1c9238c3ac59203e10213;hpb=59b0754458f601779fac99f4f9dc95d54e1ab976 diff --git a/options.c b/options.c index 20b64648..0d64e7c0 100644 --- a/options.c +++ b/options.c @@ -13,17 +13,19 @@ #include "lib/pattern.h" #include "options.h" #include "optgroup.h" +#include "zbd.h" char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 }; #define cb_data_to_td(data) container_of(data, struct thread_data, o) -static struct pattern_fmt_desc fmt_desc[] = { +static const struct pattern_fmt_desc fmt_desc[] = { { .fmt = "%o", .len = FIELD_SIZE(struct io_u *, offset), .paste = paste_blockoff - } + }, + { } }; /* @@ -482,7 +484,7 @@ static int str_rwmix_write_cb(void *data, unsigned long long *val) static int str_exitall_cb(void) { - exitall_on_terminate = 1; + exitall_on_terminate = true; return 0; } @@ -493,6 +495,9 @@ int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu_index) const long max_cpu = cpus_online(); cpus_in_mask = fio_cpu_count(mask); + if (!cpus_in_mask) + return 0; + cpu_index = cpu_index % cpus_in_mask; index = 0; @@ -1155,7 +1160,7 @@ static int str_steadystate_cb(void *data, const char *str) * is escaped with a '\', then that ':' is part of the filename and does not * indicate a new file. */ -static char *get_next_name(char **ptr) +char *get_next_str(char **ptr) { char *str = *ptr; char *p, *start; @@ -1197,14 +1202,14 @@ static char *get_next_name(char **ptr) } -static int get_max_name_idx(char *input) +int get_max_str_idx(char *input) { unsigned int cur_idx; char *str, *p; p = str = strdup(input); for (cur_idx = 0; ; cur_idx++) - if (get_next_name(&str) == NULL) + if (get_next_str(&str) == NULL) break; free(p); @@ -1224,15 +1229,16 @@ int set_name_idx(char *target, size_t tlen, char *input, int index, p = str = strdup(input); - index %= get_max_name_idx(input); + index %= get_max_str_idx(input); for (cur_idx = 0; cur_idx <= index; cur_idx++) - fname = get_next_name(&str); + fname = get_next_str(&str); if (client_sockaddr_str[0] && unique_filename) { len = snprintf(target, tlen, "%s/%s.", fname, client_sockaddr_str); } else - len = snprintf(target, tlen, "%s/", fname); + len = snprintf(target, tlen, "%s%c", fname, + FIO_OS_PATH_SEPARATOR); target[tlen - 1] = '\0'; free(p); @@ -1247,9 +1253,9 @@ char* get_name_by_idx(char *input, int index) p = str = strdup(input); - index %= get_max_name_idx(input); + index %= get_max_str_idx(input); for (cur_idx = 0; cur_idx <= index; cur_idx++) - fname = get_next_name(&str); + fname = get_next_str(&str); fname = strdup(fname); free(p); @@ -1273,7 +1279,7 @@ static int str_filename_cb(void *data, const char *input) if (!td->files_index) td->o.nr_files = 0; - while ((fname = get_next_name(&str)) != NULL) { + while ((fname = get_next_str(&str)) != NULL) { if (!strlen(fname)) break; add_file(td, fname, 0, 1); @@ -1294,7 +1300,7 @@ static int str_directory_cb(void *data, const char fio_unused *unused) return 0; p = str = strdup(td->o.directory); - while ((dirname = get_next_name(&str)) != NULL) { + while ((dirname = get_next_str(&str)) != NULL) { if (lstat(dirname, &sb) < 0) { ret = errno; @@ -1334,7 +1340,7 @@ static int str_buffer_pattern_cb(void *data, const char *input) /* FIXME: for now buffer pattern does not support formats */ ret = parse_and_fill_pattern(input, strlen(input), td->o.buffer_pattern, - MAX_PATTERN_SIZE, NULL, 0, NULL, NULL); + MAX_PATTERN_SIZE, NULL, NULL, NULL); if (ret < 0) return 1; @@ -1383,7 +1389,7 @@ static int str_verify_pattern_cb(void *data, const char *input) td->o.verify_fmt_sz = ARRAY_SIZE(td->o.verify_fmt); ret = parse_and_fill_pattern(input, strlen(input), td->o.verify_pattern, - MAX_PATTERN_SIZE, fmt_desc, sizeof(fmt_desc), + MAX_PATTERN_SIZE, fmt_desc, td->o.verify_fmt, &td->o.verify_fmt_sz); if (ret < 0) return 1; @@ -1404,13 +1410,20 @@ static int str_gtod_reduce_cb(void *data, int *il) struct thread_data *td = cb_data_to_td(data); int val = *il; - td->o.disable_lat = !!val; - td->o.disable_clat = !!val; - td->o.disable_slat = !!val; - td->o.disable_bw = !!val; - td->o.clat_percentiles = !val; - if (val) + /* + * Only modfiy options if gtod_reduce==1 + * Otherwise leave settings alone. + */ + if (val) { + td->o.disable_lat = 1; + td->o.disable_clat = 1; + td->o.disable_slat = 1; + td->o.disable_bw = 1; + td->o.clat_percentiles = 0; + td->o.lat_percentiles = 0; + td->o.slat_percentiles = 0; td->ts_cache_mask = 63; + } return 0; } @@ -1431,6 +1444,22 @@ static int str_offset_cb(void *data, unsigned long long *__val) return 0; } +static int str_offset_increment_cb(void *data, unsigned long long *__val) +{ + struct thread_data *td = cb_data_to_td(data); + unsigned long long v = *__val; + + if (parse_is_percent(v)) { + td->o.offset_increment = 0; + td->o.offset_increment_percent = -1ULL - v; + dprint(FD_PARSE, "SET offset_increment_percent %d\n", + td->o.offset_increment_percent); + } else + td->o.offset_increment = v; + + return 0; +} + static int str_size_cb(void *data, unsigned long long *__val) { struct thread_data *td = cb_data_to_td(data); @@ -1773,6 +1802,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "Linux native asynchronous IO", }, #endif +#ifdef ARCH_HAVE_IOURING + { .ival = "io_uring", + .help = "Fast Linux native aio", + }, +#endif #ifdef CONFIG_POSIXAIO { .ival = "posixaio", .help = "POSIX asynchronous IO", @@ -1828,11 +1862,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "RDMA IO engine", }, #endif -#ifdef CONFIG_FUSION_AW - { .ival = "fusion-aw-sync", - .help = "Fusion-io atomic write engine", - }, -#endif #ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT { .ival = "e4defrag", .help = "ext4 defrag engine", @@ -1896,6 +1925,9 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "HTTP (WebDAV/S3) IO engine", }, #endif + { .ival = "nbd", + .help = "Network Block Device (NBD) IO engine" + }, }, }, { @@ -2078,6 +2110,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .name = "offset_increment", .lname = "IO offset increment", .type = FIO_OPT_STR_VAL, + .cb = str_offset_increment_cb, .off1 = offsetof(struct thread_options, offset_increment), .help = "What is the increment from one offset to the next", .parent = "offset", @@ -2207,14 +2240,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_RANDOM, }, - { - .name = "use_os_rand", - .lname = "Use OS random", - .type = FIO_OPT_DEPRECATED, - .off1 = offsetof(struct thread_options, dep_use_os_rand), - .category = FIO_OPT_C_IO, - .group = FIO_OPT_G_RANDOM, - }, { .name = "norandommap", .lname = "No randommap", @@ -2397,14 +2422,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .parent = "nrfiles", .hide = 1, }, -#ifdef FIO_HAVE_ANY_FALLOCATE { .name = "fallocate", .lname = "Fallocate", .type = FIO_OPT_STR, .off1 = offsetof(struct thread_options, fallocate_mode), .help = "Whether pre-allocation is performed when laying out files", +#ifdef FIO_HAVE_DEFAULT_FALLOCATE .def = "native", +#else + .def = "none", +#endif .category = FIO_OPT_C_FILE, .group = FIO_OPT_G_INVALID, .posval = { @@ -2428,6 +2456,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)", }, #endif + { .ival = "truncate", + .oval = FIO_FALLOCATE_TRUNCATE, + .help = "Truncate file to final size instead of allocating" + }, /* Compatibility with former boolean values */ { .ival = "0", .oval = FIO_FALLOCATE_NONE, @@ -2441,14 +2473,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { #endif }, }, -#else /* FIO_HAVE_ANY_FALLOCATE */ - { - .name = "fallocate", - .lname = "Fallocate", - .type = FIO_OPT_UNSUPPORTED, - .help = "Your platform does not support fallocate", - }, -#endif /* FIO_HAVE_ANY_FALLOCATE */ { .name = "fadvise_hint", .lname = "Fadvise hint", @@ -3203,6 +3227,35 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IOLOG, }, + { + .name = "merge_blktrace_file", + .lname = "Merged blktrace output filename", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct thread_options, merge_blktrace_file), + .help = "Merged blktrace output filename", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IOLOG, + }, + { + .name = "merge_blktrace_scalars", + .lname = "Percentage to scale each trace", + .type = FIO_OPT_FLOAT_LIST, + .off1 = offsetof(struct thread_options, merge_blktrace_scalars), + .maxlen = FIO_IO_U_LIST_MAX_LEN, + .help = "Percentage to scale each trace", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IOLOG, + }, + { + .name = "merge_blktrace_iters", + .lname = "Number of iterations to run per trace", + .type = FIO_OPT_FLOAT_LIST, + .off1 = offsetof(struct thread_options, merge_blktrace_iters), + .maxlen = FIO_IO_U_LIST_MAX_LEN, + .help = "Number of iterations to run per trace", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IOLOG, + }, { .name = "exec_prerun", .lname = "Pre-execute runnable", @@ -3274,6 +3327,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_ZONE, }, + { + .name = "zonecapacity", + .lname = "Zone capacity", + .type = FIO_OPT_STR_VAL, + .off1 = offsetof(struct thread_options, zone_capacity), + .help = "Capacity per zone", + .def = "0", + .interval = 1024 * 1024, + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_ZONE, + }, { .name = "zonerange", .lname = "Zone range", @@ -3308,16 +3372,50 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { }, { .name = "max_open_zones", - .lname = "Maximum number of open zones", + .lname = "Per device/file maximum number of open zones", .type = FIO_OPT_INT, .off1 = offsetof(struct thread_options, max_open_zones), - .maxval = FIO_MAX_OPEN_ZBD_ZONES, - .help = "Limit random writes to SMR drives to the specified" - " number of sequential zones", + .maxval = ZBD_MAX_OPEN_ZONES, + .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd", + .def = "0", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_INVALID, + }, + { + .name = "job_max_open_zones", + .lname = "Job maximum number of open zones", + .type = FIO_OPT_INT, + .off1 = offsetof(struct thread_options, job_max_open_zones), + .maxval = ZBD_MAX_OPEN_ZONES, + .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd by one thread/process", .def = "0", .category = FIO_OPT_C_IO, .group = FIO_OPT_G_INVALID, }, + { + .name = "zone_reset_threshold", + .lname = "Zone reset threshold", + .help = "Zoned block device reset threshold", + .type = FIO_OPT_FLOAT_LIST, + .maxlen = 1, + .off1 = offsetof(struct thread_options, zrt), + .minfp = 0, + .maxfp = 1, + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_ZONE, + }, + { + .name = "zone_reset_frequency", + .lname = "Zone reset frequency", + .help = "Zoned block device zone reset frequency in HZ", + .type = FIO_OPT_FLOAT_LIST, + .maxlen = 1, + .off1 = offsetof(struct thread_options, zrf), + .minfp = 0, + .maxfp = 1, + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_ZONE, + }, { .name = "lockmem", .lname = "Lock memory", @@ -3461,7 +3559,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .name = "rate", .lname = "I/O rate", - .type = FIO_OPT_INT, + .type = FIO_OPT_ULL, .off1 = offsetof(struct thread_options, rate[DDIR_READ]), .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]), .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]), @@ -3473,7 +3571,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .name = "rate_min", .alias = "ratemin", .lname = "I/O min rate", - .type = FIO_OPT_INT, + .type = FIO_OPT_ULL, .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]), .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]), .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]), @@ -3596,6 +3694,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_LATPROF, }, + { + .name = "latency_run", + .lname = "Latency Run", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct thread_options, latency_run), + .help = "Keep adjusting queue depth to match latency_target", + .def = "0", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_LATPROF, + }, { .name = "invalidate", .lname = "Cache invalidate", @@ -3873,6 +3981,30 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_PROCESS, }, + { + .name = "exit_what", + .lname = "What jobs to quit on terminate", + .type = FIO_OPT_STR, + .off1 = offsetof(struct thread_options, exit_what), + .help = "Fine-grained control for exitall", + .def = "group", + .category = FIO_OPT_C_GENERAL, + .group = FIO_OPT_G_PROCESS, + .posval = { + { .ival = "group", + .oval = TERMINATE_GROUP, + .help = "exit_all=1 default behaviour", + }, + { .ival = "stonewall", + .oval = TERMINATE_STONEWALL, + .help = "quit all currently running jobs; continue with next stonewall", + }, + { .ival = "all", + .oval = TERMINATE_ALL, + .help = "Quit everything", + }, + }, + }, { .name = "exitall_on_error", .lname = "Exit-all on terminate in error", @@ -4220,7 +4352,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .off1 = offsetof(struct thread_options, clat_percentiles), .help = "Enable the reporting of completion latency percentiles", .def = "1", - .inverse = "lat_percentiles", .category = FIO_OPT_C_STAT, .group = FIO_OPT_G_INVALID, }, @@ -4231,7 +4362,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .off1 = offsetof(struct thread_options, lat_percentiles), .help = "Enable the reporting of IO latency percentiles", .def = "0", - .inverse = "clat_percentiles", + .category = FIO_OPT_C_STAT, + .group = FIO_OPT_G_INVALID, + }, + { + .name = "slat_percentiles", + .lname = "Submission latency percentiles", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct thread_options, slat_percentiles), + .help = "Enable the reporting of submission latency percentiles", + .def = "0", .category = FIO_OPT_C_STAT, .group = FIO_OPT_G_INVALID, }, @@ -4490,7 +4630,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .name = "kb_base", .lname = "KB Base", - .type = FIO_OPT_INT, + .type = FIO_OPT_STR, .off1 = offsetof(struct thread_options, kb_base), .prio = 1, .def = "1024", @@ -4511,7 +4651,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .name = "unit_base", .lname = "Unit for quantities of data (Bits or Bytes)", - .type = FIO_OPT_INT, + .type = FIO_OPT_STR, .off1 = offsetof(struct thread_options, unit_base), .prio = 1, .posval = { @@ -4562,20 +4702,14 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .parent = "flow_id", .hide = 1, .def = "0", + .maxval = FLOW_MAX_WEIGHT, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_FLOW, }, { .name = "flow_watermark", .lname = "I/O flow watermark", - .type = FIO_OPT_INT, - .off1 = offsetof(struct thread_options, flow_watermark), - .help = "High watermark for flow control. This option" - " should be set to the same value for all threads" - " with non-zero flow.", - .parent = "flow_id", - .hide = 1, - .def = "1024", + .type = FIO_OPT_SOFT_DEPRECATED, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_FLOW, }, @@ -4851,8 +4985,7 @@ char *fio_option_dup_subs(const char *opt) return NULL; } - in[OPT_LEN_MAX] = '\0'; - strncpy(in, opt, OPT_LEN_MAX); + snprintf(in, sizeof(in), "%s", opt); while (*inptr && nchr > 0) { if (inptr[0] == '$' && inptr[1] == '{') {