#include <ctype.h>
#include <string.h>
#include <assert.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <netinet/in.h>
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);
+ while ((v = strsep(&str, ",")) != NULL && i < FIO_MAX_DP_IDS) {
+ unsigned long long id = strtoull(v, NULL, 0);
+ if (id > 0xFFFF) {
+ log_err("Placement IDs cannot exceed 0xFFFF\n");
+ free(p);
+ return 1;
+ }
+ td->o.dp_ids[i++] = id;
+ }
free(p);
- qsort(td->o.fdp_plis, i, sizeof(*td->o.fdp_plis), fio_fdp_cmp);
- td->o.fdp_nrpli = i;
+ qsort(td->o.dp_ids, i, sizeof(*td->o.dp_ids), fio_fdp_cmp);
+ td->o.dp_nr_ids = i;
return 0;
}
int matches = 0;
char *bs_str = NULL;
long long bs_val;
- unsigned int perc = 0, class, level;
+ unsigned int perc = 0, class, level, hint;
/*
* 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
+ * bs/perc/class/level/hint - %s/%u/%u/%u/%u
*/
- matches = sscanf(str, "%m[^/]/%u/%u/%u", &bs_str, &perc, &class, &level);
+ matches = sscanf(str, "%m[^/]/%u/%u/%u/%u",
+ &bs_str, &perc, &class, &level, &hint);
if (matches < 1) {
log_err("fio: invalid cmdprio_bssplit format\n");
return 1;
case 2: /* bs/perc case */
break;
case 4: /* bs/perc/class/level case */
+ case 5: /* bs/perc/class/level/hint case */
class = min(class, (unsigned int) IOPRIO_MAX_PRIO_CLASS);
level = min(level, (unsigned int) IOPRIO_MAX_PRIO);
- entry->prio = ioprio_value(class, level);
+ if (matches == 5)
+ hint = min(hint, (unsigned int) IOPRIO_MAX_PRIO_HINT);
+ else
+ hint = 0;
+ entry->prio = ioprio_value(class, level, hint);
break;
default:
log_err("fio: invalid cmdprio_bssplit format\n");
if (!nr)
return 0;
- if (td_random(td))
- o->ddir_seq_nr = atoi(nr);
- else {
+ if (td_random(td)) {
+ long long val;
+
+ if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
+ log_err("fio: randrw postfix parsing failed\n");
+ free(nr);
+ return 1;
+ }
+ if ((val <= 0) || (val > UINT_MAX)) {
+ log_err("fio: randrw postfix parsing out of range\n");
+ free(nr);
+ return 1;
+ }
+ o->ddir_seq_nr = (unsigned int) val;
+ } else {
long long val;
if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
return 0;
}
-static int str_rwmix_read_cb(void *data, unsigned long long *val)
+static int str_rwmix_read_cb(void *data, long long *val)
{
struct thread_data *td = cb_data_to_td(data);
return 0;
}
-static int str_rwmix_write_cb(void *data, unsigned long long *val)
+static int str_rwmix_write_cb(void *data, long long *val)
{
struct thread_data *td = cb_data_to_td(data);
return 0;
}
-static int str_offset_cb(void *data, unsigned long long *__val)
+static int str_offset_cb(void *data, long long *__val)
{
struct thread_data *td = cb_data_to_td(data);
unsigned long long v = *__val;
return 0;
}
-static int str_offset_increment_cb(void *data, unsigned long long *__val)
+static int str_offset_increment_cb(void *data, long long *__val)
{
struct thread_data *td = cb_data_to_td(data);
unsigned long long v = *__val;
return 0;
}
-static int str_size_cb(void *data, unsigned long long *__val)
+static int str_size_cb(void *data, long long *__val)
{
struct thread_data *td = cb_data_to_td(data);
unsigned long long v = *__val;
return 0;
}
-static int str_zoneskip_cb(void *data, unsigned long long *__val)
+static int str_zoneskip_cb(void *data, long long *__val)
{
struct thread_data *td = cb_data_to_td(data);
unsigned long long v = *__val;
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_INVALID,
},
+ {
+ .name = "num_range",
+ .lname = "Number of ranges",
+ .type = FIO_OPT_INT,
+ .off1 = offsetof(struct thread_options, num_range),
+ .maxval = MAX_TRIM_RANGE,
+ .help = "Number of ranges for trim command",
+ .def = "1",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_INVALID,
+ },
{
.name = "bs",
.lname = "Block size",
},
{
.name = "randrepeat",
+ .alias = "allrandrepeat",
.lname = "Random repeatable",
.type = FIO_OPT_BOOL,
.off1 = offsetof(struct thread_options, rand_repeatable),
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RANDOM,
},
- {
- .name = "allrandrepeat",
- .lname = "All Random Repeat",
- .type = FIO_OPT_BOOL,
- .off1 = offsetof(struct thread_options, allrand_repeatable),
- .help = "Use repeatable random numbers for everything",
- .def = "0",
- .category = FIO_OPT_C_IO,
- .group = FIO_OPT_G_RANDOM,
- },
{
.name = "nrfiles",
.lname = "Number of files",
.oval = F_ADV_SEQUENTIAL,
.help = "Advise using FADV_SEQUENTIAL",
},
+#ifdef POSIX_FADV_NOREUSE
{ .ival = "noreuse",
.oval = F_ADV_NOREUSE,
.help = "Advise using FADV_NOREUSE",
},
+#endif
},
.help = "Use fadvise() to advise the kernel on IO pattern",
.def = "1",
.lname = "Per device/file maximum number of open zones",
.type = FIO_OPT_INT,
.off1 = offsetof(struct thread_options, max_open_zones),
- .maxval = ZBD_MAX_OPEN_ZONES,
+ .maxval = ZBD_MAX_WRITE_ZONES,
.help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd",
.def = "0",
.category = FIO_OPT_C_IO,
.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,
+ .maxval = ZBD_MAX_WRITE_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 = "fdp_pli",
- .lname = "FDP Placement ID indicies",
+ .name = "dataplacement",
+ .alias = "data_placement",
+ .lname = "Data Placement interface",
+ .type = FIO_OPT_STR,
+ .off1 = offsetof(struct thread_options, dp_type),
+ .help = "Data Placement interface to use",
+ .def = "none",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_INVALID,
+ .posval = {
+ { .ival = "none",
+ .oval = FIO_DP_NONE,
+ .help = "Do not specify a data placement interface",
+ },
+ { .ival = "fdp",
+ .oval = FIO_DP_FDP,
+ .help = "Use Flexible Data Placement interface",
+ },
+ { .ival = "streams",
+ .oval = FIO_DP_STREAMS,
+ .help = "Use Streams interface",
+ },
+ },
+ },
+ {
+ .name = "plid_select",
+ .alias = "fdp_pli_select",
+ .lname = "Data Placement ID selection strategy",
+ .type = FIO_OPT_STR,
+ .off1 = offsetof(struct thread_options, dp_id_select),
+ .help = "Strategy for selecting next Data Placement ID",
+ .def = "roundrobin",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_INVALID,
+ .posval = {
+ { .ival = "random",
+ .oval = FIO_DP_RANDOM,
+ .help = "Choose a Placement ID at random (uniform)",
+ },
+ { .ival = "roundrobin",
+ .oval = FIO_DP_RR,
+ .help = "Round robin select Placement IDs",
+ },
+ },
+ },
+ {
+ .name = "plids",
+ .alias = "fdp_pli",
+ .lname = "Stream IDs/Data Placement ID indices",
.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)",
+ .off1 = offsetof(struct thread_options, dp_ids),
+ .help = "Sets which Data Placement ids to use (defaults to all for FDP)",
.hide = 1,
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_INVALID,
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_CRED,
},
+ {
+ .name = "priohint",
+ .lname = "I/O nice priority hint",
+ .type = FIO_OPT_INT,
+ .off1 = offsetof(struct thread_options, ioprio_hint),
+ .help = "Set job IO priority hint",
+ .minval = IOPRIO_MIN_PRIO_HINT,
+ .maxval = IOPRIO_MAX_PRIO_HINT,
+ .interval = 1,
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_CRED,
+ },
#else
{
.name = "prioclass",
.type = FIO_OPT_UNSUPPORTED,
.help = "Your platform does not support IO priority classes",
},
+ {
+ .name = "priohint",
+ .lname = "I/O nice priority hint",
+ .type = FIO_OPT_UNSUPPORTED,
+ .help = "Your platform does not support IO priority hints",
+ },
#endif
{
.name = "thinktime",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_THINKTIME,
},
+ {
+ .name = "thinkcycles",
+ .lname = "Think cycles",
+ .type = FIO_OPT_INT,
+ .off1 = offsetof(struct thread_options, thinkcycles),
+ .help = "Spin for a constant amount of cycles between requests",
+ .def = "0",
+ .parent = "thinktime",
+ .hide = 1,
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_THINKTIME,
+ },
{
.name = "thinktime_blocks",
.lname = "Thinktime blocks",
.group = FIO_OPT_G_INVALID,
},
{
- .name = "log_max_value",
- .lname = "Log maximum instead of average",
- .type = FIO_OPT_BOOL,
+ .name = "log_window_value",
+ .alias = "log_max_value",
+ .lname = "Log maximum, average or both values",
+ .type = FIO_OPT_STR,
.off1 = offsetof(struct thread_options, log_max),
- .help = "Log max sample in a window instead of average",
- .def = "0",
+ .help = "Log max, average or both sample in a window",
+ .def = "avg",
.category = FIO_OPT_C_LOG,
.group = FIO_OPT_G_INVALID,
+ .posval = {
+ { .ival = "avg",
+ .oval = IO_LOG_SAMPLE_AVG,
+ .help = "Log average value over the window",
+ },
+ { .ival = "max",
+ .oval = IO_LOG_SAMPLE_MAX,
+ .help = "Log maximum value in the window",
+ },
+ { .ival = "both",
+ .oval = IO_LOG_SAMPLE_BOTH,
+ .help = "Log both average and maximum values over the window"
+ },
+ /* Compatibility with former boolean values */
+ { .ival = "0",
+ .oval = IO_LOG_SAMPLE_AVG,
+ .help = "Alias for 'avg'",
+ },
+ { .ival = "1",
+ .oval = IO_LOG_SAMPLE_MAX,
+ .help = "Alias for 'max'",
+ },
+ },
},
{
.name = "log_offset",
.help = "Install libz-dev(el) to get compression support",
},
#endif
- {
- .name = "log_unix_epoch",
- .lname = "Log epoch unix",
- .type = FIO_OPT_BOOL,
- .off1 = offsetof(struct thread_options, log_unix_epoch),
- .help = "Use Unix time in log files",
- .category = FIO_OPT_C_LOG,
- .group = FIO_OPT_G_INVALID,
- },
{
.name = "log_alternate_epoch",
+ .alias = "log_unix_epoch",
.lname = "Log epoch alternate",
.type = FIO_OPT_BOOL,
.off1 = offsetof(struct thread_options, log_alternate_epoch),
.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",
+ .help = "If log_alternate_epoch is true, this option specifies the clock_id from clock_gettime whose epoch should be used. If log_alternate_epoch is false, this option has no effect. Default value is 0, or CLOCK_REALTIME",
.category = FIO_OPT_C_LOG,
.group = FIO_OPT_G_INVALID,
},
.category = FIO_OPT_C_GENERAL,
.group = FIO_OPT_G_CLOCK,
},
+ {
+ .name = "job_start_clock_id",
+ .lname = "Job start clock_id",
+ .type = FIO_OPT_INT,
+ .off1 = offsetof(struct thread_options, job_start_clock_id),
+ .help = "The clock_id passed to the call to clock_gettime used to record job_start in the json output format. Default is 0, or CLOCK_REALTIME",
+ .verify = gtod_cpu_verify,
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_CLOCK,
+ },
{
.name = "unified_rw_reporting",
.lname = "Unified RW Reporting",