if (str_to_decimal(fname, &val, 1, o)) {
log_err("fio: bssplit conversion failed\n");
- free(o->bssplit);
+ free(bssplit);
return 1;
}
char *str, *p, *odir, *ddir;
int ret = 0;
+ if (parse_dryrun())
+ return 0;
+
p = str = strdup(input);
strip_blank_front(&str);
if (!error[i]) {
log_err("Unknown error %s, please use number value \n",
fname);
+ free(error);
return 1;
}
i++;
struct thread_data *td = data;
char *str, *p, *n;
int type = 0, ret = 1;
+
+ if (parse_dryrun())
+ return 0;
+
p = str = strdup(input);
strip_blank_front(&str);
struct thread_options *o = &td->o;
char *nr = get_opt_postfix(str);
+ if (parse_dryrun())
+ return 0;
+
o->ddir_seq_nr = 1;
o->ddir_seq_add = 0;
long max_cpu;
int ret;
+ if (parse_dryrun())
+ return 0;
+
ret = fio_cpuset_init(&td->o.cpumask);
if (ret < 0) {
log_err("fio: cpuset_init failed\n");
struct thread_data *td = data;
int ret;
+ if (parse_dryrun())
+ return 0;
+
ret = set_cpus_allowed(td, &td->o.cpumask, input);
if (!ret)
td->o.cpumask_set = 1;
{
struct thread_data *td = data;
+ if (parse_dryrun())
+ return 0;
+
/* numa_parse_nodestring() parses a character string list
* of nodes into a bit mask. The bit mask is allocated by
* numa_allocate_nodemask(), so it should be freed by
{
struct thread_data *td = data;
const char * const policy_types[] =
- { "default", "prefer", "bind", "interleave", "local" };
+ { "default", "prefer", "bind", "interleave", "local", NULL };
int i;
+ char *nodelist;
+
+ if (parse_dryrun())
+ return 0;
- char *nodelist = strchr(input, ':');
+ nodelist = strchr(input, ':');
if (nodelist) {
/* NUL-terminate mode */
*nodelist++ = '\0';
double val;
char *nr;
+ if (parse_dryrun())
+ return 0;
+
if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
val = 1.1;
else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
struct thread_data *td = data;
struct stat sb;
+ if (parse_dryrun())
+ return 0;
+
if (lstat(td->o.directory, &sb) < 0) {
int ret = errno;
{
struct thread_data *td = data;
+ if (parse_dryrun())
+ return 0;
+
if (!td->files_index)
td->o.nr_files = 0;
{
struct thread_data *td = data;
long off;
- int i = 0, j = 0, len, k, base = 10;
+ int i = 0, j = 0, len, k, base = 10, pattern_length;
char *loc1, *loc2;
loc1 = strstr(input, "0x");
* Fill the pattern all the way to the end. This greatly reduces
* the number of memcpy's we have to do when verifying the IO.
*/
+ pattern_length = i;
while (i > 1 && i * 2 <= MAX_PATTERN_SIZE) {
memcpy(&td->o.verify_pattern[i], &td->o.verify_pattern[0], i);
i *= 2;
}
+
+ /*
+ * Fill remainder, if the pattern multiple ends up not being
+ * MAX_PATTERN_SIZE.
+ */
+ while (i > 1 && i < MAX_PATTERN_SIZE) {
+ unsigned int b = min(pattern_length, MAX_PATTERN_SIZE - i);
+
+ memcpy(&td->o.verify_pattern[i], &td->o.verify_pattern[0], b);
+ i += b;
+ }
+
if (i == 1) {
/*
* The code in verify_io_u_pattern assumes a single byte pattern
return 0;
}
-static int str_lockfile_cb(void *data, const char *str)
-{
- struct thread_data *td = data;
- char *nr = get_opt_postfix(str);
-
- td->o.lockfile_batch = 1;
- if (nr) {
- td->o.lockfile_batch = atoi(nr);
- free(nr);
- }
-
- return 0;
-}
-
static int str_gtod_reduce_cb(void *data, int *il)
{
struct thread_data *td = data;
return 0;
}
-static int kb_base_verify(struct fio_option *o, void *data)
-{
- struct thread_data *td = data;
-
- if (td->o.kb_base != 1024 && td->o.kb_base != 1000) {
- log_err("fio: kb_base set to nonsensical value: %u\n",
- td->o.kb_base);
- return 1;
- }
-
- return 0;
-}
-
/*
* Option grouping
*/
.category = FIO_OPT_C_FILE,
.group = FIO_OPT_G_FILENAME,
},
+ {
+ .name = "filename_format",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(filename_format),
+ .prio = -1, /* must come after "directory" */
+ .help = "Override default $jobname.$jobnum.$filenum naming",
+ .def = "$jobname.$jobnum.$filenum",
+ .category = FIO_OPT_C_FILE,
+ .group = FIO_OPT_G_FILENAME,
+ },
{
.name = "lockfile",
.lname = "Lockfile",
.type = FIO_OPT_STR,
- .cb = str_lockfile_cb,
.off1 = td_var_offset(file_lock_mode),
.help = "Lock file when doing IO to it",
.parent = "filename",
{ .ival = "vsync",
.help = "Use readv/writev",
},
+#ifdef CONFIG_PWRITEV
+ { .ival = "pvsync",
+ .help = "Use preadv/pwritev",
+ },
+#endif
#ifdef CONFIG_LIBAIO
{ .ival = "libaio",
.help = "Linux native asynchronous IO",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_INVALID,
},
+ {
+ .name = "number_ios",
+ .lname = "Number of IOs to perform",
+ .type = FIO_OPT_STR_VAL,
+ .off1 = td_var_offset(number_ios),
+ .help = "Force job completion of this number of IOs",
+ .def = "0",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_INVALID,
+ },
{
.name = "bs",
.lname = "Block size",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_INVALID,
},
+ {
+ .name = "bs_is_seq_rand",
+ .lname = "Block size division is seq/random (not read/write)",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(bs_is_seq_rand),
+ .help = "Consider any blocksize setting to be sequential,ramdom",
+ .def = "0",
+ .parent = "blocksize",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_INVALID,
+ },
{
.name = "randrepeat",
.lname = "Random repeatable",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RANDOM,
},
+ {
+ .name = "percentage_random",
+ .lname = "Percentage Random",
+ .type = FIO_OPT_INT,
+ .off1 = td_var_offset(perc_rand[DDIR_READ]),
+ .off2 = td_var_offset(perc_rand[DDIR_WRITE]),
+ .off3 = td_var_offset(perc_rand[DDIR_TRIM]),
+ .maxval = 100,
+ .help = "Percentage of seq/random mix that should be random",
+ .def = "100,100,100",
+ .interval = 5,
+ .inverse = "percentage_sequential",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_RANDOM,
+ },
+ {
+ .name = "percentage_sequential",
+ .lname = "Percentage Sequential",
+ .type = FIO_OPT_DEPRECATED,
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_RANDOM,
+ },
{
.name = "nrfiles",
.lname = "Number of files",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_IO_TYPE,
},
+ {
+ .name = "atomic",
+ .lname = "Atomic I/O",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(oatomic),
+ .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
+ .def = "0",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_IO_TYPE,
+ },
{
.name = "buffered",
.lname = "Buffered I/O",
.lname = "Lock memory",
.type = FIO_OPT_STR_VAL,
.off1 = td_var_offset(lockmem),
- .help = "Lock down this amount of memory",
+ .help = "Lock down this amount of memory (per worker)",
.def = "0",
.interval = 1024 * 1024,
.category = FIO_OPT_C_GENERAL,
.type = FIO_OPT_STR,
.cb = str_numa_cpunodes_cb,
.help = "NUMA CPU nodes bind",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_INVALID,
},
{
.name = "numa_mem_policy",
.type = FIO_OPT_STR,
.cb = str_numa_mpol_cb,
.help = "NUMA memory policy setup",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_INVALID,
},
#endif
{
{
.name = "write_iops_log",
.lname = "Write IOPS log",
- .type = FIO_OPT_STR,
+ .type = FIO_OPT_STR_STORE,
.off1 = td_var_offset(iops_log_file),
.help = "Write log of IOPS during run",
.category = FIO_OPT_C_LOG,
{
.name = "group_reporting",
.lname = "Group reporting",
- .type = FIO_OPT_BOOL,
+ .type = FIO_OPT_STR_SET,
.off1 = td_var_offset(group_reporting),
.help = "Do reporting on a per-group basis",
- .def = "1",
.category = FIO_OPT_C_STAT,
.group = FIO_OPT_G_INVALID,
},
.lname = "Completion latency percentile list",
.type = FIO_OPT_FLOAT_LIST,
.off1 = td_var_offset(percentile_list),
- .off2 = td_var_offset(overwrite_plist),
+ .off2 = td_var_offset(percentile_precision),
.help = "Specify a custom list of percentiles to report",
+ .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,
.maxfp = 100.0,
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_CLOCK,
},
+ {
+ .name = "unified_rw_reporting",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(unified_rw_rep),
+ .help = "Unify reporting across data direction",
+ .def = "0",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_INVALID,
+ },
{
.name = "continue_on_error",
.lname = "Continue on error",
.lname = "KB Base",
.type = FIO_OPT_INT,
.off1 = td_var_offset(kb_base),
- .verify = kb_base_verify,
.prio = 1,
.def = "1024",
+ .posval = {
+ { .ival = "1024",
+ .oval = 1024,
+ .help = "Use 1024 as the K base",
+ },
+ { .ival = "1000",
+ .oval = 1000,
+ .help = "Use 1000 as the K base",
+ },
+ },
.help = "How many bytes per KB for reporting (1000 or 1024)",
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_INVALID,
},
+ {
+ .name = "unit_base",
+ .lname = "Base unit for reporting (Bits or Bytes)",
+ .type = FIO_OPT_INT,
+ .off1 = td_var_offset(unit_base),
+ .prio = 1,
+ .posval = {
+ { .ival = "0",
+ .oval = 0,
+ .help = "Auto-detect",
+ },
+ { .ival = "8",
+ .oval = 8,
+ .help = "Normal (byte based)",
+ },
+ { .ival = "1",
+ .oval = 1,
+ .help = "Bit based",
+ },
+ },
+ .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_INVALID,
+ },
{
.name = "hugepage-size",
.lname = "Hugepage size",
int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
char *val)
{
- return parse_cmd_option(opt, val, td->io_ops->options, td);
+ return parse_cmd_option(opt, val, td->io_ops->options, td->eo);
}
void fio_fill_default_options(struct thread_data *td)