X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=options.c;h=955bf959e49c3ff2a8c1c9912786f45b833b346c;hp=4714a3a1e57f7fe0767fe2caf1437457573c88b9;hb=465767437da1bcf99a375295799d33948d9fc5f0;hpb=f4cd67d8dc96ca947b294f6a5c9fdced2b64215d diff --git a/options.c b/options.c index 4714a3a1..955bf959 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), + .len = FIO_FIELD_SIZE(struct io_u *, offset), .paste = paste_blockoff - } + }, + { } }; /* @@ -42,6 +44,27 @@ static char *get_opt_postfix(const char *str) return strdup(p); } +static bool split_parse_distr(const char *str, double *val, double *center) +{ + char *cp, *p; + bool r; + + p = strdup(str); + if (!p) + return false; + + cp = strstr(p, ":"); + r = true; + if (cp) { + *cp = '\0'; + cp++; + r = str_to_float(cp, center, 0); + } + r = r && str_to_float(p, val, 0); + free(p); + return r; +} + static int bs_cmp(const void *p1, const void *p2) { const struct bssplit *bsp1 = p1; @@ -785,6 +808,7 @@ static int str_fst_cb(void *data, const char *str) { struct thread_data *td = cb_data_to_td(data); double val; + double center = -1; bool done = false; char *nr; @@ -819,7 +843,7 @@ static int str_fst_cb(void *data, const char *str) return 0; nr = get_opt_postfix(str); - if (nr && !str_to_float(nr, &val, 0)) { + if (nr && !split_parse_distr(nr, &val, ¢er)) { log_err("fio: file service type random postfix parsing failed\n"); free(nr); return 1; @@ -827,6 +851,12 @@ static int str_fst_cb(void *data, const char *str) free(nr); + if (center != -1 && (center < 0.00 || center > 1.00)) { + log_err("fio: distribution center out of range (0 <= center <= 1.0)\n"); + return 1; + } + td->random_center = center; + switch (td->o.file_service_type) { case FIO_FSERVICE_ZIPF: if (val == 1.00) { @@ -1028,6 +1058,7 @@ static int str_random_distribution_cb(void *data, const char *str) { struct thread_data *td = cb_data_to_td(data); double val; + double center = -1; char *nr; if (td->o.random_distribution == FIO_RAND_DIST_ZIPF) @@ -1044,7 +1075,7 @@ static int str_random_distribution_cb(void *data, const char *str) return 0; nr = get_opt_postfix(str); - if (nr && !str_to_float(nr, &val, 0)) { + if (nr && !split_parse_distr(nr, &val, ¢er)) { log_err("fio: random postfix parsing failed\n"); free(nr); return 1; @@ -1052,6 +1083,12 @@ static int str_random_distribution_cb(void *data, const char *str) free(nr); + if (center != -1 && (center < 0.00 || center > 1.00)) { + log_err("fio: distribution center out of range (0 <= center <= 1.0)\n"); + return 1; + } + td->o.random_center.u.f = center; + if (td->o.random_distribution == FIO_RAND_DIST_ZIPF) { if (val == 1.00) { log_err("fio: zipf theta must different than 1.0\n"); @@ -1338,7 +1375,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; @@ -1385,9 +1422,9 @@ static int str_verify_pattern_cb(void *data, const char *input) struct thread_data *td = cb_data_to_td(data); int ret; - td->o.verify_fmt_sz = ARRAY_SIZE(td->o.verify_fmt); + td->o.verify_fmt_sz = FIO_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; @@ -1474,6 +1511,26 @@ static int str_size_cb(void *data, unsigned long long *__val) return 0; } +static int str_io_size_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_uncapped(v)) { + td->o.io_size = 0; + td->o.io_size_percent = -1ULL - v; + if (td->o.io_size_percent > 100) { + log_err("fio: io_size values greater than 100%% aren't supported\n"); + return 1; + } + dprint(FD_PARSE, "SET io_size_percent %d\n", + td->o.io_size_percent); + } else + td->o.io_size = v; + + return 0; +} + static int str_write_bw_log_cb(void *data, const char *str) { struct thread_data *td = cb_data_to_td(data); @@ -1615,6 +1672,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Filename(s)", .type = FIO_OPT_STR_STORE, .off1 = offsetof(struct thread_options, filename), + .maxlen = PATH_MAX, .cb = str_filename_cb, .prio = -1, /* must come after "directory" */ .help = "File(s) to use for the workload", @@ -1850,11 +1908,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .ival = "cpuio", .help = "CPU cycle burner engine", }, -#ifdef CONFIG_GUASI - { .ival = "guasi", - .help = "GUASI IO engine", - }, -#endif #ifdef CONFIG_RDMA { .ival = "rdma", .help = "RDMA IO engine", @@ -2041,6 +2094,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .alias = "io_limit", .lname = "IO Size", .type = FIO_OPT_STR_VAL, + .cb = str_io_size_cb, .off1 = offsetof(struct thread_options, io_size), .help = "Total size of I/O to be performed", .interval = 1024 * 1024, @@ -3325,6 +3379,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", @@ -3359,12 +3424,22 @@ 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, @@ -3536,7 +3611,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]), @@ -3548,7 +3623,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]), @@ -3671,6 +3746,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", @@ -3684,14 +3769,32 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .name = "sync", .lname = "Synchronous I/O", - .type = FIO_OPT_BOOL, + .type = FIO_OPT_STR, .off1 = offsetof(struct thread_options, sync_io), - .help = "Use O_SYNC for buffered writes", - .def = "0", - .parent = "buffered", + .help = "Use synchronous write IO", + .def = "none", .hide = 1, .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_TYPE, + .posval = { + { .ival = "none", + .oval = 0, + }, + { .ival = "0", + .oval = 0, + }, + { .ival = "sync", + .oval = O_SYNC, + }, + { .ival = "1", + .oval = O_SYNC, + }, +#ifdef O_DSYNC + { .ival = "dsync", + .oval = O_DSYNC, + }, +#endif + }, }, #ifdef FIO_HAVE_WRITE_HINT { @@ -4669,20 +4772,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, }, @@ -5003,7 +5100,7 @@ static char *fio_keyword_replace(char *opt) struct fio_keyword *kw = &fio_keywords[i]; while ((s = strstr(opt, kw->word)) != NULL) { - char *new = malloc(strlen(opt) + 1); + char *new = calloc(strlen(opt) + 1, 1); char *o_org = opt; int olen = s - opt; int len; @@ -5019,9 +5116,10 @@ static char *fio_keyword_replace(char *opt) * If there's more in the original string, copy that * in too */ - opt += strlen(kw->word) + olen; + opt += olen + strlen(kw->word); + /* keeps final zero thanks to calloc */ if (strlen(opt)) - memcpy(new + olen + len, opt, opt - o_org - 1); + memcpy(new + olen + len, opt, strlen(opt)); /* * replace opt and free the old opt