char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 };
+struct pattern_fmt_desc fmt_desc[] = {
+ {
+ .fmt = "%o",
+ .len = FIELD_SIZE(struct io_u *, offset),
+ .paste = paste_blockoff
+ }
+};
+
/*
* Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
*/
return (int) bsp1->perc - (int) bsp2->perc;
}
-static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
+struct split {
+ unsigned int nr;
+ unsigned int val1[100];
+ unsigned int val2[100];
+};
+
+static int split_parse_ddir(struct thread_options *o, struct split *split,
+ enum fio_ddir ddir, char *str)
{
- struct bssplit *bssplit;
- unsigned int i, perc, perc_missing;
- unsigned int max_bs, min_bs;
+ unsigned int i, perc;
long long val;
char *fname;
- o->bssplit_nr[ddir] = 4;
- bssplit = malloc(4 * sizeof(struct bssplit));
+ split->nr = 0;
i = 0;
- max_bs = 0;
- min_bs = -1;
while ((fname = strsep(&str, ":")) != NULL) {
char *perc_str;
if (!strlen(fname))
break;
- /*
- * grow struct buffer, if needed
- */
- if (i == o->bssplit_nr[ddir]) {
- o->bssplit_nr[ddir] <<= 1;
- bssplit = realloc(bssplit, o->bssplit_nr[ddir]
- * sizeof(struct bssplit));
- }
-
perc_str = strstr(fname, "/");
if (perc_str) {
*perc_str = '\0';
if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
log_err("fio: bssplit conversion failed\n");
- free(bssplit);
return 1;
}
- if (val > max_bs)
- max_bs = val;
- if (val < min_bs)
- min_bs = val;
-
- bssplit[i].bs = val;
- bssplit[i].perc = perc;
+ split->val1[i] = val;
+ split->val2[i] = perc;
i++;
+ if (i == 100)
+ break;
}
- o->bssplit_nr[ddir] = i;
+ split->nr = i;
+ return 0;
+}
+
+static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str)
+{
+ unsigned int i, perc, perc_missing;
+ unsigned int max_bs, min_bs;
+ struct split split;
+
+ memset(&split, 0, sizeof(split));
+
+ if (split_parse_ddir(o, &split, ddir, str))
+ return 1;
+ if (!split.nr)
+ return 0;
+
+ max_bs = 0;
+ min_bs = -1;
+ o->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
+ o->bssplit_nr[ddir] = split.nr;
+ for (i = 0; i < split.nr; i++) {
+ if (split.val1[i] > max_bs)
+ max_bs = split.val1[i];
+ if (split.val1[i] < min_bs)
+ min_bs = split.val1[i];
+
+ o->bssplit[ddir][i].bs = split.val1[i];
+ o->bssplit[ddir][i].perc =split.val2[i];
+ }
/*
* Now check if the percentages add up, and how much is missing
*/
perc = perc_missing = 0;
for (i = 0; i < o->bssplit_nr[ddir]; i++) {
- struct bssplit *bsp = &bssplit[i];
+ struct bssplit *bsp = &o->bssplit[ddir][i];
if (bsp->perc == -1U)
perc_missing++;
if (perc > 100 && perc_missing > 1) {
log_err("fio: bssplit percentages add to more than 100%%\n");
- free(bssplit);
+ free(o->bssplit[ddir]);
+ o->bssplit[ddir] = NULL;
return 1;
}
if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
perc = 100;
for (i = 0; i < o->bssplit_nr[ddir]; i++) {
- struct bssplit *bsp = &bssplit[i];
+ struct bssplit *bsp = &o->bssplit[ddir][i];
if (bsp->perc == -1U)
bsp->perc = (100 - perc) / perc_missing;
/*
* now sort based on percentages, for ease of lookup
*/
- qsort(bssplit, o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
- o->bssplit[ddir] = bssplit;
+ qsort(o->bssplit[ddir], o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
return 0;
}
-static int str_bssplit_cb(void *data, const char *input)
+typedef int (split_parse_fn)(struct thread_options *, enum fio_ddir, char *);
+
+static int str_split_parse(struct thread_data *td, char *str, split_parse_fn *fn)
{
- struct thread_data *td = data;
- char *str, *p, *odir, *ddir;
+ char *odir, *ddir;
int ret = 0;
- if (parse_dryrun())
- return 0;
-
- p = str = strdup(input);
-
- strip_blank_front(&str);
- strip_blank_end(str);
-
odir = strchr(str, ',');
if (odir) {
ddir = strchr(odir + 1, ',');
if (ddir) {
- ret = bssplit_ddir(&td->o, DDIR_TRIM, ddir + 1);
+ ret = fn(&td->o, DDIR_TRIM, ddir + 1);
if (!ret)
*ddir = '\0';
} else {
char *op;
op = strdup(odir + 1);
- ret = bssplit_ddir(&td->o, DDIR_TRIM, op);
+ ret = fn(&td->o, DDIR_TRIM, op);
free(op);
}
if (!ret)
- ret = bssplit_ddir(&td->o, DDIR_WRITE, odir + 1);
+ ret = fn(&td->o, DDIR_WRITE, odir + 1);
if (!ret) {
*odir = '\0';
- ret = bssplit_ddir(&td->o, DDIR_READ, str);
+ ret = fn(&td->o, DDIR_READ, str);
}
} else {
char *op;
op = strdup(str);
- ret = bssplit_ddir(&td->o, DDIR_WRITE, op);
+ ret = fn(&td->o, DDIR_WRITE, op);
free(op);
if (!ret) {
op = strdup(str);
- ret = bssplit_ddir(&td->o, DDIR_TRIM, op);
+ ret = fn(&td->o, DDIR_TRIM, op);
free(op);
}
if (!ret)
- ret = bssplit_ddir(&td->o, DDIR_READ, str);
+ ret = fn(&td->o, DDIR_READ, str);
+ }
+
+ return ret;
+}
+
+static int str_bssplit_cb(void *data, const char *input)
+{
+ struct thread_data *td = data;
+ char *str, *p;
+ int ret = 0;
+
+ p = str = strdup(input);
+
+ strip_blank_front(&str);
+ strip_blank_end(str);
+
+ ret = str_split_parse(td, str, bssplit_ddir);
+
+ if (parse_dryrun()) {
+ int i;
+
+ for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+ free(td->o.bssplit[i]);
+ td->o.bssplit[i] = NULL;
+ td->o.bssplit_nr[i] = 0;
+ }
}
free(p);
"EINVAL", "ENFILE", "EMFILE", "ENOTTY",
"ETXTBSY","EFBIG", "ENOSPC", "ESPIPE",
"EROFS","EMLINK", "EPIPE", "EDOM", "ERANGE" };
- int i = 0, num = sizeof(err) / sizeof(void *);
+ int i = 0, num = sizeof(err) / sizeof(char *);
while (i < num) {
if (!strcmp(err[i], str))
static int str_fst_cb(void *data, const char *str)
{
struct thread_data *td = data;
- char *nr = get_opt_postfix(str);
+ double val;
+ bool done = false;
+ char *nr;
td->file_service_nr = 1;
- if (nr) {
- td->file_service_nr = atoi(nr);
+
+ switch (td->o.file_service_type) {
+ case FIO_FSERVICE_RANDOM:
+ case FIO_FSERVICE_RR:
+ case FIO_FSERVICE_SEQ:
+ nr = get_opt_postfix(str);
+ if (nr) {
+ td->file_service_nr = atoi(nr);
+ free(nr);
+ }
+ done = true;
+ break;
+ case FIO_FSERVICE_ZIPF:
+ val = FIO_DEF_ZIPF;
+ break;
+ case FIO_FSERVICE_PARETO:
+ val = FIO_DEF_PARETO;
+ break;
+ case FIO_FSERVICE_GAUSS:
+ val = 0.0;
+ break;
+ default:
+ log_err("fio: bad file service type: %d\n", td->o.file_service_type);
+ return 1;
+ }
+
+ if (done)
+ return 0;
+
+ nr = get_opt_postfix(str);
+ if (nr && !str_to_float(nr, &val, 0)) {
+ log_err("fio: file service type random postfix parsing failed\n");
free(nr);
+ return 1;
+ }
+
+ free(nr);
+
+ switch (td->o.file_service_type) {
+ case FIO_FSERVICE_ZIPF:
+ if (val == 1.00) {
+ log_err("fio: zipf theta must be different than 1.0\n");
+ return 1;
+ }
+ if (parse_dryrun())
+ return 0;
+ td->zipf_theta = val;
+ break;
+ case FIO_FSERVICE_PARETO:
+ if (val <= 0.00 || val >= 1.00) {
+ log_err("fio: pareto input out of range (0 < input < 1.0)\n");
+ return 1;
+ }
+ if (parse_dryrun())
+ return 0;
+ td->pareto_h = val;
+ break;
+ case FIO_FSERVICE_GAUSS:
+ if (val < 0.00 || val >= 100.00) {
+ log_err("fio: normal deviation out of range (0 <= input < 100.0)\n");
+ return 1;
+ }
+ if (parse_dryrun())
+ return 0;
+ td->gauss_dev = val;
+ break;
}
return 0;
return (int) zsp2->access_perc - (int) zsp1->access_perc;
}
-static int zone_split_ddir(struct thread_options *o, int ddir, char *str)
+static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
+ char *str)
{
- struct zone_split *zsplit;
unsigned int i, perc, perc_missing, sperc, sperc_missing;
- long long val;
- char *fname;
-
- o->zone_split_nr[ddir] = 4;
- zsplit = malloc(4 * sizeof(struct zone_split));
-
- i = 0;
- while ((fname = strsep(&str, ":")) != NULL) {
- char *perc_str;
+ struct split split;
- if (!strlen(fname))
- break;
+ memset(&split, 0, sizeof(split));
- /*
- * grow struct buffer, if needed
- */
- if (i == o->zone_split_nr[ddir]) {
- o->zone_split_nr[ddir] <<= 1;
- zsplit = realloc(zsplit, o->zone_split_nr[ddir]
- * sizeof(struct zone_split));
- }
-
- perc_str = strstr(fname, "/");
- if (perc_str) {
- *perc_str = '\0';
- perc_str++;
- perc = atoi(perc_str);
- if (perc > 100)
- perc = 100;
- else if (!perc)
- perc = -1U;
- } else
- perc = -1U;
-
- if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
- log_err("fio: zone_split conversion failed\n");
- free(zsplit);
- return 1;
- }
+ if (split_parse_ddir(o, &split, ddir, str))
+ return 1;
+ if (!split.nr)
+ return 0;
- zsplit[i].access_perc = val;
- zsplit[i].size_perc = perc;
- i++;
+ o->zone_split[ddir] = malloc(split.nr * sizeof(struct zone_split));
+ o->zone_split_nr[ddir] = split.nr;
+ for (i = 0; i < split.nr; i++) {
+ o->zone_split[ddir][i].access_perc = split.val1[i];
+ o->zone_split[ddir][i].size_perc = split.val2[i];
}
- o->zone_split_nr[ddir] = i;
-
/*
* Now check if the percentages add up, and how much is missing
*/
perc = perc_missing = 0;
sperc = sperc_missing = 0;
for (i = 0; i < o->zone_split_nr[ddir]; i++) {
- struct zone_split *zsp = &zsplit[i];
+ struct zone_split *zsp = &o->zone_split[ddir][i];
if (zsp->access_perc == (uint8_t) -1U)
perc_missing++;
if (perc > 100 || sperc > 100) {
log_err("fio: zone_split percentages add to more than 100%%\n");
- free(zsplit);
+ free(o->zone_split[ddir]);
+ o->zone_split[ddir] = NULL;
return 1;
}
if (perc < 100) {
log_err("fio: access percentage don't add up to 100 for zoned "
"random distribution (got=%u)\n", perc);
- free(zsplit);
+ free(o->zone_split[ddir]);
+ o->zone_split[ddir] = NULL;
return 1;
}
if (perc_missing == 1 && o->zone_split_nr[ddir] == 1)
perc = 100;
for (i = 0; i < o->zone_split_nr[ddir]; i++) {
- struct zone_split *zsp = &zsplit[i];
+ struct zone_split *zsp = &o->zone_split[ddir][i];
if (zsp->access_perc == (uint8_t) -1U)
zsp->access_perc = (100 - perc) / perc_missing;
if (sperc_missing == 1 && o->zone_split_nr[ddir] == 1)
sperc = 100;
for (i = 0; i < o->zone_split_nr[ddir]; i++) {
- struct zone_split *zsp = &zsplit[i];
+ struct zone_split *zsp = &o->zone_split[ddir][i];
if (zsp->size_perc == (uint8_t) -1U)
zsp->size_perc = (100 - sperc) / sperc_missing;
/*
* now sort based on percentages, for ease of lookup
*/
- qsort(zsplit, o->zone_split_nr[ddir], sizeof(struct zone_split), zone_cmp);
- o->zone_split[ddir] = zsplit;
+ qsort(o->zone_split[ddir], o->zone_split_nr[ddir], sizeof(struct zone_split), zone_cmp);
return 0;
}
__td_zone_gen_index(td, i);
}
-
static int parse_zoned_distribution(struct thread_data *td, const char *input)
{
- char *str, *p, *odir, *ddir;
+ char *str, *p;
int i, ret = 0;
p = str = strdup(input);
}
str += strlen("zoned:");
- odir = strchr(str, ',');
- if (odir) {
- ddir = strchr(odir + 1, ',');
- if (ddir) {
- ret = zone_split_ddir(&td->o, DDIR_TRIM, ddir + 1);
- if (!ret)
- *ddir = '\0';
- } else {
- char *op;
-
- op = strdup(odir + 1);
- ret = zone_split_ddir(&td->o, DDIR_TRIM, op);
-
- free(op);
- }
- if (!ret)
- ret = zone_split_ddir(&td->o, DDIR_WRITE, odir + 1);
- if (!ret) {
- *odir = '\0';
- ret = zone_split_ddir(&td->o, DDIR_READ, str);
- }
- } else {
- char *op;
-
- op = strdup(str);
- ret = zone_split_ddir(&td->o, DDIR_WRITE, op);
- free(op);
-
- if (!ret) {
- op = strdup(str);
- ret = zone_split_ddir(&td->o, DDIR_TRIM, op);
- free(op);
- }
- if (!ret)
- ret = zone_split_ddir(&td->o, DDIR_READ, str);
- }
+ ret = str_split_parse(td, str, zone_split_ddir);
free(p);
}
}
+ if (parse_dryrun()) {
+ int i;
+
+ for (i = 0; i < DDIR_RWDIR_CNT; i++) {
+ free(td->o.zone_split[i]);
+ td->o.zone_split[i] = NULL;
+ td->o.zone_split_nr[i] = 0;
+ }
+
+ return ret;
+ }
+
if (!ret)
td_zone_gen_index(td);
+ else {
+ for (i = 0; i < DDIR_RWDIR_CNT; i++)
+ td->o.zone_split_nr[i] = 0;
+ }
return ret;
}
double val;
char *nr;
- if (parse_dryrun())
- return 0;
-
if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
val = FIO_DEF_ZIPF;
else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
log_err("fio: zipf theta must different than 1.0\n");
return 1;
}
+ if (parse_dryrun())
+ return 0;
td->o.zipf_theta.u.f = val;
} else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
if (val <= 0.00 || val >= 1.00) {
log_err("fio: pareto input out of range (0 < input < 1.0)\n");
return 1;
}
+ if (parse_dryrun())
+ return 0;
td->o.pareto_h.u.f = val;
} else {
- if (val <= 0.00 || val >= 100.0) {
- log_err("fio: normal deviation out of range (0 < input < 100.0)\n");
+ if (val < 0.00 || val >= 100.0) {
+ log_err("fio: normal deviation out of range (0 <= input < 100.0)\n");
return 1;
}
+ if (parse_dryrun())
+ return 0;
td->o.gauss_dev.u.f = val;
}
* Returns the directory at the index, indexes > entires will be
* assigned via modulo division of the index
*/
-int set_name_idx(char *target, size_t tlen, char *input, int index)
+int set_name_idx(char *target, size_t tlen, char *input, int index,
+ bool unique_filename)
{
unsigned int cur_idx;
int len;
for (cur_idx = 0; cur_idx <= index; cur_idx++)
fname = get_next_name(&str);
- if (client_sockaddr_str[0]) {
+ if (client_sockaddr_str[0] && unique_filename) {
len = snprintf(target, tlen, "%s/%s.", fname,
client_sockaddr_str);
} else
static int str_verify_pattern_cb(void *data, const char *input)
{
- struct pattern_fmt_desc fmt_desc[] = {
- {
- .fmt = "%o",
- .len = FIELD_SIZE(struct io_u *, offset),
- .paste = paste_blockoff
- }
- };
struct thread_data *td = data;
int ret;
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),
- td->o.verify_fmt, &td->o.verify_fmt_sz);
+ MAX_PATTERN_SIZE, fmt_desc, sizeof(fmt_desc),
+ td->o.verify_fmt, &td->o.verify_fmt_sz);
if (ret < 0)
return 1;
},
{
.name = "filename_format",
+ .lname = "Filename Format",
.type = FIO_OPT_STR_STORE,
.off1 = td_var_offset(filename_format),
.prio = -1, /* must come after "directory" */
.category = FIO_OPT_C_FILE,
.group = FIO_OPT_G_FILENAME,
},
+ {
+ .name = "unique_filename",
+ .lname = "Unique Filename",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(unique_filename),
+ .help = "For network clients, prefix file with source IP",
+ .def = "1",
+ .category = FIO_OPT_C_FILE,
+ .group = FIO_OPT_G_FILENAME,
+ },
{
.name = "lockfile",
.lname = "Lockfile",
.help = "Use preadv/pwritev",
},
#endif
-#ifdef CONFIG_PWRITEV
+#ifdef FIO_HAVE_PWRITEV2
{ .ival = "pvsync2",
.help = "Use preadv2/pwritev2",
},
{ .ival = "libhdfs",
.help = "Hadoop Distributed Filesystem (HDFS) engine"
},
+#endif
+#ifdef CONFIG_PMEMBLK
+ { .ival = "pmemblk",
+ .help = "NVML libpmemblk based IO engine",
+ },
+
#endif
{ .ival = "external",
.help = "Load external engine (append name)",
.help = "Number of IO buffers to submit in one go",
.parent = "iodepth",
.hide = 1,
- .minval = 1,
.interval = 1,
.def = "1",
.category = FIO_OPT_C_IO,
},
{
.name = "random_generator",
+ .lname = "Random Generator",
.type = FIO_OPT_STR,
.off1 = td_var_offset(random_generator),
.help = "Type of random number generator to use",
},
{
.name = "random_distribution",
+ .lname = "Random Distribution",
.type = FIO_OPT_STR,
.off1 = td_var_offset(random_distribution),
.cb = str_random_distribution_cb,
},
{ .ival = "normal",
.oval = FIO_RAND_DIST_GAUSS,
- .help = "Normal (gaussian) distribution",
+ .help = "Normal (Gaussian) distribution",
},
{ .ival = "zoned",
.oval = FIO_RAND_DIST_ZONED,
},
{
.name = "allrandrepeat",
+ .lname = "All Random Repeat",
.type = FIO_OPT_BOOL,
.off1 = td_var_offset(allrand_repeatable),
.help = "Use repeatable random numbers for everything",
.posval = {
{ .ival = "random",
.oval = FIO_FSERVICE_RANDOM,
- .help = "Choose a file at random",
+ .help = "Choose a file at random (uniform)",
+ },
+ { .ival = "zipf",
+ .oval = FIO_FSERVICE_ZIPF,
+ .help = "Zipf randomized",
+ },
+ { .ival = "pareto",
+ .oval = FIO_FSERVICE_PARETO,
+ .help = "Pareto randomized",
+ },
+ { .ival = "gauss",
+ .oval = FIO_FSERVICE_GAUSS,
+ .help = "Normal (guassian) distribution",
},
{ .ival = "roundrobin",
.oval = FIO_FSERVICE_RR,
},
},
},
-#endif /* CONFIG_POSIX_FALLOCATE */
+#else /* CONFIG_POSIX_FALLOCATE */
+ {
+ .name = "fallocate",
+ .lname = "Fallocate",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support fallocate",
+ },
+#endif /* CONFIG_POSIX_FALLOCATE */
{
.name = "fadvise_hint",
.lname = "Fadvise hint",
.category = FIO_OPT_C_FILE,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "fadvise_stream",
+ .lname = "Fadvise stream",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support fadvise stream ID",
+ },
#endif
{
.name = "fsync",
.category = FIO_OPT_C_FILE,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "sync_file_range",
+ .lname = "Sync file range",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support sync_file_range",
+ },
#endif
{
.name = "direct",
},
{
.name = "verifysort_nr",
+ .lname = "Verify Sort Nr",
.type = FIO_OPT_INT,
.off1 = td_var_offset(verifysort_nr),
.help = "Pre-load and sort verify blocks for a read workload",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_VERIFY,
},
+#else
+ {
+ .name = "verify_async_cpus",
+ .lname = "Async verify CPUs",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support CPU affinities",
+ },
#endif
{
.name = "experimental_verify",
+ .lname = "Experimental Verify",
.off1 = td_var_offset(experimental_verify),
.type = FIO_OPT_BOOL,
.help = "Enable experimental verification",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_TRIM,
},
+#else
+ {
+ .name = "trim_percentage",
+ .lname = "Trim percentage",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Fio does not support TRIM on your platform",
+ },
+ {
+ .name = "trim_verify_zero",
+ .lname = "Verify trim zero",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Fio does not support TRIM on your platform",
+ },
+ {
+ .name = "trim_backlog",
+ .lname = "Trim backlog",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Fio does not support TRIM on your platform",
+ },
+ {
+ .name = "trim_backlog_batch",
+ .lname = "Trim backlog batch",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Fio does not support TRIM on your platform",
+ },
#endif
{
.name = "write_iolog",
.category = FIO_OPT_C_FILE,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "ioscheduler",
+ .lname = "I/O scheduler",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support IO scheduler switching",
+ },
#endif
{
.name = "zonesize",
.type = FIO_OPT_INT,
.off1 = td_var_offset(ioprio),
.help = "Set job IO priority value",
- .minval = 0,
- .maxval = 7,
+ .minval = IOPRIO_MIN_PRIO,
+ .maxval = IOPRIO_MAX_PRIO,
.interval = 1,
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_CRED,
},
+#else
+ {
+ .name = "prio",
+ .lname = "I/O nice priority",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support IO priorities",
+ },
+#endif
+#ifdef FIO_HAVE_IOPRIO_CLASS
+#ifndef FIO_HAVE_IOPRIO
+#error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
+#endif
{
.name = "prioclass",
.lname = "I/O nice priority class",
.type = FIO_OPT_INT,
.off1 = td_var_offset(ioprio_class),
.help = "Set job IO priority class",
- .minval = 0,
- .maxval = 3,
+ .minval = IOPRIO_MIN_PRIO_CLASS,
+ .maxval = IOPRIO_MAX_PRIO_CLASS,
.interval = 1,
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_CRED,
},
+#else
+ {
+ .name = "prioclass",
+ .lname = "I/O nice priority class",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support IO priority classes",
+ },
#endif
{
.name = "thinktime",
},
{
.name = "max_latency",
+ .lname = "Max Latency",
.type = FIO_OPT_INT,
.off1 = td_var_offset(max_latency),
.help = "Maximum tolerated IO latency (usec)",
},
{
.name = "create_only",
+ .lname = "Create Only",
.type = FIO_OPT_BOOL,
.off1 = td_var_offset(create_only),
.help = "Only perform file creation phase",
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_CRED,
},
+#else
+ {
+ .name = "cpumask",
+ .lname = "CPU mask",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support CPU affinities",
+ },
+ {
+ .name = "cpus_allowed",
+ .lname = "CPUs allowed",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support CPU affinities",
+ },
+ {
+ .name = "cpus_allowed_policy",
+ .lname = "CPUs allowed distribution policy",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support CPU affinities",
+ },
#endif
#ifdef CONFIG_LIBNUMA
{
.name = "numa_cpu_nodes",
+ .lname = "NUMA CPU Nodes",
.type = FIO_OPT_STR,
.cb = str_numa_cpunodes_cb,
.off1 = td_var_offset(numa_cpunodes),
},
{
.name = "numa_mem_policy",
+ .lname = "NUMA Memory Policy",
.type = FIO_OPT_STR,
.cb = str_numa_mpol_cb,
.off1 = td_var_offset(numa_memnodes),
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "numa_cpu_nodes",
+ .lname = "NUMA CPU Nodes",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Build fio with libnuma-dev(el) to enable this option",
+ },
+ {
+ .name = "numa_mem_policy",
+ .lname = "NUMA Memory Policy",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Build fio with libnuma-dev(el) to enable this option",
+ },
#endif
{
.name = "end_fsync",
{
.name = "exitall_on_error",
.lname = "Exit-all on terminate in error",
- .type = FIO_OPT_BOOL,
- .off1 = td_var_offset(unlink),
+ .type = FIO_OPT_STR_SET,
+ .off1 = td_var_offset(exitall_error),
.help = "Terminate all jobs when one exits in error",
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_PROCESS,
},
{
.name = "per_job_logs",
+ .lname = "Per Job Logs",
.type = FIO_OPT_BOOL,
.off1 = td_var_offset(per_job_logs),
.help = "Include job number in generated log files or not",
.category = FIO_OPT_C_LOG,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "log_compression_cpus",
+ .lname = "Log Compression CPUs",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support CPU affinities",
+ },
#endif
{
.name = "log_store_compressed",
.category = FIO_OPT_C_LOG,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "log_compression",
+ .lname = "Log compression",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Install libz-dev(el) to get compression support",
+ },
+ {
+ .name = "log_store_compressed",
+ .lname = "Log store compressed",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Install libz-dev(el) to get compression support",
+ },
#endif
{
.name = "block_error_percentiles",
.category = FIO_OPT_C_STAT,
.group = FIO_OPT_G_INVALID,
},
+#else
+ {
+ .name = "disk_util",
+ .lname = "Disk utilization",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support disk utilization",
+ },
#endif
{
.name = "gtod_reduce",
},
{
.name = "unified_rw_reporting",
+ .lname = "Unified RW Reporting",
.type = FIO_OPT_BOOL,
.off1 = td_var_offset(unified_rw_rep),
.help = "Unify reporting across data direction",
},
{
.name = "ignore_error",
+ .lname = "Ignore Error",
.type = FIO_OPT_STR,
.cb = str_ignore_error_cb,
.off1 = td_var_offset(ignore_error_nr),
},
{
.name = "error_dump",
+ .lname = "Error Dump",
.type = FIO_OPT_BOOL,
.off1 = td_var_offset(error_dump),
.def = "0",
i++;
}
- if (best_option != -1 && string_distance_ok(name, best_distance))
+ if (best_option != -1 && string_distance_ok(name, best_distance) &&
+ fio_options[best_option].type != FIO_OPT_UNSUPPORTED)
log_err("Did you mean %s?\n", fio_options[best_option].name);
free(name);
free(td->eo);
td->eo = NULL;
}
- if (td->zone_state_index) {
- int i;
-
- for (i = 0; i < DDIR_RWDIR_CNT; i++)
- free(td->zone_state_index[i]);
- free(td->zone_state_index);
- td->zone_state_index = NULL;
- }
}
struct fio_option *fio_option_find(const char *name)