X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=options.c;h=91049af5472e55abecf65a266aa28b2162ea1d15;hb=ebd9b4dd690808f720712b9c1a1288ae0742f361;hp=460cf4ff086c441775181e35e8daa994d22326cc;hpb=a7194b2d3d427e7e5678c55a128639df9caf4a48;p=fio.git diff --git a/options.c b/options.c index 460cf4ff..91049af5 100644 --- a/options.c +++ b/options.c @@ -251,6 +251,34 @@ int str_split_parse(struct thread_data *td, char *str, return ret; } +static int fio_fdp_cmp(const void *p1, const void *p2) +{ + const uint16_t *t1 = p1; + const uint16_t *t2 = p2; + + return *t1 - *t2; +} + +static int str_fdp_pli_cb(void *data, const char *input) +{ + struct thread_data *td = cb_data_to_td(data); + char *str, *p, *v; + int i = 0; + + p = str = strdup(input); + strip_blank_front(&str); + strip_blank_end(str); + + while ((v = strsep(&str, ",")) != NULL && i < FIO_MAX_PLIS) + td->o.fdp_plis[i++] = strtoll(v, NULL, 0); + free(p); + + qsort(td->o.fdp_plis, i, sizeof(*td->o.fdp_plis), fio_fdp_cmp); + td->o.fdp_nrpli = i; + + return 0; +} + static int str_bssplit_cb(void *data, const char *input) { struct thread_data *td = cb_data_to_td(data); @@ -278,6 +306,128 @@ static int str_bssplit_cb(void *data, const char *input) return ret; } +static int parse_cmdprio_bssplit_entry(struct thread_options *o, + struct split_prio *entry, char *str) +{ + int matches = 0; + char *bs_str = NULL; + long long bs_val; + unsigned int perc = 0, class, level; + + /* + * valid entry formats: + * bs/ - %s/ - set perc to 0, prio to -1. + * bs/perc - %s/%u - set prio to -1. + * bs/perc/class/level - %s/%u/%u/%u + */ + matches = sscanf(str, "%m[^/]/%u/%u/%u", &bs_str, &perc, &class, &level); + if (matches < 1) { + log_err("fio: invalid cmdprio_bssplit format\n"); + return 1; + } + + if (str_to_decimal(bs_str, &bs_val, 1, o, 0, 0)) { + log_err("fio: split conversion failed\n"); + free(bs_str); + return 1; + } + free(bs_str); + + entry->bs = bs_val; + entry->perc = min(perc, 100u); + entry->prio = -1; + switch (matches) { + case 1: /* bs/ case */ + case 2: /* bs/perc case */ + break; + case 4: /* bs/perc/class/level case */ + class = min(class, (unsigned int) IOPRIO_MAX_PRIO_CLASS); + level = min(level, (unsigned int) IOPRIO_MAX_PRIO); + entry->prio = ioprio_value(class, level); + break; + default: + log_err("fio: invalid cmdprio_bssplit format\n"); + return 1; + } + + return 0; +} + +/* + * Returns a negative integer if the first argument should be before the second + * argument in the sorted list. A positive integer if the first argument should + * be after the second argument in the sorted list. A zero if they are equal. + */ +static int fio_split_prio_cmp(const void *p1, const void *p2) +{ + const struct split_prio *tmp1 = p1; + const struct split_prio *tmp2 = p2; + + if (tmp1->bs > tmp2->bs) + return 1; + if (tmp1->bs < tmp2->bs) + return -1; + return 0; +} + +int split_parse_prio_ddir(struct thread_options *o, struct split_prio **entries, + int *nr_entries, char *str) +{ + struct split_prio *tmp_entries; + unsigned int nr_bssplits; + char *str_cpy, *p, *fname; + + /* strsep modifies the string, dup it so that we can use strsep twice */ + p = str_cpy = strdup(str); + if (!p) + return 1; + + nr_bssplits = 0; + while ((fname = strsep(&str_cpy, ":")) != NULL) { + if (!strlen(fname)) + break; + nr_bssplits++; + } + free(p); + + if (nr_bssplits > BSSPLIT_MAX) { + log_err("fio: too many cmdprio_bssplit entries\n"); + return 1; + } + + tmp_entries = calloc(nr_bssplits, sizeof(*tmp_entries)); + if (!tmp_entries) + return 1; + + nr_bssplits = 0; + while ((fname = strsep(&str, ":")) != NULL) { + struct split_prio *entry; + + if (!strlen(fname)) + break; + + entry = &tmp_entries[nr_bssplits]; + + if (parse_cmdprio_bssplit_entry(o, entry, fname)) { + log_err("fio: failed to parse cmdprio_bssplit entry\n"); + free(tmp_entries); + return 1; + } + + /* skip zero perc entries, they provide no useful information */ + if (entry->perc) + nr_bssplits++; + } + + qsort(tmp_entries, nr_bssplits, sizeof(*tmp_entries), + fio_split_prio_cmp); + + *entries = tmp_entries; + *nr_entries = nr_bssplits; + + return 0; +} + static int str2error(char *str) { const char *err[] = { "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO", @@ -505,7 +655,7 @@ static int str_exitall_cb(void) int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu_index) { unsigned int i, index, cpus_in_mask; - const long max_cpu = cpus_online(); + const long max_cpu = cpus_configured(); cpus_in_mask = fio_cpu_count(mask); if (!cpus_in_mask) @@ -544,7 +694,7 @@ static int str_cpumask_cb(void *data, unsigned long long *val) return 1; } - max_cpu = cpus_online(); + max_cpu = cpus_configured(); for (i = 0; i < sizeof(int) * 8; i++) { if ((1 << i) & *val) { @@ -580,7 +730,7 @@ static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask, strip_blank_front(&str); strip_blank_end(str); - max_cpu = cpus_online(); + max_cpu = cpus_configured(); while ((cpu = strsep(&str, ",")) != NULL) { char *str2, *cpu2; @@ -1244,7 +1394,7 @@ int get_max_str_idx(char *input) } /* - * Returns the directory at the index, indexes > entires will be + * Returns the directory at the index, indexes > entries will be * assigned via modulo division of the index */ int set_name_idx(char *target, size_t tlen, char *input, int index, @@ -1366,8 +1516,8 @@ static int str_buffer_pattern_cb(void *data, const char *input) int ret; /* 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, NULL, NULL); + ret = parse_and_fill_pattern_alloc(input, strlen(input), + &td->o.buffer_pattern, NULL, NULL, NULL); if (ret < 0) return 1; @@ -1415,9 +1565,9 @@ static int str_verify_pattern_cb(void *data, const char *input) int ret; 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, - td->o.verify_fmt, &td->o.verify_fmt_sz); + ret = parse_and_fill_pattern_alloc(input, strlen(input), + &td->o.verify_pattern, fmt_desc, td->o.verify_fmt, + &td->o.verify_fmt_sz); if (ret < 0) return 1; @@ -1438,7 +1588,7 @@ static int str_gtod_reduce_cb(void *data, int *il) int val = *il; /* - * Only modfiy options if gtod_reduce==1 + * Only modify options if gtod_reduce==1 * Otherwise leave settings alone. */ if (val) { @@ -1825,6 +1975,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = TD_DDIR_TRIMWRITE, .help = "Trim and write mix, trims preceding writes" }, + { .ival = "randtrimwrite", + .oval = TD_DDIR_RANDTRIMWRITE, + .help = "Randomly trim and write mix, trims preceding writes" + }, }, }, { @@ -1970,12 +2124,6 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "Hadoop Distributed Filesystem (HDFS) engine" }, #endif -#ifdef CONFIG_PMEMBLK - { .ival = "pmemblk", - .help = "PMDK libpmemblk based IO engine", - }, - -#endif #ifdef CONFIG_IME { .ival = "ime_psync", .help = "DDN's IME synchronous IO engine", @@ -2018,10 +2166,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "DAOS File System (dfs) IO engine", }, #endif -#ifdef CONFIG_NFS +#ifdef CONFIG_LIBNFS { .ival = "nfs", .help = "NFS IO engine", }, +#endif +#ifdef CONFIG_LIBXNVME + { .ival = "xnvme", + .help = "XNVME IO engine", + }, #endif }, }, @@ -3518,6 +3671,27 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_ZONE, }, + { + .name = "fdp", + .lname = "Flexible data placement", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct thread_options, fdp), + .help = "Use Data placement directive (FDP)", + .def = "0", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_INVALID, + }, + { + .name = "fdp_pli", + .lname = "FDP Placement ID indicies", + .type = FIO_OPT_STR, + .cb = str_fdp_pli_cb, + .off1 = offsetof(struct thread_options, fdp_plis), + .help = "Sets which placement ids to use (defaults to all)", + .hide = 1, + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_INVALID, + }, { .name = "lockmem", .lname = "Lock memory", @@ -4244,6 +4418,18 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_LOG, .group = FIO_OPT_G_INVALID, }, + { + .name = "log_entries", + .lname = "Log entries", + .type = FIO_OPT_INT, + .off1 = offsetof(struct thread_options, log_entries), + .help = "Initial number of entries in a job IO log", + .def = __fio_stringify(DEF_LOG_ENTRIES), + .minval = DEF_LOG_ENTRIES, + .maxval = MAX_LOG_ENTRIES, + .category = FIO_OPT_C_LOG, + .group = FIO_OPT_G_INVALID, + }, { .name = "log_avg_msec", .lname = "Log averaging (msec)", @@ -4380,6 +4566,24 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_LOG, .group = FIO_OPT_G_INVALID, }, + { + .name = "log_alternate_epoch", + .lname = "Log epoch alternate", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct thread_options, log_alternate_epoch), + .help = "Use alternate epoch time in log files. Uses the same epoch as that is used by clock_gettime with specified log_alternate_epoch_clock_id.", + .category = FIO_OPT_C_LOG, + .group = FIO_OPT_G_INVALID, + }, + { + .name = "log_alternate_epoch_clock_id", + .lname = "Log alternate epoch clock_id", + .type = FIO_OPT_INT, + .off1 = offsetof(struct thread_options, log_alternate_epoch_clock_id), + .help = "If log_alternate_epoch or log_unix_epoch is true, this option specifies the clock_id from clock_gettime whose epoch should be used. If neither of those is true, this option has no effect. Default value is 0, or CLOCK_REALTIME", + .category = FIO_OPT_C_LOG, + .group = FIO_OPT_G_INVALID, + }, { .name = "block_error_percentiles", .lname = "Block error percentiles", @@ -4513,6 +4717,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_IO_BUF, }, + { + .name = "dedupe_global", + .lname = "Global deduplication", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct thread_options, dedupe_global), + .help = "Share deduplication buffers across jobs", + .def = "0", + .category = FIO_OPT_C_IO, + .group = FIO_OPT_G_IO_BUF, + }, { .name = "dedupe_mode", .lname = "Dedupe mode", @@ -5134,7 +5348,7 @@ void fio_keywords_init(void) sprintf(buf, "%llu", mb_memory); fio_keywords[1].replace = strdup(buf); - l = cpus_online(); + l = cpus_configured(); sprintf(buf, "%lu", l); fio_keywords[2].replace = strdup(buf); }