8 #include <netinet/in.h>
13 #include "lib/pattern.h"
18 char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 };
20 #define cb_data_to_td(data) container_of(data, struct thread_data, o)
22 static const struct pattern_fmt_desc fmt_desc[] = {
25 .len = FIO_FIELD_SIZE(struct io_u *, offset),
26 .paste = paste_blockoff
32 * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
34 static char *get_opt_postfix(const char *str)
36 char *p = strstr(str, ":");
42 strip_blank_front(&p);
47 static bool split_parse_distr(const char *str, double *val, double *center)
61 r = str_to_float(cp, center, 0);
63 r = r && str_to_float(p, val, 0);
68 static int bs_cmp(const void *p1, const void *p2)
70 const struct bssplit *bsp1 = p1;
71 const struct bssplit *bsp2 = p2;
73 return (int) bsp1->perc - (int) bsp2->perc;
76 int split_parse_ddir(struct thread_options *o, struct split *split,
77 char *str, bool absolute, unsigned int max_splits)
79 unsigned long long perc;
87 while ((fname = strsep(&str, ":")) != NULL) {
93 perc_str = strstr(fname, "/");
98 if (str_to_decimal(perc_str, &val, 1, o, 0, 0)) {
99 log_err("fio: split conversion failed\n");
104 perc = atoi(perc_str);
117 if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
118 log_err("fio: split conversion failed\n");
122 split->val1[i] = val;
123 split->val2[i] = perc;
125 if (i == max_splits) {
126 log_err("fio: hit max of %d split entries\n", i);
135 static int bssplit_ddir(struct thread_options *o, void *eo,
136 enum fio_ddir ddir, char *str, bool data)
138 unsigned int i, perc, perc_missing;
139 unsigned long long max_bs, min_bs;
142 memset(&split, 0, sizeof(split));
144 if (split_parse_ddir(o, &split, str, data, BSSPLIT_MAX))
151 o->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
152 o->bssplit_nr[ddir] = split.nr;
153 for (i = 0; i < split.nr; i++) {
154 if (split.val1[i] > max_bs)
155 max_bs = split.val1[i];
156 if (split.val1[i] < min_bs)
157 min_bs = split.val1[i];
159 o->bssplit[ddir][i].bs = split.val1[i];
160 o->bssplit[ddir][i].perc =split.val2[i];
164 * Now check if the percentages add up, and how much is missing
166 perc = perc_missing = 0;
167 for (i = 0; i < o->bssplit_nr[ddir]; i++) {
168 struct bssplit *bsp = &o->bssplit[ddir][i];
170 if (bsp->perc == -1U)
176 if (perc > 100 && perc_missing > 1) {
177 log_err("fio: bssplit percentages add to more than 100%%\n");
178 free(o->bssplit[ddir]);
179 o->bssplit[ddir] = NULL;
184 * If values didn't have a percentage set, divide the remains between
188 if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
190 for (i = 0; i < o->bssplit_nr[ddir]; i++) {
191 struct bssplit *bsp = &o->bssplit[ddir][i];
193 if (bsp->perc == -1U)
194 bsp->perc = (100 - perc) / perc_missing;
198 o->min_bs[ddir] = min_bs;
199 o->max_bs[ddir] = max_bs;
202 * now sort based on percentages, for ease of lookup
204 qsort(o->bssplit[ddir], o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
208 int str_split_parse(struct thread_data *td, char *str,
209 split_parse_fn *fn, void *eo, bool data)
214 odir = strchr(str, ',');
216 ddir = strchr(odir + 1, ',');
218 ret = fn(&td->o, eo, DDIR_TRIM, ddir + 1, data);
224 op = strdup(odir + 1);
225 ret = fn(&td->o, eo, DDIR_TRIM, op, data);
230 ret = fn(&td->o, eo, DDIR_WRITE, odir + 1, data);
233 ret = fn(&td->o, eo, DDIR_READ, str, data);
239 ret = fn(&td->o, eo, DDIR_WRITE, op, data);
244 ret = fn(&td->o, eo, DDIR_TRIM, op, data);
248 ret = fn(&td->o, eo, DDIR_READ, str, data);
254 static int fio_fdp_cmp(const void *p1, const void *p2)
256 const uint16_t *t1 = p1;
257 const uint16_t *t2 = p2;
262 static int str_fdp_pli_cb(void *data, const char *input)
264 struct thread_data *td = cb_data_to_td(data);
268 p = str = strdup(input);
269 strip_blank_front(&str);
270 strip_blank_end(str);
272 while ((v = strsep(&str, ",")) != NULL && i < FIO_MAX_PLIS)
273 td->o.fdp_plis[i++] = strtoll(v, NULL, 0);
276 qsort(td->o.fdp_plis, i, sizeof(*td->o.fdp_plis), fio_fdp_cmp);
282 static int str_bssplit_cb(void *data, const char *input)
284 struct thread_data *td = cb_data_to_td(data);
288 p = str = strdup(input);
290 strip_blank_front(&str);
291 strip_blank_end(str);
293 ret = str_split_parse(td, str, bssplit_ddir, NULL, false);
295 if (parse_dryrun()) {
298 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
299 free(td->o.bssplit[i]);
300 td->o.bssplit[i] = NULL;
301 td->o.bssplit_nr[i] = 0;
309 static int parse_cmdprio_bssplit_entry(struct thread_options *o,
310 struct split_prio *entry, char *str)
315 unsigned int perc = 0, class, level;
318 * valid entry formats:
319 * bs/ - %s/ - set perc to 0, prio to -1.
320 * bs/perc - %s/%u - set prio to -1.
321 * bs/perc/class/level - %s/%u/%u/%u
323 matches = sscanf(str, "%m[^/]/%u/%u/%u", &bs_str, &perc, &class, &level);
325 log_err("fio: invalid cmdprio_bssplit format\n");
329 if (str_to_decimal(bs_str, &bs_val, 1, o, 0, 0)) {
330 log_err("fio: split conversion failed\n");
337 entry->perc = min(perc, 100u);
340 case 1: /* bs/ case */
341 case 2: /* bs/perc case */
343 case 4: /* bs/perc/class/level case */
344 class = min(class, (unsigned int) IOPRIO_MAX_PRIO_CLASS);
345 level = min(level, (unsigned int) IOPRIO_MAX_PRIO);
346 entry->prio = ioprio_value(class, level);
349 log_err("fio: invalid cmdprio_bssplit format\n");
357 * Returns a negative integer if the first argument should be before the second
358 * argument in the sorted list. A positive integer if the first argument should
359 * be after the second argument in the sorted list. A zero if they are equal.
361 static int fio_split_prio_cmp(const void *p1, const void *p2)
363 const struct split_prio *tmp1 = p1;
364 const struct split_prio *tmp2 = p2;
366 if (tmp1->bs > tmp2->bs)
368 if (tmp1->bs < tmp2->bs)
373 int split_parse_prio_ddir(struct thread_options *o, struct split_prio **entries,
374 int *nr_entries, char *str)
376 struct split_prio *tmp_entries;
377 unsigned int nr_bssplits;
378 char *str_cpy, *p, *fname;
380 /* strsep modifies the string, dup it so that we can use strsep twice */
381 p = str_cpy = strdup(str);
386 while ((fname = strsep(&str_cpy, ":")) != NULL) {
393 if (nr_bssplits > BSSPLIT_MAX) {
394 log_err("fio: too many cmdprio_bssplit entries\n");
398 tmp_entries = calloc(nr_bssplits, sizeof(*tmp_entries));
403 while ((fname = strsep(&str, ":")) != NULL) {
404 struct split_prio *entry;
409 entry = &tmp_entries[nr_bssplits];
411 if (parse_cmdprio_bssplit_entry(o, entry, fname)) {
412 log_err("fio: failed to parse cmdprio_bssplit entry\n");
417 /* skip zero perc entries, they provide no useful information */
422 qsort(tmp_entries, nr_bssplits, sizeof(*tmp_entries),
425 *entries = tmp_entries;
426 *nr_entries = nr_bssplits;
431 static int str2error(char *str)
433 const char *err[] = { "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
434 "ENXIO", "E2BIG", "ENOEXEC", "EBADF",
435 "ECHILD", "EAGAIN", "ENOMEM", "EACCES",
436 "EFAULT", "ENOTBLK", "EBUSY", "EEXIST",
437 "EXDEV", "ENODEV", "ENOTDIR", "EISDIR",
438 "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
439 "ETXTBSY","EFBIG", "ENOSPC", "ESPIPE",
440 "EROFS","EMLINK", "EPIPE", "EDOM", "ERANGE" };
441 int i = 0, num = sizeof(err) / sizeof(char *);
444 if (!strcmp(err[i], str))
451 static int ignore_error_type(struct thread_data *td, enum error_type_bit etype,
458 if (etype >= ERROR_TYPE_CNT) {
459 log_err("Illegal error type\n");
463 td->o.ignore_error_nr[etype] = 4;
464 error = calloc(4, sizeof(int));
467 while ((fname = strsep(&str, ":")) != NULL) {
473 * grow struct buffer, if needed
475 if (i == td->o.ignore_error_nr[etype]) {
476 td->o.ignore_error_nr[etype] <<= 1;
477 error = realloc(error, td->o.ignore_error_nr[etype]
480 if (fname[0] == 'E') {
481 error[i] = str2error(fname);
483 error[i] = atoi(fname);
485 error[i] = -error[i];
488 log_err("Unknown error %s, please use number value\n",
490 td->o.ignore_error_nr[etype] = 0;
497 td->o.continue_on_error |= 1 << etype;
498 td->o.ignore_error_nr[etype] = i;
499 td->o.ignore_error[etype] = error;
501 td->o.ignore_error_nr[etype] = 0;
509 static int str_replay_skip_cb(void *data, const char *input)
511 struct thread_data *td = cb_data_to_td(data);
518 p = str = strdup(input);
520 strip_blank_front(&str);
521 strip_blank_end(str);
527 if (!strcmp(p, "read"))
528 td->o.replay_skip |= 1u << DDIR_READ;
529 else if (!strcmp(p, "write"))
530 td->o.replay_skip |= 1u << DDIR_WRITE;
531 else if (!strcmp(p, "trim"))
532 td->o.replay_skip |= 1u << DDIR_TRIM;
533 else if (!strcmp(p, "sync"))
534 td->o.replay_skip |= 1u << DDIR_SYNC;
536 log_err("Unknown skip type: %s\n", p);
546 static int str_ignore_error_cb(void *data, const char *input)
548 struct thread_data *td = cb_data_to_td(data);
551 enum error_type_bit type = 0;
556 p = str = strdup(input);
558 strip_blank_front(&str);
559 strip_blank_end(str);
565 ret = ignore_error_type(td, type, p);
575 static int str_rw_cb(void *data, const char *str)
577 struct thread_data *td = cb_data_to_td(data);
578 struct thread_options *o = &td->o;
587 nr = get_opt_postfix(str);
592 o->ddir_seq_nr = atoi(nr);
596 if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
597 log_err("fio: rw postfix parsing failed\n");
602 o->ddir_seq_add = val;
609 static int str_mem_cb(void *data, const char *mem)
611 struct thread_data *td = cb_data_to_td(data);
613 if (td->o.mem_type == MEM_MMAPHUGE || td->o.mem_type == MEM_MMAP ||
614 td->o.mem_type == MEM_MMAPSHARED)
615 td->o.mmapfile = get_opt_postfix(mem);
620 static int fio_clock_source_cb(void *data, const char *str)
622 struct thread_data *td = cb_data_to_td(data);
624 fio_clock_source = td->o.clocksource;
625 fio_clock_source_set = 1;
630 static int str_rwmix_read_cb(void *data, unsigned long long *val)
632 struct thread_data *td = cb_data_to_td(data);
634 td->o.rwmix[DDIR_READ] = *val;
635 td->o.rwmix[DDIR_WRITE] = 100 - *val;
639 static int str_rwmix_write_cb(void *data, unsigned long long *val)
641 struct thread_data *td = cb_data_to_td(data);
643 td->o.rwmix[DDIR_WRITE] = *val;
644 td->o.rwmix[DDIR_READ] = 100 - *val;
648 static int str_exitall_cb(void)
650 exitall_on_terminate = true;
654 #ifdef FIO_HAVE_CPU_AFFINITY
655 int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu_index)
657 unsigned int i, index, cpus_in_mask;
658 const long max_cpu = cpus_configured();
660 cpus_in_mask = fio_cpu_count(mask);
664 cpu_index = cpu_index % cpus_in_mask;
667 for (i = 0; i < max_cpu; i++) {
668 if (!fio_cpu_isset(mask, i))
671 if (cpu_index != index)
672 fio_cpu_clear(mask, i);
677 return fio_cpu_count(mask);
680 static int str_cpumask_cb(void *data, unsigned long long *val)
682 struct thread_data *td = cb_data_to_td(data);
690 ret = fio_cpuset_init(&td->o.cpumask);
692 log_err("fio: cpuset_init failed\n");
693 td_verror(td, ret, "fio_cpuset_init");
697 max_cpu = cpus_configured();
699 for (i = 0; i < sizeof(int) * 8; i++) {
700 if ((1 << i) & *val) {
702 log_err("fio: CPU %d too large (max=%ld)\n", i,
706 dprint(FD_PARSE, "set cpu allowed %d\n", i);
707 fio_cpu_set(&td->o.cpumask, i);
714 static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask,
721 ret = fio_cpuset_init(mask);
723 log_err("fio: cpuset_init failed\n");
724 td_verror(td, ret, "fio_cpuset_init");
728 p = str = strdup(input);
730 strip_blank_front(&str);
731 strip_blank_end(str);
733 max_cpu = cpus_configured();
735 while ((cpu = strsep(&str, ",")) != NULL) {
744 while ((cpu2 = strsep(&str2, "-")) != NULL) {
754 while (icpu <= icpu2) {
755 if (icpu >= FIO_MAX_CPUS) {
756 log_err("fio: your OS only supports up to"
757 " %d CPUs\n", (int) FIO_MAX_CPUS);
761 if (icpu >= max_cpu) {
762 log_err("fio: CPU %d too large (max=%ld)\n",
768 dprint(FD_PARSE, "set cpu allowed %d\n", icpu);
769 fio_cpu_set(mask, icpu);
780 static int str_cpus_allowed_cb(void *data, const char *input)
782 struct thread_data *td = cb_data_to_td(data);
787 return set_cpus_allowed(td, &td->o.cpumask, input);
790 static int str_verify_cpus_allowed_cb(void *data, const char *input)
792 struct thread_data *td = cb_data_to_td(data);
797 return set_cpus_allowed(td, &td->o.verify_cpumask, input);
801 static int str_log_cpus_allowed_cb(void *data, const char *input)
803 struct thread_data *td = cb_data_to_td(data);
808 return set_cpus_allowed(td, &td->o.log_gz_cpumask, input);
810 #endif /* CONFIG_ZLIB */
812 #endif /* FIO_HAVE_CPU_AFFINITY */
814 #ifdef CONFIG_LIBNUMA
815 static int str_numa_cpunodes_cb(void *data, char *input)
817 struct thread_data *td = cb_data_to_td(data);
818 struct bitmask *verify_bitmask;
823 /* numa_parse_nodestring() parses a character string list
824 * of nodes into a bit mask. The bit mask is allocated by
825 * numa_allocate_nodemask(), so it should be freed by
826 * numa_free_nodemask().
828 verify_bitmask = numa_parse_nodestring(input);
829 if (verify_bitmask == NULL) {
830 log_err("fio: numa_parse_nodestring failed\n");
831 td_verror(td, 1, "str_numa_cpunodes_cb");
834 numa_free_nodemask(verify_bitmask);
836 td->o.numa_cpunodes = strdup(input);
840 static int str_numa_mpol_cb(void *data, char *input)
842 struct thread_data *td = cb_data_to_td(data);
843 const char * const policy_types[] =
844 { "default", "prefer", "bind", "interleave", "local", NULL };
847 struct bitmask *verify_bitmask;
852 nodelist = strchr(input, ':');
854 /* NUL-terminate mode */
858 for (i = 0; i <= MPOL_LOCAL; i++) {
859 if (!strcmp(input, policy_types[i])) {
860 td->o.numa_mem_mode = i;
864 if (i > MPOL_LOCAL) {
865 log_err("fio: memory policy should be: default, prefer, bind, interleave, local\n");
869 switch (td->o.numa_mem_mode) {
872 * Insist on a nodelist of one node only
875 char *rest = nodelist;
876 while (isdigit(*rest))
879 log_err("fio: one node only for \'prefer\'\n");
883 log_err("fio: one node is needed for \'prefer\'\n");
887 case MPOL_INTERLEAVE:
889 * Default to online nodes with memory if no nodelist
892 nodelist = strdup("all");
897 * Don't allow a nodelist
900 log_err("fio: NO nodelist for \'local\'\n");
906 * Insist on a nodelist
909 log_err("fio: a nodelist is needed for \'bind\'\n");
916 /* numa_parse_nodestring() parses a character string list
917 * of nodes into a bit mask. The bit mask is allocated by
918 * numa_allocate_nodemask(), so it should be freed by
919 * numa_free_nodemask().
921 switch (td->o.numa_mem_mode) {
923 td->o.numa_mem_prefer_node = atoi(nodelist);
925 case MPOL_INTERLEAVE:
927 verify_bitmask = numa_parse_nodestring(nodelist);
928 if (verify_bitmask == NULL) {
929 log_err("fio: numa_parse_nodestring failed\n");
930 td_verror(td, 1, "str_numa_memnodes_cb");
933 td->o.numa_memnodes = strdup(nodelist);
934 numa_free_nodemask(verify_bitmask);
949 static int str_fst_cb(void *data, const char *str)
951 struct thread_data *td = cb_data_to_td(data);
957 td->file_service_nr = 1;
959 switch (td->o.file_service_type) {
960 case FIO_FSERVICE_RANDOM:
961 case FIO_FSERVICE_RR:
962 case FIO_FSERVICE_SEQ:
963 nr = get_opt_postfix(str);
965 td->file_service_nr = atoi(nr);
970 case FIO_FSERVICE_ZIPF:
973 case FIO_FSERVICE_PARETO:
974 val = FIO_DEF_PARETO;
976 case FIO_FSERVICE_GAUSS:
980 log_err("fio: bad file service type: %d\n", td->o.file_service_type);
987 nr = get_opt_postfix(str);
988 if (nr && !split_parse_distr(nr, &val, ¢er)) {
989 log_err("fio: file service type random postfix parsing failed\n");
996 if (center != -1 && (center < 0.00 || center > 1.00)) {
997 log_err("fio: distribution center out of range (0 <= center <= 1.0)\n");
1000 td->random_center = center;
1002 switch (td->o.file_service_type) {
1003 case FIO_FSERVICE_ZIPF:
1005 log_err("fio: zipf theta must be different than 1.0\n");
1010 td->zipf_theta = val;
1012 case FIO_FSERVICE_PARETO:
1013 if (val <= 0.00 || val >= 1.00) {
1014 log_err("fio: pareto input out of range (0 < input < 1.0)\n");
1021 case FIO_FSERVICE_GAUSS:
1022 if (val < 0.00 || val >= 100.00) {
1023 log_err("fio: normal deviation out of range (0 <= input < 100.0)\n");
1028 td->gauss_dev = val;
1035 #ifdef CONFIG_SYNC_FILE_RANGE
1036 static int str_sfr_cb(void *data, const char *str)
1038 struct thread_data *td = cb_data_to_td(data);
1039 char *nr = get_opt_postfix(str);
1041 td->sync_file_range_nr = 1;
1043 td->sync_file_range_nr = atoi(nr);
1051 static int zone_split_ddir(struct thread_options *o, void *eo,
1052 enum fio_ddir ddir, char *str, bool absolute)
1054 unsigned int i, perc, perc_missing, sperc, sperc_missing;
1057 memset(&split, 0, sizeof(split));
1059 if (split_parse_ddir(o, &split, str, absolute, ZONESPLIT_MAX))
1064 o->zone_split[ddir] = malloc(split.nr * sizeof(struct zone_split));
1065 o->zone_split_nr[ddir] = split.nr;
1066 for (i = 0; i < split.nr; i++) {
1067 o->zone_split[ddir][i].access_perc = split.val1[i];
1069 o->zone_split[ddir][i].size = split.val2[i];
1071 o->zone_split[ddir][i].size_perc = split.val2[i];
1075 * Now check if the percentages add up, and how much is missing
1077 perc = perc_missing = 0;
1078 sperc = sperc_missing = 0;
1079 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
1080 struct zone_split *zsp = &o->zone_split[ddir][i];
1082 if (zsp->access_perc == (uint8_t) -1U)
1085 perc += zsp->access_perc;
1088 if (zsp->size_perc == (uint8_t) -1U)
1091 sperc += zsp->size_perc;
1095 if (perc > 100 || sperc > 100) {
1096 log_err("fio: zone_split percentages add to more than 100%%\n");
1097 free(o->zone_split[ddir]);
1098 o->zone_split[ddir] = NULL;
1102 log_err("fio: access percentage don't add up to 100 for zoned "
1103 "random distribution (got=%u)\n", perc);
1104 free(o->zone_split[ddir]);
1105 o->zone_split[ddir] = NULL;
1110 * If values didn't have a percentage set, divide the remains between
1114 if (perc_missing == 1 && o->zone_split_nr[ddir] == 1)
1116 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
1117 struct zone_split *zsp = &o->zone_split[ddir][i];
1119 if (zsp->access_perc == (uint8_t) -1U)
1120 zsp->access_perc = (100 - perc) / perc_missing;
1123 if (sperc_missing) {
1124 if (sperc_missing == 1 && o->zone_split_nr[ddir] == 1)
1126 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
1127 struct zone_split *zsp = &o->zone_split[ddir][i];
1129 if (zsp->size_perc == (uint8_t) -1U)
1130 zsp->size_perc = (100 - sperc) / sperc_missing;
1137 static int parse_zoned_distribution(struct thread_data *td, const char *input,
1140 const char *pre = absolute ? "zoned_abs:" : "zoned:";
1144 p = str = strdup(input);
1146 strip_blank_front(&str);
1147 strip_blank_end(str);
1149 /* We expect it to start like that, bail if not */
1150 if (strncmp(str, pre, strlen(pre))) {
1151 log_err("fio: mismatch in zoned input <%s>\n", str);
1157 ret = str_split_parse(td, str, zone_split_ddir, NULL, absolute);
1161 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
1164 dprint(FD_PARSE, "zone ddir %d (nr=%u): \n", i, td->o.zone_split_nr[i]);
1166 for (j = 0; j < td->o.zone_split_nr[i]; j++) {
1167 struct zone_split *zsp = &td->o.zone_split[i][j];
1170 dprint(FD_PARSE, "\t%d: %u/%llu\n", j,
1172 (unsigned long long) zsp->size);
1174 dprint(FD_PARSE, "\t%d: %u/%u\n", j,
1181 if (parse_dryrun()) {
1182 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
1183 free(td->o.zone_split[i]);
1184 td->o.zone_split[i] = NULL;
1185 td->o.zone_split_nr[i] = 0;
1192 for (i = 0; i < DDIR_RWDIR_CNT; i++)
1193 td->o.zone_split_nr[i] = 0;
1199 static int str_random_distribution_cb(void *data, const char *str)
1201 struct thread_data *td = cb_data_to_td(data);
1206 if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
1208 else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
1209 val = FIO_DEF_PARETO;
1210 else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
1212 else if (td->o.random_distribution == FIO_RAND_DIST_ZONED)
1213 return parse_zoned_distribution(td, str, false);
1214 else if (td->o.random_distribution == FIO_RAND_DIST_ZONED_ABS)
1215 return parse_zoned_distribution(td, str, true);
1219 nr = get_opt_postfix(str);
1220 if (nr && !split_parse_distr(nr, &val, ¢er)) {
1221 log_err("fio: random postfix parsing failed\n");
1228 if (center != -1 && (center < 0.00 || center > 1.00)) {
1229 log_err("fio: distribution center out of range (0 <= center <= 1.0)\n");
1232 td->o.random_center.u.f = center;
1234 if (td->o.random_distribution == FIO_RAND_DIST_ZIPF) {
1236 log_err("fio: zipf theta must different than 1.0\n");
1241 td->o.zipf_theta.u.f = val;
1242 } else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
1243 if (val <= 0.00 || val >= 1.00) {
1244 log_err("fio: pareto input out of range (0 < input < 1.0)\n");
1249 td->o.pareto_h.u.f = val;
1251 if (val < 0.00 || val >= 100.0) {
1252 log_err("fio: normal deviation out of range (0 <= input < 100.0)\n");
1257 td->o.gauss_dev.u.f = val;
1263 static int str_steadystate_cb(void *data, const char *str)
1265 struct thread_data *td = cb_data_to_td(data);
1271 if (td->o.ss_state != FIO_SS_IOPS && td->o.ss_state != FIO_SS_IOPS_SLOPE &&
1272 td->o.ss_state != FIO_SS_BW && td->o.ss_state != FIO_SS_BW_SLOPE) {
1273 /* should be impossible to get here */
1274 log_err("fio: unknown steady state criterion\n");
1278 nr = get_opt_postfix(str);
1280 log_err("fio: steadystate threshold must be specified in addition to criterion\n");
1285 /* ENHANCEMENT Allow fio to understand size=10.2% and use here */
1286 pct = strstr(nr, "%");
1289 strip_blank_end(nr);
1290 if (!str_to_float(nr, &val, 0)) {
1291 log_err("fio: could not parse steadystate threshold percentage\n");
1296 dprint(FD_PARSE, "set steady state threshold to %f%%\n", val);
1301 td->o.ss_state |= FIO_SS_PCT;
1302 td->o.ss_limit.u.f = val;
1303 } else if (td->o.ss_state & FIO_SS_IOPS) {
1304 if (!str_to_float(nr, &val, 0)) {
1305 log_err("fio: steadystate IOPS threshold postfix parsing failed\n");
1310 dprint(FD_PARSE, "set steady state IOPS threshold to %f\n", val);
1315 td->o.ss_limit.u.f = val;
1316 } else { /* bandwidth criterion */
1317 if (str_to_decimal(nr, &ll, 1, td, 0, 0)) {
1318 log_err("fio: steadystate BW threshold postfix parsing failed\n");
1323 dprint(FD_PARSE, "set steady state BW threshold to %lld\n", ll);
1328 td->o.ss_limit.u.f = (double) ll;
1331 td->ss.state = td->o.ss_state;
1336 * Return next name in the string. Files are separated with ':'. If the ':'
1337 * is escaped with a '\', then that ':' is part of the filename and does not
1338 * indicate a new file.
1340 char *get_next_str(char **ptr)
1345 if (!str || !strlen(str))
1351 * No colon, we are done
1353 p = strchr(str, ':');
1360 * We got a colon, but it's the first character. Skip and
1368 if (*(p - 1) != '\\') {
1374 memmove(p - 1, p, strlen(p) + 1);
1382 int get_max_str_idx(char *input)
1384 unsigned int cur_idx;
1387 p = str = strdup(input);
1388 for (cur_idx = 0; ; cur_idx++)
1389 if (get_next_str(&str) == NULL)
1397 * Returns the directory at the index, indexes > entries will be
1398 * assigned via modulo division of the index
1400 int set_name_idx(char *target, size_t tlen, char *input, int index,
1401 bool unique_filename)
1403 unsigned int cur_idx;
1405 char *fname, *str, *p;
1407 p = str = strdup(input);
1409 index %= get_max_str_idx(input);
1410 for (cur_idx = 0; cur_idx <= index; cur_idx++)
1411 fname = get_next_str(&str);
1413 if (client_sockaddr_str[0] && unique_filename) {
1414 len = snprintf(target, tlen, "%s/%s.", fname,
1415 client_sockaddr_str);
1417 len = snprintf(target, tlen, "%s%c", fname,
1418 FIO_OS_PATH_SEPARATOR);
1420 target[tlen - 1] = '\0';
1426 char* get_name_by_idx(char *input, int index)
1428 unsigned int cur_idx;
1429 char *fname, *str, *p;
1431 p = str = strdup(input);
1433 index %= get_max_str_idx(input);
1434 for (cur_idx = 0; cur_idx <= index; cur_idx++)
1435 fname = get_next_str(&str);
1437 fname = strdup(fname);
1443 static int str_filename_cb(void *data, const char *input)
1445 struct thread_data *td = cb_data_to_td(data);
1446 char *fname, *str, *p;
1448 p = str = strdup(input);
1450 strip_blank_front(&str);
1451 strip_blank_end(str);
1454 * Ignore what we may already have from nrfiles option.
1456 if (!td->files_index)
1459 while ((fname = get_next_str(&str)) != NULL) {
1462 add_file(td, fname, 0, 1);
1469 static int str_directory_cb(void *data, const char fio_unused *unused)
1471 struct thread_data *td = cb_data_to_td(data);
1473 char *dirname, *str, *p;
1479 p = str = strdup(td->o.directory);
1480 while ((dirname = get_next_str(&str)) != NULL) {
1481 if (lstat(dirname, &sb) < 0) {
1484 log_err("fio: %s is not a directory\n", dirname);
1485 td_verror(td, ret, "lstat");
1488 if (!S_ISDIR(sb.st_mode)) {
1489 log_err("fio: %s is not a directory\n", dirname);
1500 static int str_opendir_cb(void *data, const char fio_unused *str)
1502 struct thread_data *td = cb_data_to_td(data);
1507 if (!td->files_index)
1510 return add_dir_files(td, td->o.opendir);
1513 static int str_buffer_pattern_cb(void *data, const char *input)
1515 struct thread_data *td = cb_data_to_td(data);
1518 /* FIXME: for now buffer pattern does not support formats */
1519 ret = parse_and_fill_pattern_alloc(input, strlen(input),
1520 &td->o.buffer_pattern, NULL, NULL, NULL);
1525 td->o.buffer_pattern_bytes = ret;
1528 * If this job is doing any reading or has compression set,
1529 * ensure that we refill buffers for writes or we could be
1530 * invalidating the pattern through reads.
1532 if (!td->o.compress_percentage && !td_read(td))
1533 td->o.refill_buffers = 0;
1535 td->o.refill_buffers = 1;
1537 td->o.scramble_buffers = 0;
1538 td->o.zero_buffers = 0;
1543 static int str_buffer_compress_cb(void *data, unsigned long long *il)
1545 struct thread_data *td = cb_data_to_td(data);
1547 td->flags |= TD_F_COMPRESS;
1548 td->o.compress_percentage = *il;
1552 static int str_dedupe_cb(void *data, unsigned long long *il)
1554 struct thread_data *td = cb_data_to_td(data);
1556 td->flags |= TD_F_COMPRESS;
1557 td->o.dedupe_percentage = *il;
1558 td->o.refill_buffers = 1;
1562 static int str_verify_pattern_cb(void *data, const char *input)
1564 struct thread_data *td = cb_data_to_td(data);
1567 td->o.verify_fmt_sz = FIO_ARRAY_SIZE(td->o.verify_fmt);
1568 ret = parse_and_fill_pattern_alloc(input, strlen(input),
1569 &td->o.verify_pattern, fmt_desc, td->o.verify_fmt,
1570 &td->o.verify_fmt_sz);
1575 td->o.verify_pattern_bytes = ret;
1577 * VERIFY_* could already be set
1579 if (!fio_option_is_set(&td->o, verify))
1580 td->o.verify = VERIFY_PATTERN;
1585 static int str_gtod_reduce_cb(void *data, int *il)
1587 struct thread_data *td = cb_data_to_td(data);
1591 * Only modify options if gtod_reduce==1
1592 * Otherwise leave settings alone.
1595 td->o.disable_lat = 1;
1596 td->o.disable_clat = 1;
1597 td->o.disable_slat = 1;
1598 td->o.disable_bw = 1;
1599 td->o.clat_percentiles = 0;
1600 td->o.lat_percentiles = 0;
1601 td->o.slat_percentiles = 0;
1602 td->ts_cache_mask = 63;
1608 static int str_offset_cb(void *data, unsigned long long *__val)
1610 struct thread_data *td = cb_data_to_td(data);
1611 unsigned long long v = *__val;
1613 if (parse_is_percent(v)) {
1614 td->o.start_offset = 0;
1615 td->o.start_offset_percent = -1ULL - v;
1616 td->o.start_offset_nz = 0;
1617 dprint(FD_PARSE, "SET start_offset_percent %d\n",
1618 td->o.start_offset_percent);
1619 } else if (parse_is_zone(v)) {
1620 td->o.start_offset = 0;
1621 td->o.start_offset_percent = 0;
1622 td->o.start_offset_nz = v - ZONE_BASE_VAL;
1624 td->o.start_offset = v;
1629 static int str_offset_increment_cb(void *data, unsigned long long *__val)
1631 struct thread_data *td = cb_data_to_td(data);
1632 unsigned long long v = *__val;
1634 if (parse_is_percent(v)) {
1635 td->o.offset_increment = 0;
1636 td->o.offset_increment_percent = -1ULL - v;
1637 td->o.offset_increment_nz = 0;
1638 dprint(FD_PARSE, "SET offset_increment_percent %d\n",
1639 td->o.offset_increment_percent);
1640 } else if (parse_is_zone(v)) {
1641 td->o.offset_increment = 0;
1642 td->o.offset_increment_percent = 0;
1643 td->o.offset_increment_nz = v - ZONE_BASE_VAL;
1645 td->o.offset_increment = v;
1650 static int str_size_cb(void *data, unsigned long long *__val)
1652 struct thread_data *td = cb_data_to_td(data);
1653 unsigned long long v = *__val;
1655 if (parse_is_percent(v)) {
1657 td->o.size_percent = -1ULL - v;
1658 dprint(FD_PARSE, "SET size_percent %d\n",
1659 td->o.size_percent);
1660 } else if (parse_is_zone(v)) {
1662 td->o.size_percent = 0;
1663 td->o.size_nz = v - ZONE_BASE_VAL;
1670 static int str_io_size_cb(void *data, unsigned long long *__val)
1672 struct thread_data *td = cb_data_to_td(data);
1673 unsigned long long v = *__val;
1675 if (parse_is_percent_uncapped(v)) {
1677 td->o.io_size_percent = -1ULL - v;
1678 if (td->o.io_size_percent > 100) {
1679 log_err("fio: io_size values greater than 100%% aren't supported\n");
1682 dprint(FD_PARSE, "SET io_size_percent %d\n",
1683 td->o.io_size_percent);
1684 } else if (parse_is_zone(v)) {
1686 td->o.io_size_percent = 0;
1687 td->o.io_size_nz = v - ZONE_BASE_VAL;
1694 static int str_zoneskip_cb(void *data, unsigned long long *__val)
1696 struct thread_data *td = cb_data_to_td(data);
1697 unsigned long long v = *__val;
1699 if (parse_is_zone(v)) {
1700 td->o.zone_skip = 0;
1701 td->o.zone_skip_nz = v - ZONE_BASE_VAL;
1703 td->o.zone_skip = v;
1708 static int str_write_bw_log_cb(void *data, const char *str)
1710 struct thread_data *td = cb_data_to_td(data);
1713 td->o.bw_log_file = strdup(str);
1715 td->o.write_bw_log = 1;
1719 static int str_write_lat_log_cb(void *data, const char *str)
1721 struct thread_data *td = cb_data_to_td(data);
1724 td->o.lat_log_file = strdup(str);
1726 td->o.write_lat_log = 1;
1730 static int str_write_iops_log_cb(void *data, const char *str)
1732 struct thread_data *td = cb_data_to_td(data);
1735 td->o.iops_log_file = strdup(str);
1737 td->o.write_iops_log = 1;
1741 static int str_write_hist_log_cb(void *data, const char *str)
1743 struct thread_data *td = cb_data_to_td(data);
1746 td->o.hist_log_file = strdup(str);
1748 td->o.write_hist_log = 1;
1753 * str is supposed to be a substring of the strdup'd original string,
1754 * and is valid only if it's a regular file path.
1755 * This function keeps the pointer to the path as needed later.
1757 * "external:/path/to/so\0" <- original pointer updated with strdup'd
1758 * "external\0" <- above pointer after parsed, i.e. ->ioengine
1759 * "/path/to/so\0" <- str argument, i.e. ->ioengine_so_path
1761 static int str_ioengine_external_cb(void *data, const char *str)
1763 struct thread_data *td = cb_data_to_td(data);
1768 log_err("fio: null external ioengine path\n");
1772 p = (char *)str; /* str is mutable */
1773 strip_blank_front(&p);
1776 if (stat(p, &sb) || !S_ISREG(sb.st_mode)) {
1777 log_err("fio: invalid external ioengine path \"%s\"\n", p);
1781 td->o.ioengine_so_path = p;
1785 static int rw_verify(const struct fio_option *o, void *data)
1787 struct thread_data *td = cb_data_to_td(data);
1789 if (read_only && (td_write(td) || td_trim(td))) {
1790 log_err("fio: job <%s> has write or trim bit set, but"
1791 " fio is in read-only mode\n", td->o.name);
1798 static int gtod_cpu_verify(const struct fio_option *o, void *data)
1800 #ifndef FIO_HAVE_CPU_AFFINITY
1801 struct thread_data *td = cb_data_to_td(data);
1803 if (td->o.gtod_cpu) {
1804 log_err("fio: platform must support CPU affinity for"
1805 "gettimeofday() offloading\n");
1814 * Map of job/command line options
1816 struct fio_option fio_options[FIO_MAX_OPTS] = {
1818 .name = "description",
1819 .lname = "Description of job",
1820 .type = FIO_OPT_STR_STORE,
1821 .off1 = offsetof(struct thread_options, description),
1822 .help = "Text job description",
1823 .category = FIO_OPT_C_GENERAL,
1824 .group = FIO_OPT_G_DESC,
1828 .lname = "Job name",
1829 .type = FIO_OPT_STR_STORE,
1830 .off1 = offsetof(struct thread_options, name),
1831 .help = "Name of this job",
1832 .category = FIO_OPT_C_GENERAL,
1833 .group = FIO_OPT_G_DESC,
1837 .lname = "Waitee name",
1838 .type = FIO_OPT_STR_STORE,
1839 .off1 = offsetof(struct thread_options, wait_for),
1840 .help = "Name of the job this one wants to wait for before starting",
1841 .category = FIO_OPT_C_GENERAL,
1842 .group = FIO_OPT_G_DESC,
1846 .lname = "Filename(s)",
1847 .type = FIO_OPT_STR_STORE,
1848 .off1 = offsetof(struct thread_options, filename),
1850 .cb = str_filename_cb,
1851 .prio = -1, /* must come after "directory" */
1852 .help = "File(s) to use for the workload",
1853 .category = FIO_OPT_C_FILE,
1854 .group = FIO_OPT_G_FILENAME,
1857 .name = "directory",
1858 .lname = "Directory",
1859 .type = FIO_OPT_STR_STORE,
1860 .off1 = offsetof(struct thread_options, directory),
1861 .cb = str_directory_cb,
1862 .help = "Directory to store files in",
1863 .category = FIO_OPT_C_FILE,
1864 .group = FIO_OPT_G_FILENAME,
1867 .name = "filename_format",
1868 .lname = "Filename Format",
1869 .type = FIO_OPT_STR_STORE,
1870 .off1 = offsetof(struct thread_options, filename_format),
1871 .prio = -1, /* must come after "directory" */
1872 .help = "Override default $jobname.$jobnum.$filenum naming",
1873 .def = "$jobname.$jobnum.$filenum",
1874 .category = FIO_OPT_C_FILE,
1875 .group = FIO_OPT_G_FILENAME,
1878 .name = "unique_filename",
1879 .lname = "Unique Filename",
1880 .type = FIO_OPT_BOOL,
1881 .off1 = offsetof(struct thread_options, unique_filename),
1882 .help = "For network clients, prefix file with source IP",
1884 .category = FIO_OPT_C_FILE,
1885 .group = FIO_OPT_G_FILENAME,
1889 .lname = "Lockfile",
1890 .type = FIO_OPT_STR,
1891 .off1 = offsetof(struct thread_options, file_lock_mode),
1892 .help = "Lock file when doing IO to it",
1894 .parent = "filename",
1897 .category = FIO_OPT_C_FILE,
1898 .group = FIO_OPT_G_FILENAME,
1901 .oval = FILE_LOCK_NONE,
1902 .help = "No file locking",
1904 { .ival = "exclusive",
1905 .oval = FILE_LOCK_EXCLUSIVE,
1906 .help = "Exclusive file lock",
1909 .ival = "readwrite",
1910 .oval = FILE_LOCK_READWRITE,
1911 .help = "Read vs write lock",
1917 .lname = "Open directory",
1918 .type = FIO_OPT_STR_STORE,
1919 .off1 = offsetof(struct thread_options, opendir),
1920 .cb = str_opendir_cb,
1921 .help = "Recursively add files from this directory and down",
1922 .category = FIO_OPT_C_FILE,
1923 .group = FIO_OPT_G_FILENAME,
1927 .lname = "Read/write",
1928 .alias = "readwrite",
1929 .type = FIO_OPT_STR,
1931 .off1 = offsetof(struct thread_options, td_ddir),
1932 .help = "IO direction",
1934 .verify = rw_verify,
1935 .category = FIO_OPT_C_IO,
1936 .group = FIO_OPT_G_IO_BASIC,
1939 .oval = TD_DDIR_READ,
1940 .help = "Sequential read",
1943 .oval = TD_DDIR_WRITE,
1944 .help = "Sequential write",
1947 .oval = TD_DDIR_TRIM,
1948 .help = "Sequential trim",
1950 { .ival = "randread",
1951 .oval = TD_DDIR_RANDREAD,
1952 .help = "Random read",
1954 { .ival = "randwrite",
1955 .oval = TD_DDIR_RANDWRITE,
1956 .help = "Random write",
1958 { .ival = "randtrim",
1959 .oval = TD_DDIR_RANDTRIM,
1960 .help = "Random trim",
1964 .help = "Sequential read and write mix",
1966 { .ival = "readwrite",
1968 .help = "Sequential read and write mix",
1971 .oval = TD_DDIR_RANDRW,
1972 .help = "Random read and write mix"
1974 { .ival = "trimwrite",
1975 .oval = TD_DDIR_TRIMWRITE,
1976 .help = "Trim and write mix, trims preceding writes"
1978 { .ival = "randtrimwrite",
1979 .oval = TD_DDIR_RANDTRIMWRITE,
1980 .help = "Randomly trim and write mix, trims preceding writes"
1985 .name = "rw_sequencer",
1986 .lname = "RW Sequencer",
1987 .type = FIO_OPT_STR,
1988 .off1 = offsetof(struct thread_options, rw_seq),
1989 .help = "IO offset generator modifier",
1990 .def = "sequential",
1991 .category = FIO_OPT_C_IO,
1992 .group = FIO_OPT_G_IO_BASIC,
1994 { .ival = "sequential",
1996 .help = "Generate sequential offsets",
1998 { .ival = "identical",
1999 .oval = RW_SEQ_IDENT,
2000 .help = "Generate identical offsets",
2007 .lname = "IO Engine",
2008 .type = FIO_OPT_STR_STORE,
2009 .off1 = offsetof(struct thread_options, ioengine),
2010 .help = "IO engine to use",
2011 .def = FIO_PREFERRED_ENGINE,
2012 .category = FIO_OPT_C_IO,
2013 .group = FIO_OPT_G_IO_BASIC,
2016 .help = "Use read/write",
2019 .help = "Use pread/pwrite",
2022 .help = "Use readv/writev",
2024 #ifdef CONFIG_PWRITEV
2026 .help = "Use preadv/pwritev",
2029 #ifdef FIO_HAVE_PWRITEV2
2030 { .ival = "pvsync2",
2031 .help = "Use preadv2/pwritev2",
2034 #ifdef CONFIG_LIBAIO
2036 .help = "Linux native asynchronous IO",
2039 #ifdef ARCH_HAVE_IOURING
2040 { .ival = "io_uring",
2041 .help = "Fast Linux native aio",
2044 #ifdef CONFIG_POSIXAIO
2045 { .ival = "posixaio",
2046 .help = "POSIX asynchronous IO",
2049 #ifdef CONFIG_SOLARISAIO
2050 { .ival = "solarisaio",
2051 .help = "Solaris native asynchronous IO",
2054 #ifdef CONFIG_WINDOWSAIO
2055 { .ival = "windowsaio",
2056 .help = "Windows native asynchronous IO"
2061 .help = "Rados Block Device asynchronous IO"
2065 .help = "Memory mapped IO"
2067 #ifdef CONFIG_LINUX_SPLICE
2069 .help = "splice/vmsplice based IO",
2071 { .ival = "netsplice",
2072 .help = "splice/vmsplice to/from the network",
2075 #ifdef FIO_HAVE_SGIO
2077 .help = "SCSI generic v3 IO",
2081 .help = "Testing engine (no data transfer)",
2084 .help = "Network IO",
2087 .help = "CPU cycle burner engine",
2091 .help = "RDMA IO engine",
2094 #ifdef CONFIG_LIBRPMA_APM
2095 { .ival = "librpma_apm",
2096 .help = "librpma IO engine in APM mode",
2099 #ifdef CONFIG_LIBRPMA_GPSPM
2100 { .ival = "librpma_gpspm",
2101 .help = "librpma IO engine in GPSPM mode",
2104 #ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
2105 { .ival = "e4defrag",
2106 .help = "ext4 defrag engine",
2109 #ifdef CONFIG_LINUX_FALLOCATE
2111 .help = "fallocate() file based engine",
2116 .help = "Glusterfs libgfapi(sync) based engine"
2118 { .ival = "gfapi_async",
2119 .help = "Glusterfs libgfapi(async) based engine"
2122 #ifdef CONFIG_LIBHDFS
2123 { .ival = "libhdfs",
2124 .help = "Hadoop Distributed Filesystem (HDFS) engine"
2128 { .ival = "ime_psync",
2129 .help = "DDN's IME synchronous IO engine",
2131 { .ival = "ime_psyncv",
2132 .help = "DDN's IME synchronous IO engine using iovecs",
2134 { .ival = "ime_aio",
2135 .help = "DDN's IME asynchronous IO engine",
2138 #ifdef CONFIG_LINUX_DEVDAX
2139 { .ival = "dev-dax",
2140 .help = "DAX Device based IO engine",
2144 .ival = "filecreate",
2145 .help = "File creation engine",
2147 { .ival = "external",
2148 .help = "Load external engine (append name)",
2149 .cb = str_ioengine_external_cb,
2151 #ifdef CONFIG_LIBPMEM
2152 { .ival = "libpmem",
2153 .help = "PMDK libpmem based IO engine",
2158 .help = "HTTP (WebDAV/S3) IO engine",
2162 .help = "Network Block Device (NBD) IO engine"
2166 .help = "DAOS File System (dfs) IO engine",
2169 #ifdef CONFIG_LIBNFS
2171 .help = "NFS IO engine",
2174 #ifdef CONFIG_LIBXNVME
2176 .help = "XNVME IO engine",
2183 .lname = "IO Depth",
2184 .type = FIO_OPT_INT,
2185 .off1 = offsetof(struct thread_options, iodepth),
2186 .help = "Number of IO buffers to keep in flight",
2190 .category = FIO_OPT_C_IO,
2191 .group = FIO_OPT_G_IO_BASIC,
2194 .name = "iodepth_batch",
2195 .lname = "IO Depth batch",
2196 .alias = "iodepth_batch_submit",
2197 .type = FIO_OPT_INT,
2198 .off1 = offsetof(struct thread_options, iodepth_batch),
2199 .help = "Number of IO buffers to submit in one go",
2200 .parent = "iodepth",
2204 .category = FIO_OPT_C_IO,
2205 .group = FIO_OPT_G_IO_BASIC,
2208 .name = "iodepth_batch_complete_min",
2209 .lname = "Min IO depth batch complete",
2210 .alias = "iodepth_batch_complete",
2211 .type = FIO_OPT_INT,
2212 .off1 = offsetof(struct thread_options, iodepth_batch_complete_min),
2213 .help = "Min number of IO buffers to retrieve in one go",
2214 .parent = "iodepth",
2219 .category = FIO_OPT_C_IO,
2220 .group = FIO_OPT_G_IO_BASIC,
2223 .name = "iodepth_batch_complete_max",
2224 .lname = "Max IO depth batch complete",
2225 .type = FIO_OPT_INT,
2226 .off1 = offsetof(struct thread_options, iodepth_batch_complete_max),
2227 .help = "Max number of IO buffers to retrieve in one go",
2228 .parent = "iodepth",
2232 .category = FIO_OPT_C_IO,
2233 .group = FIO_OPT_G_IO_BASIC,
2236 .name = "iodepth_low",
2237 .lname = "IO Depth batch low",
2238 .type = FIO_OPT_INT,
2239 .off1 = offsetof(struct thread_options, iodepth_low),
2240 .help = "Low water mark for queuing depth",
2241 .parent = "iodepth",
2244 .category = FIO_OPT_C_IO,
2245 .group = FIO_OPT_G_IO_BASIC,
2248 .name = "serialize_overlap",
2249 .lname = "Serialize overlap",
2250 .off1 = offsetof(struct thread_options, serialize_overlap),
2251 .type = FIO_OPT_BOOL,
2252 .help = "Wait for in-flight IOs that collide to complete",
2253 .parent = "iodepth",
2255 .category = FIO_OPT_C_IO,
2256 .group = FIO_OPT_G_IO_BASIC,
2259 .name = "io_submit_mode",
2260 .lname = "IO submit mode",
2261 .type = FIO_OPT_STR,
2262 .off1 = offsetof(struct thread_options, io_submit_mode),
2263 .help = "How IO submissions and completions are done",
2265 .category = FIO_OPT_C_IO,
2266 .group = FIO_OPT_G_IO_BASIC,
2269 .oval = IO_MODE_INLINE,
2270 .help = "Submit and complete IO inline",
2272 { .ival = "offload",
2273 .oval = IO_MODE_OFFLOAD,
2274 .help = "Offload submit and complete to threads",
2281 .type = FIO_OPT_STR_VAL_ZONE,
2283 .off1 = offsetof(struct thread_options, size),
2284 .help = "Total size of device or files",
2285 .category = FIO_OPT_C_IO,
2286 .group = FIO_OPT_G_INVALID,
2290 .alias = "io_limit",
2292 .type = FIO_OPT_STR_VAL_ZONE,
2293 .cb = str_io_size_cb,
2294 .off1 = offsetof(struct thread_options, io_size),
2295 .help = "Total size of I/O to be performed",
2296 .category = FIO_OPT_C_IO,
2297 .group = FIO_OPT_G_INVALID,
2300 .name = "fill_device",
2301 .lname = "Fill device",
2303 .type = FIO_OPT_BOOL,
2304 .off1 = offsetof(struct thread_options, fill_device),
2305 .help = "Write until an ENOSPC error occurs",
2307 .category = FIO_OPT_C_FILE,
2308 .group = FIO_OPT_G_INVALID,
2312 .lname = "File size",
2313 .type = FIO_OPT_STR_VAL,
2314 .off1 = offsetof(struct thread_options, file_size_low),
2315 .off2 = offsetof(struct thread_options, file_size_high),
2317 .help = "Size of individual files",
2318 .interval = 1024 * 1024,
2319 .category = FIO_OPT_C_FILE,
2320 .group = FIO_OPT_G_INVALID,
2323 .name = "file_append",
2324 .lname = "File append",
2325 .type = FIO_OPT_BOOL,
2326 .off1 = offsetof(struct thread_options, file_append),
2327 .help = "IO will start at the end of the file(s)",
2329 .category = FIO_OPT_C_FILE,
2330 .group = FIO_OPT_G_INVALID,
2334 .lname = "IO offset",
2335 .alias = "fileoffset",
2336 .type = FIO_OPT_STR_VAL_ZONE,
2337 .cb = str_offset_cb,
2338 .off1 = offsetof(struct thread_options, start_offset),
2339 .help = "Start IO from this offset",
2341 .category = FIO_OPT_C_IO,
2342 .group = FIO_OPT_G_INVALID,
2345 .name = "offset_align",
2346 .lname = "IO offset alignment",
2347 .type = FIO_OPT_INT,
2348 .off1 = offsetof(struct thread_options, start_offset_align),
2349 .help = "Start IO from this offset alignment",
2352 .category = FIO_OPT_C_IO,
2353 .group = FIO_OPT_G_INVALID,
2356 .name = "offset_increment",
2357 .lname = "IO offset increment",
2358 .type = FIO_OPT_STR_VAL_ZONE,
2359 .cb = str_offset_increment_cb,
2360 .off1 = offsetof(struct thread_options, offset_increment),
2361 .help = "What is the increment from one offset to the next",
2365 .category = FIO_OPT_C_IO,
2366 .group = FIO_OPT_G_INVALID,
2369 .name = "number_ios",
2370 .lname = "Number of IOs to perform",
2371 .type = FIO_OPT_STR_VAL,
2372 .off1 = offsetof(struct thread_options, number_ios),
2373 .help = "Force job completion after this number of IOs",
2375 .category = FIO_OPT_C_IO,
2376 .group = FIO_OPT_G_INVALID,
2380 .lname = "Block size",
2381 .alias = "blocksize",
2382 .type = FIO_OPT_ULL,
2383 .off1 = offsetof(struct thread_options, bs[DDIR_READ]),
2384 .off2 = offsetof(struct thread_options, bs[DDIR_WRITE]),
2385 .off3 = offsetof(struct thread_options, bs[DDIR_TRIM]),
2387 .help = "Block size unit",
2392 .category = FIO_OPT_C_IO,
2393 .group = FIO_OPT_G_INVALID,
2397 .lname = "Block size align",
2398 .alias = "blockalign",
2399 .type = FIO_OPT_ULL,
2400 .off1 = offsetof(struct thread_options, ba[DDIR_READ]),
2401 .off2 = offsetof(struct thread_options, ba[DDIR_WRITE]),
2402 .off3 = offsetof(struct thread_options, ba[DDIR_TRIM]),
2404 .help = "IO block offset alignment",
2408 .category = FIO_OPT_C_IO,
2409 .group = FIO_OPT_G_INVALID,
2413 .lname = "Block size range",
2414 .alias = "blocksize_range",
2415 .type = FIO_OPT_RANGE,
2416 .off1 = offsetof(struct thread_options, min_bs[DDIR_READ]),
2417 .off2 = offsetof(struct thread_options, max_bs[DDIR_READ]),
2418 .off3 = offsetof(struct thread_options, min_bs[DDIR_WRITE]),
2419 .off4 = offsetof(struct thread_options, max_bs[DDIR_WRITE]),
2420 .off5 = offsetof(struct thread_options, min_bs[DDIR_TRIM]),
2421 .off6 = offsetof(struct thread_options, max_bs[DDIR_TRIM]),
2423 .help = "Set block size range (in more detail than bs)",
2427 .category = FIO_OPT_C_IO,
2428 .group = FIO_OPT_G_INVALID,
2432 .lname = "Block size split",
2433 .type = FIO_OPT_STR_ULL,
2434 .cb = str_bssplit_cb,
2435 .off1 = offsetof(struct thread_options, bssplit),
2436 .help = "Set a specific mix of block sizes",
2439 .category = FIO_OPT_C_IO,
2440 .group = FIO_OPT_G_INVALID,
2443 .name = "bs_unaligned",
2444 .lname = "Block size unaligned",
2445 .alias = "blocksize_unaligned",
2446 .type = FIO_OPT_STR_SET,
2447 .off1 = offsetof(struct thread_options, bs_unaligned),
2448 .help = "Don't sector align IO buffer sizes",
2451 .category = FIO_OPT_C_IO,
2452 .group = FIO_OPT_G_INVALID,
2455 .name = "bs_is_seq_rand",
2456 .lname = "Block size division is seq/random (not read/write)",
2457 .type = FIO_OPT_BOOL,
2458 .off1 = offsetof(struct thread_options, bs_is_seq_rand),
2459 .help = "Consider any blocksize setting to be sequential,random",
2461 .parent = "blocksize",
2462 .category = FIO_OPT_C_IO,
2463 .group = FIO_OPT_G_INVALID,
2466 .name = "randrepeat",
2467 .lname = "Random repeatable",
2468 .type = FIO_OPT_BOOL,
2469 .off1 = offsetof(struct thread_options, rand_repeatable),
2470 .help = "Use repeatable random IO pattern",
2474 .category = FIO_OPT_C_IO,
2475 .group = FIO_OPT_G_RANDOM,
2479 .lname = "The random generator seed",
2480 .type = FIO_OPT_STR_VAL,
2481 .off1 = offsetof(struct thread_options, rand_seed),
2482 .help = "Set the random generator seed value",
2485 .category = FIO_OPT_C_IO,
2486 .group = FIO_OPT_G_RANDOM,
2489 .name = "norandommap",
2490 .lname = "No randommap",
2491 .type = FIO_OPT_STR_SET,
2492 .off1 = offsetof(struct thread_options, norandommap),
2493 .help = "Accept potential duplicate random blocks",
2497 .category = FIO_OPT_C_IO,
2498 .group = FIO_OPT_G_RANDOM,
2501 .name = "softrandommap",
2502 .lname = "Soft randommap",
2503 .type = FIO_OPT_BOOL,
2504 .off1 = offsetof(struct thread_options, softrandommap),
2505 .help = "Set norandommap if randommap allocation fails",
2506 .parent = "norandommap",
2509 .category = FIO_OPT_C_IO,
2510 .group = FIO_OPT_G_RANDOM,
2513 .name = "random_generator",
2514 .lname = "Random Generator",
2515 .type = FIO_OPT_STR,
2516 .off1 = offsetof(struct thread_options, random_generator),
2517 .help = "Type of random number generator to use",
2518 .def = "tausworthe",
2520 { .ival = "tausworthe",
2521 .oval = FIO_RAND_GEN_TAUSWORTHE,
2522 .help = "Strong Tausworthe generator",
2525 .oval = FIO_RAND_GEN_LFSR,
2526 .help = "Variable length LFSR",
2529 .ival = "tausworthe64",
2530 .oval = FIO_RAND_GEN_TAUSWORTHE64,
2531 .help = "64-bit Tausworthe variant",
2534 .category = FIO_OPT_C_IO,
2535 .group = FIO_OPT_G_RANDOM,
2538 .name = "random_distribution",
2539 .lname = "Random Distribution",
2540 .type = FIO_OPT_STR,
2541 .off1 = offsetof(struct thread_options, random_distribution),
2542 .cb = str_random_distribution_cb,
2543 .help = "Random offset distribution generator",
2547 .oval = FIO_RAND_DIST_RANDOM,
2548 .help = "Completely random",
2551 .oval = FIO_RAND_DIST_ZIPF,
2552 .help = "Zipf distribution",
2555 .oval = FIO_RAND_DIST_PARETO,
2556 .help = "Pareto distribution",
2559 .oval = FIO_RAND_DIST_GAUSS,
2560 .help = "Normal (Gaussian) distribution",
2563 .oval = FIO_RAND_DIST_ZONED,
2564 .help = "Zoned random distribution",
2566 { .ival = "zoned_abs",
2567 .oval = FIO_RAND_DIST_ZONED_ABS,
2568 .help = "Zoned absolute random distribution",
2571 .category = FIO_OPT_C_IO,
2572 .group = FIO_OPT_G_RANDOM,
2575 .name = "percentage_random",
2576 .lname = "Percentage Random",
2577 .type = FIO_OPT_INT,
2578 .off1 = offsetof(struct thread_options, perc_rand[DDIR_READ]),
2579 .off2 = offsetof(struct thread_options, perc_rand[DDIR_WRITE]),
2580 .off3 = offsetof(struct thread_options, perc_rand[DDIR_TRIM]),
2582 .help = "Percentage of seq/random mix that should be random",
2583 .def = "100,100,100",
2585 .inverse = "percentage_sequential",
2586 .category = FIO_OPT_C_IO,
2587 .group = FIO_OPT_G_RANDOM,
2590 .name = "percentage_sequential",
2591 .lname = "Percentage Sequential",
2592 .type = FIO_OPT_DEPRECATED,
2593 .category = FIO_OPT_C_IO,
2594 .group = FIO_OPT_G_RANDOM,
2597 .name = "allrandrepeat",
2598 .lname = "All Random Repeat",
2599 .type = FIO_OPT_BOOL,
2600 .off1 = offsetof(struct thread_options, allrand_repeatable),
2601 .help = "Use repeatable random numbers for everything",
2603 .category = FIO_OPT_C_IO,
2604 .group = FIO_OPT_G_RANDOM,
2608 .lname = "Number of files",
2609 .alias = "nr_files",
2610 .type = FIO_OPT_INT,
2611 .off1 = offsetof(struct thread_options, nr_files),
2612 .help = "Split job workload between this number of files",
2615 .category = FIO_OPT_C_FILE,
2616 .group = FIO_OPT_G_INVALID,
2619 .name = "openfiles",
2620 .lname = "Number of open files",
2621 .type = FIO_OPT_INT,
2622 .off1 = offsetof(struct thread_options, open_files),
2623 .help = "Number of files to keep open at the same time",
2624 .category = FIO_OPT_C_FILE,
2625 .group = FIO_OPT_G_INVALID,
2628 .name = "file_service_type",
2629 .lname = "File service type",
2630 .type = FIO_OPT_STR,
2632 .off1 = offsetof(struct thread_options, file_service_type),
2633 .help = "How to select which file to service next",
2634 .def = "roundrobin",
2635 .category = FIO_OPT_C_FILE,
2636 .group = FIO_OPT_G_INVALID,
2639 .oval = FIO_FSERVICE_RANDOM,
2640 .help = "Choose a file at random (uniform)",
2643 .oval = FIO_FSERVICE_ZIPF,
2644 .help = "Zipf randomized",
2647 .oval = FIO_FSERVICE_PARETO,
2648 .help = "Pareto randomized",
2651 .oval = FIO_FSERVICE_GAUSS,
2652 .help = "Normal (Gaussian) randomized",
2655 .oval = FIO_FSERVICE_GAUSS,
2656 .help = "Alias for normal",
2658 { .ival = "roundrobin",
2659 .oval = FIO_FSERVICE_RR,
2660 .help = "Round robin select files",
2662 { .ival = "sequential",
2663 .oval = FIO_FSERVICE_SEQ,
2664 .help = "Finish one file before moving to the next",
2667 .parent = "nrfiles",
2671 .name = "fallocate",
2672 .lname = "Fallocate",
2673 .type = FIO_OPT_STR,
2674 .off1 = offsetof(struct thread_options, fallocate_mode),
2675 .help = "Whether pre-allocation is performed when laying out files",
2676 #ifdef FIO_HAVE_DEFAULT_FALLOCATE
2681 .category = FIO_OPT_C_FILE,
2682 .group = FIO_OPT_G_INVALID,
2685 .oval = FIO_FALLOCATE_NONE,
2686 .help = "Do not pre-allocate space",
2689 .oval = FIO_FALLOCATE_NATIVE,
2690 .help = "Use native pre-allocation if possible",
2692 #ifdef CONFIG_POSIX_FALLOCATE
2694 .oval = FIO_FALLOCATE_POSIX,
2695 .help = "Use posix_fallocate()",
2698 #ifdef CONFIG_LINUX_FALLOCATE
2700 .oval = FIO_FALLOCATE_KEEP_SIZE,
2701 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
2704 { .ival = "truncate",
2705 .oval = FIO_FALLOCATE_TRUNCATE,
2706 .help = "Truncate file to final size instead of allocating"
2708 /* Compatibility with former boolean values */
2710 .oval = FIO_FALLOCATE_NONE,
2711 .help = "Alias for 'none'",
2713 #ifdef CONFIG_POSIX_FALLOCATE
2715 .oval = FIO_FALLOCATE_POSIX,
2716 .help = "Alias for 'posix'",
2722 .name = "fadvise_hint",
2723 .lname = "Fadvise hint",
2724 .type = FIO_OPT_STR,
2725 .off1 = offsetof(struct thread_options, fadvise_hint),
2729 .help = "Don't issue fadvise/madvise",
2733 .help = "Advise using fio IO pattern",
2736 .oval = F_ADV_RANDOM,
2737 .help = "Advise using FADV_RANDOM",
2739 { .ival = "sequential",
2740 .oval = F_ADV_SEQUENTIAL,
2741 .help = "Advise using FADV_SEQUENTIAL",
2744 .help = "Use fadvise() to advise the kernel on IO pattern",
2746 .category = FIO_OPT_C_FILE,
2747 .group = FIO_OPT_G_INVALID,
2752 .type = FIO_OPT_INT,
2753 .off1 = offsetof(struct thread_options, fsync_blocks),
2754 .help = "Issue fsync for writes every given number of blocks",
2757 .category = FIO_OPT_C_FILE,
2758 .group = FIO_OPT_G_INVALID,
2761 .name = "fdatasync",
2762 .lname = "Fdatasync",
2763 .type = FIO_OPT_INT,
2764 .off1 = offsetof(struct thread_options, fdatasync_blocks),
2765 .help = "Issue fdatasync for writes every given number of blocks",
2768 .category = FIO_OPT_C_FILE,
2769 .group = FIO_OPT_G_INVALID,
2772 .name = "write_barrier",
2773 .lname = "Write barrier",
2774 .type = FIO_OPT_INT,
2775 .off1 = offsetof(struct thread_options, barrier_blocks),
2776 .help = "Make every Nth write a barrier write",
2779 .category = FIO_OPT_C_IO,
2780 .group = FIO_OPT_G_INVALID,
2782 #ifdef CONFIG_SYNC_FILE_RANGE
2784 .name = "sync_file_range",
2785 .lname = "Sync file range",
2787 { .ival = "wait_before",
2788 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
2789 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
2793 .oval = SYNC_FILE_RANGE_WRITE,
2794 .help = "SYNC_FILE_RANGE_WRITE",
2798 .ival = "wait_after",
2799 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
2800 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
2804 .type = FIO_OPT_STR_MULTI,
2806 .off1 = offsetof(struct thread_options, sync_file_range),
2807 .help = "Use sync_file_range()",
2808 .category = FIO_OPT_C_FILE,
2809 .group = FIO_OPT_G_INVALID,
2813 .name = "sync_file_range",
2814 .lname = "Sync file range",
2815 .type = FIO_OPT_UNSUPPORTED,
2816 .help = "Your platform does not support sync_file_range",
2821 .lname = "Direct I/O",
2822 .type = FIO_OPT_BOOL,
2823 .off1 = offsetof(struct thread_options, odirect),
2824 .help = "Use O_DIRECT IO (negates buffered)",
2826 .inverse = "buffered",
2827 .category = FIO_OPT_C_IO,
2828 .group = FIO_OPT_G_IO_TYPE,
2832 .lname = "Atomic I/O",
2833 .type = FIO_OPT_BOOL,
2834 .off1 = offsetof(struct thread_options, oatomic),
2835 .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
2837 .category = FIO_OPT_C_IO,
2838 .group = FIO_OPT_G_IO_TYPE,
2842 .lname = "Buffered I/O",
2843 .type = FIO_OPT_BOOL,
2844 .off1 = offsetof(struct thread_options, odirect),
2846 .help = "Use buffered IO (negates direct)",
2848 .inverse = "direct",
2849 .category = FIO_OPT_C_IO,
2850 .group = FIO_OPT_G_IO_TYPE,
2853 .name = "overwrite",
2854 .lname = "Overwrite",
2855 .type = FIO_OPT_BOOL,
2856 .off1 = offsetof(struct thread_options, overwrite),
2857 .help = "When writing, set whether to overwrite current data",
2859 .category = FIO_OPT_C_FILE,
2860 .group = FIO_OPT_G_INVALID,
2865 .type = FIO_OPT_INT,
2866 .off1 = offsetof(struct thread_options, loops),
2867 .help = "Number of times to run the job",
2870 .category = FIO_OPT_C_GENERAL,
2871 .group = FIO_OPT_G_RUNTIME,
2875 .lname = "Number of jobs",
2876 .type = FIO_OPT_INT,
2877 .off1 = offsetof(struct thread_options, numjobs),
2878 .help = "Duplicate this job this many times",
2881 .category = FIO_OPT_C_GENERAL,
2882 .group = FIO_OPT_G_RUNTIME,
2885 .name = "startdelay",
2886 .lname = "Start delay",
2887 .type = FIO_OPT_STR_VAL_TIME,
2888 .off1 = offsetof(struct thread_options, start_delay),
2889 .off2 = offsetof(struct thread_options, start_delay_high),
2890 .help = "Only start job when this period has passed",
2894 .category = FIO_OPT_C_GENERAL,
2895 .group = FIO_OPT_G_RUNTIME,
2901 .type = FIO_OPT_STR_VAL_TIME,
2902 .off1 = offsetof(struct thread_options, timeout),
2903 .help = "Stop workload when this amount of time has passed",
2907 .category = FIO_OPT_C_GENERAL,
2908 .group = FIO_OPT_G_RUNTIME,
2911 .name = "time_based",
2912 .lname = "Time based",
2913 .type = FIO_OPT_STR_SET,
2914 .off1 = offsetof(struct thread_options, time_based),
2915 .help = "Keep running until runtime/timeout is met",
2916 .category = FIO_OPT_C_GENERAL,
2917 .group = FIO_OPT_G_RUNTIME,
2920 .name = "verify_only",
2921 .lname = "Verify only",
2922 .type = FIO_OPT_STR_SET,
2923 .off1 = offsetof(struct thread_options, verify_only),
2924 .help = "Verifies previously written data is still valid",
2925 .category = FIO_OPT_C_GENERAL,
2926 .group = FIO_OPT_G_RUNTIME,
2929 .name = "ramp_time",
2930 .lname = "Ramp time",
2931 .type = FIO_OPT_STR_VAL_TIME,
2932 .off1 = offsetof(struct thread_options, ramp_time),
2933 .help = "Ramp up time before measuring performance",
2936 .category = FIO_OPT_C_GENERAL,
2937 .group = FIO_OPT_G_RUNTIME,
2940 .name = "clocksource",
2941 .lname = "Clock source",
2942 .type = FIO_OPT_STR,
2943 .cb = fio_clock_source_cb,
2944 .off1 = offsetof(struct thread_options, clocksource),
2945 .help = "What type of timing source to use",
2946 .category = FIO_OPT_C_GENERAL,
2947 .group = FIO_OPT_G_CLOCK,
2949 #ifdef CONFIG_GETTIMEOFDAY
2950 { .ival = "gettimeofday",
2952 .help = "Use gettimeofday(2) for timing",
2955 #ifdef CONFIG_CLOCK_GETTIME
2956 { .ival = "clock_gettime",
2957 .oval = CS_CGETTIME,
2958 .help = "Use clock_gettime(2) for timing",
2961 #ifdef ARCH_HAVE_CPU_CLOCK
2963 .oval = CS_CPUCLOCK,
2964 .help = "Use CPU private clock",
2972 .lname = "I/O Memory",
2973 .type = FIO_OPT_STR,
2975 .off1 = offsetof(struct thread_options, mem_type),
2976 .help = "Backing type for IO buffers",
2978 .category = FIO_OPT_C_IO,
2979 .group = FIO_OPT_G_INVALID,
2983 .help = "Use malloc(3) for IO buffers",
2985 #ifndef CONFIG_NO_SHM
2988 .help = "Use shared memory segments for IO buffers",
2990 #ifdef FIO_HAVE_HUGETLB
2991 { .ival = "shmhuge",
2992 .oval = MEM_SHMHUGE,
2993 .help = "Like shm, but use huge pages",
2999 .help = "Use mmap(2) (file or anon) for IO buffers",
3001 { .ival = "mmapshared",
3002 .oval = MEM_MMAPSHARED,
3003 .help = "Like mmap, but use the shared flag",
3005 #ifdef FIO_HAVE_HUGETLB
3006 { .ival = "mmaphuge",
3007 .oval = MEM_MMAPHUGE,
3008 .help = "Like mmap, but use huge pages",
3012 { .ival = "cudamalloc",
3013 .oval = MEM_CUDA_MALLOC,
3014 .help = "Allocate GPU device memory for GPUDirect RDMA",
3020 .name = "iomem_align",
3021 .alias = "mem_align",
3022 .lname = "I/O memory alignment",
3023 .type = FIO_OPT_INT,
3024 .off1 = offsetof(struct thread_options, mem_align),
3026 .help = "IO memory buffer offset alignment",
3030 .category = FIO_OPT_C_IO,
3031 .group = FIO_OPT_G_INVALID,
3036 .type = FIO_OPT_STR,
3037 .off1 = offsetof(struct thread_options, verify),
3038 .help = "Verify data written",
3040 .category = FIO_OPT_C_IO,
3041 .group = FIO_OPT_G_VERIFY,
3044 .oval = VERIFY_NONE,
3045 .help = "Don't do IO verification",
3049 .help = "Use md5 checksums for verification",
3052 .oval = VERIFY_CRC64,
3053 .help = "Use crc64 checksums for verification",
3056 .oval = VERIFY_CRC32,
3057 .help = "Use crc32 checksums for verification",
3059 { .ival = "crc32c-intel",
3060 .oval = VERIFY_CRC32C,
3061 .help = "Use crc32c checksums for verification (hw assisted, if available)",
3064 .oval = VERIFY_CRC32C,
3065 .help = "Use crc32c checksums for verification (hw assisted, if available)",
3068 .oval = VERIFY_CRC16,
3069 .help = "Use crc16 checksums for verification",
3072 .oval = VERIFY_CRC7,
3073 .help = "Use crc7 checksums for verification",
3076 .oval = VERIFY_SHA1,
3077 .help = "Use sha1 checksums for verification",
3080 .oval = VERIFY_SHA256,
3081 .help = "Use sha256 checksums for verification",
3084 .oval = VERIFY_SHA512,
3085 .help = "Use sha512 checksums for verification",
3087 { .ival = "sha3-224",
3088 .oval = VERIFY_SHA3_224,
3089 .help = "Use sha3-224 checksums for verification",
3091 { .ival = "sha3-256",
3092 .oval = VERIFY_SHA3_256,
3093 .help = "Use sha3-256 checksums for verification",
3095 { .ival = "sha3-384",
3096 .oval = VERIFY_SHA3_384,
3097 .help = "Use sha3-384 checksums for verification",
3099 { .ival = "sha3-512",
3100 .oval = VERIFY_SHA3_512,
3101 .help = "Use sha3-512 checksums for verification",
3104 .oval = VERIFY_XXHASH,
3105 .help = "Use xxhash checksums for verification",
3107 /* Meta information was included into verify_header,
3108 * 'meta' verification is implied by default. */
3110 .oval = VERIFY_HDR_ONLY,
3111 .help = "Use io information for verification. "
3112 "Now is implied by default, thus option is obsolete, "
3115 { .ival = "pattern",
3116 .oval = VERIFY_PATTERN_NO_HDR,
3117 .help = "Verify strict pattern",
3121 .oval = VERIFY_NULL,
3122 .help = "Pretend to verify",
3127 .name = "do_verify",
3128 .lname = "Perform verify step",
3129 .type = FIO_OPT_BOOL,
3130 .off1 = offsetof(struct thread_options, do_verify),
3131 .help = "Run verification stage after write",
3135 .category = FIO_OPT_C_IO,
3136 .group = FIO_OPT_G_VERIFY,
3139 .name = "verifysort",
3140 .lname = "Verify sort",
3141 .type = FIO_OPT_SOFT_DEPRECATED,
3142 .category = FIO_OPT_C_IO,
3143 .group = FIO_OPT_G_VERIFY,
3146 .name = "verifysort_nr",
3147 .lname = "Verify Sort Nr",
3148 .type = FIO_OPT_SOFT_DEPRECATED,
3149 .category = FIO_OPT_C_IO,
3150 .group = FIO_OPT_G_VERIFY,
3153 .name = "verify_interval",
3154 .lname = "Verify interval",
3155 .type = FIO_OPT_INT,
3156 .off1 = offsetof(struct thread_options, verify_interval),
3157 .minval = 2 * sizeof(struct verify_header),
3158 .help = "Store verify buffer header every N bytes",
3161 .interval = 2 * sizeof(struct verify_header),
3162 .category = FIO_OPT_C_IO,
3163 .group = FIO_OPT_G_VERIFY,
3166 .name = "verify_offset",
3167 .lname = "Verify offset",
3168 .type = FIO_OPT_INT,
3169 .help = "Offset verify header location by N bytes",
3170 .off1 = offsetof(struct thread_options, verify_offset),
3171 .minval = sizeof(struct verify_header),
3174 .category = FIO_OPT_C_IO,
3175 .group = FIO_OPT_G_VERIFY,
3178 .name = "verify_pattern",
3179 .lname = "Verify pattern",
3180 .type = FIO_OPT_STR,
3181 .cb = str_verify_pattern_cb,
3182 .off1 = offsetof(struct thread_options, verify_pattern),
3183 .help = "Fill pattern for IO buffers",
3186 .category = FIO_OPT_C_IO,
3187 .group = FIO_OPT_G_VERIFY,
3190 .name = "verify_fatal",
3191 .lname = "Verify fatal",
3192 .type = FIO_OPT_BOOL,
3193 .off1 = offsetof(struct thread_options, verify_fatal),
3195 .help = "Exit on a single verify failure, don't continue",
3198 .category = FIO_OPT_C_IO,
3199 .group = FIO_OPT_G_VERIFY,
3202 .name = "verify_dump",
3203 .lname = "Verify dump",
3204 .type = FIO_OPT_BOOL,
3205 .off1 = offsetof(struct thread_options, verify_dump),
3207 .help = "Dump contents of good and bad blocks on failure",
3210 .category = FIO_OPT_C_IO,
3211 .group = FIO_OPT_G_VERIFY,
3214 .name = "verify_async",
3215 .lname = "Verify asynchronously",
3216 .type = FIO_OPT_INT,
3217 .off1 = offsetof(struct thread_options, verify_async),
3219 .help = "Number of async verifier threads to use",
3222 .category = FIO_OPT_C_IO,
3223 .group = FIO_OPT_G_VERIFY,
3226 .name = "verify_backlog",
3227 .lname = "Verify backlog",
3228 .type = FIO_OPT_STR_VAL,
3229 .off1 = offsetof(struct thread_options, verify_backlog),
3230 .help = "Verify after this number of blocks are written",
3233 .category = FIO_OPT_C_IO,
3234 .group = FIO_OPT_G_VERIFY,
3237 .name = "verify_backlog_batch",
3238 .lname = "Verify backlog batch",
3239 .type = FIO_OPT_INT,
3240 .off1 = offsetof(struct thread_options, verify_batch),
3241 .help = "Verify this number of IO blocks",
3244 .category = FIO_OPT_C_IO,
3245 .group = FIO_OPT_G_VERIFY,
3247 #ifdef FIO_HAVE_CPU_AFFINITY
3249 .name = "verify_async_cpus",
3250 .lname = "Async verify CPUs",
3251 .type = FIO_OPT_STR,
3252 .cb = str_verify_cpus_allowed_cb,
3253 .off1 = offsetof(struct thread_options, verify_cpumask),
3254 .help = "Set CPUs allowed for async verify threads",
3255 .parent = "verify_async",
3257 .category = FIO_OPT_C_IO,
3258 .group = FIO_OPT_G_VERIFY,
3262 .name = "verify_async_cpus",
3263 .lname = "Async verify CPUs",
3264 .type = FIO_OPT_UNSUPPORTED,
3265 .help = "Your platform does not support CPU affinities",
3269 .name = "experimental_verify",
3270 .lname = "Experimental Verify",
3271 .off1 = offsetof(struct thread_options, experimental_verify),
3272 .type = FIO_OPT_BOOL,
3273 .help = "Enable experimental verification",
3275 .category = FIO_OPT_C_IO,
3276 .group = FIO_OPT_G_VERIFY,
3279 .name = "verify_state_load",
3280 .lname = "Load verify state",
3281 .off1 = offsetof(struct thread_options, verify_state),
3282 .type = FIO_OPT_BOOL,
3283 .help = "Load verify termination state",
3285 .category = FIO_OPT_C_IO,
3286 .group = FIO_OPT_G_VERIFY,
3289 .name = "verify_state_save",
3290 .lname = "Save verify state",
3291 .off1 = offsetof(struct thread_options, verify_state_save),
3292 .type = FIO_OPT_BOOL,
3294 .help = "Save verify state on termination",
3296 .category = FIO_OPT_C_IO,
3297 .group = FIO_OPT_G_VERIFY,
3299 #ifdef FIO_HAVE_TRIM
3301 .name = "trim_percentage",
3302 .lname = "Trim percentage",
3303 .type = FIO_OPT_INT,
3304 .off1 = offsetof(struct thread_options, trim_percentage),
3307 .help = "Number of verify blocks to trim (i.e., discard)",
3312 .category = FIO_OPT_C_IO,
3313 .group = FIO_OPT_G_TRIM,
3316 .name = "trim_verify_zero",
3317 .lname = "Verify trim zero",
3318 .type = FIO_OPT_BOOL,
3319 .help = "Verify that trimmed (i.e., discarded) blocks are returned as zeroes",
3320 .off1 = offsetof(struct thread_options, trim_zero),
3321 .parent = "trim_percentage",
3324 .category = FIO_OPT_C_IO,
3325 .group = FIO_OPT_G_TRIM,
3328 .name = "trim_backlog",
3329 .lname = "Trim backlog",
3330 .type = FIO_OPT_STR_VAL,
3331 .off1 = offsetof(struct thread_options, trim_backlog),
3332 .help = "Trim after this number of blocks are written",
3333 .parent = "trim_percentage",
3336 .category = FIO_OPT_C_IO,
3337 .group = FIO_OPT_G_TRIM,
3340 .name = "trim_backlog_batch",
3341 .lname = "Trim backlog batch",
3342 .type = FIO_OPT_INT,
3343 .off1 = offsetof(struct thread_options, trim_batch),
3344 .help = "Trim this number of IO blocks",
3345 .parent = "trim_percentage",
3348 .category = FIO_OPT_C_IO,
3349 .group = FIO_OPT_G_TRIM,
3353 .name = "trim_percentage",
3354 .lname = "Trim percentage",
3355 .type = FIO_OPT_UNSUPPORTED,
3356 .help = "Fio does not support TRIM on your platform",
3359 .name = "trim_verify_zero",
3360 .lname = "Verify trim zero",
3361 .type = FIO_OPT_UNSUPPORTED,
3362 .help = "Fio does not support TRIM on your platform",
3365 .name = "trim_backlog",
3366 .lname = "Trim backlog",
3367 .type = FIO_OPT_UNSUPPORTED,
3368 .help = "Fio does not support TRIM on your platform",
3371 .name = "trim_backlog_batch",
3372 .lname = "Trim backlog batch",
3373 .type = FIO_OPT_UNSUPPORTED,
3374 .help = "Fio does not support TRIM on your platform",
3378 .name = "write_iolog",
3379 .lname = "Write I/O log",
3380 .type = FIO_OPT_STR_STORE,
3381 .off1 = offsetof(struct thread_options, write_iolog_file),
3382 .help = "Store IO pattern to file",
3383 .category = FIO_OPT_C_IO,
3384 .group = FIO_OPT_G_IOLOG,
3387 .name = "read_iolog",
3388 .lname = "Read I/O log",
3389 .type = FIO_OPT_STR_STORE,
3390 .off1 = offsetof(struct thread_options, read_iolog_file),
3391 .help = "Playback IO pattern from file",
3392 .category = FIO_OPT_C_IO,
3393 .group = FIO_OPT_G_IOLOG,
3396 .name = "read_iolog_chunked",
3397 .lname = "Read I/O log in parts",
3398 .type = FIO_OPT_BOOL,
3399 .off1 = offsetof(struct thread_options, read_iolog_chunked),
3401 .parent = "read_iolog",
3402 .help = "Parse IO pattern in chunks",
3403 .category = FIO_OPT_C_IO,
3404 .group = FIO_OPT_G_IOLOG,
3407 .name = "replay_no_stall",
3408 .lname = "Don't stall on replay",
3409 .type = FIO_OPT_BOOL,
3410 .off1 = offsetof(struct thread_options, no_stall),
3412 .parent = "read_iolog",
3414 .help = "Playback IO pattern file as fast as possible without stalls",
3415 .category = FIO_OPT_C_IO,
3416 .group = FIO_OPT_G_IOLOG,
3419 .name = "replay_redirect",
3420 .lname = "Redirect device for replay",
3421 .type = FIO_OPT_STR_STORE,
3422 .off1 = offsetof(struct thread_options, replay_redirect),
3423 .parent = "read_iolog",
3425 .help = "Replay all I/O onto this device, regardless of trace device",
3426 .category = FIO_OPT_C_IO,
3427 .group = FIO_OPT_G_IOLOG,
3430 .name = "replay_scale",
3431 .lname = "Replace offset scale factor",
3432 .type = FIO_OPT_INT,
3433 .off1 = offsetof(struct thread_options, replay_scale),
3434 .parent = "read_iolog",
3436 .help = "Align offsets to this blocksize",
3437 .category = FIO_OPT_C_IO,
3438 .group = FIO_OPT_G_IOLOG,
3441 .name = "replay_align",
3442 .lname = "Replace alignment",
3443 .type = FIO_OPT_INT,
3444 .off1 = offsetof(struct thread_options, replay_align),
3445 .parent = "read_iolog",
3446 .help = "Scale offset down by this factor",
3447 .category = FIO_OPT_C_IO,
3448 .group = FIO_OPT_G_IOLOG,
3452 .name = "replay_time_scale",
3453 .lname = "Replay Time Scale",
3454 .type = FIO_OPT_INT,
3455 .off1 = offsetof(struct thread_options, replay_time_scale),
3458 .parent = "read_iolog",
3460 .help = "Scale time for replay events",
3461 .category = FIO_OPT_C_IO,
3462 .group = FIO_OPT_G_IOLOG,
3465 .name = "replay_skip",
3466 .lname = "Replay Skip",
3467 .type = FIO_OPT_STR,
3468 .cb = str_replay_skip_cb,
3469 .off1 = offsetof(struct thread_options, replay_skip),
3470 .parent = "read_iolog",
3471 .help = "Skip certain IO types (read,write,trim,flush)",
3472 .category = FIO_OPT_C_IO,
3473 .group = FIO_OPT_G_IOLOG,
3476 .name = "merge_blktrace_file",
3477 .lname = "Merged blktrace output filename",
3478 .type = FIO_OPT_STR_STORE,
3479 .off1 = offsetof(struct thread_options, merge_blktrace_file),
3480 .help = "Merged blktrace output filename",
3481 .category = FIO_OPT_C_IO,
3482 .group = FIO_OPT_G_IOLOG,
3485 .name = "merge_blktrace_scalars",
3486 .lname = "Percentage to scale each trace",
3487 .type = FIO_OPT_FLOAT_LIST,
3488 .off1 = offsetof(struct thread_options, merge_blktrace_scalars),
3489 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3490 .help = "Percentage to scale each trace",
3491 .category = FIO_OPT_C_IO,
3492 .group = FIO_OPT_G_IOLOG,
3495 .name = "merge_blktrace_iters",
3496 .lname = "Number of iterations to run per trace",
3497 .type = FIO_OPT_FLOAT_LIST,
3498 .off1 = offsetof(struct thread_options, merge_blktrace_iters),
3499 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3500 .help = "Number of iterations to run per trace",
3501 .category = FIO_OPT_C_IO,
3502 .group = FIO_OPT_G_IOLOG,
3505 .name = "exec_prerun",
3506 .lname = "Pre-execute runnable",
3507 .type = FIO_OPT_STR_STORE,
3508 .off1 = offsetof(struct thread_options, exec_prerun),
3509 .help = "Execute this file prior to running job",
3510 .category = FIO_OPT_C_GENERAL,
3511 .group = FIO_OPT_G_INVALID,
3514 .name = "exec_postrun",
3515 .lname = "Post-execute runnable",
3516 .type = FIO_OPT_STR_STORE,
3517 .off1 = offsetof(struct thread_options, exec_postrun),
3518 .help = "Execute this file after running job",
3519 .category = FIO_OPT_C_GENERAL,
3520 .group = FIO_OPT_G_INVALID,
3522 #ifdef FIO_HAVE_IOSCHED_SWITCH
3524 .name = "ioscheduler",
3525 .lname = "I/O scheduler",
3526 .type = FIO_OPT_STR_STORE,
3527 .off1 = offsetof(struct thread_options, ioscheduler),
3528 .help = "Use this IO scheduler on the backing device",
3529 .category = FIO_OPT_C_FILE,
3530 .group = FIO_OPT_G_INVALID,
3534 .name = "ioscheduler",
3535 .lname = "I/O scheduler",
3536 .type = FIO_OPT_UNSUPPORTED,
3537 .help = "Your platform does not support IO scheduler switching",
3542 .lname = "Zone mode",
3543 .help = "Mode for the zonesize, zonerange and zoneskip parameters",
3544 .type = FIO_OPT_STR,
3545 .off1 = offsetof(struct thread_options, zone_mode),
3547 .category = FIO_OPT_C_IO,
3548 .group = FIO_OPT_G_ZONE,
3551 .oval = ZONE_MODE_NONE,
3552 .help = "no zoning",
3554 { .ival = "strided",
3555 .oval = ZONE_MODE_STRIDED,
3556 .help = "strided mode - random I/O is restricted to a single zone",
3559 .oval = ZONE_MODE_ZBD,
3560 .help = "zoned block device mode - random I/O selects one of multiple zones randomly",
3566 .lname = "Zone size",
3567 .type = FIO_OPT_STR_VAL,
3568 .off1 = offsetof(struct thread_options, zone_size),
3569 .help = "Amount of data to read per zone",
3571 .interval = 1024 * 1024,
3572 .category = FIO_OPT_C_IO,
3573 .group = FIO_OPT_G_ZONE,
3576 .name = "zonecapacity",
3577 .lname = "Zone capacity",
3578 .type = FIO_OPT_STR_VAL,
3579 .off1 = offsetof(struct thread_options, zone_capacity),
3580 .help = "Capacity per zone",
3582 .interval = 1024 * 1024,
3583 .category = FIO_OPT_C_IO,
3584 .group = FIO_OPT_G_ZONE,
3587 .name = "zonerange",
3588 .lname = "Zone range",
3589 .type = FIO_OPT_STR_VAL,
3590 .off1 = offsetof(struct thread_options, zone_range),
3591 .help = "Give size of an IO zone",
3593 .interval = 1024 * 1024,
3594 .category = FIO_OPT_C_IO,
3595 .group = FIO_OPT_G_ZONE,
3599 .lname = "Zone skip",
3600 .type = FIO_OPT_STR_VAL_ZONE,
3601 .cb = str_zoneskip_cb,
3602 .off1 = offsetof(struct thread_options, zone_skip),
3603 .help = "Space between IO zones",
3605 .category = FIO_OPT_C_IO,
3606 .group = FIO_OPT_G_ZONE,
3609 .name = "read_beyond_wp",
3610 .lname = "Allow reads beyond the zone write pointer",
3611 .type = FIO_OPT_BOOL,
3612 .off1 = offsetof(struct thread_options, read_beyond_wp),
3613 .help = "Allow reads beyond the zone write pointer",
3615 .category = FIO_OPT_C_IO,
3616 .group = FIO_OPT_G_INVALID,
3619 .name = "max_open_zones",
3620 .lname = "Per device/file maximum number of open zones",
3621 .type = FIO_OPT_INT,
3622 .off1 = offsetof(struct thread_options, max_open_zones),
3623 .maxval = ZBD_MAX_OPEN_ZONES,
3624 .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd",
3626 .category = FIO_OPT_C_IO,
3627 .group = FIO_OPT_G_INVALID,
3630 .name = "job_max_open_zones",
3631 .lname = "Job maximum number of open zones",
3632 .type = FIO_OPT_INT,
3633 .off1 = offsetof(struct thread_options, job_max_open_zones),
3634 .maxval = ZBD_MAX_OPEN_ZONES,
3635 .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd by one thread/process",
3637 .category = FIO_OPT_C_IO,
3638 .group = FIO_OPT_G_INVALID,
3641 .name = "ignore_zone_limits",
3642 .lname = "Ignore zone resource limits",
3643 .type = FIO_OPT_BOOL,
3644 .off1 = offsetof(struct thread_options, ignore_zone_limits),
3646 .help = "Ignore the zone resource limits (max open/active zones) reported by the device",
3647 .category = FIO_OPT_C_IO,
3648 .group = FIO_OPT_G_INVALID,
3651 .name = "zone_reset_threshold",
3652 .lname = "Zone reset threshold",
3653 .help = "Zoned block device reset threshold",
3654 .type = FIO_OPT_FLOAT_LIST,
3656 .off1 = offsetof(struct thread_options, zrt),
3659 .category = FIO_OPT_C_IO,
3660 .group = FIO_OPT_G_ZONE,
3663 .name = "zone_reset_frequency",
3664 .lname = "Zone reset frequency",
3665 .help = "Zoned block device zone reset frequency in HZ",
3666 .type = FIO_OPT_FLOAT_LIST,
3668 .off1 = offsetof(struct thread_options, zrf),
3671 .category = FIO_OPT_C_IO,
3672 .group = FIO_OPT_G_ZONE,
3676 .lname = "Flexible data placement",
3677 .type = FIO_OPT_BOOL,
3678 .off1 = offsetof(struct thread_options, fdp),
3679 .help = "Use Data placement directive (FDP)",
3681 .category = FIO_OPT_C_IO,
3682 .group = FIO_OPT_G_INVALID,
3686 .lname = "FDP Placement ID indicies",
3687 .type = FIO_OPT_STR,
3688 .cb = str_fdp_pli_cb,
3689 .off1 = offsetof(struct thread_options, fdp_plis),
3690 .help = "Sets which placement ids to use (defaults to all)",
3692 .category = FIO_OPT_C_IO,
3693 .group = FIO_OPT_G_INVALID,
3697 .lname = "Lock memory",
3698 .type = FIO_OPT_STR_VAL,
3699 .off1 = offsetof(struct thread_options, lockmem),
3700 .help = "Lock down this amount of memory (per worker)",
3702 .interval = 1024 * 1024,
3703 .category = FIO_OPT_C_GENERAL,
3704 .group = FIO_OPT_G_INVALID,
3707 .name = "rwmixread",
3708 .lname = "Read/write mix read",
3709 .type = FIO_OPT_INT,
3710 .cb = str_rwmix_read_cb,
3711 .off1 = offsetof(struct thread_options, rwmix[DDIR_READ]),
3713 .help = "Percentage of mixed workload that is reads",
3716 .inverse = "rwmixwrite",
3717 .category = FIO_OPT_C_IO,
3718 .group = FIO_OPT_G_RWMIX,
3721 .name = "rwmixwrite",
3722 .lname = "Read/write mix write",
3723 .type = FIO_OPT_INT,
3724 .cb = str_rwmix_write_cb,
3725 .off1 = offsetof(struct thread_options, rwmix[DDIR_WRITE]),
3727 .help = "Percentage of mixed workload that is writes",
3730 .inverse = "rwmixread",
3731 .category = FIO_OPT_C_IO,
3732 .group = FIO_OPT_G_RWMIX,
3735 .name = "rwmixcycle",
3736 .lname = "Read/write mix cycle",
3737 .type = FIO_OPT_DEPRECATED,
3738 .category = FIO_OPT_C_IO,
3739 .group = FIO_OPT_G_RWMIX,
3744 .type = FIO_OPT_INT,
3745 .off1 = offsetof(struct thread_options, nice),
3746 .help = "Set job CPU nice value",
3751 .category = FIO_OPT_C_GENERAL,
3752 .group = FIO_OPT_G_CRED,
3754 #ifdef FIO_HAVE_IOPRIO
3757 .lname = "I/O nice priority",
3758 .type = FIO_OPT_INT,
3759 .off1 = offsetof(struct thread_options, ioprio),
3760 .help = "Set job IO priority value",
3761 .minval = IOPRIO_MIN_PRIO,
3762 .maxval = IOPRIO_MAX_PRIO,
3764 .category = FIO_OPT_C_GENERAL,
3765 .group = FIO_OPT_G_CRED,
3770 .lname = "I/O nice priority",
3771 .type = FIO_OPT_UNSUPPORTED,
3772 .help = "Your platform does not support IO priorities",
3775 #ifdef FIO_HAVE_IOPRIO_CLASS
3776 #ifndef FIO_HAVE_IOPRIO
3777 #error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
3780 .name = "prioclass",
3781 .lname = "I/O nice priority class",
3782 .type = FIO_OPT_INT,
3783 .off1 = offsetof(struct thread_options, ioprio_class),
3784 .help = "Set job IO priority class",
3785 .minval = IOPRIO_MIN_PRIO_CLASS,
3786 .maxval = IOPRIO_MAX_PRIO_CLASS,
3788 .category = FIO_OPT_C_GENERAL,
3789 .group = FIO_OPT_G_CRED,
3793 .name = "prioclass",
3794 .lname = "I/O nice priority class",
3795 .type = FIO_OPT_UNSUPPORTED,
3796 .help = "Your platform does not support IO priority classes",
3800 .name = "thinktime",
3801 .lname = "Thinktime",
3802 .type = FIO_OPT_INT,
3803 .off1 = offsetof(struct thread_options, thinktime),
3804 .help = "Idle time between IO buffers (usec)",
3807 .category = FIO_OPT_C_IO,
3808 .group = FIO_OPT_G_THINKTIME,
3811 .name = "thinktime_spin",
3812 .lname = "Thinktime spin",
3813 .type = FIO_OPT_INT,
3814 .off1 = offsetof(struct thread_options, thinktime_spin),
3815 .help = "Start think time by spinning this amount (usec)",
3818 .parent = "thinktime",
3820 .category = FIO_OPT_C_IO,
3821 .group = FIO_OPT_G_THINKTIME,
3824 .name = "thinktime_blocks",
3825 .lname = "Thinktime blocks",
3826 .type = FIO_OPT_INT,
3827 .off1 = offsetof(struct thread_options, thinktime_blocks),
3828 .help = "IO buffer period between 'thinktime'",
3830 .parent = "thinktime",
3832 .category = FIO_OPT_C_IO,
3833 .group = FIO_OPT_G_THINKTIME,
3836 .name = "thinktime_blocks_type",
3837 .lname = "Thinktime blocks type",
3838 .type = FIO_OPT_STR,
3839 .off1 = offsetof(struct thread_options, thinktime_blocks_type),
3840 .help = "How thinktime_blocks takes effect",
3842 .category = FIO_OPT_C_IO,
3843 .group = FIO_OPT_G_THINKTIME,
3845 { .ival = "complete",
3846 .oval = THINKTIME_BLOCKS_TYPE_COMPLETE,
3847 .help = "thinktime_blocks takes effect at the completion side",
3851 .oval = THINKTIME_BLOCKS_TYPE_ISSUE,
3852 .help = "thinktime_blocks takes effect at the issue side",
3855 .parent = "thinktime",
3858 .name = "thinktime_iotime",
3859 .lname = "Thinktime interval",
3860 .type = FIO_OPT_INT,
3861 .off1 = offsetof(struct thread_options, thinktime_iotime),
3862 .help = "IO time interval between 'thinktime'",
3864 .parent = "thinktime",
3868 .category = FIO_OPT_C_IO,
3869 .group = FIO_OPT_G_THINKTIME,
3873 .lname = "I/O rate",
3874 .type = FIO_OPT_ULL,
3875 .off1 = offsetof(struct thread_options, rate[DDIR_READ]),
3876 .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]),
3877 .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]),
3878 .help = "Set bandwidth rate",
3879 .category = FIO_OPT_C_IO,
3880 .group = FIO_OPT_G_RATE,
3885 .lname = "I/O min rate",
3886 .type = FIO_OPT_ULL,
3887 .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]),
3888 .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]),
3889 .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]),
3890 .help = "Job must meet this rate or it will be shutdown",
3893 .category = FIO_OPT_C_IO,
3894 .group = FIO_OPT_G_RATE,
3897 .name = "rate_iops",
3898 .lname = "I/O rate IOPS",
3899 .type = FIO_OPT_INT,
3900 .off1 = offsetof(struct thread_options, rate_iops[DDIR_READ]),
3901 .off2 = offsetof(struct thread_options, rate_iops[DDIR_WRITE]),
3902 .off3 = offsetof(struct thread_options, rate_iops[DDIR_TRIM]),
3903 .help = "Limit IO used to this number of IO operations/sec",
3905 .category = FIO_OPT_C_IO,
3906 .group = FIO_OPT_G_RATE,
3909 .name = "rate_iops_min",
3910 .lname = "I/O min rate IOPS",
3911 .type = FIO_OPT_INT,
3912 .off1 = offsetof(struct thread_options, rate_iops_min[DDIR_READ]),
3913 .off2 = offsetof(struct thread_options, rate_iops_min[DDIR_WRITE]),
3914 .off3 = offsetof(struct thread_options, rate_iops_min[DDIR_TRIM]),
3915 .help = "Job must meet this rate or it will be shut down",
3916 .parent = "rate_iops",
3918 .category = FIO_OPT_C_IO,
3919 .group = FIO_OPT_G_RATE,
3922 .name = "rate_process",
3923 .lname = "Rate Process",
3924 .type = FIO_OPT_STR,
3925 .off1 = offsetof(struct thread_options, rate_process),
3926 .help = "What process controls how rated IO is managed",
3928 .category = FIO_OPT_C_IO,
3929 .group = FIO_OPT_G_RATE,
3932 .oval = RATE_PROCESS_LINEAR,
3933 .help = "Linear rate of IO",
3937 .oval = RATE_PROCESS_POISSON,
3938 .help = "Rate follows Poisson process",
3944 .name = "rate_cycle",
3945 .alias = "ratecycle",
3946 .lname = "I/O rate cycle",
3947 .type = FIO_OPT_INT,
3948 .off1 = offsetof(struct thread_options, ratecycle),
3949 .help = "Window average for rate limits (msec)",
3953 .category = FIO_OPT_C_IO,
3954 .group = FIO_OPT_G_RATE,
3957 .name = "rate_ignore_thinktime",
3958 .lname = "Rate ignore thinktime",
3959 .type = FIO_OPT_BOOL,
3960 .off1 = offsetof(struct thread_options, rate_ign_think),
3961 .help = "Rated IO ignores thinktime settings",
3963 .category = FIO_OPT_C_IO,
3964 .group = FIO_OPT_G_RATE,
3967 .name = "max_latency",
3968 .lname = "Max Latency (usec)",
3969 .type = FIO_OPT_ULL,
3970 .off1 = offsetof(struct thread_options, max_latency[DDIR_READ]),
3971 .off2 = offsetof(struct thread_options, max_latency[DDIR_WRITE]),
3972 .off3 = offsetof(struct thread_options, max_latency[DDIR_TRIM]),
3973 .help = "Maximum tolerated IO latency (usec)",
3975 .category = FIO_OPT_C_IO,
3976 .group = FIO_OPT_G_LATPROF,
3979 .name = "latency_target",
3980 .lname = "Latency Target (usec)",
3981 .type = FIO_OPT_STR_VAL_TIME,
3982 .off1 = offsetof(struct thread_options, latency_target),
3983 .help = "Ramp to max queue depth supporting this latency",
3985 .category = FIO_OPT_C_IO,
3986 .group = FIO_OPT_G_LATPROF,
3989 .name = "latency_window",
3990 .lname = "Latency Window (usec)",
3991 .type = FIO_OPT_STR_VAL_TIME,
3992 .off1 = offsetof(struct thread_options, latency_window),
3993 .help = "Time to sustain latency_target",
3995 .category = FIO_OPT_C_IO,
3996 .group = FIO_OPT_G_LATPROF,
3999 .name = "latency_percentile",
4000 .lname = "Latency Percentile",
4001 .type = FIO_OPT_FLOAT_LIST,
4002 .off1 = offsetof(struct thread_options, latency_percentile),
4003 .help = "Percentile of IOs must be below latency_target",
4008 .category = FIO_OPT_C_IO,
4009 .group = FIO_OPT_G_LATPROF,
4012 .name = "latency_run",
4013 .lname = "Latency Run",
4014 .type = FIO_OPT_BOOL,
4015 .off1 = offsetof(struct thread_options, latency_run),
4016 .help = "Keep adjusting queue depth to match latency_target",
4018 .category = FIO_OPT_C_IO,
4019 .group = FIO_OPT_G_LATPROF,
4022 .name = "invalidate",
4023 .lname = "Cache invalidate",
4024 .type = FIO_OPT_BOOL,
4025 .off1 = offsetof(struct thread_options, invalidate_cache),
4026 .help = "Invalidate buffer/page cache prior to running job",
4028 .category = FIO_OPT_C_IO,
4029 .group = FIO_OPT_G_IO_TYPE,
4033 .lname = "Synchronous I/O",
4034 .type = FIO_OPT_STR,
4035 .off1 = offsetof(struct thread_options, sync_io),
4036 .help = "Use synchronous write IO",
4039 .category = FIO_OPT_C_IO,
4040 .group = FIO_OPT_G_IO_TYPE,
4061 #ifdef FIO_HAVE_WRITE_HINT
4063 .name = "write_hint",
4064 .lname = "Write hint",
4065 .type = FIO_OPT_STR,
4066 .off1 = offsetof(struct thread_options, write_hint),
4067 .help = "Set expected write life time",
4068 .category = FIO_OPT_C_ENGINE,
4069 .group = FIO_OPT_G_INVALID,
4072 .oval = RWH_WRITE_LIFE_NONE,
4075 .oval = RWH_WRITE_LIFE_SHORT,
4078 .oval = RWH_WRITE_LIFE_MEDIUM,
4081 .oval = RWH_WRITE_LIFE_LONG,
4083 { .ival = "extreme",
4084 .oval = RWH_WRITE_LIFE_EXTREME,
4090 .name = "create_serialize",
4091 .lname = "Create serialize",
4092 .type = FIO_OPT_BOOL,
4093 .off1 = offsetof(struct thread_options, create_serialize),
4094 .help = "Serialize creation of job files",
4096 .category = FIO_OPT_C_FILE,
4097 .group = FIO_OPT_G_INVALID,
4100 .name = "create_fsync",
4101 .lname = "Create fsync",
4102 .type = FIO_OPT_BOOL,
4103 .off1 = offsetof(struct thread_options, create_fsync),
4104 .help = "fsync file after creation",
4106 .category = FIO_OPT_C_FILE,
4107 .group = FIO_OPT_G_INVALID,
4110 .name = "create_on_open",
4111 .lname = "Create on open",
4112 .type = FIO_OPT_BOOL,
4113 .off1 = offsetof(struct thread_options, create_on_open),
4114 .help = "Create files when they are opened for IO",
4116 .category = FIO_OPT_C_FILE,
4117 .group = FIO_OPT_G_INVALID,
4120 .name = "create_only",
4121 .lname = "Create Only",
4122 .type = FIO_OPT_BOOL,
4123 .off1 = offsetof(struct thread_options, create_only),
4124 .help = "Only perform file creation phase",
4125 .category = FIO_OPT_C_FILE,
4129 .name = "allow_file_create",
4130 .lname = "Allow file create",
4131 .type = FIO_OPT_BOOL,
4132 .off1 = offsetof(struct thread_options, allow_create),
4133 .help = "Permit fio to create files, if they don't exist",
4135 .category = FIO_OPT_C_FILE,
4136 .group = FIO_OPT_G_FILENAME,
4139 .name = "allow_mounted_write",
4140 .lname = "Allow mounted write",
4141 .type = FIO_OPT_BOOL,
4142 .off1 = offsetof(struct thread_options, allow_mounted_write),
4143 .help = "Allow writes to a mounted partition",
4145 .category = FIO_OPT_C_FILE,
4146 .group = FIO_OPT_G_FILENAME,
4150 .lname = "Pre-read files",
4151 .type = FIO_OPT_BOOL,
4152 .off1 = offsetof(struct thread_options, pre_read),
4153 .help = "Pre-read files before starting official testing",
4155 .category = FIO_OPT_C_FILE,
4156 .group = FIO_OPT_G_INVALID,
4158 #ifdef FIO_HAVE_CPU_AFFINITY
4161 .lname = "CPU mask",
4162 .type = FIO_OPT_INT,
4163 .cb = str_cpumask_cb,
4164 .off1 = offsetof(struct thread_options, cpumask),
4165 .help = "CPU affinity mask",
4166 .category = FIO_OPT_C_GENERAL,
4167 .group = FIO_OPT_G_CRED,
4170 .name = "cpus_allowed",
4171 .lname = "CPUs allowed",
4172 .type = FIO_OPT_STR,
4173 .cb = str_cpus_allowed_cb,
4174 .off1 = offsetof(struct thread_options, cpumask),
4175 .help = "Set CPUs allowed",
4176 .category = FIO_OPT_C_GENERAL,
4177 .group = FIO_OPT_G_CRED,
4180 .name = "cpus_allowed_policy",
4181 .lname = "CPUs allowed distribution policy",
4182 .type = FIO_OPT_STR,
4183 .off1 = offsetof(struct thread_options, cpus_allowed_policy),
4184 .help = "Distribution policy for cpus_allowed",
4185 .parent = "cpus_allowed",
4189 .oval = FIO_CPUS_SHARED,
4190 .help = "Mask shared between threads",
4193 .oval = FIO_CPUS_SPLIT,
4194 .help = "Mask split between threads",
4197 .category = FIO_OPT_C_GENERAL,
4198 .group = FIO_OPT_G_CRED,
4203 .lname = "CPU mask",
4204 .type = FIO_OPT_UNSUPPORTED,
4205 .help = "Your platform does not support CPU affinities",
4208 .name = "cpus_allowed",
4209 .lname = "CPUs allowed",
4210 .type = FIO_OPT_UNSUPPORTED,
4211 .help = "Your platform does not support CPU affinities",
4214 .name = "cpus_allowed_policy",
4215 .lname = "CPUs allowed distribution policy",
4216 .type = FIO_OPT_UNSUPPORTED,
4217 .help = "Your platform does not support CPU affinities",
4220 #ifdef CONFIG_LIBNUMA
4222 .name = "numa_cpu_nodes",
4223 .lname = "NUMA CPU Nodes",
4224 .type = FIO_OPT_STR,
4225 .cb = str_numa_cpunodes_cb,
4226 .off1 = offsetof(struct thread_options, numa_cpunodes),
4227 .help = "NUMA CPU nodes bind",
4228 .category = FIO_OPT_C_GENERAL,
4229 .group = FIO_OPT_G_INVALID,
4232 .name = "numa_mem_policy",
4233 .lname = "NUMA Memory Policy",
4234 .type = FIO_OPT_STR,
4235 .cb = str_numa_mpol_cb,
4236 .off1 = offsetof(struct thread_options, numa_memnodes),
4237 .help = "NUMA memory policy setup",
4238 .category = FIO_OPT_C_GENERAL,
4239 .group = FIO_OPT_G_INVALID,
4243 .name = "numa_cpu_nodes",
4244 .lname = "NUMA CPU Nodes",
4245 .type = FIO_OPT_UNSUPPORTED,
4246 .help = "Build fio with libnuma-dev(el) to enable this option",
4249 .name = "numa_mem_policy",
4250 .lname = "NUMA Memory Policy",
4251 .type = FIO_OPT_UNSUPPORTED,
4252 .help = "Build fio with libnuma-dev(el) to enable this option",
4257 .name = "gpu_dev_id",
4258 .lname = "GPU device ID",
4259 .type = FIO_OPT_INT,
4260 .off1 = offsetof(struct thread_options, gpu_dev_id),
4261 .help = "Set GPU device ID for GPUDirect RDMA",
4263 .category = FIO_OPT_C_GENERAL,
4264 .group = FIO_OPT_G_INVALID,
4268 .name = "end_fsync",
4269 .lname = "End fsync",
4270 .type = FIO_OPT_BOOL,
4271 .off1 = offsetof(struct thread_options, end_fsync),
4272 .help = "Include fsync at the end of job",
4274 .category = FIO_OPT_C_FILE,
4275 .group = FIO_OPT_G_INVALID,
4278 .name = "fsync_on_close",
4279 .lname = "Fsync on close",
4280 .type = FIO_OPT_BOOL,
4281 .off1 = offsetof(struct thread_options, fsync_on_close),
4282 .help = "fsync files on close",
4284 .category = FIO_OPT_C_FILE,
4285 .group = FIO_OPT_G_INVALID,
4289 .lname = "Unlink file",
4290 .type = FIO_OPT_BOOL,
4291 .off1 = offsetof(struct thread_options, unlink),
4292 .help = "Unlink created files after job has completed",
4294 .category = FIO_OPT_C_FILE,
4295 .group = FIO_OPT_G_INVALID,
4298 .name = "unlink_each_loop",
4299 .lname = "Unlink file after each loop of a job",
4300 .type = FIO_OPT_BOOL,
4301 .off1 = offsetof(struct thread_options, unlink_each_loop),
4302 .help = "Unlink created files after each loop in a job has completed",
4304 .category = FIO_OPT_C_FILE,
4305 .group = FIO_OPT_G_INVALID,
4309 .lname = "Exit-all on terminate",
4310 .type = FIO_OPT_STR_SET,
4311 .cb = str_exitall_cb,
4312 .help = "Terminate all jobs when one exits",
4313 .category = FIO_OPT_C_GENERAL,
4314 .group = FIO_OPT_G_PROCESS,
4317 .name = "exit_what",
4318 .lname = "What jobs to quit on terminate",
4319 .type = FIO_OPT_STR,
4320 .off1 = offsetof(struct thread_options, exit_what),
4321 .help = "Fine-grained control for exitall",
4323 .category = FIO_OPT_C_GENERAL,
4324 .group = FIO_OPT_G_PROCESS,
4327 .oval = TERMINATE_GROUP,
4328 .help = "exit_all=1 default behaviour",
4330 { .ival = "stonewall",
4331 .oval = TERMINATE_STONEWALL,
4332 .help = "quit all currently running jobs; continue with next stonewall",
4335 .oval = TERMINATE_ALL,
4336 .help = "Quit everything",
4341 .name = "exitall_on_error",
4342 .lname = "Exit-all on terminate in error",
4343 .type = FIO_OPT_STR_SET,
4344 .off1 = offsetof(struct thread_options, exitall_error),
4345 .help = "Terminate all jobs when one exits in error",
4346 .category = FIO_OPT_C_GENERAL,
4347 .group = FIO_OPT_G_PROCESS,
4350 .name = "stonewall",
4351 .lname = "Wait for previous",
4352 .alias = "wait_for_previous",
4353 .type = FIO_OPT_STR_SET,
4354 .off1 = offsetof(struct thread_options, stonewall),
4355 .help = "Insert a hard barrier between this job and previous",
4356 .category = FIO_OPT_C_GENERAL,
4357 .group = FIO_OPT_G_PROCESS,
4360 .name = "new_group",
4361 .lname = "New group",
4362 .type = FIO_OPT_STR_SET,
4363 .off1 = offsetof(struct thread_options, new_group),
4364 .help = "Mark the start of a new group (for reporting)",
4365 .category = FIO_OPT_C_GENERAL,
4366 .group = FIO_OPT_G_PROCESS,
4371 .type = FIO_OPT_STR_SET,
4372 .off1 = offsetof(struct thread_options, use_thread),
4373 .help = "Use threads instead of processes",
4374 #ifdef CONFIG_NO_SHM
4378 .category = FIO_OPT_C_GENERAL,
4379 .group = FIO_OPT_G_PROCESS,
4382 .name = "per_job_logs",
4383 .lname = "Per Job Logs",
4384 .type = FIO_OPT_BOOL,
4385 .off1 = offsetof(struct thread_options, per_job_logs),
4386 .help = "Include job number in generated log files or not",
4388 .category = FIO_OPT_C_LOG,
4389 .group = FIO_OPT_G_INVALID,
4392 .name = "write_bw_log",
4393 .lname = "Write bandwidth log",
4394 .type = FIO_OPT_STR,
4395 .off1 = offsetof(struct thread_options, bw_log_file),
4396 .cb = str_write_bw_log_cb,
4397 .help = "Write log of bandwidth during run",
4398 .category = FIO_OPT_C_LOG,
4399 .group = FIO_OPT_G_INVALID,
4402 .name = "write_lat_log",
4403 .lname = "Write latency log",
4404 .type = FIO_OPT_STR,
4405 .off1 = offsetof(struct thread_options, lat_log_file),
4406 .cb = str_write_lat_log_cb,
4407 .help = "Write log of latency during run",
4408 .category = FIO_OPT_C_LOG,
4409 .group = FIO_OPT_G_INVALID,
4412 .name = "write_iops_log",
4413 .lname = "Write IOPS log",
4414 .type = FIO_OPT_STR,
4415 .off1 = offsetof(struct thread_options, iops_log_file),
4416 .cb = str_write_iops_log_cb,
4417 .help = "Write log of IOPS during run",
4418 .category = FIO_OPT_C_LOG,
4419 .group = FIO_OPT_G_INVALID,
4422 .name = "log_entries",
4423 .lname = "Log entries",
4424 .type = FIO_OPT_INT,
4425 .off1 = offsetof(struct thread_options, log_entries),
4426 .help = "Initial number of entries in a job IO log",
4427 .def = __fio_stringify(DEF_LOG_ENTRIES),
4428 .minval = DEF_LOG_ENTRIES,
4429 .maxval = MAX_LOG_ENTRIES,
4430 .category = FIO_OPT_C_LOG,
4431 .group = FIO_OPT_G_INVALID,
4434 .name = "log_avg_msec",
4435 .lname = "Log averaging (msec)",
4436 .type = FIO_OPT_INT,
4437 .off1 = offsetof(struct thread_options, log_avg_msec),
4438 .help = "Average bw/iops/lat logs over this period of time",
4440 .category = FIO_OPT_C_LOG,
4441 .group = FIO_OPT_G_INVALID,
4444 .name = "log_hist_msec",
4445 .lname = "Log histograms (msec)",
4446 .type = FIO_OPT_INT,
4447 .off1 = offsetof(struct thread_options, log_hist_msec),
4448 .help = "Dump completion latency histograms at frequency of this time value",
4450 .category = FIO_OPT_C_LOG,
4451 .group = FIO_OPT_G_INVALID,
4454 .name = "log_hist_coarseness",
4455 .lname = "Histogram logs coarseness",
4456 .type = FIO_OPT_INT,