#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
- }
+ },
+ { }
};
/*
static int str_exitall_cb(void)
{
- exitall_on_terminate = 1;
+ exitall_on_terminate = true;
return 0;
}
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;
* 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;
}
-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);
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);
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);
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);
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;
/* 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;
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;
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;
}
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);
.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",
.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",
.help = "HTTP (WebDAV/S3) IO engine",
},
#endif
+ { .ival = "nbd",
+ .help = "Network Block Device (NBD) IO engine"
+ },
},
},
{
.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",
.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",
.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 = {
.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,
#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",
.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",
},
{
.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 = "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]),
.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]),
.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",
.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",
.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,
},
.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,
},
{
.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",
{
.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 = {
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] == '{') {