t/io_uring: Vectored fixed buffer test support for nvme passthrough path
[fio.git] / options.c
CommitLineData
214e1eca
JA
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <ctype.h>
5#include <string.h>
214e1eca 6#include <assert.h>
638689b1 7#include <fcntl.h>
5921e80c 8#include <sys/stat.h>
e13c3b50 9#include <netinet/in.h>
214e1eca
JA
10
11#include "fio.h"
4f5af7b2 12#include "verify.h"
214e1eca 13#include "parse.h"
61b9861d 14#include "lib/pattern.h"
9f988e2e 15#include "options.h"
d220c761 16#include "optgroup.h"
b7694961 17#include "zbd.h"
214e1eca 18
e13c3b50 19char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 };
72a703da 20
a609f12a
JA
21#define cb_data_to_td(data) container_of(data, struct thread_data, o)
22
26f14c31 23static const struct pattern_fmt_desc fmt_desc[] = {
4205998f
JA
24 {
25 .fmt = "%o",
59f94d26 26 .len = FIO_FIELD_SIZE(struct io_u *, offset),
4205998f 27 .paste = paste_blockoff
969b9fbb
BVA
28 },
29 { }
4205998f
JA
30};
31
214e1eca
JA
32/*
33 * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
34 */
35static char *get_opt_postfix(const char *str)
36{
37 char *p = strstr(str, ":");
38
39 if (!p)
40 return NULL;
41
42 p++;
43 strip_blank_front(&p);
44 strip_blank_end(p);
45 return strdup(p);
46}
47
a87c90fd
AK
48static bool split_parse_distr(const char *str, double *val, double *center)
49{
50 char *cp, *p;
51 bool r;
52
53 p = strdup(str);
54 if (!p)
55 return false;
56
57 cp = strstr(p, ":");
58 r = true;
59 if (cp) {
60 *cp = '\0';
61 cp++;
62 r = str_to_float(cp, center, 0);
63 }
64 r = r && str_to_float(p, val, 0);
65 free(p);
66 return r;
67}
68
564ca972
JA
69static int bs_cmp(const void *p1, const void *p2)
70{
71 const struct bssplit *bsp1 = p1;
72 const struct bssplit *bsp2 = p2;
73
a7cd478d 74 return (int) bsp1->perc - (int) bsp2->perc;
564ca972
JA
75}
76
f311f5f3 77int split_parse_ddir(struct thread_options *o, struct split *split,
517c9c72 78 char *str, bool absolute, unsigned int max_splits)
564ca972 79{
59466396
JA
80 unsigned long long perc;
81 unsigned int i;
564ca972 82 long long val;
720e84ad 83 char *fname;
564ca972 84
d2835319 85 split->nr = 0;
564ca972
JA
86
87 i = 0;
564ca972
JA
88 while ((fname = strsep(&str, ":")) != NULL) {
89 char *perc_str;
90
91 if (!strlen(fname))
92 break;
93
564ca972
JA
94 perc_str = strstr(fname, "/");
95 if (perc_str) {
96 *perc_str = '\0';
97 perc_str++;
59466396
JA
98 if (absolute) {
99 if (str_to_decimal(perc_str, &val, 1, o, 0, 0)) {
100 log_err("fio: split conversion failed\n");
101 return 1;
102 }
103 perc = val;
104 } else {
105 perc = atoi(perc_str);
106 if (perc > 100)
107 perc = 100;
108 else if (!perc)
109 perc = -1U;
110 }
111 } else {
112 if (absolute)
113 perc = 0;
114 else
d711cce5 115 perc = -1U;
59466396 116 }
564ca972 117
88038bc7 118 if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
59466396 119 log_err("fio: split conversion failed\n");
564ca972
JA
120 return 1;
121 }
122
d2835319
JA
123 split->val1[i] = val;
124 split->val2[i] = perc;
564ca972 125 i++;
c32e1a09
JA
126 if (i == max_splits) {
127 log_err("fio: hit max of %d split entries\n", i);
d2835319 128 break;
c32e1a09 129 }
564ca972
JA
130 }
131
d2835319
JA
132 split->nr = i;
133 return 0;
134}
135
f311f5f3
DLM
136static int bssplit_ddir(struct thread_options *o, void *eo,
137 enum fio_ddir ddir, char *str, bool data)
d2835319
JA
138{
139 unsigned int i, perc, perc_missing;
5fff9543 140 unsigned long long max_bs, min_bs;
d2835319
JA
141 struct split split;
142
143 memset(&split, 0, sizeof(split));
144
517c9c72 145 if (split_parse_ddir(o, &split, str, data, BSSPLIT_MAX))
d2835319
JA
146 return 1;
147 if (!split.nr)
148 return 0;
149
150 max_bs = 0;
151 min_bs = -1;
152 o->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
153 o->bssplit_nr[ddir] = split.nr;
154 for (i = 0; i < split.nr; i++) {
155 if (split.val1[i] > max_bs)
156 max_bs = split.val1[i];
157 if (split.val1[i] < min_bs)
158 min_bs = split.val1[i];
159
160 o->bssplit[ddir][i].bs = split.val1[i];
161 o->bssplit[ddir][i].perc =split.val2[i];
162 }
564ca972
JA
163
164 /*
165 * Now check if the percentages add up, and how much is missing
166 */
167 perc = perc_missing = 0;
83ea422a 168 for (i = 0; i < o->bssplit_nr[ddir]; i++) {
d2835319 169 struct bssplit *bsp = &o->bssplit[ddir][i];
564ca972 170
d711cce5 171 if (bsp->perc == -1U)
564ca972
JA
172 perc_missing++;
173 else
174 perc += bsp->perc;
175 }
176
40bafa33 177 if (perc > 100 && perc_missing > 1) {
564ca972 178 log_err("fio: bssplit percentages add to more than 100%%\n");
d2835319
JA
179 free(o->bssplit[ddir]);
180 o->bssplit[ddir] = NULL;
564ca972
JA
181 return 1;
182 }
d711cce5 183
564ca972
JA
184 /*
185 * If values didn't have a percentage set, divide the remains between
186 * them.
187 */
188 if (perc_missing) {
d711cce5 189 if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
40bafa33 190 perc = 100;
83ea422a 191 for (i = 0; i < o->bssplit_nr[ddir]; i++) {
d2835319 192 struct bssplit *bsp = &o->bssplit[ddir][i];
564ca972 193
d711cce5 194 if (bsp->perc == -1U)
564ca972
JA
195 bsp->perc = (100 - perc) / perc_missing;
196 }
197 }
198
83ea422a
JA
199 o->min_bs[ddir] = min_bs;
200 o->max_bs[ddir] = max_bs;
564ca972
JA
201
202 /*
203 * now sort based on percentages, for ease of lookup
204 */
d2835319 205 qsort(o->bssplit[ddir], o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
720e84ad 206 return 0;
720e84ad
JA
207}
208
f311f5f3
DLM
209int str_split_parse(struct thread_data *td, char *str,
210 split_parse_fn *fn, void *eo, bool data)
720e84ad 211{
764593c0 212 char *odir, *ddir;
720e84ad
JA
213 int ret = 0;
214
720e84ad
JA
215 odir = strchr(str, ',');
216 if (odir) {
6eaf09d6
SL
217 ddir = strchr(odir + 1, ',');
218 if (ddir) {
f311f5f3 219 ret = fn(&td->o, eo, DDIR_TRIM, ddir + 1, data);
6eaf09d6
SL
220 if (!ret)
221 *ddir = '\0';
222 } else {
223 char *op;
224
225 op = strdup(odir + 1);
f311f5f3 226 ret = fn(&td->o, eo, DDIR_TRIM, op, data);
6eaf09d6
SL
227
228 free(op);
229 }
d79db122 230 if (!ret)
f311f5f3 231 ret = fn(&td->o, eo, DDIR_WRITE, odir + 1, data);
720e84ad
JA
232 if (!ret) {
233 *odir = '\0';
f311f5f3 234 ret = fn(&td->o, eo, DDIR_READ, str, data);
720e84ad
JA
235 }
236 } else {
237 char *op;
238
239 op = strdup(str);
f311f5f3 240 ret = fn(&td->o, eo, DDIR_WRITE, op, data);
6eaf09d6 241 free(op);
720e84ad 242
6eaf09d6
SL
243 if (!ret) {
244 op = strdup(str);
f311f5f3 245 ret = fn(&td->o, eo, DDIR_TRIM, op, data);
6eaf09d6
SL
246 free(op);
247 }
f0c9c217 248 if (!ret)
f311f5f3 249 ret = fn(&td->o, eo, DDIR_READ, str, data);
720e84ad 250 }
564ca972 251
764593c0
JA
252 return ret;
253}
254
a7e8aae0
KB
255static int fio_fdp_cmp(const void *p1, const void *p2)
256{
257 const uint16_t *t1 = p1;
258 const uint16_t *t2 = p2;
259
260 return *t1 - *t2;
261}
262
263static int str_fdp_pli_cb(void *data, const char *input)
264{
265 struct thread_data *td = cb_data_to_td(data);
4518667d
VF
266 char *str, *p, *id1;
267 int i = 0, ret = 0;
a7e8aae0
KB
268
269 p = str = strdup(input);
270 strip_blank_front(&str);
271 strip_blank_end(str);
272
4518667d
VF
273 while ((id1 = strsep(&str, ",")) != NULL) {
274 char *str2, *id2;
275 unsigned int start, end;
276
277 if (!strlen(id1))
278 break;
279
280 str2 = id1;
281 end = -1;
282 while ((id2 = strsep(&str2, "-")) != NULL) {
283 if (!strlen(id2))
284 break;
285
286 end = strtoull(id2, NULL, 0);
3dabef7c 287 }
4518667d
VF
288
289 start = strtoull(id1, NULL, 0);
290 if (end == -1)
291 end = start;
292 if (start > end) {
293 ret = 1;
294 break;
295 }
296
297 while (start <= end) {
298 if (i >= FIO_MAX_DP_IDS) {
299 log_err("fio: only %d IDs supported\n", FIO_MAX_DP_IDS);
300 ret = 1;
301 break;
302 }
303 if (start > 0xFFFF) {
304 log_err("Placement IDs cannot exceed 0xFFFF\n");
305 ret = 1;
306 break;
307 }
308 td->o.dp_ids[i++] = start++;
309 }
310
311 if (ret)
312 break;
3dabef7c 313 }
4518667d 314
a7e8aae0
KB
315 free(p);
316
65ca6791
VF
317 qsort(td->o.dp_ids, i, sizeof(*td->o.dp_ids), fio_fdp_cmp);
318 td->o.dp_nr_ids = i;
a7e8aae0 319
4518667d 320 return ret;
a7e8aae0
KB
321}
322
04d5add8
HP
323/* str_dp_scheme_cb() is a callback function for parsing the fdp_scheme option
324 This function validates the fdp_scheme filename. */
325static int str_dp_scheme_cb(void *data, const char *input)
326{
327 struct thread_data *td = cb_data_to_td(data);
328 struct stat sb;
329 char *filename;
330 int ret = 0;
331
332 if (parse_dryrun())
333 return 0;
334
335 filename = strdup(td->o.dp_scheme_file);
336 strip_blank_front(&filename);
337 strip_blank_end(filename);
338
339 strcpy(td->o.dp_scheme_file, filename);
340
341 if (lstat(filename, &sb) < 0){
342 ret = errno;
343 log_err("fio: lstat() error related to %s\n", filename);
344 td_verror(td, ret, "lstat");
345 goto out;
346 }
347
348 if (!S_ISREG(sb.st_mode)) {
349 ret = errno;
350 log_err("fio: %s is not a file\n", filename);
351 td_verror(td, ret, "S_ISREG");
352 goto out;
353 }
354
355out:
356 free(filename);
357 return ret;
358}
359
764593c0
JA
360static int str_bssplit_cb(void *data, const char *input)
361{
a609f12a 362 struct thread_data *td = cb_data_to_td(data);
764593c0
JA
363 char *str, *p;
364 int ret = 0;
365
764593c0
JA
366 p = str = strdup(input);
367
368 strip_blank_front(&str);
369 strip_blank_end(str);
370
f311f5f3 371 ret = str_split_parse(td, str, bssplit_ddir, NULL, false);
764593c0 372
55baca06
JA
373 if (parse_dryrun()) {
374 int i;
375
376 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
377 free(td->o.bssplit[i]);
378 td->o.bssplit[i] = NULL;
379 td->o.bssplit_nr[i] = 0;
380 }
381 }
382
564ca972 383 free(p);
720e84ad 384 return ret;
564ca972
JA
385}
386
68be9966
NC
387static int parse_cmdprio_bssplit_entry(struct thread_options *o,
388 struct split_prio *entry, char *str)
389{
390 int matches = 0;
391 char *bs_str = NULL;
392 long long bs_val;
79012fec 393 unsigned int perc = 0, class, level, hint;
68be9966
NC
394
395 /*
396 * valid entry formats:
397 * bs/ - %s/ - set perc to 0, prio to -1.
398 * bs/perc - %s/%u - set prio to -1.
399 * bs/perc/class/level - %s/%u/%u/%u
79012fec 400 * bs/perc/class/level/hint - %s/%u/%u/%u/%u
68be9966 401 */
79012fec
DLM
402 matches = sscanf(str, "%m[^/]/%u/%u/%u/%u",
403 &bs_str, &perc, &class, &level, &hint);
68be9966
NC
404 if (matches < 1) {
405 log_err("fio: invalid cmdprio_bssplit format\n");
406 return 1;
407 }
408
409 if (str_to_decimal(bs_str, &bs_val, 1, o, 0, 0)) {
410 log_err("fio: split conversion failed\n");
411 free(bs_str);
412 return 1;
413 }
414 free(bs_str);
415
416 entry->bs = bs_val;
417 entry->perc = min(perc, 100u);
418 entry->prio = -1;
419 switch (matches) {
420 case 1: /* bs/ case */
421 case 2: /* bs/perc case */
422 break;
423 case 4: /* bs/perc/class/level case */
79012fec 424 case 5: /* bs/perc/class/level/hint case */
68be9966
NC
425 class = min(class, (unsigned int) IOPRIO_MAX_PRIO_CLASS);
426 level = min(level, (unsigned int) IOPRIO_MAX_PRIO);
79012fec
DLM
427 if (matches == 5)
428 hint = min(hint, (unsigned int) IOPRIO_MAX_PRIO_HINT);
429 else
430 hint = 0;
431 entry->prio = ioprio_value(class, level, hint);
68be9966
NC
432 break;
433 default:
434 log_err("fio: invalid cmdprio_bssplit format\n");
435 return 1;
436 }
437
438 return 0;
439}
440
441/*
442 * Returns a negative integer if the first argument should be before the second
443 * argument in the sorted list. A positive integer if the first argument should
444 * be after the second argument in the sorted list. A zero if they are equal.
445 */
446static int fio_split_prio_cmp(const void *p1, const void *p2)
447{
448 const struct split_prio *tmp1 = p1;
449 const struct split_prio *tmp2 = p2;
450
451 if (tmp1->bs > tmp2->bs)
452 return 1;
453 if (tmp1->bs < tmp2->bs)
454 return -1;
455 return 0;
456}
457
458int split_parse_prio_ddir(struct thread_options *o, struct split_prio **entries,
459 int *nr_entries, char *str)
460{
461 struct split_prio *tmp_entries;
462 unsigned int nr_bssplits;
463 char *str_cpy, *p, *fname;
464
465 /* strsep modifies the string, dup it so that we can use strsep twice */
466 p = str_cpy = strdup(str);
467 if (!p)
468 return 1;
469
470 nr_bssplits = 0;
471 while ((fname = strsep(&str_cpy, ":")) != NULL) {
472 if (!strlen(fname))
473 break;
474 nr_bssplits++;
475 }
476 free(p);
477
478 if (nr_bssplits > BSSPLIT_MAX) {
479 log_err("fio: too many cmdprio_bssplit entries\n");
480 return 1;
481 }
482
483 tmp_entries = calloc(nr_bssplits, sizeof(*tmp_entries));
484 if (!tmp_entries)
485 return 1;
486
487 nr_bssplits = 0;
488 while ((fname = strsep(&str, ":")) != NULL) {
489 struct split_prio *entry;
490
491 if (!strlen(fname))
492 break;
493
494 entry = &tmp_entries[nr_bssplits];
495
496 if (parse_cmdprio_bssplit_entry(o, entry, fname)) {
497 log_err("fio: failed to parse cmdprio_bssplit entry\n");
498 free(tmp_entries);
499 return 1;
500 }
501
502 /* skip zero perc entries, they provide no useful information */
503 if (entry->perc)
504 nr_bssplits++;
505 }
506
507 qsort(tmp_entries, nr_bssplits, sizeof(*tmp_entries),
508 fio_split_prio_cmp);
509
510 *entries = tmp_entries;
511 *nr_entries = nr_bssplits;
512
513 return 0;
514}
515
8b28bd41
DM
516static int str2error(char *str)
517{
a94eb99a 518 const char *err[] = { "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
8b28bd41
DM
519 "ENXIO", "E2BIG", "ENOEXEC", "EBADF",
520 "ECHILD", "EAGAIN", "ENOMEM", "EACCES",
521 "EFAULT", "ENOTBLK", "EBUSY", "EEXIST",
522 "EXDEV", "ENODEV", "ENOTDIR", "EISDIR",
523 "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
524 "ETXTBSY","EFBIG", "ENOSPC", "ESPIPE",
a94eb99a 525 "EROFS","EMLINK", "EPIPE", "EDOM", "ERANGE" };
7fe481b4 526 int i = 0, num = sizeof(err) / sizeof(char *);
8b28bd41 527
a94eb99a 528 while (i < num) {
8b28bd41
DM
529 if (!strcmp(err[i], str))
530 return i + 1;
531 i++;
532 }
533 return 0;
534}
535
3ed673c6
TK
536static int ignore_error_type(struct thread_data *td, enum error_type_bit etype,
537 char *str)
8b28bd41
DM
538{
539 unsigned int i;
540 int *error;
541 char *fname;
542
543 if (etype >= ERROR_TYPE_CNT) {
544 log_err("Illegal error type\n");
545 return 1;
546 }
547
548 td->o.ignore_error_nr[etype] = 4;
685ffd57 549 error = calloc(4, sizeof(int));
8b28bd41
DM
550
551 i = 0;
552 while ((fname = strsep(&str, ":")) != NULL) {
553
554 if (!strlen(fname))
555 break;
556
557 /*
558 * grow struct buffer, if needed
559 */
560 if (i == td->o.ignore_error_nr[etype]) {
561 td->o.ignore_error_nr[etype] <<= 1;
562 error = realloc(error, td->o.ignore_error_nr[etype]
563 * sizeof(int));
564 }
565 if (fname[0] == 'E') {
566 error[i] = str2error(fname);
567 } else {
f26af3dd
MI
568 int base = 10;
569 if (!strncmp(fname, "0x", 2) ||
570 !strncmp(fname, "0X", 2))
571 base = 16;
572 error[i] = strtol(fname, NULL, base);
8b28bd41 573 if (error[i] < 0)
1616e025 574 error[i] = -error[i];
8b28bd41
DM
575 }
576 if (!error[i]) {
d503e281 577 log_err("Unknown error %s, please use number value\n",
8b28bd41 578 fname);
d503e281 579 td->o.ignore_error_nr[etype] = 0;
0fddbf7a 580 free(error);
8b28bd41
DM
581 return 1;
582 }
583 i++;
584 }
585 if (i) {
586 td->o.continue_on_error |= 1 << etype;
587 td->o.ignore_error_nr[etype] = i;
588 td->o.ignore_error[etype] = error;
d503e281
TK
589 } else {
590 td->o.ignore_error_nr[etype] = 0;
c7b086be 591 free(error);
d503e281 592 }
c7b086be 593
8b28bd41
DM
594 return 0;
595
596}
597
d7235efb
JA
598static int str_replay_skip_cb(void *data, const char *input)
599{
600 struct thread_data *td = cb_data_to_td(data);
601 char *str, *p, *n;
602 int ret = 0;
603
604 if (parse_dryrun())
605 return 0;
606
607 p = str = strdup(input);
608
609 strip_blank_front(&str);
610 strip_blank_end(str);
611
612 while (p) {
613 n = strchr(p, ',');
614 if (n)
615 *n++ = '\0';
616 if (!strcmp(p, "read"))
617 td->o.replay_skip |= 1u << DDIR_READ;
618 else if (!strcmp(p, "write"))
619 td->o.replay_skip |= 1u << DDIR_WRITE;
620 else if (!strcmp(p, "trim"))
621 td->o.replay_skip |= 1u << DDIR_TRIM;
622 else if (!strcmp(p, "sync"))
623 td->o.replay_skip |= 1u << DDIR_SYNC;
624 else {
625 log_err("Unknown skip type: %s\n", p);
626 ret = 1;
627 break;
628 }
629 p = n;
630 }
631 free(str);
632 return ret;
633}
634
8b28bd41
DM
635static int str_ignore_error_cb(void *data, const char *input)
636{
a609f12a 637 struct thread_data *td = cb_data_to_td(data);
8b28bd41 638 char *str, *p, *n;
3ed673c6
TK
639 int ret = 1;
640 enum error_type_bit type = 0;
52c0cea3
JA
641
642 if (parse_dryrun())
643 return 0;
644
8b28bd41
DM
645 p = str = strdup(input);
646
647 strip_blank_front(&str);
648 strip_blank_end(str);
649
650 while (p) {
651 n = strchr(p, ',');
652 if (n)
653 *n++ = '\0';
654 ret = ignore_error_type(td, type, p);
655 if (ret)
656 break;
657 p = n;
658 type++;
659 }
660 free(str);
661 return ret;
662}
663
211097b2
JA
664static int str_rw_cb(void *data, const char *str)
665{
a609f12a 666 struct thread_data *td = cb_data_to_td(data);
83ea422a 667 struct thread_options *o = &td->o;
27ca949f 668 char *nr;
211097b2 669
52c0cea3
JA
670 if (parse_dryrun())
671 return 0;
672
83ea422a
JA
673 o->ddir_seq_nr = 1;
674 o->ddir_seq_add = 0;
059b0802 675
27ca949f 676 nr = get_opt_postfix(str);
059b0802
JA
677 if (!nr)
678 return 0;
679
2e0a5259 680 if (td_random(td)) {
681 long long val;
682
683 if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
684 log_err("fio: randrw postfix parsing failed\n");
685 free(nr);
686 return 1;
687 }
688 if ((val <= 0) || (val > UINT_MAX)) {
689 log_err("fio: randrw postfix parsing out of range\n");
690 free(nr);
691 return 1;
692 }
693 o->ddir_seq_nr = (unsigned int) val;
694 } else {
059b0802
JA
695 long long val;
696
88038bc7 697 if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
059b0802
JA
698 log_err("fio: rw postfix parsing failed\n");
699 free(nr);
700 return 1;
701 }
702
83ea422a 703 o->ddir_seq_add = val;
182ec6ee 704 }
211097b2 705
059b0802 706 free(nr);
211097b2
JA
707 return 0;
708}
709
214e1eca
JA
710static int str_mem_cb(void *data, const char *mem)
711{
a609f12a 712 struct thread_data *td = cb_data_to_td(data);
214e1eca 713
217b0f1d
LG
714 if (td->o.mem_type == MEM_MMAPHUGE || td->o.mem_type == MEM_MMAP ||
715 td->o.mem_type == MEM_MMAPSHARED)
836fcc0f 716 td->o.mmapfile = get_opt_postfix(mem);
214e1eca
JA
717
718 return 0;
719}
720
c223da83
JA
721static int fio_clock_source_cb(void *data, const char *str)
722{
a609f12a 723 struct thread_data *td = cb_data_to_td(data);
c223da83
JA
724
725 fio_clock_source = td->o.clocksource;
fa80feae 726 fio_clock_source_set = 1;
01423eae 727 fio_clock_init();
c223da83
JA
728 return 0;
729}
730
dcb1f3a9 731static int str_rwmix_read_cb(void *data, long long *val)
cb499fc4 732{
a609f12a 733 struct thread_data *td = cb_data_to_td(data);
cb499fc4
JA
734
735 td->o.rwmix[DDIR_READ] = *val;
736 td->o.rwmix[DDIR_WRITE] = 100 - *val;
737 return 0;
738}
739
dcb1f3a9 740static int str_rwmix_write_cb(void *data, long long *val)
cb499fc4 741{
a609f12a 742 struct thread_data *td = cb_data_to_td(data);
cb499fc4
JA
743
744 td->o.rwmix[DDIR_WRITE] = *val;
745 td->o.rwmix[DDIR_READ] = 100 - *val;
746 return 0;
747}
748
214e1eca
JA
749static int str_exitall_cb(void)
750{
f1867a7f 751 exitall_on_terminate = true;
214e1eca
JA
752 return 0;
753}
754
214e1eca 755#ifdef FIO_HAVE_CPU_AFFINITY
50b5860b 756int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu_index)
c2acfbac 757{
50b5860b 758 unsigned int i, index, cpus_in_mask;
40f61ec7 759 const long max_cpu = cpus_configured();
c2acfbac 760
50b5860b 761 cpus_in_mask = fio_cpu_count(mask);
3a294b87
VF
762 if (!cpus_in_mask)
763 return 0;
764
50b5860b
JA
765 cpu_index = cpu_index % cpus_in_mask;
766
767 index = 0;
c2acfbac 768 for (i = 0; i < max_cpu; i++) {
50b5860b 769 if (!fio_cpu_isset(mask, i))
c2acfbac 770 continue;
50b5860b
JA
771
772 if (cpu_index != index)
773 fio_cpu_clear(mask, i);
774
775 index++;
c2acfbac
JA
776 }
777
778 return fio_cpu_count(mask);
779}
780
85bc833b 781static int str_cpumask_cb(void *data, unsigned long long *val)
d2e268b0 782{
a609f12a 783 struct thread_data *td = cb_data_to_td(data);
214e1eca 784 unsigned int i;
b03daafb 785 long max_cpu;
d2ce18b5
JA
786 int ret;
787
52c0cea3
JA
788 if (parse_dryrun())
789 return 0;
790
d2ce18b5
JA
791 ret = fio_cpuset_init(&td->o.cpumask);
792 if (ret < 0) {
793 log_err("fio: cpuset_init failed\n");
794 td_verror(td, ret, "fio_cpuset_init");
795 return 1;
796 }
214e1eca 797
40f61ec7 798 max_cpu = cpus_configured();
214e1eca 799
62a7273d
JA
800 for (i = 0; i < sizeof(int) * 8; i++) {
801 if ((1 << i) & *val) {
b8411399 802 if (i >= max_cpu) {
b03daafb 803 log_err("fio: CPU %d too large (max=%ld)\n", i,
b8411399 804 max_cpu - 1);
b03daafb
JA
805 return 1;
806 }
62a7273d 807 dprint(FD_PARSE, "set cpu allowed %d\n", i);
6d459ee7 808 fio_cpu_set(&td->o.cpumask, i);
62a7273d
JA
809 }
810 }
d2e268b0 811
d2e268b0 812 return 0;
214e1eca
JA
813}
814
e8462bd8
JA
815static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask,
816 const char *input)
214e1eca 817{
d2e268b0 818 char *cpu, *str, *p;
b03daafb 819 long max_cpu;
19608d6c 820 int ret = 0;
d2e268b0 821
e8462bd8 822 ret = fio_cpuset_init(mask);
d2ce18b5
JA
823 if (ret < 0) {
824 log_err("fio: cpuset_init failed\n");
825 td_verror(td, ret, "fio_cpuset_init");
826 return 1;
827 }
d2e268b0
JA
828
829 p = str = strdup(input);
214e1eca 830
d2e268b0
JA
831 strip_blank_front(&str);
832 strip_blank_end(str);
833
40f61ec7 834 max_cpu = cpus_configured();
b03daafb 835
d2e268b0 836 while ((cpu = strsep(&str, ",")) != NULL) {
62a7273d
JA
837 char *str2, *cpu2;
838 int icpu, icpu2;
839
d2e268b0
JA
840 if (!strlen(cpu))
841 break;
62a7273d
JA
842
843 str2 = cpu;
844 icpu2 = -1;
845 while ((cpu2 = strsep(&str2, "-")) != NULL) {
846 if (!strlen(cpu2))
847 break;
848
849 icpu2 = atoi(cpu2);
850 }
851
852 icpu = atoi(cpu);
853 if (icpu2 == -1)
854 icpu2 = icpu;
855 while (icpu <= icpu2) {
6d459ee7 856 if (icpu >= FIO_MAX_CPUS) {
19608d6c 857 log_err("fio: your OS only supports up to"
6d459ee7 858 " %d CPUs\n", (int) FIO_MAX_CPUS);
19608d6c
JA
859 ret = 1;
860 break;
861 }
9e986889 862 if (icpu >= max_cpu) {
b03daafb 863 log_err("fio: CPU %d too large (max=%ld)\n",
9e986889 864 icpu, max_cpu - 1);
b03daafb
JA
865 ret = 1;
866 break;
867 }
0b9d69ec 868
62a7273d 869 dprint(FD_PARSE, "set cpu allowed %d\n", icpu);
e8462bd8 870 fio_cpu_set(mask, icpu);
62a7273d
JA
871 icpu++;
872 }
19608d6c
JA
873 if (ret)
874 break;
d2e268b0
JA
875 }
876
877 free(p);
19608d6c 878 return ret;
214e1eca 879}
e8462bd8
JA
880
881static int str_cpus_allowed_cb(void *data, const char *input)
882{
a609f12a 883 struct thread_data *td = cb_data_to_td(data);
e8462bd8 884
52c0cea3
JA
885 if (parse_dryrun())
886 return 0;
887
b2a9e649 888 return set_cpus_allowed(td, &td->o.cpumask, input);
e8462bd8
JA
889}
890
891static int str_verify_cpus_allowed_cb(void *data, const char *input)
892{
a609f12a 893 struct thread_data *td = cb_data_to_td(data);
e8462bd8 894
466155e2
JA
895 if (parse_dryrun())
896 return 0;
897
b2a9e649 898 return set_cpus_allowed(td, &td->o.verify_cpumask, input);
e8462bd8 899}
c08f9fe2 900
105157ad 901#ifdef CONFIG_ZLIB
c08f9fe2
JA
902static int str_log_cpus_allowed_cb(void *data, const char *input)
903{
a609f12a 904 struct thread_data *td = cb_data_to_td(data);
c08f9fe2
JA
905
906 if (parse_dryrun())
907 return 0;
908
909 return set_cpus_allowed(td, &td->o.log_gz_cpumask, input);
910}
105157ad 911#endif /* CONFIG_ZLIB */
c08f9fe2 912
105157ad 913#endif /* FIO_HAVE_CPU_AFFINITY */
214e1eca 914
67bf9823 915#ifdef CONFIG_LIBNUMA
d0b937ed
YR
916static int str_numa_cpunodes_cb(void *data, char *input)
917{
a609f12a 918 struct thread_data *td = cb_data_to_td(data);
43522848 919 struct bitmask *verify_bitmask;
d0b937ed 920
52c0cea3
JA
921 if (parse_dryrun())
922 return 0;
923
d0b937ed
YR
924 /* numa_parse_nodestring() parses a character string list
925 * of nodes into a bit mask. The bit mask is allocated by
926 * numa_allocate_nodemask(), so it should be freed by
927 * numa_free_nodemask().
928 */
43522848
DG
929 verify_bitmask = numa_parse_nodestring(input);
930 if (verify_bitmask == NULL) {
d0b937ed
YR
931 log_err("fio: numa_parse_nodestring failed\n");
932 td_verror(td, 1, "str_numa_cpunodes_cb");
933 return 1;
934 }
43522848 935 numa_free_nodemask(verify_bitmask);
d0b937ed 936
43522848 937 td->o.numa_cpunodes = strdup(input);
d0b937ed
YR
938 return 0;
939}
940
941static int str_numa_mpol_cb(void *data, char *input)
942{
a609f12a 943 struct thread_data *td = cb_data_to_td(data);
d0b937ed 944 const char * const policy_types[] =
05d6f44b 945 { "default", "prefer", "bind", "interleave", "local", NULL };
d0b937ed 946 int i;
52c0cea3 947 char *nodelist;
43522848 948 struct bitmask *verify_bitmask;
52c0cea3
JA
949
950 if (parse_dryrun())
951 return 0;
d0b937ed 952
52c0cea3 953 nodelist = strchr(input, ':');
d0b937ed
YR
954 if (nodelist) {
955 /* NUL-terminate mode */
956 *nodelist++ = '\0';
957 }
958
959 for (i = 0; i <= MPOL_LOCAL; i++) {
960 if (!strcmp(input, policy_types[i])) {
961 td->o.numa_mem_mode = i;
962 break;
963 }
964 }
965 if (i > MPOL_LOCAL) {
966 log_err("fio: memory policy should be: default, prefer, bind, interleave, local\n");
967 goto out;
968 }
969
970 switch (td->o.numa_mem_mode) {
971 case MPOL_PREFERRED:
972 /*
973 * Insist on a nodelist of one node only
974 */
975 if (nodelist) {
976 char *rest = nodelist;
977 while (isdigit(*rest))
978 rest++;
979 if (*rest) {
980 log_err("fio: one node only for \'prefer\'\n");
981 goto out;
982 }
983 } else {
984 log_err("fio: one node is needed for \'prefer\'\n");
985 goto out;
986 }
987 break;
988 case MPOL_INTERLEAVE:
989 /*
990 * Default to online nodes with memory if no nodelist
991 */
992 if (!nodelist)
993 nodelist = strdup("all");
994 break;
995 case MPOL_LOCAL:
996 case MPOL_DEFAULT:
997 /*
998 * Don't allow a nodelist
999 */
1000 if (nodelist) {
1001 log_err("fio: NO nodelist for \'local\'\n");
1002 goto out;
1003 }
1004 break;
1005 case MPOL_BIND:
1006 /*
1007 * Insist on a nodelist
1008 */
1009 if (!nodelist) {
1010 log_err("fio: a nodelist is needed for \'bind\'\n");
1011 goto out;
1012 }
1013 break;
1014 }
1015
1016
1017 /* numa_parse_nodestring() parses a character string list
1018 * of nodes into a bit mask. The bit mask is allocated by
1019 * numa_allocate_nodemask(), so it should be freed by
1020 * numa_free_nodemask().
1021 */
1022 switch (td->o.numa_mem_mode) {
1023 case MPOL_PREFERRED:
1024 td->o.numa_mem_prefer_node = atoi(nodelist);
1025 break;
1026 case MPOL_INTERLEAVE:
1027 case MPOL_BIND:
43522848
DG
1028 verify_bitmask = numa_parse_nodestring(nodelist);
1029 if (verify_bitmask == NULL) {
d0b937ed
YR
1030 log_err("fio: numa_parse_nodestring failed\n");
1031 td_verror(td, 1, "str_numa_memnodes_cb");
1032 return 1;
1033 }
43522848
DG
1034 td->o.numa_memnodes = strdup(nodelist);
1035 numa_free_nodemask(verify_bitmask);
b74e419e 1036
d0b937ed
YR
1037 break;
1038 case MPOL_LOCAL:
1039 case MPOL_DEFAULT:
1040 default:
1041 break;
1042 }
1043
d0b937ed 1044 return 0;
d0b937ed
YR
1045out:
1046 return 1;
1047}
1048#endif
1049
214e1eca
JA
1050static int str_fst_cb(void *data, const char *str)
1051{
a609f12a 1052 struct thread_data *td = cb_data_to_td(data);
8c07860d 1053 double val;
a87c90fd 1054 double center = -1;
8c07860d
JA
1055 bool done = false;
1056 char *nr;
214e1eca
JA
1057
1058 td->file_service_nr = 1;
8c07860d
JA
1059
1060 switch (td->o.file_service_type) {
1061 case FIO_FSERVICE_RANDOM:
1062 case FIO_FSERVICE_RR:
1063 case FIO_FSERVICE_SEQ:
1064 nr = get_opt_postfix(str);
1065 if (nr) {
1066 td->file_service_nr = atoi(nr);
1067 free(nr);
1068 }
1069 done = true;
1070 break;
1071 case FIO_FSERVICE_ZIPF:
1072 val = FIO_DEF_ZIPF;
1073 break;
1074 case FIO_FSERVICE_PARETO:
1075 val = FIO_DEF_PARETO;
1076 break;
1077 case FIO_FSERVICE_GAUSS:
1078 val = 0.0;
1079 break;
1080 default:
1081 log_err("fio: bad file service type: %d\n", td->o.file_service_type);
1082 return 1;
1083 }
1084
1085 if (done)
1086 return 0;
1087
1088 nr = get_opt_postfix(str);
a87c90fd 1089 if (nr && !split_parse_distr(nr, &val, &center)) {
8c07860d 1090 log_err("fio: file service type random postfix parsing failed\n");
182ec6ee 1091 free(nr);
8c07860d
JA
1092 return 1;
1093 }
1094
1095 free(nr);
1096
a87c90fd
AK
1097 if (center != -1 && (center < 0.00 || center > 1.00)) {
1098 log_err("fio: distribution center out of range (0 <= center <= 1.0)\n");
1099 return 1;
1100 }
1101 td->random_center = center;
1102
8c07860d
JA
1103 switch (td->o.file_service_type) {
1104 case FIO_FSERVICE_ZIPF:
1105 if (val == 1.00) {
1106 log_err("fio: zipf theta must be different than 1.0\n");
1107 return 1;
1108 }
1109 if (parse_dryrun())
1110 return 0;
1111 td->zipf_theta = val;
1112 break;
1113 case FIO_FSERVICE_PARETO:
1114 if (val <= 0.00 || val >= 1.00) {
1115 log_err("fio: pareto input out of range (0 < input < 1.0)\n");
1116 return 1;
1117 }
1118 if (parse_dryrun())
1119 return 0;
1120 td->pareto_h = val;
1121 break;
1122 case FIO_FSERVICE_GAUSS:
1123 if (val < 0.00 || val >= 100.00) {
99c94a6b 1124 log_err("fio: normal deviation out of range (0 <= input < 100.0)\n");
8c07860d
JA
1125 return 1;
1126 }
1127 if (parse_dryrun())
1128 return 0;
1129 td->gauss_dev = val;
1130 break;
182ec6ee 1131 }
214e1eca
JA
1132
1133 return 0;
1134}
1135
67bf9823 1136#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
1137static int str_sfr_cb(void *data, const char *str)
1138{
a609f12a 1139 struct thread_data *td = cb_data_to_td(data);
44f29692
JA
1140 char *nr = get_opt_postfix(str);
1141
1142 td->sync_file_range_nr = 1;
1143 if (nr) {
1144 td->sync_file_range_nr = atoi(nr);
1145 free(nr);
1146 }
1147
1148 return 0;
1149}
3ae06371 1150#endif
44f29692 1151
f311f5f3
DLM
1152static int zone_split_ddir(struct thread_options *o, void *eo,
1153 enum fio_ddir ddir, char *str, bool absolute)
e0a04ac1 1154{
e0a04ac1 1155 unsigned int i, perc, perc_missing, sperc, sperc_missing;
d2835319 1156 struct split split;
e0a04ac1 1157
d2835319 1158 memset(&split, 0, sizeof(split));
e0a04ac1 1159
517c9c72 1160 if (split_parse_ddir(o, &split, str, absolute, ZONESPLIT_MAX))
d2835319
JA
1161 return 1;
1162 if (!split.nr)
1163 return 0;
e0a04ac1 1164
d2835319
JA
1165 o->zone_split[ddir] = malloc(split.nr * sizeof(struct zone_split));
1166 o->zone_split_nr[ddir] = split.nr;
1167 for (i = 0; i < split.nr; i++) {
1168 o->zone_split[ddir][i].access_perc = split.val1[i];
59466396
JA
1169 if (absolute)
1170 o->zone_split[ddir][i].size = split.val2[i];
1171 else
1172 o->zone_split[ddir][i].size_perc = split.val2[i];
e0a04ac1
JA
1173 }
1174
e0a04ac1
JA
1175 /*
1176 * Now check if the percentages add up, and how much is missing
1177 */
1178 perc = perc_missing = 0;
1179 sperc = sperc_missing = 0;
1180 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
d2835319 1181 struct zone_split *zsp = &o->zone_split[ddir][i];
e0a04ac1
JA
1182
1183 if (zsp->access_perc == (uint8_t) -1U)
1184 perc_missing++;
1185 else
1186 perc += zsp->access_perc;
1187
59466396
JA
1188 if (!absolute) {
1189 if (zsp->size_perc == (uint8_t) -1U)
1190 sperc_missing++;
1191 else
1192 sperc += zsp->size_perc;
1193 }
e0a04ac1
JA
1194 }
1195
1196 if (perc > 100 || sperc > 100) {
1197 log_err("fio: zone_split percentages add to more than 100%%\n");
d2835319
JA
1198 free(o->zone_split[ddir]);
1199 o->zone_split[ddir] = NULL;
e0a04ac1
JA
1200 return 1;
1201 }
1202 if (perc < 100) {
1203 log_err("fio: access percentage don't add up to 100 for zoned "
1204 "random distribution (got=%u)\n", perc);
d2835319
JA
1205 free(o->zone_split[ddir]);
1206 o->zone_split[ddir] = NULL;
e0a04ac1
JA
1207 return 1;
1208 }
1209
1210 /*
1211 * If values didn't have a percentage set, divide the remains between
1212 * them.
1213 */
1214 if (perc_missing) {
1215 if (perc_missing == 1 && o->zone_split_nr[ddir] == 1)
1216 perc = 100;
1217 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
d2835319 1218 struct zone_split *zsp = &o->zone_split[ddir][i];
e0a04ac1
JA
1219
1220 if (zsp->access_perc == (uint8_t) -1U)
1221 zsp->access_perc = (100 - perc) / perc_missing;
1222 }
1223 }
1224 if (sperc_missing) {
1225 if (sperc_missing == 1 && o->zone_split_nr[ddir] == 1)
1226 sperc = 100;
1227 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
d2835319 1228 struct zone_split *zsp = &o->zone_split[ddir][i];
e0a04ac1
JA
1229
1230 if (zsp->size_perc == (uint8_t) -1U)
1231 zsp->size_perc = (100 - sperc) / sperc_missing;
1232 }
1233 }
1234
e0a04ac1
JA
1235 return 0;
1236}
1237
59466396
JA
1238static int parse_zoned_distribution(struct thread_data *td, const char *input,
1239 bool absolute)
e0a04ac1 1240{
59466396 1241 const char *pre = absolute ? "zoned_abs:" : "zoned:";
764593c0 1242 char *str, *p;
e0a04ac1
JA
1243 int i, ret = 0;
1244
1245 p = str = strdup(input);
1246
1247 strip_blank_front(&str);
1248 strip_blank_end(str);
1249
1250 /* We expect it to start like that, bail if not */
59466396 1251 if (strncmp(str, pre, strlen(pre))) {
e0a04ac1
JA
1252 log_err("fio: mismatch in zoned input <%s>\n", str);
1253 free(p);
1254 return 1;
1255 }
59466396 1256 str += strlen(pre);
e0a04ac1 1257
f311f5f3 1258 ret = str_split_parse(td, str, zone_split_ddir, NULL, absolute);
e0a04ac1
JA
1259
1260 free(p);
1261
1262 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
1263 int j;
1264
1265 dprint(FD_PARSE, "zone ddir %d (nr=%u): \n", i, td->o.zone_split_nr[i]);
1266
1267 for (j = 0; j < td->o.zone_split_nr[i]; j++) {
1268 struct zone_split *zsp = &td->o.zone_split[i][j];
1269
59466396
JA
1270 if (absolute) {
1271 dprint(FD_PARSE, "\t%d: %u/%llu\n", j,
1272 zsp->access_perc,
1273 (unsigned long long) zsp->size);
1274 } else {
1275 dprint(FD_PARSE, "\t%d: %u/%u\n", j,
1276 zsp->access_perc,
1277 zsp->size_perc);
1278 }
e0a04ac1
JA
1279 }
1280 }
1281
55baca06 1282 if (parse_dryrun()) {
55baca06
JA
1283 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
1284 free(td->o.zone_split[i]);
1285 td->o.zone_split[i] = NULL;
1286 td->o.zone_split_nr[i] = 0;
1287 }
1288
1289 return ret;
1290 }
1291
81bdb791 1292 if (ret) {
dc4bffb8
JA
1293 for (i = 0; i < DDIR_RWDIR_CNT; i++)
1294 td->o.zone_split_nr[i] = 0;
1295 }
e0a04ac1
JA
1296
1297 return ret;
1298}
1299
e25839d4
JA
1300static int str_random_distribution_cb(void *data, const char *str)
1301{
a609f12a 1302 struct thread_data *td = cb_data_to_td(data);
e25839d4 1303 double val;
a87c90fd 1304 double center = -1;
e25839d4
JA
1305 char *nr;
1306
925fee33 1307 if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
c95f9404 1308 val = FIO_DEF_ZIPF;
925fee33 1309 else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
c95f9404 1310 val = FIO_DEF_PARETO;
56d9fa4b
JA
1311 else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
1312 val = 0.0;
e0a04ac1 1313 else if (td->o.random_distribution == FIO_RAND_DIST_ZONED)
59466396
JA
1314 return parse_zoned_distribution(td, str, false);
1315 else if (td->o.random_distribution == FIO_RAND_DIST_ZONED_ABS)
1316 return parse_zoned_distribution(td, str, true);
925fee33 1317 else
e25839d4
JA
1318 return 0;
1319
1320 nr = get_opt_postfix(str);
a87c90fd 1321 if (nr && !split_parse_distr(nr, &val, &center)) {
e25839d4
JA
1322 log_err("fio: random postfix parsing failed\n");
1323 free(nr);
1324 return 1;
1325 }
1326
078189c1
JA
1327 free(nr);
1328
a87c90fd
AK
1329 if (center != -1 && (center < 0.00 || center > 1.00)) {
1330 log_err("fio: distribution center out of range (0 <= center <= 1.0)\n");
1331 return 1;
1332 }
1333 td->o.random_center.u.f = center;
1334
18ded917
JA
1335 if (td->o.random_distribution == FIO_RAND_DIST_ZIPF) {
1336 if (val == 1.00) {
1337 log_err("fio: zipf theta must different than 1.0\n");
1338 return 1;
1339 }
55baca06
JA
1340 if (parse_dryrun())
1341 return 0;
1e5324e7 1342 td->o.zipf_theta.u.f = val;
56d9fa4b 1343 } else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
078189c1
JA
1344 if (val <= 0.00 || val >= 1.00) {
1345 log_err("fio: pareto input out of range (0 < input < 1.0)\n");
1346 return 1;
1347 }
55baca06
JA
1348 if (parse_dryrun())
1349 return 0;
1e5324e7 1350 td->o.pareto_h.u.f = val;
3cdb8cf3 1351 } else {
76527b19 1352 if (val < 0.00 || val >= 100.0) {
99c94a6b 1353 log_err("fio: normal deviation out of range (0 <= input < 100.0)\n");
3cdb8cf3
JA
1354 return 1;
1355 }
55baca06
JA
1356 if (parse_dryrun())
1357 return 0;
f88cd222 1358 td->o.gauss_dev.u.f = val;
3cdb8cf3 1359 }
921c766f
JA
1360
1361 return 0;
1362}
1363
16e56d25
VF
1364static int str_steadystate_cb(void *data, const char *str)
1365{
94f218f6 1366 struct thread_data *td = cb_data_to_td(data);
16e56d25
VF
1367 double val;
1368 char *nr;
1369 char *pct;
1370 long long ll;
1371
2c5d94bc
VF
1372 if (td->o.ss_state != FIO_SS_IOPS && td->o.ss_state != FIO_SS_IOPS_SLOPE &&
1373 td->o.ss_state != FIO_SS_BW && td->o.ss_state != FIO_SS_BW_SLOPE) {
16e56d25
VF
1374 /* should be impossible to get here */
1375 log_err("fio: unknown steady state criterion\n");
1376 return 1;
1377 }
1378
1379 nr = get_opt_postfix(str);
1380 if (!nr) {
1381 log_err("fio: steadystate threshold must be specified in addition to criterion\n");
1382 free(nr);
1383 return 1;
1384 }
1385
1386 /* ENHANCEMENT Allow fio to understand size=10.2% and use here */
1387 pct = strstr(nr, "%");
1388 if (pct) {
1389 *pct = '\0';
1390 strip_blank_end(nr);
1391 if (!str_to_float(nr, &val, 0)) {
1392 log_err("fio: could not parse steadystate threshold percentage\n");
1393 free(nr);
1394 return 1;
1395 }
1396
1397 dprint(FD_PARSE, "set steady state threshold to %f%%\n", val);
1398 free(nr);
1399 if (parse_dryrun())
1400 return 0;
1401
c8caba48 1402 td->o.ss_state |= FIO_SS_PCT;
16e56d25 1403 td->o.ss_limit.u.f = val;
c8caba48 1404 } else if (td->o.ss_state & FIO_SS_IOPS) {
16e56d25
VF
1405 if (!str_to_float(nr, &val, 0)) {
1406 log_err("fio: steadystate IOPS threshold postfix parsing failed\n");
1407 free(nr);
1408 return 1;
1409 }
1410
1411 dprint(FD_PARSE, "set steady state IOPS threshold to %f\n", val);
1412 free(nr);
1413 if (parse_dryrun())
1414 return 0;
1415
16e56d25 1416 td->o.ss_limit.u.f = val;
16e56d25
VF
1417 } else { /* bandwidth criterion */
1418 if (str_to_decimal(nr, &ll, 1, td, 0, 0)) {
1419 log_err("fio: steadystate BW threshold postfix parsing failed\n");
1420 free(nr);
1421 return 1;
1422 }
1423
1424 dprint(FD_PARSE, "set steady state BW threshold to %lld\n", ll);
1425 free(nr);
1426 if (parse_dryrun())
1427 return 0;
1428
16e56d25 1429 td->o.ss_limit.u.f = (double) ll;
16e56d25
VF
1430 }
1431
2c5d94bc 1432 td->ss.state = td->o.ss_state;
16e56d25
VF
1433 return 0;
1434}
1435
8e827d35 1436/*
bcbfeefa 1437 * Return next name in the string. Files are separated with ':'. If the ':'
8e827d35
JA
1438 * is escaped with a '\', then that ':' is part of the filename and does not
1439 * indicate a new file.
1440 */
532eda7e 1441char *get_next_str(char **ptr)
8e827d35
JA
1442{
1443 char *str = *ptr;
1444 char *p, *start;
1445
1446 if (!str || !strlen(str))
1447 return NULL;
1448
1449 start = str;
1450 do {
1451 /*
1452 * No colon, we are done
1453 */
1454 p = strchr(str, ':');
1455 if (!p) {
1456 *ptr = NULL;
1457 break;
1458 }
1459
1460 /*
1461 * We got a colon, but it's the first character. Skip and
1462 * continue
1463 */
1464 if (p == start) {
1465 str = ++start;
1466 continue;
1467 }
1468
1469 if (*(p - 1) != '\\') {
1470 *p = '\0';
1471 *ptr = p + 1;
1472 break;
1473 }
1474
1475 memmove(p - 1, p, strlen(p) + 1);
1476 str = p;
1477 } while (1);
1478
1479 return start;
1480}
1481
bcbfeefa 1482
532eda7e 1483int get_max_str_idx(char *input)
bcbfeefa
CE
1484{
1485 unsigned int cur_idx;
1486 char *str, *p;
1487
1488 p = str = strdup(input);
1489 for (cur_idx = 0; ; cur_idx++)
532eda7e 1490 if (get_next_str(&str) == NULL)
bcbfeefa
CE
1491 break;
1492
1493 free(p);
1494 return cur_idx;
1495}
1496
1497/*
fc002f14 1498 * Returns the directory at the index, indexes > entries will be
bcbfeefa
CE
1499 * assigned via modulo division of the index
1500 */
922a5be8
JA
1501int set_name_idx(char *target, size_t tlen, char *input, int index,
1502 bool unique_filename)
bcbfeefa
CE
1503{
1504 unsigned int cur_idx;
1505 int len;
1506 char *fname, *str, *p;
1507
1508 p = str = strdup(input);
1509
532eda7e 1510 index %= get_max_str_idx(input);
bcbfeefa 1511 for (cur_idx = 0; cur_idx <= index; cur_idx++)
532eda7e 1512 fname = get_next_str(&str);
bcbfeefa 1513
922a5be8 1514 if (client_sockaddr_str[0] && unique_filename) {
e13c3b50
JA
1515 len = snprintf(target, tlen, "%s/%s.", fname,
1516 client_sockaddr_str);
1517 } else
df18600f
SW
1518 len = snprintf(target, tlen, "%s%c", fname,
1519 FIO_OS_PATH_SEPARATOR);
72a703da 1520
e13c3b50 1521 target[tlen - 1] = '\0';
bcbfeefa
CE
1522 free(p);
1523
1524 return len;
1525}
1526
c70c7f58
AK
1527char* get_name_by_idx(char *input, int index)
1528{
1529 unsigned int cur_idx;
1530 char *fname, *str, *p;
1531
1532 p = str = strdup(input);
1533
532eda7e 1534 index %= get_max_str_idx(input);
c70c7f58 1535 for (cur_idx = 0; cur_idx <= index; cur_idx++)
532eda7e 1536 fname = get_next_str(&str);
c70c7f58
AK
1537
1538 fname = strdup(fname);
1539 free(p);
1540
1541 return fname;
1542}
1543
214e1eca
JA
1544static int str_filename_cb(void *data, const char *input)
1545{
a609f12a 1546 struct thread_data *td = cb_data_to_td(data);
214e1eca
JA
1547 char *fname, *str, *p;
1548
1549 p = str = strdup(input);
1550
1551 strip_blank_front(&str);
1552 strip_blank_end(str);
1553
79591fa9
TK
1554 /*
1555 * Ignore what we may already have from nrfiles option.
1556 */
214e1eca 1557 if (!td->files_index)
2dc1bbeb 1558 td->o.nr_files = 0;
214e1eca 1559
532eda7e 1560 while ((fname = get_next_str(&str)) != NULL) {
214e1eca
JA
1561 if (!strlen(fname))
1562 break;
5903e7b7 1563 add_file(td, fname, 0, 1);
214e1eca
JA
1564 }
1565
1566 free(p);
1567 return 0;
1568}
1569
bcbfeefa 1570static int str_directory_cb(void *data, const char fio_unused *unused)
214e1eca 1571{
a609f12a 1572 struct thread_data *td = cb_data_to_td(data);
214e1eca 1573 struct stat sb;
bcbfeefa
CE
1574 char *dirname, *str, *p;
1575 int ret = 0;
214e1eca 1576
f9633d72
JA
1577 if (parse_dryrun())
1578 return 0;
1579
bcbfeefa 1580 p = str = strdup(td->o.directory);
532eda7e 1581 while ((dirname = get_next_str(&str)) != NULL) {
bcbfeefa
CE
1582 if (lstat(dirname, &sb) < 0) {
1583 ret = errno;
921c766f 1584
bcbfeefa
CE
1585 log_err("fio: %s is not a directory\n", dirname);
1586 td_verror(td, ret, "lstat");
1587 goto out;
1588 }
1589 if (!S_ISDIR(sb.st_mode)) {
1590 log_err("fio: %s is not a directory\n", dirname);
1591 ret = 1;
1592 goto out;
1593 }
214e1eca
JA
1594 }
1595
bcbfeefa
CE
1596out:
1597 free(p);
1598 return ret;
214e1eca
JA
1599}
1600
1601static int str_opendir_cb(void *data, const char fio_unused *str)
1602{
a609f12a 1603 struct thread_data *td = cb_data_to_td(data);
214e1eca 1604
52c0cea3
JA
1605 if (parse_dryrun())
1606 return 0;
1607
214e1eca 1608 if (!td->files_index)
2dc1bbeb 1609 td->o.nr_files = 0;
214e1eca 1610
2dc1bbeb 1611 return add_dir_files(td, td->o.opendir);
214e1eca
JA
1612}
1613
ce35b1ec
JA
1614static int str_buffer_pattern_cb(void *data, const char *input)
1615{
a609f12a 1616 struct thread_data *td = cb_data_to_td(data);
ce35b1ec
JA
1617 int ret;
1618
61b9861d 1619 /* FIXME: for now buffer pattern does not support formats */
1dc47d6b
LG
1620 ret = parse_and_fill_pattern_alloc(input, strlen(input),
1621 &td->o.buffer_pattern, NULL, NULL, NULL);
61b9861d
RP
1622 if (ret < 0)
1623 return 1;
ce35b1ec 1624
61b9861d
RP
1625 assert(ret != 0);
1626 td->o.buffer_pattern_bytes = ret;
c55fae03
JA
1627
1628 /*
1629 * If this job is doing any reading or has compression set,
1630 * ensure that we refill buffers for writes or we could be
1631 * invalidating the pattern through reads.
1632 */
1633 if (!td->o.compress_percentage && !td_read(td))
61b9861d 1634 td->o.refill_buffers = 0;
c55fae03
JA
1635 else
1636 td->o.refill_buffers = 1;
1637
61b9861d
RP
1638 td->o.scramble_buffers = 0;
1639 td->o.zero_buffers = 0;
efcd9dcc 1640
61b9861d 1641 return 0;
ce35b1ec
JA
1642}
1643
bedc9dc2
JA
1644static int str_buffer_compress_cb(void *data, unsigned long long *il)
1645{
a609f12a 1646 struct thread_data *td = cb_data_to_td(data);
bedc9dc2
JA
1647
1648 td->flags |= TD_F_COMPRESS;
1649 td->o.compress_percentage = *il;
1650 return 0;
1651}
1652
5c94b008
JA
1653static int str_dedupe_cb(void *data, unsigned long long *il)
1654{
a609f12a 1655 struct thread_data *td = cb_data_to_td(data);
5c94b008
JA
1656
1657 td->flags |= TD_F_COMPRESS;
1658 td->o.dedupe_percentage = *il;
1659 td->o.refill_buffers = 1;
1660 return 0;
1661}
1662
ce35b1ec
JA
1663static int str_verify_pattern_cb(void *data, const char *input)
1664{
a609f12a 1665 struct thread_data *td = cb_data_to_td(data);
ce35b1ec
JA
1666 int ret;
1667
59f94d26 1668 td->o.verify_fmt_sz = FIO_ARRAY_SIZE(td->o.verify_fmt);
1dc47d6b
LG
1669 ret = parse_and_fill_pattern_alloc(input, strlen(input),
1670 &td->o.verify_pattern, fmt_desc, td->o.verify_fmt,
1671 &td->o.verify_fmt_sz);
61b9861d
RP
1672 if (ret < 0)
1673 return 1;
efcd9dcc 1674
61b9861d
RP
1675 assert(ret != 0);
1676 td->o.verify_pattern_bytes = ret;
92bf48d5 1677 /*
b638d82f 1678 * VERIFY_* could already be set
92bf48d5 1679 */
61b9861d 1680 if (!fio_option_is_set(&td->o, verify))
92bf48d5 1681 td->o.verify = VERIFY_PATTERN;
efcd9dcc 1682
61b9861d 1683 return 0;
90059d65 1684}
214e1eca 1685
993bf48b
JA
1686static int str_gtod_reduce_cb(void *data, int *il)
1687{
a609f12a 1688 struct thread_data *td = cb_data_to_td(data);
993bf48b
JA
1689 int val = *il;
1690
56440e63 1691 /*
fc002f14 1692 * Only modify options if gtod_reduce==1
56440e63
VF
1693 * Otherwise leave settings alone.
1694 */
1695 if (val) {
1696 td->o.disable_lat = 1;
1697 td->o.disable_clat = 1;
1698 td->o.disable_slat = 1;
1699 td->o.disable_bw = 1;
1700 td->o.clat_percentiles = 0;
1701 td->o.lat_percentiles = 0;
1702 td->o.slat_percentiles = 0;
8b6a404c 1703 td->ts_cache_mask = 63;
56440e63 1704 }
993bf48b
JA
1705
1706 return 0;
1707}
1708
dcb1f3a9 1709static int str_offset_cb(void *data, long long *__val)
89978a6b
BW
1710{
1711 struct thread_data *td = cb_data_to_td(data);
1712 unsigned long long v = *__val;
1713
1714 if (parse_is_percent(v)) {
1715 td->o.start_offset = 0;
1716 td->o.start_offset_percent = -1ULL - v;
8f39afa7 1717 td->o.start_offset_nz = 0;
872e0415
JA
1718 dprint(FD_PARSE, "SET start_offset_percent %d\n",
1719 td->o.start_offset_percent);
8f39afa7
AD
1720 } else if (parse_is_zone(v)) {
1721 td->o.start_offset = 0;
1722 td->o.start_offset_percent = 0;
1723 td->o.start_offset_nz = v - ZONE_BASE_VAL;
89978a6b
BW
1724 } else
1725 td->o.start_offset = v;
1726
1727 return 0;
1728}
1729
dcb1f3a9 1730static int str_offset_increment_cb(void *data, long long *__val)
0b288ba1
VF
1731{
1732 struct thread_data *td = cb_data_to_td(data);
1733 unsigned long long v = *__val;
1734
1735 if (parse_is_percent(v)) {
1736 td->o.offset_increment = 0;
1737 td->o.offset_increment_percent = -1ULL - v;
8f39afa7 1738 td->o.offset_increment_nz = 0;
0b288ba1
VF
1739 dprint(FD_PARSE, "SET offset_increment_percent %d\n",
1740 td->o.offset_increment_percent);
8f39afa7
AD
1741 } else if (parse_is_zone(v)) {
1742 td->o.offset_increment = 0;
1743 td->o.offset_increment_percent = 0;
1744 td->o.offset_increment_nz = v - ZONE_BASE_VAL;
0b288ba1
VF
1745 } else
1746 td->o.offset_increment = v;
1747
1748 return 0;
1749}
1750
dcb1f3a9 1751static int str_size_cb(void *data, long long *__val)
7bb59102 1752{
a609f12a 1753 struct thread_data *td = cb_data_to_td(data);
7bb59102
JA
1754 unsigned long long v = *__val;
1755
1756 if (parse_is_percent(v)) {
1757 td->o.size = 0;
1758 td->o.size_percent = -1ULL - v;
24e4321c
TK
1759 dprint(FD_PARSE, "SET size_percent %d\n",
1760 td->o.size_percent);
8f39afa7
AD
1761 } else if (parse_is_zone(v)) {
1762 td->o.size = 0;
1763 td->o.size_percent = 0;
1764 td->o.size_nz = v - ZONE_BASE_VAL;
7bb59102
JA
1765 } else
1766 td->o.size = v;
1767
1768 return 0;
1769}
1770
8b38f401
AD
1771static int str_io_size_cb(void *data, unsigned long long *__val)
1772{
1773 struct thread_data *td = cb_data_to_td(data);
1774 unsigned long long v = *__val;
1775
f248a525 1776 if (parse_is_percent_uncapped(v)) {
8b38f401
AD
1777 td->o.io_size = 0;
1778 td->o.io_size_percent = -1ULL - v;
f248a525
AD
1779 if (td->o.io_size_percent > 100) {
1780 log_err("fio: io_size values greater than 100%% aren't supported\n");
1781 return 1;
1782 }
8b38f401
AD
1783 dprint(FD_PARSE, "SET io_size_percent %d\n",
1784 td->o.io_size_percent);
8f39afa7
AD
1785 } else if (parse_is_zone(v)) {
1786 td->o.io_size = 0;
1787 td->o.io_size_percent = 0;
1788 td->o.io_size_nz = v - ZONE_BASE_VAL;
8b38f401
AD
1789 } else
1790 td->o.io_size = v;
1791
1792 return 0;
1793}
1794
dcb1f3a9 1795static int str_zoneskip_cb(void *data, long long *__val)
8f39afa7
AD
1796{
1797 struct thread_data *td = cb_data_to_td(data);
1798 unsigned long long v = *__val;
1799
1800 if (parse_is_zone(v)) {
1801 td->o.zone_skip = 0;
1802 td->o.zone_skip_nz = v - ZONE_BASE_VAL;
1803 } else
1804 td->o.zone_skip = v;
1805
1806 return 0;
1807}
1808
dded427c
OS
1809static int str_write_bw_log_cb(void *data, const char *str)
1810{
1811 struct thread_data *td = cb_data_to_td(data);
1812
1813 if (str)
1814 td->o.bw_log_file = strdup(str);
1815
1816 td->o.write_bw_log = 1;
1817 return 0;
1818}
1819
1820static int str_write_lat_log_cb(void *data, const char *str)
1821{
1822 struct thread_data *td = cb_data_to_td(data);
1823
1824 if (str)
1825 td->o.lat_log_file = strdup(str);
1826
1827 td->o.write_lat_log = 1;
1828 return 0;
1829}
1830
1831static int str_write_iops_log_cb(void *data, const char *str)
1832{
1833 struct thread_data *td = cb_data_to_td(data);
1834
1835 if (str)
1836 td->o.iops_log_file = strdup(str);
1837
1838 td->o.write_iops_log = 1;
1839 return 0;
1840}
1841
1842static int str_write_hist_log_cb(void *data, const char *str)
1843{
1844 struct thread_data *td = cb_data_to_td(data);
1845
1846 if (str)
1847 td->o.hist_log_file = strdup(str);
1848
1849 td->o.write_hist_log = 1;
1850 return 0;
1851}
1852
6730b40f
TK
1853/*
1854 * str is supposed to be a substring of the strdup'd original string,
1855 * and is valid only if it's a regular file path.
1856 * This function keeps the pointer to the path as needed later.
1857 *
1858 * "external:/path/to/so\0" <- original pointer updated with strdup'd
1859 * "external\0" <- above pointer after parsed, i.e. ->ioengine
1860 * "/path/to/so\0" <- str argument, i.e. ->ioengine_so_path
1861 */
1862static int str_ioengine_external_cb(void *data, const char *str)
1863{
1864 struct thread_data *td = cb_data_to_td(data);
1865 struct stat sb;
1866 char *p;
1867
1868 if (!str) {
1869 log_err("fio: null external ioengine path\n");
1870 return 1;
1871 }
1872
1873 p = (char *)str; /* str is mutable */
1874 strip_blank_front(&p);
1875 strip_blank_end(p);
1876
1877 if (stat(p, &sb) || !S_ISREG(sb.st_mode)) {
1878 log_err("fio: invalid external ioengine path \"%s\"\n", p);
1879 return 1;
1880 }
1881
1882 td->o.ioengine_so_path = p;
1883 return 0;
1884}
1885
9109883a 1886static int rw_verify(const struct fio_option *o, void *data)
896cac2a 1887{
a609f12a 1888 struct thread_data *td = cb_data_to_td(data);
896cac2a 1889
d81d0f99
VF
1890 if (read_only && (td_write(td) || td_trim(td))) {
1891 log_err("fio: job <%s> has write or trim bit set, but"
1892 " fio is in read-only mode\n", td->o.name);
896cac2a
JA
1893 return 1;
1894 }
1895
1896 return 0;
1897}
1898
9109883a 1899static int gtod_cpu_verify(const struct fio_option *o, void *data)
29d43ff9 1900{
276ca4f7 1901#ifndef FIO_HAVE_CPU_AFFINITY
a609f12a 1902 struct thread_data *td = cb_data_to_td(data);
29d43ff9 1903
29d43ff9
JA
1904 if (td->o.gtod_cpu) {
1905 log_err("fio: platform must support CPU affinity for"
1906 "gettimeofday() offloading\n");
1907 return 1;
1908 }
1909#endif
1910
1911 return 0;
1912}
1913
214e1eca
JA
1914/*
1915 * Map of job/command line options
1916 */
9af4a244 1917struct fio_option fio_options[FIO_MAX_OPTS] = {
214e1eca
JA
1918 {
1919 .name = "description",
e8b0e958 1920 .lname = "Description of job",
214e1eca 1921 .type = FIO_OPT_STR_STORE,
a609f12a 1922 .off1 = offsetof(struct thread_options, description),
214e1eca 1923 .help = "Text job description",
e8b0e958 1924 .category = FIO_OPT_C_GENERAL,
0626037e 1925 .group = FIO_OPT_G_DESC,
214e1eca
JA
1926 },
1927 {
1928 .name = "name",
e8b0e958 1929 .lname = "Job name",
214e1eca 1930 .type = FIO_OPT_STR_STORE,
a609f12a 1931 .off1 = offsetof(struct thread_options, name),
214e1eca 1932 .help = "Name of this job",
e8b0e958 1933 .category = FIO_OPT_C_GENERAL,
0626037e 1934 .group = FIO_OPT_G_DESC,
214e1eca 1935 },
9cc8cb91
AK
1936 {
1937 .name = "wait_for",
1938 .lname = "Waitee name",
1939 .type = FIO_OPT_STR_STORE,
a609f12a 1940 .off1 = offsetof(struct thread_options, wait_for),
9cc8cb91
AK
1941 .help = "Name of the job this one wants to wait for before starting",
1942 .category = FIO_OPT_C_GENERAL,
1943 .group = FIO_OPT_G_DESC,
1944 },
214e1eca
JA
1945 {
1946 .name = "filename",
e8b0e958 1947 .lname = "Filename(s)",
214e1eca 1948 .type = FIO_OPT_STR_STORE,
a609f12a 1949 .off1 = offsetof(struct thread_options, filename),
46576743 1950 .maxlen = PATH_MAX,
214e1eca 1951 .cb = str_filename_cb,
f0d524b0 1952 .prio = -1, /* must come after "directory" */
214e1eca 1953 .help = "File(s) to use for the workload",
e8b0e958 1954 .category = FIO_OPT_C_FILE,
0626037e 1955 .group = FIO_OPT_G_FILENAME,
214e1eca 1956 },
80271ca1
ST
1957 {
1958 .name = "filetype",
1959 .lname = "file_type",
1960 .type = FIO_OPT_STR,
1961 .off1 = offsetof(struct thread_options, filetype),
1962 .help = "Assume all files defined in a job are of this type",
1963 .def = "none",
1964 .group = FIO_OPT_G_IO_BASIC,
1965 .category = FIO_OPT_C_FILE,
1966 .posval = {
1967 { .ival = "none", .oval = 0 },
1968 { .ival = "file", .oval = FIO_TYPE_FILE },
1969 { .ival = "block", .oval = FIO_TYPE_BLOCK },
1970 { .ival = "char", .oval = FIO_TYPE_CHAR },
1971 },
1972 },
90fef2d1 1973 {
e8b0e958
JA
1974 .name = "directory",
1975 .lname = "Directory",
1976 .type = FIO_OPT_STR_STORE,
a609f12a 1977 .off1 = offsetof(struct thread_options, directory),
e8b0e958
JA
1978 .cb = str_directory_cb,
1979 .help = "Directory to store files in",
1980 .category = FIO_OPT_C_FILE,
0626037e 1981 .group = FIO_OPT_G_FILENAME,
90fef2d1 1982 },
de98bd30
JA
1983 {
1984 .name = "filename_format",
922a5be8 1985 .lname = "Filename Format",
de98bd30 1986 .type = FIO_OPT_STR_STORE,
a609f12a 1987 .off1 = offsetof(struct thread_options, filename_format),
de98bd30
JA
1988 .prio = -1, /* must come after "directory" */
1989 .help = "Override default $jobname.$jobnum.$filenum naming",
1990 .def = "$jobname.$jobnum.$filenum",
93bb626a
JA
1991 .category = FIO_OPT_C_FILE,
1992 .group = FIO_OPT_G_FILENAME,
ad705bcb 1993 },
922a5be8
JA
1994 {
1995 .name = "unique_filename",
1996 .lname = "Unique Filename",
1997 .type = FIO_OPT_BOOL,
a609f12a 1998 .off1 = offsetof(struct thread_options, unique_filename),
922a5be8
JA
1999 .help = "For network clients, prefix file with source IP",
2000 .def = "1",
2001 .category = FIO_OPT_C_FILE,
2002 .group = FIO_OPT_G_FILENAME,
2003 },
29c1349f
JA
2004 {
2005 .name = "lockfile",
e8b0e958 2006 .lname = "Lockfile",
4d4e80f2 2007 .type = FIO_OPT_STR,
a609f12a 2008 .off1 = offsetof(struct thread_options, file_lock_mode),
29c1349f 2009 .help = "Lock file when doing IO to it",
bc6a0a5d 2010 .prio = 1,
29c1349f 2011 .parent = "filename",
d71c154c 2012 .hide = 0,
4d4e80f2 2013 .def = "none",
e8b0e958 2014 .category = FIO_OPT_C_FILE,
0626037e 2015 .group = FIO_OPT_G_FILENAME,
4d4e80f2
JA
2016 .posval = {
2017 { .ival = "none",
2018 .oval = FILE_LOCK_NONE,
2019 .help = "No file locking",
2020 },
2021 { .ival = "exclusive",
2022 .oval = FILE_LOCK_EXCLUSIVE,
2023 .help = "Exclusive file lock",
2024 },
2025 {
2026 .ival = "readwrite",
2027 .oval = FILE_LOCK_READWRITE,
2028 .help = "Read vs write lock",
2029 },
2030 },
29c1349f 2031 },
214e1eca
JA
2032 {
2033 .name = "opendir",
e8b0e958 2034 .lname = "Open directory",
214e1eca 2035 .type = FIO_OPT_STR_STORE,
a609f12a 2036 .off1 = offsetof(struct thread_options, opendir),
214e1eca
JA
2037 .cb = str_opendir_cb,
2038 .help = "Recursively add files from this directory and down",
e8b0e958 2039 .category = FIO_OPT_C_FILE,
0626037e 2040 .group = FIO_OPT_G_FILENAME,
214e1eca
JA
2041 },
2042 {
2043 .name = "rw",
e8b0e958 2044 .lname = "Read/write",
d3aad8f2 2045 .alias = "readwrite",
214e1eca 2046 .type = FIO_OPT_STR,
211097b2 2047 .cb = str_rw_cb,
a609f12a 2048 .off1 = offsetof(struct thread_options, td_ddir),
214e1eca
JA
2049 .help = "IO direction",
2050 .def = "read",
896cac2a 2051 .verify = rw_verify,
e8b0e958 2052 .category = FIO_OPT_C_IO,
0626037e 2053 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
2054 .posval = {
2055 { .ival = "read",
2056 .oval = TD_DDIR_READ,
2057 .help = "Sequential read",
2058 },
2059 { .ival = "write",
2060 .oval = TD_DDIR_WRITE,
2061 .help = "Sequential write",
2062 },
6eaf09d6
SL
2063 { .ival = "trim",
2064 .oval = TD_DDIR_TRIM,
2065 .help = "Sequential trim",
2066 },
214e1eca
JA
2067 { .ival = "randread",
2068 .oval = TD_DDIR_RANDREAD,
2069 .help = "Random read",
2070 },
2071 { .ival = "randwrite",
2072 .oval = TD_DDIR_RANDWRITE,
2073 .help = "Random write",
2074 },
6eaf09d6
SL
2075 { .ival = "randtrim",
2076 .oval = TD_DDIR_RANDTRIM,
2077 .help = "Random trim",
2078 },
214e1eca
JA
2079 { .ival = "rw",
2080 .oval = TD_DDIR_RW,
2081 .help = "Sequential read and write mix",
2082 },
10b023db
JA
2083 { .ival = "readwrite",
2084 .oval = TD_DDIR_RW,
2085 .help = "Sequential read and write mix",
2086 },
214e1eca
JA
2087 { .ival = "randrw",
2088 .oval = TD_DDIR_RANDRW,
2089 .help = "Random read and write mix"
2090 },
82a90686
JA
2091 { .ival = "trimwrite",
2092 .oval = TD_DDIR_TRIMWRITE,
2093 .help = "Trim and write mix, trims preceding writes"
0e4dd95c 2094 },
c16dc793
JA
2095 { .ival = "randtrimwrite",
2096 .oval = TD_DDIR_RANDTRIMWRITE,
2097 .help = "Randomly trim and write mix, trims preceding writes"
2098 },
214e1eca
JA
2099 },
2100 },
38dad62d
JA
2101 {
2102 .name = "rw_sequencer",
e8b0e958 2103 .lname = "RW Sequencer",
38dad62d 2104 .type = FIO_OPT_STR,
a609f12a 2105 .off1 = offsetof(struct thread_options, rw_seq),
38dad62d
JA
2106 .help = "IO offset generator modifier",
2107 .def = "sequential",
e8b0e958 2108 .category = FIO_OPT_C_IO,
0626037e 2109 .group = FIO_OPT_G_IO_BASIC,
38dad62d
JA
2110 .posval = {
2111 { .ival = "sequential",
2112 .oval = RW_SEQ_SEQ,
2113 .help = "Generate sequential offsets",
2114 },
2115 { .ival = "identical",
2116 .oval = RW_SEQ_IDENT,
2117 .help = "Generate identical offsets",
2118 },
2119 },
2120 },
2121
214e1eca
JA
2122 {
2123 .name = "ioengine",
e8b0e958 2124 .lname = "IO Engine",
214e1eca 2125 .type = FIO_OPT_STR_STORE,
a609f12a 2126 .off1 = offsetof(struct thread_options, ioengine),
214e1eca 2127 .help = "IO engine to use",
58483fa4 2128 .def = FIO_PREFERRED_ENGINE,
e8b0e958 2129 .category = FIO_OPT_C_IO,
0626037e 2130 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
2131 .posval = {
2132 { .ival = "sync",
2133 .help = "Use read/write",
2134 },
a31041ea 2135 { .ival = "psync",
2136 .help = "Use pread/pwrite",
2137 },
1d2af02a 2138 { .ival = "vsync",
03e20d68 2139 .help = "Use readv/writev",
1d2af02a 2140 },
07fc0acd
JA
2141#ifdef CONFIG_PWRITEV
2142 { .ival = "pvsync",
2143 .help = "Use preadv/pwritev",
2144 },
2145#endif
6562685f 2146#ifdef FIO_HAVE_PWRITEV2
2cafffbe
JA
2147 { .ival = "pvsync2",
2148 .help = "Use preadv2/pwritev2",
2149 },
2150#endif
67bf9823 2151#ifdef CONFIG_LIBAIO
214e1eca
JA
2152 { .ival = "libaio",
2153 .help = "Linux native asynchronous IO",
2154 },
2155#endif
bffad86f
JA
2156#ifdef ARCH_HAVE_IOURING
2157 { .ival = "io_uring",
2158 .help = "Fast Linux native aio",
52885fa2
JA
2159 },
2160#endif
67bf9823 2161#ifdef CONFIG_POSIXAIO
214e1eca
JA
2162 { .ival = "posixaio",
2163 .help = "POSIX asynchronous IO",
2164 },
417f0068 2165#endif
997843cb 2166#ifdef CONFIG_SOLARISAIO
417f0068
JA
2167 { .ival = "solarisaio",
2168 .help = "Solaris native asynchronous IO",
2169 },
214e1eca 2170#endif
4700b234 2171#ifdef CONFIG_WINDOWSAIO
03e20d68 2172 { .ival = "windowsaio",
3be80071 2173 .help = "Windows native asynchronous IO"
de890a1e 2174 },
fc5c0345
DG
2175#endif
2176#ifdef CONFIG_RBD
2177 { .ival = "rbd",
2178 .help = "Rados Block Device asynchronous IO"
2179 },
3be80071 2180#endif
214e1eca 2181 { .ival = "mmap",
03e20d68 2182 .help = "Memory mapped IO"
214e1eca 2183 },
67bf9823 2184#ifdef CONFIG_LINUX_SPLICE
214e1eca
JA
2185 { .ival = "splice",
2186 .help = "splice/vmsplice based IO",
2187 },
9cce02e8
JA
2188 { .ival = "netsplice",
2189 .help = "splice/vmsplice to/from the network",
2190 },
214e1eca
JA
2191#endif
2192#ifdef FIO_HAVE_SGIO
2193 { .ival = "sg",
2194 .help = "SCSI generic v3 IO",
2195 },
2196#endif
2197 { .ival = "null",
2198 .help = "Testing engine (no data transfer)",
2199 },
2200 { .ival = "net",
2201 .help = "Network IO",
2202 },
214e1eca 2203 { .ival = "cpuio",
03e20d68 2204 .help = "CPU cycle burner engine",
214e1eca 2205 },
67bf9823 2206#ifdef CONFIG_RDMA
21b8aee8 2207 { .ival = "rdma",
2208 .help = "RDMA IO engine",
2209 },
8200b8c7 2210#endif
997843cb 2211#ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
1ecc95ca
JA
2212 { .ival = "e4defrag",
2213 .help = "ext4 defrag engine",
2214 },
2215#endif
997843cb 2216#ifdef CONFIG_LINUX_FALLOCATE
1ecc95ca
JA
2217 { .ival = "falloc",
2218 .help = "fallocate() file based engine",
2219 },
b8c82a46 2220#endif
a7c386f4 2221#ifdef CONFIG_GFAPI
2222 { .ival = "gfapi",
cc47f094 2223 .help = "Glusterfs libgfapi(sync) based engine"
2224 },
2225 { .ival = "gfapi_async",
2226 .help = "Glusterfs libgfapi(async) based engine"
a7c386f4 2227 },
2228#endif
1b10477b 2229#ifdef CONFIG_LIBHDFS
b74e419e 2230 { .ival = "libhdfs",
1b10477b
MM
2231 .help = "Hadoop Distributed Filesystem (HDFS) engine"
2232 },
5c4ef02e 2233#endif
a40e7a59
GB
2234#ifdef CONFIG_IME
2235 { .ival = "ime_psync",
2236 .help = "DDN's IME synchronous IO engine",
2237 },
2238 { .ival = "ime_psyncv",
2239 .help = "DDN's IME synchronous IO engine using iovecs",
2240 },
2241 { .ival = "ime_aio",
2242 .help = "DDN's IME asynchronous IO engine",
2243 },
2244#endif
104ee4de
DJ
2245#ifdef CONFIG_LINUX_DEVDAX
2246 { .ival = "dev-dax",
2247 .help = "DAX Device based IO engine",
2248 },
1b10477b 2249#endif
edc5fa12
JA
2250 {
2251 .ival = "filecreate",
2252 .help = "File creation engine",
2253 },
214e1eca
JA
2254 { .ival = "external",
2255 .help = "Load external engine (append name)",
6730b40f 2256 .cb = str_ioengine_external_cb,
214e1eca 2257 },
ae0db592
TI
2258#ifdef CONFIG_LIBPMEM
2259 { .ival = "libpmem",
363a5f65 2260 .help = "PMDK libpmem based IO engine",
ae0db592 2261 },
c2f6a13d
LMB
2262#endif
2263#ifdef CONFIG_HTTP
2264 { .ival = "http",
2265 .help = "HTTP (WebDAV/S3) IO engine",
2266 },
ae0db592 2267#endif
d643a1e2
RJ
2268 { .ival = "nbd",
2269 .help = "Network Block Device (NBD) IO engine"
2270 },
c363fdd7
JL
2271#ifdef CONFIG_DFS
2272 { .ival = "dfs",
2273 .help = "DAOS File System (dfs) IO engine",
2274 },
9326926b 2275#endif
98ab1262 2276#ifdef CONFIG_LIBNFS
9326926b
TG
2277 { .ival = "nfs",
2278 .help = "NFS IO engine",
2279 },
a3ff873e
AK
2280#endif
2281#ifdef CONFIG_LIBXNVME
2282 { .ival = "xnvme",
2283 .help = "XNVME IO engine",
2284 },
c363fdd7 2285#endif
214e1eca
JA
2286 },
2287 },
2288 {
2289 .name = "iodepth",
e8b0e958 2290 .lname = "IO Depth",
214e1eca 2291 .type = FIO_OPT_INT,
a609f12a 2292 .off1 = offsetof(struct thread_options, iodepth),
03e20d68 2293 .help = "Number of IO buffers to keep in flight",
757aff4f 2294 .minval = 1,
20eb06bd 2295 .interval = 1,
214e1eca 2296 .def = "1",
e8b0e958 2297 .category = FIO_OPT_C_IO,
0626037e 2298 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
2299 },
2300 {
2301 .name = "iodepth_batch",
e8b0e958 2302 .lname = "IO Depth batch",
4950421a 2303 .alias = "iodepth_batch_submit",
214e1eca 2304 .type = FIO_OPT_INT,
a609f12a 2305 .off1 = offsetof(struct thread_options, iodepth_batch),
d65db441 2306 .help = "Number of IO buffers to submit in one go",
afdf9352 2307 .parent = "iodepth",
d71c154c 2308 .hide = 1,
20eb06bd 2309 .interval = 1,
a2e6f8ac 2310 .def = "1",
e8b0e958 2311 .category = FIO_OPT_C_IO,
0626037e 2312 .group = FIO_OPT_G_IO_BASIC,
4950421a
JA
2313 },
2314 {
82407585
RP
2315 .name = "iodepth_batch_complete_min",
2316 .lname = "Min IO depth batch complete",
2317 .alias = "iodepth_batch_complete",
4950421a 2318 .type = FIO_OPT_INT,
a609f12a 2319 .off1 = offsetof(struct thread_options, iodepth_batch_complete_min),
82407585 2320 .help = "Min number of IO buffers to retrieve in one go",
4950421a 2321 .parent = "iodepth",
d71c154c 2322 .hide = 1,
4950421a 2323 .minval = 0,
20eb06bd 2324 .interval = 1,
4950421a 2325 .def = "1",
e8b0e958 2326 .category = FIO_OPT_C_IO,
0626037e 2327 .group = FIO_OPT_G_IO_BASIC,
214e1eca 2328 },
82407585
RP
2329 {
2330 .name = "iodepth_batch_complete_max",
2331 .lname = "Max IO depth batch complete",
2332 .type = FIO_OPT_INT,
a609f12a 2333 .off1 = offsetof(struct thread_options, iodepth_batch_complete_max),
82407585
RP
2334 .help = "Max number of IO buffers to retrieve in one go",
2335 .parent = "iodepth",
2336 .hide = 1,
2337 .minval = 0,
2338 .interval = 1,
2339 .category = FIO_OPT_C_IO,
2340 .group = FIO_OPT_G_IO_BASIC,
2341 },
214e1eca
JA
2342 {
2343 .name = "iodepth_low",
e8b0e958 2344 .lname = "IO Depth batch low",
214e1eca 2345 .type = FIO_OPT_INT,
a609f12a 2346 .off1 = offsetof(struct thread_options, iodepth_low),
214e1eca 2347 .help = "Low water mark for queuing depth",
afdf9352 2348 .parent = "iodepth",
d71c154c 2349 .hide = 1,
20eb06bd 2350 .interval = 1,
e8b0e958 2351 .category = FIO_OPT_C_IO,
0626037e 2352 .group = FIO_OPT_G_IO_BASIC,
214e1eca 2353 },
997b5680
SW
2354 {
2355 .name = "serialize_overlap",
2356 .lname = "Serialize overlap",
2357 .off1 = offsetof(struct thread_options, serialize_overlap),
2358 .type = FIO_OPT_BOOL,
2359 .help = "Wait for in-flight IOs that collide to complete",
2360 .parent = "iodepth",
2361 .def = "0",
2362 .category = FIO_OPT_C_IO,
2363 .group = FIO_OPT_G_IO_BASIC,
2364 },
a9da8ab2
JA
2365 {
2366 .name = "io_submit_mode",
2367 .lname = "IO submit mode",
2368 .type = FIO_OPT_STR,
a609f12a 2369 .off1 = offsetof(struct thread_options, io_submit_mode),
a9da8ab2
JA
2370 .help = "How IO submissions and completions are done",
2371 .def = "inline",
2372 .category = FIO_OPT_C_IO,
2373 .group = FIO_OPT_G_IO_BASIC,
2374 .posval = {
2375 { .ival = "inline",
2376 .oval = IO_MODE_INLINE,
2377 .help = "Submit and complete IO inline",
2378 },
2379 { .ival = "offload",
2380 .oval = IO_MODE_OFFLOAD,
2381 .help = "Offload submit and complete to threads",
2382 },
2383 },
2384 },
214e1eca
JA
2385 {
2386 .name = "size",
e8b0e958 2387 .lname = "Size",
8f39afa7 2388 .type = FIO_OPT_STR_VAL_ZONE,
7bb59102 2389 .cb = str_size_cb,
a609f12a 2390 .off1 = offsetof(struct thread_options, size),
214e1eca 2391 .help = "Total size of device or files",
e8b0e958
JA
2392 .category = FIO_OPT_C_IO,
2393 .group = FIO_OPT_G_INVALID,
214e1eca 2394 },
77731b29 2395 {
a4d3b4db
JA
2396 .name = "io_size",
2397 .alias = "io_limit",
2398 .lname = "IO Size",
8f39afa7 2399 .type = FIO_OPT_STR_VAL_ZONE,
8b38f401 2400 .cb = str_io_size_cb,
5be9bf09 2401 .off1 = offsetof(struct thread_options, io_size),
1684f7fd 2402 .help = "Total size of I/O to be performed",
77731b29
JA
2403 .category = FIO_OPT_C_IO,
2404 .group = FIO_OPT_G_INVALID,
2405 },
aa31f1f1
SL
2406 {
2407 .name = "fill_device",
e8b0e958 2408 .lname = "Fill device",
74586c1e 2409 .alias = "fill_fs",
aa31f1f1 2410 .type = FIO_OPT_BOOL,
a609f12a 2411 .off1 = offsetof(struct thread_options, fill_device),
aa31f1f1
SL
2412 .help = "Write until an ENOSPC error occurs",
2413 .def = "0",
e8b0e958
JA
2414 .category = FIO_OPT_C_FILE,
2415 .group = FIO_OPT_G_INVALID,
aa31f1f1 2416 },
214e1eca
JA
2417 {
2418 .name = "filesize",
e8b0e958 2419 .lname = "File size",
214e1eca 2420 .type = FIO_OPT_STR_VAL,
a609f12a
JA
2421 .off1 = offsetof(struct thread_options, file_size_low),
2422 .off2 = offsetof(struct thread_options, file_size_high),
c3edbdba 2423 .minval = 1,
214e1eca 2424 .help = "Size of individual files",
20eb06bd 2425 .interval = 1024 * 1024,
e8b0e958
JA
2426 .category = FIO_OPT_C_FILE,
2427 .group = FIO_OPT_G_INVALID,
214e1eca 2428 },
bedc9dc2
JA
2429 {
2430 .name = "file_append",
2431 .lname = "File append",
2432 .type = FIO_OPT_BOOL,
a609f12a 2433 .off1 = offsetof(struct thread_options, file_append),
bedc9dc2
JA
2434 .help = "IO will start at the end of the file(s)",
2435 .def = "0",
2436 .category = FIO_OPT_C_FILE,
2437 .group = FIO_OPT_G_INVALID,
2438 },
67a1000f
JA
2439 {
2440 .name = "offset",
e8b0e958 2441 .lname = "IO offset",
67a1000f 2442 .alias = "fileoffset",
8f39afa7 2443 .type = FIO_OPT_STR_VAL_ZONE,
89978a6b 2444 .cb = str_offset_cb,
a609f12a 2445 .off1 = offsetof(struct thread_options, start_offset),
67a1000f
JA
2446 .help = "Start IO from this offset",
2447 .def = "0",
e8b0e958
JA
2448 .category = FIO_OPT_C_IO,
2449 .group = FIO_OPT_G_INVALID,
67a1000f 2450 },
83c8b093
JF
2451 {
2452 .name = "offset_align",
2453 .lname = "IO offset alignment",
2454 .type = FIO_OPT_INT,
2455 .off1 = offsetof(struct thread_options, start_offset_align),
2456 .help = "Start IO from this offset alignment",
2457 .def = "0",
2458 .interval = 512,
2459 .category = FIO_OPT_C_IO,
2460 .group = FIO_OPT_G_INVALID,
2461 },
2d7cd868
JA
2462 {
2463 .name = "offset_increment",
e8b0e958 2464 .lname = "IO offset increment",
8f39afa7 2465 .type = FIO_OPT_STR_VAL_ZONE,
0b288ba1 2466 .cb = str_offset_increment_cb,
a609f12a 2467 .off1 = offsetof(struct thread_options, offset_increment),
2d7cd868
JA
2468 .help = "What is the increment from one offset to the next",
2469 .parent = "offset",
d71c154c 2470 .hide = 1,
2d7cd868 2471 .def = "0",
e8b0e958
JA
2472 .category = FIO_OPT_C_IO,
2473 .group = FIO_OPT_G_INVALID,
2d7cd868 2474 },
ddf24e42
JA
2475 {
2476 .name = "number_ios",
2477 .lname = "Number of IOs to perform",
2478 .type = FIO_OPT_STR_VAL,
a609f12a 2479 .off1 = offsetof(struct thread_options, number_ios),
be3fec7d 2480 .help = "Force job completion after this number of IOs",
ddf24e42
JA
2481 .def = "0",
2482 .category = FIO_OPT_C_IO,
2483 .group = FIO_OPT_G_INVALID,
2484 },
b3251e31
AK
2485 {
2486 .name = "num_range",
2487 .lname = "Number of ranges",
2488 .type = FIO_OPT_INT,
2489 .off1 = offsetof(struct thread_options, num_range),
2490 .maxval = MAX_TRIM_RANGE,
2491 .help = "Number of ranges for trim command",
2492 .def = "1",
2493 .category = FIO_OPT_C_IO,
2494 .group = FIO_OPT_G_INVALID,
2495 },
214e1eca
JA
2496 {
2497 .name = "bs",
e8b0e958 2498 .lname = "Block size",
d3aad8f2 2499 .alias = "blocksize",
5fff9543 2500 .type = FIO_OPT_ULL,
a609f12a
JA
2501 .off1 = offsetof(struct thread_options, bs[DDIR_READ]),
2502 .off2 = offsetof(struct thread_options, bs[DDIR_WRITE]),
2503 .off3 = offsetof(struct thread_options, bs[DDIR_TRIM]),
c3edbdba 2504 .minval = 1,
214e1eca 2505 .help = "Block size unit",
2b9136a3 2506 .def = "4096",
67a1000f 2507 .parent = "rw",
d71c154c 2508 .hide = 1,
20eb06bd 2509 .interval = 512,
e8b0e958
JA
2510 .category = FIO_OPT_C_IO,
2511 .group = FIO_OPT_G_INVALID,
214e1eca 2512 },
2b7a01d0
JA
2513 {
2514 .name = "ba",
e8b0e958 2515 .lname = "Block size align",
2b7a01d0 2516 .alias = "blockalign",
5fff9543 2517 .type = FIO_OPT_ULL,
a609f12a
JA
2518 .off1 = offsetof(struct thread_options, ba[DDIR_READ]),
2519 .off2 = offsetof(struct thread_options, ba[DDIR_WRITE]),
2520 .off3 = offsetof(struct thread_options, ba[DDIR_TRIM]),
2b7a01d0
JA
2521 .minval = 1,
2522 .help = "IO block offset alignment",
2523 .parent = "rw",
d71c154c 2524 .hide = 1,
20eb06bd 2525 .interval = 512,
e8b0e958
JA
2526 .category = FIO_OPT_C_IO,
2527 .group = FIO_OPT_G_INVALID,
2b7a01d0 2528 },
214e1eca
JA
2529 {
2530 .name = "bsrange",
e8b0e958 2531 .lname = "Block size range",
d3aad8f2 2532 .alias = "blocksize_range",
214e1eca 2533 .type = FIO_OPT_RANGE,
a609f12a
JA
2534 .off1 = offsetof(struct thread_options, min_bs[DDIR_READ]),
2535 .off2 = offsetof(struct thread_options, max_bs[DDIR_READ]),
2536 .off3 = offsetof(struct thread_options, min_bs[DDIR_WRITE]),
2537 .off4 = offsetof(struct thread_options, max_bs[DDIR_WRITE]),
2538 .off5 = offsetof(struct thread_options, min_bs[DDIR_TRIM]),
2539 .off6 = offsetof(struct thread_options, max_bs[DDIR_TRIM]),
c3edbdba 2540 .minval = 1,
214e1eca 2541 .help = "Set block size range (in more detail than bs)",
67a1000f 2542 .parent = "rw",
d71c154c 2543 .hide = 1,
20eb06bd 2544 .interval = 4096,
e8b0e958
JA
2545 .category = FIO_OPT_C_IO,
2546 .group = FIO_OPT_G_INVALID,
214e1eca 2547 },
564ca972
JA
2548 {
2549 .name = "bssplit",
e8b0e958 2550 .lname = "Block size split",
5fff9543 2551 .type = FIO_OPT_STR_ULL,
564ca972 2552 .cb = str_bssplit_cb,
a609f12a 2553 .off1 = offsetof(struct thread_options, bssplit),
564ca972
JA
2554 .help = "Set a specific mix of block sizes",
2555 .parent = "rw",
d71c154c 2556 .hide = 1,
e8b0e958
JA
2557 .category = FIO_OPT_C_IO,
2558 .group = FIO_OPT_G_INVALID,
564ca972 2559 },
214e1eca
JA
2560 {
2561 .name = "bs_unaligned",
e8b0e958 2562 .lname = "Block size unaligned",
d3aad8f2 2563 .alias = "blocksize_unaligned",
214e1eca 2564 .type = FIO_OPT_STR_SET,
a609f12a 2565 .off1 = offsetof(struct thread_options, bs_unaligned),
214e1eca 2566 .help = "Don't sector align IO buffer sizes",
67a1000f 2567 .parent = "rw",
d71c154c 2568 .hide = 1,
e8b0e958
JA
2569 .category = FIO_OPT_C_IO,
2570 .group = FIO_OPT_G_INVALID,
214e1eca 2571 },
6aca9b3d
JA
2572 {
2573 .name = "bs_is_seq_rand",
2574 .lname = "Block size division is seq/random (not read/write)",
2575 .type = FIO_OPT_BOOL,
a609f12a 2576 .off1 = offsetof(struct thread_options, bs_is_seq_rand),
86d59660 2577 .help = "Consider any blocksize setting to be sequential,random",
6aca9b3d
JA
2578 .def = "0",
2579 .parent = "blocksize",
2580 .category = FIO_OPT_C_IO,
2581 .group = FIO_OPT_G_INVALID,
2582 },
214e1eca
JA
2583 {
2584 .name = "randrepeat",
95282650 2585 .alias = "allrandrepeat",
e8b0e958 2586 .lname = "Random repeatable",
214e1eca 2587 .type = FIO_OPT_BOOL,
a609f12a 2588 .off1 = offsetof(struct thread_options, rand_repeatable),
214e1eca
JA
2589 .help = "Use repeatable random IO pattern",
2590 .def = "1",
67a1000f 2591 .parent = "rw",
d71c154c 2592 .hide = 1,
e8b0e958 2593 .category = FIO_OPT_C_IO,
3ceb458f 2594 .group = FIO_OPT_G_RANDOM,
214e1eca 2595 },
04778baf
JA
2596 {
2597 .name = "randseed",
2598 .lname = "The random generator seed",
363cffa7 2599 .type = FIO_OPT_STR_VAL,
a609f12a 2600 .off1 = offsetof(struct thread_options, rand_seed),
04778baf 2601 .help = "Set the random generator seed value",
40fe5e7b 2602 .def = "0x89",
04778baf
JA
2603 .parent = "rw",
2604 .category = FIO_OPT_C_IO,
2605 .group = FIO_OPT_G_RANDOM,
2606 },
214e1eca
JA
2607 {
2608 .name = "norandommap",
e8b0e958 2609 .lname = "No randommap",
214e1eca 2610 .type = FIO_OPT_STR_SET,
a609f12a 2611 .off1 = offsetof(struct thread_options, norandommap),
214e1eca 2612 .help = "Accept potential duplicate random blocks",
67a1000f 2613 .parent = "rw",
d71c154c 2614 .hide = 1,
b2452a43 2615 .hide_on_set = 1,
e8b0e958 2616 .category = FIO_OPT_C_IO,
3ceb458f 2617 .group = FIO_OPT_G_RANDOM,
214e1eca 2618 },
2b386d25
JA
2619 {
2620 .name = "softrandommap",
e8b0e958 2621 .lname = "Soft randommap",
2b386d25 2622 .type = FIO_OPT_BOOL,
a609f12a 2623 .off1 = offsetof(struct thread_options, softrandommap),
f66ab3c8 2624 .help = "Set norandommap if randommap allocation fails",
2b386d25 2625 .parent = "norandommap",
d71c154c 2626 .hide = 1,
2b386d25 2627 .def = "0",
e8b0e958 2628 .category = FIO_OPT_C_IO,
3ceb458f 2629 .group = FIO_OPT_G_RANDOM,
2b386d25 2630 },
811162f6
TW
2631 {
2632 .name = "sprandom",
2633 .lname = "Sandisk Pseudo Random Preconditioning",
2634 .type = FIO_OPT_BOOL,
2635 .off1 = offsetof(struct thread_options, sprandom),
2636 .help = "Set up Sandisk Pseudo Random Preconditioning",
2637 .parent = "rw",
2638 .hide = 1,
2639 .def = "0",
2640 .category = FIO_OPT_C_IO,
2641 .group = FIO_OPT_G_RANDOM,
2642 },
2643 {
2644 .name = "spr_num_regions",
2645 .lname = "SPRandom number of regions",
2646 .type = FIO_OPT_INT,
2647 .off1 = offsetof(struct thread_options, spr_num_regions),
2648 .help = "Number of regions for sprandom",
2649 .parent = "sprandom",
2650 .hide = 1,
2651 .def = "100",
2652 .category = FIO_OPT_C_IO,
2653 .group = FIO_OPT_G_RANDOM,
2654 },
2655 {
2656 .name = "spr_op",
2657 .lname = "SPRandom Over provisioning",
2658 .type = FIO_OPT_FLOAT_LIST,
2659 .off1 = offsetof(struct thread_options, spr_over_provisioning),
2660 .help = "Over provisioning ratio for SPRandom",
2661 .parent = "sprandom",
2662 .maxlen = 1,
2663 .hide = 1,
2664 .def = "0.15",
2665 .category = FIO_OPT_C_IO,
2666 .group = FIO_OPT_G_RANDOM,
2667 },
8055e41d
JA
2668 {
2669 .name = "random_generator",
cce2fdfe 2670 .lname = "Random Generator",
8055e41d 2671 .type = FIO_OPT_STR,
a609f12a 2672 .off1 = offsetof(struct thread_options, random_generator),
8055e41d
JA
2673 .help = "Type of random number generator to use",
2674 .def = "tausworthe",
2675 .posval = {
2676 { .ival = "tausworthe",
2677 .oval = FIO_RAND_GEN_TAUSWORTHE,
2678 .help = "Strong Tausworthe generator",
2679 },
2680 { .ival = "lfsr",
2681 .oval = FIO_RAND_GEN_LFSR,
2682 .help = "Variable length LFSR",
2683 },
c3546b53
JA
2684 {
2685 .ival = "tausworthe64",
2686 .oval = FIO_RAND_GEN_TAUSWORTHE64,
2687 .help = "64-bit Tausworthe variant",
2688 },
8055e41d 2689 },
48107598
JA
2690 .category = FIO_OPT_C_IO,
2691 .group = FIO_OPT_G_RANDOM,
8055e41d 2692 },
e25839d4
JA
2693 {
2694 .name = "random_distribution",
cce2fdfe 2695 .lname = "Random Distribution",
e25839d4 2696 .type = FIO_OPT_STR,
a609f12a 2697 .off1 = offsetof(struct thread_options, random_distribution),
e25839d4
JA
2698 .cb = str_random_distribution_cb,
2699 .help = "Random offset distribution generator",
2700 .def = "random",
2701 .posval = {
2702 { .ival = "random",
2703 .oval = FIO_RAND_DIST_RANDOM,
2704 .help = "Completely random",
2705 },
2706 { .ival = "zipf",
2707 .oval = FIO_RAND_DIST_ZIPF,
2708 .help = "Zipf distribution",
2709 },
925fee33
JA
2710 { .ival = "pareto",
2711 .oval = FIO_RAND_DIST_PARETO,
2712 .help = "Pareto distribution",
2713 },
56d9fa4b
JA
2714 { .ival = "normal",
2715 .oval = FIO_RAND_DIST_GAUSS,
ba2b3b07 2716 .help = "Normal (Gaussian) distribution",
56d9fa4b 2717 },
e0a04ac1
JA
2718 { .ival = "zoned",
2719 .oval = FIO_RAND_DIST_ZONED,
2720 .help = "Zoned random distribution",
2721 },
59466396
JA
2722 { .ival = "zoned_abs",
2723 .oval = FIO_RAND_DIST_ZONED_ABS,
2724 .help = "Zoned absolute random distribution",
2725 },
e25839d4 2726 },
48107598
JA
2727 .category = FIO_OPT_C_IO,
2728 .group = FIO_OPT_G_RANDOM,
e25839d4 2729 },
211c9b89
JA
2730 {
2731 .name = "percentage_random",
2732 .lname = "Percentage Random",
2733 .type = FIO_OPT_INT,
a609f12a
JA
2734 .off1 = offsetof(struct thread_options, perc_rand[DDIR_READ]),
2735 .off2 = offsetof(struct thread_options, perc_rand[DDIR_WRITE]),
2736 .off3 = offsetof(struct thread_options, perc_rand[DDIR_TRIM]),
211c9b89
JA
2737 .maxval = 100,
2738 .help = "Percentage of seq/random mix that should be random",
d9472271 2739 .def = "100,100,100",
211c9b89
JA
2740 .interval = 5,
2741 .inverse = "percentage_sequential",
2742 .category = FIO_OPT_C_IO,
2743 .group = FIO_OPT_G_RANDOM,
2744 },
2745 {
2746 .name = "percentage_sequential",
2747 .lname = "Percentage Sequential",
d9472271 2748 .type = FIO_OPT_DEPRECATED,
211c9b89
JA
2749 .category = FIO_OPT_C_IO,
2750 .group = FIO_OPT_G_RANDOM,
2751 },
214e1eca
JA
2752 {
2753 .name = "nrfiles",
e8b0e958 2754 .lname = "Number of files",
d7c8be03 2755 .alias = "nr_files",
214e1eca 2756 .type = FIO_OPT_INT,
a609f12a 2757 .off1 = offsetof(struct thread_options, nr_files),
214e1eca
JA
2758 .help = "Split job workload between this number of files",
2759 .def = "1",
20eb06bd 2760 .interval = 1,
e8b0e958
JA
2761 .category = FIO_OPT_C_FILE,
2762 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2763 },
2764 {
2765 .name = "openfiles",
e8b0e958 2766 .lname = "Number of open files",
214e1eca 2767 .type = FIO_OPT_INT,
a609f12a 2768 .off1 = offsetof(struct thread_options, open_files),
214e1eca 2769 .help = "Number of files to keep open at the same time",
e8b0e958
JA
2770 .category = FIO_OPT_C_FILE,
2771 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2772 },
2773 {
2774 .name = "file_service_type",
e8b0e958 2775 .lname = "File service type",
214e1eca
JA
2776 .type = FIO_OPT_STR,
2777 .cb = str_fst_cb,
a609f12a 2778 .off1 = offsetof(struct thread_options, file_service_type),
214e1eca
JA
2779 .help = "How to select which file to service next",
2780 .def = "roundrobin",
e8b0e958
JA
2781 .category = FIO_OPT_C_FILE,
2782 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2783 .posval = {
2784 { .ival = "random",
2785 .oval = FIO_FSERVICE_RANDOM,
8c07860d
JA
2786 .help = "Choose a file at random (uniform)",
2787 },
2788 { .ival = "zipf",
2789 .oval = FIO_FSERVICE_ZIPF,
2790 .help = "Zipf randomized",
2791 },
2792 { .ival = "pareto",
2793 .oval = FIO_FSERVICE_PARETO,
2794 .help = "Pareto randomized",
2795 },
dd3503d3
SW
2796 { .ival = "normal",
2797 .oval = FIO_FSERVICE_GAUSS,
2798 .help = "Normal (Gaussian) randomized",
2799 },
8c07860d
JA
2800 { .ival = "gauss",
2801 .oval = FIO_FSERVICE_GAUSS,
dd3503d3 2802 .help = "Alias for normal",
214e1eca
JA
2803 },
2804 { .ival = "roundrobin",
2805 .oval = FIO_FSERVICE_RR,
2806 .help = "Round robin select files",
2807 },
a086c257
JA
2808 { .ival = "sequential",
2809 .oval = FIO_FSERVICE_SEQ,
2810 .help = "Finish one file before moving to the next",
2811 },
214e1eca 2812 },
67a1000f 2813 .parent = "nrfiles",
d71c154c 2814 .hide = 1,
67a1000f 2815 },
7bc8c2cf
JA
2816 {
2817 .name = "fallocate",
e8b0e958 2818 .lname = "Fallocate",
a596f047 2819 .type = FIO_OPT_STR,
a609f12a 2820 .off1 = offsetof(struct thread_options, fallocate_mode),
a596f047 2821 .help = "Whether pre-allocation is performed when laying out files",
38ca5f03 2822#ifdef FIO_HAVE_DEFAULT_FALLOCATE
2c3e17be 2823 .def = "native",
38ca5f03
TV
2824#else
2825 .def = "none",
2826#endif
e8b0e958
JA
2827 .category = FIO_OPT_C_FILE,
2828 .group = FIO_OPT_G_INVALID,
a596f047
EG
2829 .posval = {
2830 { .ival = "none",
2831 .oval = FIO_FALLOCATE_NONE,
2832 .help = "Do not pre-allocate space",
2833 },
2c3e17be
SW
2834 { .ival = "native",
2835 .oval = FIO_FALLOCATE_NATIVE,
2836 .help = "Use native pre-allocation if possible",
2837 },
2838#ifdef CONFIG_POSIX_FALLOCATE
a596f047
EG
2839 { .ival = "posix",
2840 .oval = FIO_FALLOCATE_POSIX,
2841 .help = "Use posix_fallocate()",
2842 },
2c3e17be 2843#endif
97ac992c 2844#ifdef CONFIG_LINUX_FALLOCATE
a596f047
EG
2845 { .ival = "keep",
2846 .oval = FIO_FALLOCATE_KEEP_SIZE,
2847 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
2848 },
7bc8c2cf 2849#endif
38ca5f03
TV
2850 { .ival = "truncate",
2851 .oval = FIO_FALLOCATE_TRUNCATE,
2852 .help = "Truncate file to final size instead of allocating"
2853 },
a596f047
EG
2854 /* Compatibility with former boolean values */
2855 { .ival = "0",
2856 .oval = FIO_FALLOCATE_NONE,
2857 .help = "Alias for 'none'",
2858 },
2c3e17be 2859#ifdef CONFIG_POSIX_FALLOCATE
a596f047
EG
2860 { .ival = "1",
2861 .oval = FIO_FALLOCATE_POSIX,
2862 .help = "Alias for 'posix'",
2863 },
2c3e17be 2864#endif
a596f047
EG
2865 },
2866 },
67a1000f
JA
2867 {
2868 .name = "fadvise_hint",
e8b0e958 2869 .lname = "Fadvise hint",
ecb2083d 2870 .type = FIO_OPT_STR,
a609f12a 2871 .off1 = offsetof(struct thread_options, fadvise_hint),
ecb2083d
JA
2872 .posval = {
2873 { .ival = "0",
2874 .oval = F_ADV_NONE,
c712c97a 2875 .help = "Don't issue fadvise/madvise",
ecb2083d
JA
2876 },
2877 { .ival = "1",
2878 .oval = F_ADV_TYPE,
2879 .help = "Advise using fio IO pattern",
2880 },
2881 { .ival = "random",
2882 .oval = F_ADV_RANDOM,
2883 .help = "Advise using FADV_RANDOM",
2884 },
2885 { .ival = "sequential",
2886 .oval = F_ADV_SEQUENTIAL,
2887 .help = "Advise using FADV_SEQUENTIAL",
2888 },
638689b1 2889#ifdef POSIX_FADV_NOREUSE
eb314e70
YX
2890 { .ival = "noreuse",
2891 .oval = F_ADV_NOREUSE,
2892 .help = "Advise using FADV_NOREUSE",
2893 },
638689b1 2894#endif
ecb2083d 2895 },
67a1000f
JA
2896 .help = "Use fadvise() to advise the kernel on IO pattern",
2897 .def = "1",
e8b0e958
JA
2898 .category = FIO_OPT_C_FILE,
2899 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2900 },
2901 {
2902 .name = "fsync",
e8b0e958 2903 .lname = "Fsync",
214e1eca 2904 .type = FIO_OPT_INT,
a609f12a 2905 .off1 = offsetof(struct thread_options, fsync_blocks),
214e1eca
JA
2906 .help = "Issue fsync for writes every given number of blocks",
2907 .def = "0",
20eb06bd 2908 .interval = 1,
e8b0e958
JA
2909 .category = FIO_OPT_C_FILE,
2910 .group = FIO_OPT_G_INVALID,
214e1eca 2911 },
5f9099ea
JA
2912 {
2913 .name = "fdatasync",
e8b0e958 2914 .lname = "Fdatasync",
5f9099ea 2915 .type = FIO_OPT_INT,
a609f12a 2916 .off1 = offsetof(struct thread_options, fdatasync_blocks),
5f9099ea
JA
2917 .help = "Issue fdatasync for writes every given number of blocks",
2918 .def = "0",
20eb06bd 2919 .interval = 1,
e8b0e958
JA
2920 .category = FIO_OPT_C_FILE,
2921 .group = FIO_OPT_G_INVALID,
5f9099ea 2922 },
1ef2b6be
JA
2923 {
2924 .name = "write_barrier",
e8b0e958 2925 .lname = "Write barrier",
1ef2b6be 2926 .type = FIO_OPT_INT,
a609f12a 2927 .off1 = offsetof(struct thread_options, barrier_blocks),
1ef2b6be
JA
2928 .help = "Make every Nth write a barrier write",
2929 .def = "0",
20eb06bd 2930 .interval = 1,
e8b0e958
JA
2931 .category = FIO_OPT_C_IO,
2932 .group = FIO_OPT_G_INVALID,
1ef2b6be 2933 },
67bf9823 2934#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
2935 {
2936 .name = "sync_file_range",
e8b0e958 2937 .lname = "Sync file range",
44f29692
JA
2938 .posval = {
2939 { .ival = "wait_before",
2940 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
2941 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
ebadc0ce 2942 .orval = 1,
44f29692
JA
2943 },
2944 { .ival = "write",
2945 .oval = SYNC_FILE_RANGE_WRITE,
2946 .help = "SYNC_FILE_RANGE_WRITE",
ebadc0ce 2947 .orval = 1,
44f29692
JA
2948 },
2949 {
2950 .ival = "wait_after",
2951 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
2952 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
ebadc0ce 2953 .orval = 1,
44f29692
JA
2954 },
2955 },
3843deb3 2956 .type = FIO_OPT_STR_MULTI,
44f29692 2957 .cb = str_sfr_cb,
a609f12a 2958 .off1 = offsetof(struct thread_options, sync_file_range),
44f29692 2959 .help = "Use sync_file_range()",
e8b0e958
JA
2960 .category = FIO_OPT_C_FILE,
2961 .group = FIO_OPT_G_INVALID,
44f29692 2962 },
a275c37a 2963#else
54d0a315 2964 {
a275c37a
JA
2965 .name = "sync_file_range",
2966 .lname = "Sync file range",
2967 .type = FIO_OPT_UNSUPPORTED,
2968 .help = "Your platform does not support sync_file_range",
2969 },
44f29692 2970#endif
214e1eca
JA
2971 {
2972 .name = "direct",
e8b0e958 2973 .lname = "Direct I/O",
214e1eca 2974 .type = FIO_OPT_BOOL,
a609f12a 2975 .off1 = offsetof(struct thread_options, odirect),
214e1eca
JA
2976 .help = "Use O_DIRECT IO (negates buffered)",
2977 .def = "0",
a01a1bc5 2978 .inverse = "buffered",
e8b0e958 2979 .category = FIO_OPT_C_IO,
3ceb458f 2980 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2981 },
40f1fc11 2982#ifdef FIO_HAVE_RWF_ATOMIC
d01612f3
CM
2983 {
2984 .name = "atomic",
2985 .lname = "Atomic I/O",
2986 .type = FIO_OPT_BOOL,
a609f12a 2987 .off1 = offsetof(struct thread_options, oatomic),
d01612f3
CM
2988 .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
2989 .def = "0",
2990 .category = FIO_OPT_C_IO,
2991 .group = FIO_OPT_G_IO_TYPE,
2992 },
40f1fc11 2993#endif
214e1eca
JA
2994 {
2995 .name = "buffered",
e8b0e958 2996 .lname = "Buffered I/O",
214e1eca 2997 .type = FIO_OPT_BOOL,
a609f12a 2998 .off1 = offsetof(struct thread_options, odirect),
214e1eca
JA
2999 .neg = 1,
3000 .help = "Use buffered IO (negates direct)",
3001 .def = "1",
a01a1bc5 3002 .inverse = "direct",
e8b0e958 3003 .category = FIO_OPT_C_IO,
3ceb458f 3004 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
3005 },
3006 {
3007 .name = "overwrite",
e8b0e958 3008 .lname = "Overwrite",
214e1eca 3009 .type = FIO_OPT_BOOL,
a609f12a 3010 .off1 = offsetof(struct thread_options, overwrite),
214e1eca
JA
3011 .help = "When writing, set whether to overwrite current data",
3012 .def = "0",
e8b0e958
JA
3013 .category = FIO_OPT_C_FILE,
3014 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3015 },
3016 {
3017 .name = "loops",
e8b0e958 3018 .lname = "Loops",
214e1eca 3019 .type = FIO_OPT_INT,
a609f12a 3020 .off1 = offsetof(struct thread_options, loops),
214e1eca
JA
3021 .help = "Number of times to run the job",
3022 .def = "1",
20eb06bd 3023 .interval = 1,
e8b0e958 3024 .category = FIO_OPT_C_GENERAL,
a1f6afec 3025 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
3026 },
3027 {
3028 .name = "numjobs",
e8b0e958 3029 .lname = "Number of jobs",
214e1eca 3030 .type = FIO_OPT_INT,
a609f12a 3031 .off1 = offsetof(struct thread_options, numjobs),
214e1eca
JA
3032 .help = "Duplicate this job this many times",
3033 .def = "1",
20eb06bd 3034 .interval = 1,
e8b0e958 3035 .category = FIO_OPT_C_GENERAL,
a1f6afec 3036 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
3037 },
3038 {
3039 .name = "startdelay",
e8b0e958 3040 .lname = "Start delay",
a5737c93 3041 .type = FIO_OPT_STR_VAL_TIME,
a609f12a
JA
3042 .off1 = offsetof(struct thread_options, start_delay),
3043 .off2 = offsetof(struct thread_options, start_delay_high),
214e1eca
JA
3044 .help = "Only start job when this period has passed",
3045 .def = "0",
0de5b26f 3046 .is_seconds = 1,
88038bc7 3047 .is_time = 1,
e8b0e958 3048 .category = FIO_OPT_C_GENERAL,
a1f6afec 3049 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
3050 },
3051 {
3052 .name = "runtime",
e8b0e958 3053 .lname = "Runtime",
214e1eca
JA
3054 .alias = "timeout",
3055 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3056 .off1 = offsetof(struct thread_options, timeout),
214e1eca
JA
3057 .help = "Stop workload when this amount of time has passed",
3058 .def = "0",
0de5b26f 3059 .is_seconds = 1,
88038bc7 3060 .is_time = 1,
e8b0e958 3061 .category = FIO_OPT_C_GENERAL,
a1f6afec 3062 .group = FIO_OPT_G_RUNTIME,
214e1eca 3063 },
cf4464ca
JA
3064 {
3065 .name = "time_based",
e8b0e958 3066 .lname = "Time based",
cf4464ca 3067 .type = FIO_OPT_STR_SET,
a609f12a 3068 .off1 = offsetof(struct thread_options, time_based),
cf4464ca 3069 .help = "Keep running until runtime/timeout is met",
e8b0e958 3070 .category = FIO_OPT_C_GENERAL,
a1f6afec 3071 .group = FIO_OPT_G_RUNTIME,
cf4464ca 3072 },
62167762
JC
3073 {
3074 .name = "verify_only",
3075 .lname = "Verify only",
3076 .type = FIO_OPT_STR_SET,
a609f12a 3077 .off1 = offsetof(struct thread_options, verify_only),
62167762
JC
3078 .help = "Verifies previously written data is still valid",
3079 .category = FIO_OPT_C_GENERAL,
3080 .group = FIO_OPT_G_RUNTIME,
3081 },
721938ae
JA
3082 {
3083 .name = "ramp_time",
e8b0e958 3084 .lname = "Ramp time",
721938ae 3085 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3086 .off1 = offsetof(struct thread_options, ramp_time),
721938ae 3087 .help = "Ramp up time before measuring performance",
0de5b26f 3088 .is_seconds = 1,
88038bc7 3089 .is_time = 1,
e8b0e958 3090 .category = FIO_OPT_C_GENERAL,
a1f6afec 3091 .group = FIO_OPT_G_RUNTIME,
721938ae 3092 },
c223da83
JA
3093 {
3094 .name = "clocksource",
e8b0e958 3095 .lname = "Clock source",
c223da83
JA
3096 .type = FIO_OPT_STR,
3097 .cb = fio_clock_source_cb,
a609f12a 3098 .off1 = offsetof(struct thread_options, clocksource),
c223da83 3099 .help = "What type of timing source to use",
e8b0e958 3100 .category = FIO_OPT_C_GENERAL,
10860056 3101 .group = FIO_OPT_G_CLOCK,
c223da83 3102 .posval = {
67bf9823 3103#ifdef CONFIG_GETTIMEOFDAY
c223da83
JA
3104 { .ival = "gettimeofday",
3105 .oval = CS_GTOD,
3106 .help = "Use gettimeofday(2) for timing",
3107 },
67bf9823
JA
3108#endif
3109#ifdef CONFIG_CLOCK_GETTIME
c223da83
JA
3110 { .ival = "clock_gettime",
3111 .oval = CS_CGETTIME,
3112 .help = "Use clock_gettime(2) for timing",
3113 },
67bf9823 3114#endif
c223da83
JA
3115#ifdef ARCH_HAVE_CPU_CLOCK
3116 { .ival = "cpu",
3117 .oval = CS_CPUCLOCK,
3118 .help = "Use CPU private clock",
3119 },
3120#endif
3121 },
3122 },
214e1eca
JA
3123 {
3124 .name = "mem",
d3aad8f2 3125 .alias = "iomem",
e8b0e958 3126 .lname = "I/O Memory",
214e1eca
JA
3127 .type = FIO_OPT_STR,
3128 .cb = str_mem_cb,
a609f12a 3129 .off1 = offsetof(struct thread_options, mem_type),
214e1eca
JA
3130 .help = "Backing type for IO buffers",
3131 .def = "malloc",
e8b0e958
JA
3132 .category = FIO_OPT_C_IO,
3133 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3134 .posval = {
3135 { .ival = "malloc",
3136 .oval = MEM_MALLOC,
3137 .help = "Use malloc(3) for IO buffers",
3138 },
c8931876 3139#ifndef CONFIG_NO_SHM
37c8cdfe
JA
3140 { .ival = "shm",
3141 .oval = MEM_SHM,
3142 .help = "Use shared memory segments for IO buffers",
3143 },
214e1eca
JA
3144#ifdef FIO_HAVE_HUGETLB
3145 { .ival = "shmhuge",
3146 .oval = MEM_SHMHUGE,
3147 .help = "Like shm, but use huge pages",
3148 },
c8931876 3149#endif
b370e46a 3150#endif
37c8cdfe
JA
3151 { .ival = "mmap",
3152 .oval = MEM_MMAP,
3153 .help = "Use mmap(2) (file or anon) for IO buffers",
3154 },
217b0f1d
LG
3155 { .ival = "mmapshared",
3156 .oval = MEM_MMAPSHARED,
3157 .help = "Like mmap, but use the shared flag",
3158 },
214e1eca
JA
3159#ifdef FIO_HAVE_HUGETLB
3160 { .ival = "mmaphuge",
3161 .oval = MEM_MMAPHUGE,
3162 .help = "Like mmap, but use huge pages",
3163 },
03553853
YR
3164#endif
3165#ifdef CONFIG_CUDA
3166 { .ival = "cudamalloc",
3167 .oval = MEM_CUDA_MALLOC,
3168 .help = "Allocate GPU device memory for GPUDirect RDMA",
3169 },
214e1eca
JA
3170#endif
3171 },
3172 },
d529ee19
JA
3173 {
3174 .name = "iomem_align",
3175 .alias = "mem_align",
e8b0e958 3176 .lname = "I/O memory alignment",
d529ee19 3177 .type = FIO_OPT_INT,
a609f12a 3178 .off1 = offsetof(struct thread_options, mem_align),
d529ee19
JA
3179 .minval = 0,
3180 .help = "IO memory buffer offset alignment",
3181 .def = "0",
3182 .parent = "iomem",
d71c154c 3183 .hide = 1,
e8b0e958
JA
3184 .category = FIO_OPT_C_IO,
3185 .group = FIO_OPT_G_INVALID,
d529ee19 3186 },
214e1eca
JA
3187 {
3188 .name = "verify",
e8b0e958 3189 .lname = "Verify",
214e1eca 3190 .type = FIO_OPT_STR,
a609f12a 3191 .off1 = offsetof(struct thread_options, verify),
214e1eca
JA
3192 .help = "Verify data written",
3193 .def = "0",
e8b0e958 3194 .category = FIO_OPT_C_IO,
3ceb458f 3195 .group = FIO_OPT_G_VERIFY,
214e1eca
JA
3196 .posval = {
3197 { .ival = "0",
3198 .oval = VERIFY_NONE,
3199 .help = "Don't do IO verification",
3200 },
fcca4b58
JA
3201 { .ival = "md5",
3202 .oval = VERIFY_MD5,
3203 .help = "Use md5 checksums for verification",
3204 },
d77a7af3
JA
3205 { .ival = "crc64",
3206 .oval = VERIFY_CRC64,
3207 .help = "Use crc64 checksums for verification",
3208 },
214e1eca
JA
3209 { .ival = "crc32",
3210 .oval = VERIFY_CRC32,
3211 .help = "Use crc32 checksums for verification",
3212 },
af497e6a 3213 { .ival = "crc32c-intel",
e3aaafc4
JA
3214 .oval = VERIFY_CRC32C,
3215 .help = "Use crc32c checksums for verification (hw assisted, if available)",
af497e6a 3216 },
bac39e0e
JA
3217 { .ival = "crc32c",
3218 .oval = VERIFY_CRC32C,
e3aaafc4 3219 .help = "Use crc32c checksums for verification (hw assisted, if available)",
bac39e0e 3220 },
969f7ed3
JA
3221 { .ival = "crc16",
3222 .oval = VERIFY_CRC16,
3223 .help = "Use crc16 checksums for verification",
3224 },
1e154bdb
JA
3225 { .ival = "crc7",
3226 .oval = VERIFY_CRC7,
3227 .help = "Use crc7 checksums for verification",
3228 },
7c353ceb
JA
3229 { .ival = "sha1",
3230 .oval = VERIFY_SHA1,
3231 .help = "Use sha1 checksums for verification",
3232 },
cd14cc10
JA
3233 { .ival = "sha256",
3234 .oval = VERIFY_SHA256,
3235 .help = "Use sha256 checksums for verification",
3236 },
3237 { .ival = "sha512",
3238 .oval = VERIFY_SHA512,
3239 .help = "Use sha512 checksums for verification",
ae3a5acc
JA
3240 },
3241 { .ival = "sha3-224",
3242 .oval = VERIFY_SHA3_224,
3243 .help = "Use sha3-224 checksums for verification",
3244 },
3245 { .ival = "sha3-256",
3246 .oval = VERIFY_SHA3_256,
3247 .help = "Use sha3-256 checksums for verification",
3248 },
3249 { .ival = "sha3-384",
3250 .oval = VERIFY_SHA3_384,
3251 .help = "Use sha3-384 checksums for verification",
3252 },
3253 { .ival = "sha3-512",
3254 .oval = VERIFY_SHA3_512,
3255 .help = "Use sha3-512 checksums for verification",
cd14cc10 3256 },
844ea602
JA
3257 { .ival = "xxhash",
3258 .oval = VERIFY_XXHASH,
3259 .help = "Use xxhash checksums for verification",
3260 },
b638d82f
RP
3261 /* Meta information was included into verify_header,
3262 * 'meta' verification is implied by default. */
7437ee87 3263 { .ival = "meta",
b638d82f
RP
3264 .oval = VERIFY_HDR_ONLY,
3265 .help = "Use io information for verification. "
3266 "Now is implied by default, thus option is obsolete, "
3267 "don't use it",
7437ee87 3268 },
59245381
JA
3269 { .ival = "pattern",
3270 .oval = VERIFY_PATTERN_NO_HDR,
3271 .help = "Verify strict pattern",
3272 },
ab4e5b72
VF
3273 { .ival = "pattern_hdr",
3274 .oval = VERIFY_PATTERN,
3275 .help = "Verify pattern with header",
3276 },
36690c9b
JA
3277 {
3278 .ival = "null",
3279 .oval = VERIFY_NULL,
3280 .help = "Pretend to verify",
3281 },
214e1eca
JA
3282 },
3283 },
005c565a
JA
3284 {
3285 .name = "do_verify",
e8b0e958 3286 .lname = "Perform verify step",
68e1f29a 3287 .type = FIO_OPT_BOOL,
a609f12a 3288 .off1 = offsetof(struct thread_options, do_verify),
005c565a
JA
3289 .help = "Run verification stage after write",
3290 .def = "1",
3291 .parent = "verify",
d71c154c 3292 .hide = 1,
e8b0e958
JA
3293 .category = FIO_OPT_C_IO,
3294 .group = FIO_OPT_G_VERIFY,
005c565a 3295 },
160b966d
JA
3296 {
3297 .name = "verifysort",
e8b0e958 3298 .lname = "Verify sort",
f31feaa2 3299 .type = FIO_OPT_SOFT_DEPRECATED,
e8b0e958
JA
3300 .category = FIO_OPT_C_IO,
3301 .group = FIO_OPT_G_VERIFY,
160b966d 3302 },
1ae83d45
JA
3303 {
3304 .name = "verifysort_nr",
cce2fdfe 3305 .lname = "Verify Sort Nr",
f31feaa2 3306 .type = FIO_OPT_SOFT_DEPRECATED,
836fcc0f
JA
3307 .category = FIO_OPT_C_IO,
3308 .group = FIO_OPT_G_VERIFY,
1ae83d45 3309 },
3f9f4e26 3310 {
a59e170d 3311 .name = "verify_interval",
e8b0e958 3312 .lname = "Verify interval",
e01b22b8 3313 .type = FIO_OPT_INT,
a609f12a 3314 .off1 = offsetof(struct thread_options, verify_interval),
819a9680 3315 .minval = 2 * sizeof(struct verify_header),
a59e170d 3316 .help = "Store verify buffer header every N bytes",
afdf9352 3317 .parent = "verify",
d71c154c 3318 .hide = 1,
20eb06bd 3319 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
3320 .category = FIO_OPT_C_IO,
3321 .group = FIO_OPT_G_VERIFY,
3f9f4e26 3322 },
546a9142 3323 {
a59e170d 3324 .name = "verify_offset",
e8b0e958 3325 .lname = "Verify offset",
e01b22b8 3326 .type = FIO_OPT_INT,
a59e170d 3327 .help = "Offset verify header location by N bytes",
a609f12a 3328 .off1 = offsetof(struct thread_options, verify_offset),
203160d5 3329 .minval = sizeof(struct verify_header),
afdf9352 3330 .parent = "verify",
d71c154c 3331 .hide = 1,
e8b0e958
JA
3332 .category = FIO_OPT_C_IO,
3333 .group = FIO_OPT_G_VERIFY,
546a9142 3334 },
e28218f3
SL
3335 {
3336 .name = "verify_pattern",
e8b0e958 3337 .lname = "Verify pattern",
0e92f873 3338 .type = FIO_OPT_STR,
e28218f3 3339 .cb = str_verify_pattern_cb,
a609f12a 3340 .off1 = offsetof(struct thread_options, verify_pattern),
e28218f3
SL
3341 .help = "Fill pattern for IO buffers",
3342 .parent = "verify",
d71c154c 3343 .hide = 1,
e8b0e958
JA
3344 .category = FIO_OPT_C_IO,
3345 .group = FIO_OPT_G_VERIFY,
e28218f3 3346 },
79330c25
VF
3347 {
3348 .name = "verify_pattern_interval",
3349 .lname = "Running verify pattern",
3350 .type = FIO_OPT_INT,
3351 .off1 = offsetof(struct thread_options, verify_pattern_interval),
3352 .def = "0",
3353 .help = "Re-create verify pattern every N bytes",
3354 .parent = "verify",
3355 .hide = 1,
3356 .category = FIO_OPT_C_IO,
3357 .group = FIO_OPT_G_VERIFY,
3358 },
a12a3b4d
JA
3359 {
3360 .name = "verify_fatal",
e8b0e958 3361 .lname = "Verify fatal",
68e1f29a 3362 .type = FIO_OPT_BOOL,
a609f12a 3363 .off1 = offsetof(struct thread_options, verify_fatal),
a12a3b4d
JA
3364 .def = "0",
3365 .help = "Exit on a single verify failure, don't continue",
3366 .parent = "verify",
d71c154c 3367 .hide = 1,
e8b0e958
JA
3368 .category = FIO_OPT_C_IO,
3369 .group = FIO_OPT_G_VERIFY,
a12a3b4d 3370 },
b463e936
JA
3371 {
3372 .name = "verify_dump",
e8b0e958 3373 .lname = "Verify dump",
b463e936 3374 .type = FIO_OPT_BOOL,
a609f12a 3375 .off1 = offsetof(struct thread_options, verify_dump),
ef71e317 3376 .def = "0",
b463e936
JA
3377 .help = "Dump contents of good and bad blocks on failure",
3378 .parent = "verify",
d71c154c 3379 .hide = 1,
e8b0e958
JA
3380 .category = FIO_OPT_C_IO,
3381 .group = FIO_OPT_G_VERIFY,
b463e936 3382 },
e8462bd8
JA
3383 {
3384 .name = "verify_async",
e8b0e958 3385 .lname = "Verify asynchronously",
e8462bd8 3386 .type = FIO_OPT_INT,
a609f12a 3387 .off1 = offsetof(struct thread_options, verify_async),
e8462bd8
JA
3388 .def = "0",
3389 .help = "Number of async verifier threads to use",
3390 .parent = "verify",
d71c154c 3391 .hide = 1,
e8b0e958
JA
3392 .category = FIO_OPT_C_IO,
3393 .group = FIO_OPT_G_VERIFY,
e8462bd8 3394 },
9e144189
JA
3395 {
3396 .name = "verify_backlog",
e8b0e958 3397 .lname = "Verify backlog",
9e144189 3398 .type = FIO_OPT_STR_VAL,
a609f12a 3399 .off1 = offsetof(struct thread_options, verify_backlog),
9e144189
JA
3400 .help = "Verify after this number of blocks are written",
3401 .parent = "verify",
d71c154c 3402 .hide = 1,
e8b0e958
JA
3403 .category = FIO_OPT_C_IO,
3404 .group = FIO_OPT_G_VERIFY,
9e144189
JA
3405 },
3406 {
3407 .name = "verify_backlog_batch",
e8b0e958 3408 .lname = "Verify backlog batch",
9e144189 3409 .type = FIO_OPT_INT,
a609f12a 3410 .off1 = offsetof(struct thread_options, verify_batch),
9e144189 3411 .help = "Verify this number of IO blocks",
0d29de83 3412 .parent = "verify",
d71c154c 3413 .hide = 1,
e8b0e958
JA
3414 .category = FIO_OPT_C_IO,
3415 .group = FIO_OPT_G_VERIFY,
9e144189 3416 },
e8462bd8
JA
3417#ifdef FIO_HAVE_CPU_AFFINITY
3418 {
3419 .name = "verify_async_cpus",
e8b0e958 3420 .lname = "Async verify CPUs",
e8462bd8
JA
3421 .type = FIO_OPT_STR,
3422 .cb = str_verify_cpus_allowed_cb,
a609f12a 3423 .off1 = offsetof(struct thread_options, verify_cpumask),
e8462bd8
JA
3424 .help = "Set CPUs allowed for async verify threads",
3425 .parent = "verify_async",
d71c154c 3426 .hide = 1,
e8b0e958
JA
3427 .category = FIO_OPT_C_IO,
3428 .group = FIO_OPT_G_VERIFY,
e8462bd8 3429 },
a275c37a
JA
3430#else
3431 {
3432 .name = "verify_async_cpus",
3433 .lname = "Async verify CPUs",
3434 .type = FIO_OPT_UNSUPPORTED,
54d0a315 3435 .help = "Your platform does not support CPU affinities",
a275c37a 3436 },
0d29de83 3437#endif
51aa2da8
JA
3438 {
3439 .name = "experimental_verify",
cce2fdfe 3440 .lname = "Experimental Verify",
a609f12a 3441 .off1 = offsetof(struct thread_options, experimental_verify),
51aa2da8 3442 .type = FIO_OPT_BOOL,
b31eaac9 3443 .help = "Enable experimental verification",
ca09be4b
JA
3444 .parent = "verify",
3445 .category = FIO_OPT_C_IO,
3446 .group = FIO_OPT_G_VERIFY,
3447 },
3448 {
3449 .name = "verify_state_load",
3450 .lname = "Load verify state",
a609f12a 3451 .off1 = offsetof(struct thread_options, verify_state),
ca09be4b
JA
3452 .type = FIO_OPT_BOOL,
3453 .help = "Load verify termination state",
3454 .parent = "verify",
3455 .category = FIO_OPT_C_IO,
3456 .group = FIO_OPT_G_VERIFY,
3457 },
3458 {
3459 .name = "verify_state_save",
3460 .lname = "Save verify state",
a609f12a 3461 .off1 = offsetof(struct thread_options, verify_state_save),
ca09be4b
JA
3462 .type = FIO_OPT_BOOL,
3463 .def = "1",
3464 .help = "Save verify state on termination",
3465 .parent = "verify",
836fcc0f
JA
3466 .category = FIO_OPT_C_IO,
3467 .group = FIO_OPT_G_VERIFY,
51aa2da8 3468 },
2dd80ee4
JG
3469 {
3470 .name = "verify_write_sequence",
3471 .lname = "Verify write sequence number",
3472 .off1 = offsetof(struct thread_options, verify_write_sequence),
3473 .type = FIO_OPT_BOOL,
3474 .def = "1",
3475 .help = "Verify header write sequence number",
3476 .parent = "verify",
3477 .category = FIO_OPT_C_IO,
3478 .group = FIO_OPT_G_VERIFY,
3479 },
703d04e7
AK
3480 {
3481 .name = "verify_header_seed",
3482 .lname = "Verify header seed",
3483 .off1 = offsetof(struct thread_options, verify_header_seed),
3484 .type = FIO_OPT_BOOL,
3485 .def = "1",
3486 .help = "Verify the header seed used to generate the buffer contents",
3487 .parent = "verify",
3488 .category = FIO_OPT_C_IO,
3489 .group = FIO_OPT_G_VERIFY,
3490 },
0d29de83
JA
3491#ifdef FIO_HAVE_TRIM
3492 {
3493 .name = "trim_percentage",
e8b0e958 3494 .lname = "Trim percentage",
0d29de83 3495 .type = FIO_OPT_INT,
a609f12a 3496 .off1 = offsetof(struct thread_options, trim_percentage),
20eb06bd 3497 .minval = 0,
0d29de83 3498 .maxval = 100,
169c098d 3499 .help = "Number of verify blocks to trim (i.e., discard)",
0d29de83
JA
3500 .parent = "verify",
3501 .def = "0",
20eb06bd 3502 .interval = 1,
d71c154c 3503 .hide = 1,
e8b0e958
JA
3504 .category = FIO_OPT_C_IO,
3505 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3506 },
3507 {
3508 .name = "trim_verify_zero",
e8b0e958 3509 .lname = "Verify trim zero",
20eb06bd 3510 .type = FIO_OPT_BOOL,
169c098d 3511 .help = "Verify that trimmed (i.e., discarded) blocks are returned as zeroes",
a609f12a 3512 .off1 = offsetof(struct thread_options, trim_zero),
0d29de83 3513 .parent = "trim_percentage",
d71c154c 3514 .hide = 1,
0d29de83 3515 .def = "1",
e8b0e958
JA
3516 .category = FIO_OPT_C_IO,
3517 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3518 },
3519 {
3520 .name = "trim_backlog",
e8b0e958 3521 .lname = "Trim backlog",
0d29de83 3522 .type = FIO_OPT_STR_VAL,
a609f12a 3523 .off1 = offsetof(struct thread_options, trim_backlog),
0d29de83
JA
3524 .help = "Trim after this number of blocks are written",
3525 .parent = "trim_percentage",
d71c154c 3526 .hide = 1,
20eb06bd 3527 .interval = 1,
e8b0e958
JA
3528 .category = FIO_OPT_C_IO,
3529 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3530 },
3531 {
3532 .name = "trim_backlog_batch",
e8b0e958 3533 .lname = "Trim backlog batch",
0d29de83 3534 .type = FIO_OPT_INT,
a609f12a 3535 .off1 = offsetof(struct thread_options, trim_batch),
0d29de83
JA
3536 .help = "Trim this number of IO blocks",
3537 .parent = "trim_percentage",
d71c154c 3538 .hide = 1,
20eb06bd 3539 .interval = 1,
e8b0e958
JA
3540 .category = FIO_OPT_C_IO,
3541 .group = FIO_OPT_G_TRIM,
0d29de83 3542 },
a275c37a
JA
3543#else
3544 {
3545 .name = "trim_percentage",
3546 .lname = "Trim percentage",
3547 .type = FIO_OPT_UNSUPPORTED,
3548 .help = "Fio does not support TRIM on your platform",
3549 },
3550 {
3551 .name = "trim_verify_zero",
3552 .lname = "Verify trim zero",
3553 .type = FIO_OPT_UNSUPPORTED,
3554 .help = "Fio does not support TRIM on your platform",
3555 },
3556 {
3557 .name = "trim_backlog",
3558 .lname = "Trim backlog",
3559 .type = FIO_OPT_UNSUPPORTED,
3560 .help = "Fio does not support TRIM on your platform",
3561 },
3562 {
3563 .name = "trim_backlog_batch",
3564 .lname = "Trim backlog batch",
3565 .type = FIO_OPT_UNSUPPORTED,
3566 .help = "Fio does not support TRIM on your platform",
3567 },
e8462bd8 3568#endif
214e1eca
JA
3569 {
3570 .name = "write_iolog",
e8b0e958 3571 .lname = "Write I/O log",
214e1eca 3572 .type = FIO_OPT_STR_STORE,
a609f12a 3573 .off1 = offsetof(struct thread_options, write_iolog_file),
214e1eca 3574 .help = "Store IO pattern to file",
e8b0e958
JA
3575 .category = FIO_OPT_C_IO,
3576 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
3577 },
3578 {
3579 .name = "read_iolog",
e8b0e958 3580 .lname = "Read I/O log",
214e1eca 3581 .type = FIO_OPT_STR_STORE,
a609f12a 3582 .off1 = offsetof(struct thread_options, read_iolog_file),
214e1eca 3583 .help = "Playback IO pattern from file",
e8b0e958
JA
3584 .category = FIO_OPT_C_IO,
3585 .group = FIO_OPT_G_IOLOG,
214e1eca 3586 },
98e7161c
AK
3587 {
3588 .name = "read_iolog_chunked",
3589 .lname = "Read I/O log in parts",
3590 .type = FIO_OPT_BOOL,
3591 .off1 = offsetof(struct thread_options, read_iolog_chunked),
3592 .def = "0",
3593 .parent = "read_iolog",
3594 .help = "Parse IO pattern in chunks",
3595 .category = FIO_OPT_C_IO,
3596 .group = FIO_OPT_G_IOLOG,
3597 },
64bbb865
DN
3598 {
3599 .name = "replay_no_stall",
e8b0e958 3600 .lname = "Don't stall on replay",
20eb06bd 3601 .type = FIO_OPT_BOOL,
a609f12a 3602 .off1 = offsetof(struct thread_options, no_stall),
64bbb865 3603 .def = "0",
87e7a972 3604 .parent = "read_iolog",
d71c154c 3605 .hide = 1,
64bbb865 3606 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
3607 .category = FIO_OPT_C_IO,
3608 .group = FIO_OPT_G_IOLOG,
64bbb865 3609 },
d1c46c04
DN
3610 {
3611 .name = "replay_redirect",
e8b0e958 3612 .lname = "Redirect device for replay",
d1c46c04 3613 .type = FIO_OPT_STR_STORE,
a609f12a 3614 .off1 = offsetof(struct thread_options, replay_redirect),
d1c46c04 3615 .parent = "read_iolog",
d71c154c 3616 .hide = 1,
d1c46c04 3617 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
3618 .category = FIO_OPT_C_IO,
3619 .group = FIO_OPT_G_IOLOG,
d1c46c04 3620 },
0c63576e
JA
3621 {
3622 .name = "replay_scale",
3623 .lname = "Replace offset scale factor",
3624 .type = FIO_OPT_INT,
a609f12a 3625 .off1 = offsetof(struct thread_options, replay_scale),
0c63576e
JA
3626 .parent = "read_iolog",
3627 .def = "1",
3628 .help = "Align offsets to this blocksize",
3629 .category = FIO_OPT_C_IO,
3630 .group = FIO_OPT_G_IOLOG,
3631 },
3632 {
3633 .name = "replay_align",
3634 .lname = "Replace alignment",
3635 .type = FIO_OPT_INT,
a609f12a 3636 .off1 = offsetof(struct thread_options, replay_align),
0c63576e
JA
3637 .parent = "read_iolog",
3638 .help = "Scale offset down by this factor",
3639 .category = FIO_OPT_C_IO,
3640 .group = FIO_OPT_G_IOLOG,
3641 .pow2 = 1,
3642 },
6dd7fa77
JA
3643 {
3644 .name = "replay_time_scale",
3645 .lname = "Replay Time Scale",
3646 .type = FIO_OPT_INT,
3647 .off1 = offsetof(struct thread_options, replay_time_scale),
3648 .def = "100",
3649 .minval = 1,
3650 .parent = "read_iolog",
3651 .hide = 1,
3652 .help = "Scale time for replay events",
3653 .category = FIO_OPT_C_IO,
3654 .group = FIO_OPT_G_IOLOG,
3655 },
d7235efb
JA
3656 {
3657 .name = "replay_skip",
3658 .lname = "Replay Skip",
3659 .type = FIO_OPT_STR,
3660 .cb = str_replay_skip_cb,
3661 .off1 = offsetof(struct thread_options, replay_skip),
3662 .parent = "read_iolog",
3663 .help = "Skip certain IO types (read,write,trim,flush)",
3664 .category = FIO_OPT_C_IO,
3665 .group = FIO_OPT_G_IOLOG,
3666 },
b9921d1a
DZ
3667 {
3668 .name = "merge_blktrace_file",
3669 .lname = "Merged blktrace output filename",
3670 .type = FIO_OPT_STR_STORE,
3671 .off1 = offsetof(struct thread_options, merge_blktrace_file),
3672 .help = "Merged blktrace output filename",
3673 .category = FIO_OPT_C_IO,
3674 .group = FIO_OPT_G_IOLOG,
3675 },
87a48ada
DZ
3676 {
3677 .name = "merge_blktrace_scalars",
3678 .lname = "Percentage to scale each trace",
3679 .type = FIO_OPT_FLOAT_LIST,
3680 .off1 = offsetof(struct thread_options, merge_blktrace_scalars),
3681 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3682 .help = "Percentage to scale each trace",
3683 .category = FIO_OPT_C_IO,
3684 .group = FIO_OPT_G_IOLOG,
3685 },
55bfd8c8
DZ
3686 {
3687 .name = "merge_blktrace_iters",
3688 .lname = "Number of iterations to run per trace",
3689 .type = FIO_OPT_FLOAT_LIST,
3690 .off1 = offsetof(struct thread_options, merge_blktrace_iters),
3691 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3692 .help = "Number of iterations to run per trace",
3693 .category = FIO_OPT_C_IO,
3694 .group = FIO_OPT_G_IOLOG,
3695 },
214e1eca
JA
3696 {
3697 .name = "exec_prerun",
e8b0e958 3698 .lname = "Pre-execute runnable",
214e1eca 3699 .type = FIO_OPT_STR_STORE,
a609f12a 3700 .off1 = offsetof(struct thread_options, exec_prerun),
214e1eca 3701 .help = "Execute this file prior to running job",
e8b0e958
JA
3702 .category = FIO_OPT_C_GENERAL,
3703 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3704 },
3705 {
3706 .name = "exec_postrun",
e8b0e958 3707 .lname = "Post-execute runnable",
214e1eca 3708 .type = FIO_OPT_STR_STORE,
a609f12a 3709 .off1 = offsetof(struct thread_options, exec_postrun),
214e1eca 3710 .help = "Execute this file after running job",
e8b0e958
JA
3711 .category = FIO_OPT_C_GENERAL,
3712 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3713 },
3714#ifdef FIO_HAVE_IOSCHED_SWITCH
3715 {
3716 .name = "ioscheduler",
e8b0e958 3717 .lname = "I/O scheduler",
214e1eca 3718 .type = FIO_OPT_STR_STORE,
a609f12a 3719 .off1 = offsetof(struct thread_options, ioscheduler),
214e1eca 3720 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
3721 .category = FIO_OPT_C_FILE,
3722 .group = FIO_OPT_G_INVALID,
214e1eca 3723 },
a275c37a
JA
3724#else
3725 {
3726 .name = "ioscheduler",
3727 .lname = "I/O scheduler",
3728 .type = FIO_OPT_UNSUPPORTED,
3729 .help = "Your platform does not support IO scheduler switching",
3730 },
214e1eca 3731#endif
7b865a2f
BVA
3732 {
3733 .name = "zonemode",
3734 .lname = "Zone mode",
3735 .help = "Mode for the zonesize, zonerange and zoneskip parameters",
3736 .type = FIO_OPT_STR,
3737 .off1 = offsetof(struct thread_options, zone_mode),
3738 .def = "none",
3739 .category = FIO_OPT_C_IO,
3740 .group = FIO_OPT_G_ZONE,
3741 .posval = {
3742 { .ival = "none",
3743 .oval = ZONE_MODE_NONE,
3744 .help = "no zoning",
3745 },
3746 { .ival = "strided",
3747 .oval = ZONE_MODE_STRIDED,
3748 .help = "strided mode - random I/O is restricted to a single zone",
3749 },
3750 { .ival = "zbd",
3751 .oval = ZONE_MODE_ZBD,
3752 .help = "zoned block device mode - random I/O selects one of multiple zones randomly",
3753 },
3754 },
3755 },
214e1eca
JA
3756 {
3757 .name = "zonesize",
e8b0e958 3758 .lname = "Zone size",
214e1eca 3759 .type = FIO_OPT_STR_VAL,
a609f12a 3760 .off1 = offsetof(struct thread_options, zone_size),
ed335855
SN
3761 .help = "Amount of data to read per zone",
3762 .def = "0",
20eb06bd 3763 .interval = 1024 * 1024,
e8b0e958
JA
3764 .category = FIO_OPT_C_IO,
3765 .group = FIO_OPT_G_ZONE,
ed335855 3766 },
b8dd9750
HH
3767 {
3768 .name = "zonecapacity",
3769 .lname = "Zone capacity",
3770 .type = FIO_OPT_STR_VAL,
3771 .off1 = offsetof(struct thread_options, zone_capacity),
3772 .help = "Capacity per zone",
3773 .def = "0",
3774 .interval = 1024 * 1024,
3775 .category = FIO_OPT_C_IO,
3776 .group = FIO_OPT_G_ZONE,
3777 },
ed335855
SN
3778 {
3779 .name = "zonerange",
e8b0e958 3780 .lname = "Zone range",
ed335855 3781 .type = FIO_OPT_STR_VAL,
a609f12a 3782 .off1 = offsetof(struct thread_options, zone_range),
214e1eca
JA
3783 .help = "Give size of an IO zone",
3784 .def = "0",
20eb06bd 3785 .interval = 1024 * 1024,
e8b0e958
JA
3786 .category = FIO_OPT_C_IO,
3787 .group = FIO_OPT_G_ZONE,
214e1eca
JA
3788 },
3789 {
3790 .name = "zoneskip",
e8b0e958 3791 .lname = "Zone skip",
8f39afa7
AD
3792 .type = FIO_OPT_STR_VAL_ZONE,
3793 .cb = str_zoneskip_cb,
a609f12a 3794 .off1 = offsetof(struct thread_options, zone_skip),
214e1eca
JA
3795 .help = "Space between IO zones",
3796 .def = "0",
e8b0e958
JA
3797 .category = FIO_OPT_C_IO,
3798 .group = FIO_OPT_G_ZONE,
214e1eca 3799 },
bfbdd35b
BVA
3800 {
3801 .name = "read_beyond_wp",
3802 .lname = "Allow reads beyond the zone write pointer",
3803 .type = FIO_OPT_BOOL,
3804 .off1 = offsetof(struct thread_options, read_beyond_wp),
3805 .help = "Allow reads beyond the zone write pointer",
3806 .def = "0",
3807 .category = FIO_OPT_C_IO,
3808 .group = FIO_OPT_G_INVALID,
3809 },
59b07544
BVA
3810 {
3811 .name = "max_open_zones",
219c662d 3812 .lname = "Per device/file maximum number of open zones",
59b07544
BVA
3813 .type = FIO_OPT_INT,
3814 .off1 = offsetof(struct thread_options, max_open_zones),
a4807046 3815 .maxval = ZBD_MAX_WRITE_ZONES,
219c662d
AD
3816 .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd",
3817 .def = "0",
3818 .category = FIO_OPT_C_IO,
3819 .group = FIO_OPT_G_INVALID,
3820 },
3821 {
3822 .name = "job_max_open_zones",
3823 .lname = "Job maximum number of open zones",
3824 .type = FIO_OPT_INT,
3825 .off1 = offsetof(struct thread_options, job_max_open_zones),
a4807046 3826 .maxval = ZBD_MAX_WRITE_ZONES,
219c662d 3827 .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd by one thread/process",
59b07544
BVA
3828 .def = "0",
3829 .category = FIO_OPT_C_IO,
3830 .group = FIO_OPT_G_INVALID,
3831 },
575686bb
NC
3832 {
3833 .name = "ignore_zone_limits",
3834 .lname = "Ignore zone resource limits",
3835 .type = FIO_OPT_BOOL,
3836 .off1 = offsetof(struct thread_options, ignore_zone_limits),
3837 .def = "0",
3838 .help = "Ignore the zone resource limits (max open/active zones) reported by the device",
3839 .category = FIO_OPT_C_IO,
3840 .group = FIO_OPT_G_INVALID,
3841 },
a7c2b6fc
BVA
3842 {
3843 .name = "zone_reset_threshold",
3844 .lname = "Zone reset threshold",
3845 .help = "Zoned block device reset threshold",
3846 .type = FIO_OPT_FLOAT_LIST,
3847 .maxlen = 1,
3848 .off1 = offsetof(struct thread_options, zrt),
3849 .minfp = 0,
3850 .maxfp = 1,
3851 .category = FIO_OPT_C_IO,
3852 .group = FIO_OPT_G_ZONE,
3853 },
3854 {
3855 .name = "zone_reset_frequency",
3856 .lname = "Zone reset frequency",
3857 .help = "Zoned block device zone reset frequency in HZ",
3858 .type = FIO_OPT_FLOAT_LIST,
3859 .maxlen = 1,
3860 .off1 = offsetof(struct thread_options, zrf),
3861 .minfp = 0,
3862 .maxfp = 1,
3863 .category = FIO_OPT_C_IO,
3864 .group = FIO_OPT_G_ZONE,
3865 },
650c4ad3
SK
3866 {
3867 .name = "recover_zbd_write_error",
3868 .lname = "Recover write errors when zonemode=zbd is set",
3869 .type = FIO_OPT_BOOL,
3870 .off1 = offsetof(struct thread_options, recover_zbd_write_error),
3871 .def = 0,
3872 .help = "Continue writes for sequential write required zones after recovering write errors with care for partial write pointer move",
3873 .category = FIO_OPT_C_IO,
3874 .group = FIO_OPT_G_ZONE,
3875 },
a7e8aae0
KB
3876 {
3877 .name = "fdp",
3878 .lname = "Flexible data placement",
3879 .type = FIO_OPT_BOOL,
3880 .off1 = offsetof(struct thread_options, fdp),
3881 .help = "Use Data placement directive (FDP)",
3882 .def = "0",
3883 .category = FIO_OPT_C_IO,
3884 .group = FIO_OPT_G_INVALID,
3885 },
d3e310c5 3886 {
65ca6791
VF
3887 .name = "dataplacement",
3888 .alias = "data_placement",
3889 .lname = "Data Placement interface",
d3e310c5 3890 .type = FIO_OPT_STR,
65ca6791
VF
3891 .off1 = offsetof(struct thread_options, dp_type),
3892 .help = "Data Placement interface to use",
3893 .def = "none",
3894 .category = FIO_OPT_C_IO,
3895 .group = FIO_OPT_G_INVALID,
3896 .posval = {
3897 { .ival = "none",
3898 .oval = FIO_DP_NONE,
3899 .help = "Do not specify a data placement interface",
3900 },
3901 { .ival = "fdp",
3902 .oval = FIO_DP_FDP,
3903 .help = "Use Flexible Data Placement interface",
3904 },
3905 { .ival = "streams",
3906 .oval = FIO_DP_STREAMS,
3907 .help = "Use Streams interface",
3908 },
3909 },
3910 },
3911 {
3912 .name = "plid_select",
3913 .alias = "fdp_pli_select",
3914 .lname = "Data Placement ID selection strategy",
3915 .type = FIO_OPT_STR,
3916 .off1 = offsetof(struct thread_options, dp_id_select),
3917 .help = "Strategy for selecting next Data Placement ID",
d3e310c5
AK
3918 .def = "roundrobin",
3919 .category = FIO_OPT_C_IO,
3920 .group = FIO_OPT_G_INVALID,
3921 .posval = {
3922 { .ival = "random",
65ca6791 3923 .oval = FIO_DP_RANDOM,
d3e310c5
AK
3924 .help = "Choose a Placement ID at random (uniform)",
3925 },
3926 { .ival = "roundrobin",
65ca6791 3927 .oval = FIO_DP_RR,
d3e310c5
AK
3928 .help = "Round robin select Placement IDs",
3929 },
04d5add8
HP
3930 { .ival = "scheme",
3931 .oval = FIO_DP_SCHEME,
3932 .help = "Use a scheme(based on LBA) to select Placement IDs",
3933 },
d3e310c5
AK
3934 },
3935 },
a7e8aae0 3936 {
65ca6791
VF
3937 .name = "plids",
3938 .alias = "fdp_pli",
3939 .lname = "Stream IDs/Data Placement ID indices",
a7e8aae0
KB
3940 .type = FIO_OPT_STR,
3941 .cb = str_fdp_pli_cb,
65ca6791
VF
3942 .off1 = offsetof(struct thread_options, dp_ids),
3943 .help = "Sets which Data Placement ids to use (defaults to all for FDP)",
a7e8aae0
KB
3944 .hide = 1,
3945 .category = FIO_OPT_C_IO,
3946 .group = FIO_OPT_G_INVALID,
3947 },
04d5add8
HP
3948 {
3949 .name = "dp_scheme",
3950 .lname = "Data Placement Scheme",
3951 .type = FIO_OPT_STR_STORE,
3952 .cb = str_dp_scheme_cb,
3953 .off1 = offsetof(struct thread_options, dp_scheme_file),
3954 .maxlen = PATH_MAX,
3955 .help = "scheme file that specifies offset-RUH mapping",
3956 .category = FIO_OPT_C_IO,
3957 .group = FIO_OPT_G_INVALID,
3958 },
214e1eca
JA
3959 {
3960 .name = "lockmem",
e8b0e958 3961 .lname = "Lock memory",
214e1eca 3962 .type = FIO_OPT_STR_VAL,
a609f12a 3963 .off1 = offsetof(struct thread_options, lockmem),
81c6b6cd 3964 .help = "Lock down this amount of memory (per worker)",
214e1eca 3965 .def = "0",
20eb06bd 3966 .interval = 1024 * 1024,
e8b0e958
JA
3967 .category = FIO_OPT_C_GENERAL,
3968 .group = FIO_OPT_G_INVALID,
214e1eca 3969 },
214e1eca
JA
3970 {
3971 .name = "rwmixread",
e8b0e958 3972 .lname = "Read/write mix read",
214e1eca 3973 .type = FIO_OPT_INT,
cb499fc4 3974 .cb = str_rwmix_read_cb,
a609f12a 3975 .off1 = offsetof(struct thread_options, rwmix[DDIR_READ]),
214e1eca
JA
3976 .maxval = 100,
3977 .help = "Percentage of mixed workload that is reads",
3978 .def = "50",
20eb06bd 3979 .interval = 5,
90265353 3980 .inverse = "rwmixwrite",
e8b0e958
JA
3981 .category = FIO_OPT_C_IO,
3982 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
3983 },
3984 {
3985 .name = "rwmixwrite",
e8b0e958 3986 .lname = "Read/write mix write",
214e1eca 3987 .type = FIO_OPT_INT,
cb499fc4 3988 .cb = str_rwmix_write_cb,
a609f12a 3989 .off1 = offsetof(struct thread_options, rwmix[DDIR_WRITE]),
214e1eca
JA
3990 .maxval = 100,
3991 .help = "Percentage of mixed workload that is writes",
3992 .def = "50",
20eb06bd 3993 .interval = 5,
90265353 3994 .inverse = "rwmixread",
e8b0e958
JA
3995 .category = FIO_OPT_C_IO,
3996 .group = FIO_OPT_G_RWMIX,
214e1eca 3997 },
afdf9352
JA
3998 {
3999 .name = "rwmixcycle",
e8b0e958 4000 .lname = "Read/write mix cycle",
15ca150e 4001 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
4002 .category = FIO_OPT_C_IO,
4003 .group = FIO_OPT_G_RWMIX,
afdf9352 4004 },
214e1eca
JA
4005 {
4006 .name = "nice",
e8b0e958 4007 .lname = "Nice",
214e1eca 4008 .type = FIO_OPT_INT,
a609f12a 4009 .off1 = offsetof(struct thread_options, nice),
214e1eca 4010 .help = "Set job CPU nice value",
11fd6aa8
RC
4011 .minval = -20,
4012 .maxval = 19,
214e1eca 4013 .def = "0",
20eb06bd 4014 .interval = 1,
e8b0e958 4015 .category = FIO_OPT_C_GENERAL,
10860056 4016 .group = FIO_OPT_G_CRED,
214e1eca
JA
4017 },
4018#ifdef FIO_HAVE_IOPRIO
4019 {
4020 .name = "prio",
e8b0e958 4021 .lname = "I/O nice priority",
214e1eca 4022 .type = FIO_OPT_INT,
a609f12a 4023 .off1 = offsetof(struct thread_options, ioprio),
214e1eca 4024 .help = "Set job IO priority value",
1767bd34
TK
4025 .minval = IOPRIO_MIN_PRIO,
4026 .maxval = IOPRIO_MAX_PRIO,
20eb06bd 4027 .interval = 1,
e8b0e958 4028 .category = FIO_OPT_C_GENERAL,
10860056 4029 .group = FIO_OPT_G_CRED,
214e1eca 4030 },
32ef447a
TK
4031#else
4032 {
4033 .name = "prio",
4034 .lname = "I/O nice priority",
4035 .type = FIO_OPT_UNSUPPORTED,
4036 .help = "Your platform does not support IO priorities",
4037 },
4038#endif
4039#ifdef FIO_HAVE_IOPRIO_CLASS
4040#ifndef FIO_HAVE_IOPRIO
4041#error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
4042#endif
214e1eca
JA
4043 {
4044 .name = "prioclass",
e8b0e958 4045 .lname = "I/O nice priority class",
214e1eca 4046 .type = FIO_OPT_INT,
a609f12a 4047 .off1 = offsetof(struct thread_options, ioprio_class),
214e1eca 4048 .help = "Set job IO priority class",
1767bd34
TK
4049 .minval = IOPRIO_MIN_PRIO_CLASS,
4050 .maxval = IOPRIO_MAX_PRIO_CLASS,
20eb06bd 4051 .interval = 1,
e8b0e958 4052 .category = FIO_OPT_C_GENERAL,
10860056 4053 .group = FIO_OPT_G_CRED,
214e1eca 4054 },
860462da
DLM
4055 {
4056 .name = "priohint",
4057 .lname = "I/O nice priority hint",
4058 .type = FIO_OPT_INT,
4059 .off1 = offsetof(struct thread_options, ioprio_hint),
4060 .help = "Set job IO priority hint",
4061 .minval = IOPRIO_MIN_PRIO_HINT,
4062 .maxval = IOPRIO_MAX_PRIO_HINT,
4063 .interval = 1,
4064 .category = FIO_OPT_C_GENERAL,
4065 .group = FIO_OPT_G_CRED,
4066 },
a275c37a 4067#else
a275c37a
JA
4068 {
4069 .name = "prioclass",
4070 .lname = "I/O nice priority class",
4071 .type = FIO_OPT_UNSUPPORTED,
32ef447a 4072 .help = "Your platform does not support IO priority classes",
a275c37a 4073 },
860462da
DLM
4074 {
4075 .name = "priohint",
4076 .lname = "I/O nice priority hint",
4077 .type = FIO_OPT_UNSUPPORTED,
4078 .help = "Your platform does not support IO priority hints",
4079 },
214e1eca
JA
4080#endif
4081 {
4082 .name = "thinktime",
e8b0e958 4083 .lname = "Thinktime",
214e1eca 4084 .type = FIO_OPT_INT,
a609f12a 4085 .off1 = offsetof(struct thread_options, thinktime),
214e1eca
JA
4086 .help = "Idle time between IO buffers (usec)",
4087 .def = "0",
88038bc7 4088 .is_time = 1,
e8b0e958 4089 .category = FIO_OPT_C_IO,
3ceb458f 4090 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
4091 },
4092 {
4093 .name = "thinktime_spin",
e8b0e958 4094 .lname = "Thinktime spin",
214e1eca 4095 .type = FIO_OPT_INT,
a609f12a 4096 .off1 = offsetof(struct thread_options, thinktime_spin),
214e1eca
JA
4097 .help = "Start think time by spinning this amount (usec)",
4098 .def = "0",
88038bc7 4099 .is_time = 1,
afdf9352 4100 .parent = "thinktime",
d71c154c 4101 .hide = 1,
e8b0e958 4102 .category = FIO_OPT_C_IO,
3ceb458f 4103 .group = FIO_OPT_G_THINKTIME,
214e1eca 4104 },
0d8cc753
CL
4105 {
4106 .name = "thinkcycles",
4107 .lname = "Think cycles",
4108 .type = FIO_OPT_INT,
4109 .off1 = offsetof(struct thread_options, thinkcycles),
4110 .help = "Spin for a constant amount of cycles between requests",
4111 .def = "0",
4112 .parent = "thinktime",
4113 .hide = 1,
4114 .category = FIO_OPT_C_IO,
4115 .group = FIO_OPT_G_THINKTIME,
4116 },
214e1eca
JA
4117 {
4118 .name = "thinktime_blocks",
e8b0e958 4119 .lname = "Thinktime blocks",
214e1eca 4120 .type = FIO_OPT_INT,
a609f12a 4121 .off1 = offsetof(struct thread_options, thinktime_blocks),
214e1eca
JA
4122 .help = "IO buffer period between 'thinktime'",
4123 .def = "1",
afdf9352 4124 .parent = "thinktime",
d71c154c 4125 .hide = 1,
e8b0e958 4126 .category = FIO_OPT_C_IO,
3ceb458f 4127 .group = FIO_OPT_G_THINKTIME,
214e1eca 4128 },
33f42c20
HQ
4129 {
4130 .name = "thinktime_blocks_type",
4131 .lname = "Thinktime blocks type",
4132 .type = FIO_OPT_STR,
4133 .off1 = offsetof(struct thread_options, thinktime_blocks_type),
4134 .help = "How thinktime_blocks takes effect",
4135 .def = "complete",
4136 .category = FIO_OPT_C_IO,
4137 .group = FIO_OPT_G_THINKTIME,
4138 .posval = {
4139 { .ival = "complete",
4140 .oval = THINKTIME_BLOCKS_TYPE_COMPLETE,
4141 .help = "thinktime_blocks takes effect at the completion side",
4142 },
4143 {
4144 .ival = "issue",
4145 .oval = THINKTIME_BLOCKS_TYPE_ISSUE,
4146 .help = "thinktime_blocks takes effect at the issue side",
4147 },
4148 },
4149 .parent = "thinktime",
4150 },
f7942acd
SK
4151 {
4152 .name = "thinktime_iotime",
4153 .lname = "Thinktime interval",
4154 .type = FIO_OPT_INT,
4155 .off1 = offsetof(struct thread_options, thinktime_iotime),
4156 .help = "IO time interval between 'thinktime'",
4157 .def = "0",
4158 .parent = "thinktime",
4159 .hide = 1,
4160 .is_seconds = 1,
4161 .is_time = 1,
4162 .category = FIO_OPT_C_IO,
4163 .group = FIO_OPT_G_THINKTIME,
4164 },
214e1eca
JA
4165 {
4166 .name = "rate",
e8b0e958 4167 .lname = "I/O rate",
140a6888 4168 .type = FIO_OPT_ULL,
a609f12a
JA
4169 .off1 = offsetof(struct thread_options, rate[DDIR_READ]),
4170 .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]),
4171 .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]),
214e1eca 4172 .help = "Set bandwidth rate",
e8b0e958
JA
4173 .category = FIO_OPT_C_IO,
4174 .group = FIO_OPT_G_RATE,
214e1eca
JA
4175 },
4176 {
6d428bcd
JA
4177 .name = "rate_min",
4178 .alias = "ratemin",
e8b0e958 4179 .lname = "I/O min rate",
140a6888 4180 .type = FIO_OPT_ULL,
a609f12a
JA
4181 .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]),
4182 .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]),
4183 .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]),
4e991c23 4184 .help = "Job must meet this rate or it will be shutdown",
afdf9352 4185 .parent = "rate",
d71c154c 4186 .hide = 1,
e8b0e958
JA
4187 .category = FIO_OPT_C_IO,
4188 .group = FIO_OPT_G_RATE,
4e991c23
JA
4189 },
4190 {
4191 .name = "rate_iops",
e8b0e958 4192 .lname = "I/O rate IOPS",
e01b22b8 4193 .type = FIO_OPT_INT,
a609f12a
JA
4194 .off1 = offsetof(struct thread_options, rate_iops[DDIR_READ]),
4195 .off2 = offsetof(struct thread_options, rate_iops[DDIR_WRITE]),
4196 .off3 = offsetof(struct thread_options, rate_iops[DDIR_TRIM]),
4e991c23 4197 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 4198 .hide = 1,
e8b0e958
JA
4199 .category = FIO_OPT_C_IO,
4200 .group = FIO_OPT_G_RATE,
4e991c23
JA
4201 },
4202 {
4203 .name = "rate_iops_min",
e8b0e958 4204 .lname = "I/O min rate IOPS",
e01b22b8 4205 .type = FIO_OPT_INT,
a609f12a
JA
4206 .off1 = offsetof(struct thread_options, rate_iops_min[DDIR_READ]),
4207 .off2 = offsetof(struct thread_options, rate_iops_min[DDIR_WRITE]),
4208 .off3 = offsetof(struct thread_options, rate_iops_min[DDIR_TRIM]),
03e20d68 4209 .help = "Job must meet this rate or it will be shut down",
afdf9352 4210 .parent = "rate_iops",
d71c154c 4211 .hide = 1,
e8b0e958
JA
4212 .category = FIO_OPT_C_IO,
4213 .group = FIO_OPT_G_RATE,
214e1eca 4214 },
ff6bb260 4215 {
6de65959
JA
4216 .name = "rate_process",
4217 .lname = "Rate Process",
4218 .type = FIO_OPT_STR,
a609f12a 4219 .off1 = offsetof(struct thread_options, rate_process),
6de65959
JA
4220 .help = "What process controls how rated IO is managed",
4221 .def = "linear",
ff6bb260
SL
4222 .category = FIO_OPT_C_IO,
4223 .group = FIO_OPT_G_RATE,
6de65959
JA
4224 .posval = {
4225 { .ival = "linear",
4226 .oval = RATE_PROCESS_LINEAR,
4227 .help = "Linear rate of IO",
4228 },
4229 {
4230 .ival = "poisson",
4231 .oval = RATE_PROCESS_POISSON,
4232 .help = "Rate follows Poisson process",
4233 },
4234 },
4235 .parent = "rate",
ff6bb260 4236 },
214e1eca 4237 {
6d428bcd
JA
4238 .name = "rate_cycle",
4239 .alias = "ratecycle",
e8b0e958 4240 .lname = "I/O rate cycle",
214e1eca 4241 .type = FIO_OPT_INT,
a609f12a 4242 .off1 = offsetof(struct thread_options, ratecycle),
214e1eca
JA
4243 .help = "Window average for rate limits (msec)",
4244 .def = "1000",
afdf9352 4245 .parent = "rate",
d71c154c 4246 .hide = 1,
e8b0e958
JA
4247 .category = FIO_OPT_C_IO,
4248 .group = FIO_OPT_G_RATE,
214e1eca 4249 },
1a9bf814
JA
4250 {
4251 .name = "rate_ignore_thinktime",
4252 .lname = "Rate ignore thinktime",
4253 .type = FIO_OPT_BOOL,
4254 .off1 = offsetof(struct thread_options, rate_ign_think),
4255 .help = "Rated IO ignores thinktime settings",
4256 .parent = "rate",
4257 .category = FIO_OPT_C_IO,
4258 .group = FIO_OPT_G_RATE,
4259 },
15501535
JA
4260 {
4261 .name = "max_latency",
dd97d866 4262 .lname = "Max Latency (usec)",
f7cf63bf
VR
4263 .type = FIO_OPT_ULL,
4264 .off1 = offsetof(struct thread_options, max_latency[DDIR_READ]),
4265 .off2 = offsetof(struct thread_options, max_latency[DDIR_WRITE]),
4266 .off3 = offsetof(struct thread_options, max_latency[DDIR_TRIM]),
15501535 4267 .help = "Maximum tolerated IO latency (usec)",
88038bc7 4268 .is_time = 1,
1e5324e7 4269 .category = FIO_OPT_C_IO,
3e260a46
JA
4270 .group = FIO_OPT_G_LATPROF,
4271 },
4272 {
4273 .name = "latency_target",
4274 .lname = "Latency Target (usec)",
4275 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 4276 .off1 = offsetof(struct thread_options, latency_target),
3e260a46 4277 .help = "Ramp to max queue depth supporting this latency",
88038bc7 4278 .is_time = 1,
3e260a46
JA
4279 .category = FIO_OPT_C_IO,
4280 .group = FIO_OPT_G_LATPROF,
4281 },
4282 {
4283 .name = "latency_window",
4284 .lname = "Latency Window (usec)",
4285 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 4286 .off1 = offsetof(struct thread_options, latency_window),
3e260a46 4287 .help = "Time to sustain latency_target",
88038bc7 4288 .is_time = 1,
3e260a46
JA
4289 .category = FIO_OPT_C_IO,
4290 .group = FIO_OPT_G_LATPROF,
4291 },
4292 {
4293 .name = "latency_percentile",
4294 .lname = "Latency Percentile",
4295 .type = FIO_OPT_FLOAT_LIST,
a609f12a 4296 .off1 = offsetof(struct thread_options, latency_percentile),
3e260a46
JA
4297 .help = "Percentile of IOs must be below latency_target",
4298 .def = "100",
4299 .maxlen = 1,
4300 .minfp = 0.0,
4301 .maxfp = 100.0,
4302 .category = FIO_OPT_C_IO,
4303 .group = FIO_OPT_G_LATPROF,
15501535 4304 },
e1bcd541
SL
4305 {
4306 .name = "latency_run",
4307 .lname = "Latency Run",
4308 .type = FIO_OPT_BOOL,
4309 .off1 = offsetof(struct thread_options, latency_run),
4310 .help = "Keep adjusting queue depth to match latency_target",
4311 .def = "0",
4312 .category = FIO_OPT_C_IO,
4313 .group = FIO_OPT_G_LATPROF,
4314 },
214e1eca
JA
4315 {
4316 .name = "invalidate",
e8b0e958 4317 .lname = "Cache invalidate",
214e1eca 4318 .type = FIO_OPT_BOOL,
a609f12a 4319 .off1 = offsetof(struct thread_options, invalidate_cache),
214e1eca
JA
4320 .help = "Invalidate buffer/page cache prior to running job",
4321 .def = "1",
e8b0e958 4322 .category = FIO_OPT_C_IO,
3ceb458f 4323 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
4324 },
4325 {
4326 .name = "sync",
e8b0e958 4327 .lname = "Synchronous I/O",
eb9f8d7f 4328 .type = FIO_OPT_STR,
a609f12a 4329 .off1 = offsetof(struct thread_options, sync_io),
eb9f8d7f
AF
4330 .help = "Use synchronous write IO",
4331 .def = "none",
d71c154c 4332 .hide = 1,
e8b0e958 4333 .category = FIO_OPT_C_IO,
3ceb458f 4334 .group = FIO_OPT_G_IO_TYPE,
eb9f8d7f
AF
4335 .posval = {
4336 { .ival = "none",
4337 .oval = 0,
4338 },
4339 { .ival = "0",
4340 .oval = 0,
4341 },
4342 { .ival = "sync",
4343 .oval = O_SYNC,
4344 },
4345 { .ival = "1",
4346 .oval = O_SYNC,
4347 },
4348#ifdef O_DSYNC
4349 { .ival = "dsync",
4350 .oval = O_DSYNC,
4351 },
4352#endif
4353 },
214e1eca 4354 },
ae8e559e
JA
4355#ifdef FIO_HAVE_WRITE_HINT
4356 {
4357 .name = "write_hint",
4358 .lname = "Write hint",
4359 .type = FIO_OPT_STR,
4360 .off1 = offsetof(struct thread_options, write_hint),
4361 .help = "Set expected write life time",
4362 .category = FIO_OPT_C_ENGINE,
4363 .group = FIO_OPT_G_INVALID,
4364 .posval = {
4365 { .ival = "none",
4366 .oval = RWH_WRITE_LIFE_NONE,
4367 },
4368 { .ival = "short",
4369 .oval = RWH_WRITE_LIFE_SHORT,
4370 },
4371 { .ival = "medium",
4372 .oval = RWH_WRITE_LIFE_MEDIUM,
4373 },
4374 { .ival = "long",
4375 .oval = RWH_WRITE_LIFE_LONG,
4376 },
4377 { .ival = "extreme",
4378 .oval = RWH_WRITE_LIFE_EXTREME,
4379 },
4380 },
4381 },
4382#endif
214e1eca
JA
4383 {
4384 .name = "create_serialize",
e8b0e958 4385 .lname = "Create serialize",
214e1eca 4386 .type = FIO_OPT_BOOL,
a609f12a 4387 .off1 = offsetof(struct thread_options, create_serialize),
c2b8035f 4388 .help = "Serialize creation of job files",
214e1eca 4389 .def = "1",
e8b0e958
JA
4390 .category = FIO_OPT_C_FILE,
4391 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4392 },
4393 {
4394 .name = "create_fsync",
e8b0e958 4395 .lname = "Create fsync",
214e1eca 4396 .type = FIO_OPT_BOOL,
a609f12a 4397 .off1 = offsetof(struct thread_options, create_fsync),
03e20d68 4398 .help = "fsync file after creation",
214e1eca 4399 .def = "1",
e8b0e958
JA
4400 .category = FIO_OPT_C_FILE,
4401 .group = FIO_OPT_G_INVALID,
214e1eca 4402 },
814452bd
JA
4403 {
4404 .name = "create_on_open",
e8b0e958 4405 .lname = "Create on open",
814452bd 4406 .type = FIO_OPT_BOOL,
a609f12a 4407 .off1 = offsetof(struct thread_options, create_on_open),
814452bd
JA
4408 .help = "Create files when they are opened for IO",
4409 .def = "0",
e8b0e958
JA
4410 .category = FIO_OPT_C_FILE,
4411 .group = FIO_OPT_G_INVALID,
814452bd 4412 },
25460cf6
JA
4413 {
4414 .name = "create_only",
cce2fdfe 4415 .lname = "Create Only",
25460cf6 4416 .type = FIO_OPT_BOOL,
a609f12a 4417 .off1 = offsetof(struct thread_options, create_only),
25460cf6 4418 .help = "Only perform file creation phase",
d17fda71 4419 .category = FIO_OPT_C_FILE,
25460cf6
JA
4420 .def = "0",
4421 },
2378826d
JA
4422 {
4423 .name = "allow_file_create",
e81ecca3 4424 .lname = "Allow file create",
2378826d 4425 .type = FIO_OPT_BOOL,
a609f12a 4426 .off1 = offsetof(struct thread_options, allow_create),
2378826d
JA
4427 .help = "Permit fio to create files, if they don't exist",
4428 .def = "1",
4429 .category = FIO_OPT_C_FILE,
4430 .group = FIO_OPT_G_FILENAME,
4431 },
e81ecca3
JA
4432 {
4433 .name = "allow_mounted_write",
4434 .lname = "Allow mounted write",
4435 .type = FIO_OPT_BOOL,
a609f12a 4436 .off1 = offsetof(struct thread_options, allow_mounted_write),
e81ecca3
JA
4437 .help = "Allow writes to a mounted partition",
4438 .def = "0",
4439 .category = FIO_OPT_C_FILE,
4440 .group = FIO_OPT_G_FILENAME,
4441 },
0b9d69ec 4442 {
afad68f7 4443 .name = "pre_read",
e8b0e958 4444 .lname = "Pre-read files",
afad68f7 4445 .type = FIO_OPT_BOOL,
a609f12a 4446 .off1 = offsetof(struct thread_options, pre_read),
03e20d68 4447 .help = "Pre-read files before starting official testing",
afad68f7 4448 .def = "0",
e8b0e958
JA
4449 .category = FIO_OPT_C_FILE,
4450 .group = FIO_OPT_G_INVALID,
afad68f7 4451 },
214e1eca
JA
4452#ifdef FIO_HAVE_CPU_AFFINITY
4453 {
4454 .name = "cpumask",
e8b0e958 4455 .lname = "CPU mask",
214e1eca
JA
4456 .type = FIO_OPT_INT,
4457 .cb = str_cpumask_cb,
a609f12a 4458 .off1 = offsetof(struct thread_options, cpumask),
214e1eca 4459 .help = "CPU affinity mask",
e8b0e958 4460 .category = FIO_OPT_C_GENERAL,
10860056 4461 .group = FIO_OPT_G_CRED,
214e1eca 4462 },
d2e268b0
JA
4463 {
4464 .name = "cpus_allowed",
e8b0e958 4465 .lname = "CPUs allowed",
d2e268b0
JA
4466 .type = FIO_OPT_STR,
4467 .cb = str_cpus_allowed_cb,
a609f12a 4468 .off1 = offsetof(struct thread_options, cpumask),
d2e268b0 4469 .help = "Set CPUs allowed",
e8b0e958 4470 .category = FIO_OPT_C_GENERAL,
10860056 4471 .group = FIO_OPT_G_CRED,
d2e268b0 4472 },
c2acfbac
JA
4473 {
4474 .name = "cpus_allowed_policy",
4475 .lname = "CPUs allowed distribution policy",
4476 .type = FIO_OPT_STR,
a609f12a 4477 .off1 = offsetof(struct thread_options, cpus_allowed_policy),
c2acfbac
JA
4478 .help = "Distribution policy for cpus_allowed",
4479 .parent = "cpus_allowed",
4480 .prio = 1,
4481 .posval = {
4482 { .ival = "shared",
4483 .oval = FIO_CPUS_SHARED,
4484 .help = "Mask shared between threads",
4485 },
4486 { .ival = "split",
4487 .oval = FIO_CPUS_SPLIT,
4488 .help = "Mask split between threads",
4489 },
4490 },
4491 .category = FIO_OPT_C_GENERAL,
4492 .group = FIO_OPT_G_CRED,
4493 },
a275c37a
JA
4494#else
4495 {
4496 .name = "cpumask",
4497 .lname = "CPU mask",
4498 .type = FIO_OPT_UNSUPPORTED,
4499 .help = "Your platform does not support CPU affinities",
4500 },
4501 {
4502 .name = "cpus_allowed",
4503 .lname = "CPUs allowed",
4504 .type = FIO_OPT_UNSUPPORTED,
4505 .help = "Your platform does not support CPU affinities",
4506 },
4507 {
4508 .name = "cpus_allowed_policy",
4509 .lname = "CPUs allowed distribution policy",
4510 .type = FIO_OPT_UNSUPPORTED,
4511 .help = "Your platform does not support CPU affinities",
4512 },
d0b937ed 4513#endif
67bf9823 4514#ifdef CONFIG_LIBNUMA
d0b937ed
YR
4515 {
4516 .name = "numa_cpu_nodes",
cce2fdfe 4517 .lname = "NUMA CPU Nodes",
d0b937ed
YR
4518 .type = FIO_OPT_STR,
4519 .cb = str_numa_cpunodes_cb,
a609f12a 4520 .off1 = offsetof(struct thread_options, numa_cpunodes),
d0b937ed 4521 .help = "NUMA CPU nodes bind",
6be54b2d
JA
4522 .category = FIO_OPT_C_GENERAL,
4523 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
4524 },
4525 {
4526 .name = "numa_mem_policy",
cce2fdfe 4527 .lname = "NUMA Memory Policy",
d0b937ed
YR
4528 .type = FIO_OPT_STR,
4529 .cb = str_numa_mpol_cb,
a609f12a 4530 .off1 = offsetof(struct thread_options, numa_memnodes),
d0b937ed 4531 .help = "NUMA memory policy setup",
6be54b2d
JA
4532 .category = FIO_OPT_C_GENERAL,
4533 .group = FIO_OPT_G_INVALID,
d0b937ed 4534 },
a275c37a
JA
4535#else
4536 {
4537 .name = "numa_cpu_nodes",
4538 .lname = "NUMA CPU Nodes",
4539 .type = FIO_OPT_UNSUPPORTED,
4540 .help = "Build fio with libnuma-dev(el) to enable this option",
4541 },
4542 {
4543 .name = "numa_mem_policy",
4544 .lname = "NUMA Memory Policy",
4545 .type = FIO_OPT_UNSUPPORTED,
4546 .help = "Build fio with libnuma-dev(el) to enable this option",
4547 },
03553853
YR
4548#endif
4549#ifdef CONFIG_CUDA
4550 {
4551 .name = "gpu_dev_id",
4552 .lname = "GPU device ID",
4553 .type = FIO_OPT_INT,
4554 .off1 = offsetof(struct thread_options, gpu_dev_id),
4555 .help = "Set GPU device ID for GPUDirect RDMA",
4556 .def = "0",
4557 .category = FIO_OPT_C_GENERAL,
4558 .group = FIO_OPT_G_INVALID,
4559 },
214e1eca
JA
4560#endif
4561 {
4562 .name = "end_fsync",
e8b0e958 4563 .lname = "End fsync",
214e1eca 4564 .type = FIO_OPT_BOOL,
a609f12a 4565 .off1 = offsetof(struct thread_options, end_fsync),
214e1eca
JA
4566 .help = "Include fsync at the end of job",
4567 .def = "0",
e8b0e958
JA
4568 .category = FIO_OPT_C_FILE,
4569 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4570 },
4571 {
4572 .name = "fsync_on_close",
e8b0e958 4573 .lname = "Fsync on close",
214e1eca 4574 .type = FIO_OPT_BOOL,
a609f12a 4575 .off1 = offsetof(struct thread_options, fsync_on_close),
214e1eca
JA
4576 .help = "fsync files on close",
4577 .def = "0",
e8b0e958
JA
4578 .category = FIO_OPT_C_FILE,
4579 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4580 },
4581 {
4582 .name = "unlink",
e8b0e958 4583 .lname = "Unlink file",
214e1eca 4584 .type = FIO_OPT_BOOL,
a609f12a 4585 .off1 = offsetof(struct thread_options, unlink),
214e1eca
JA
4586 .help = "Unlink created files after job has completed",
4587 .def = "0",
e8b0e958
JA
4588 .category = FIO_OPT_C_FILE,
4589 .group = FIO_OPT_G_INVALID,
214e1eca 4590 },
39c1c323 4591 {
4592 .name = "unlink_each_loop",
4593 .lname = "Unlink file after each loop of a job",
4594 .type = FIO_OPT_BOOL,
a609f12a 4595 .off1 = offsetof(struct thread_options, unlink_each_loop),
39c1c323 4596 .help = "Unlink created files after each loop in a job has completed",
4597 .def = "0",
4598 .category = FIO_OPT_C_FILE,
4599 .group = FIO_OPT_G_INVALID,
4600 },
214e1eca
JA
4601 {
4602 .name = "exitall",
e8b0e958 4603 .lname = "Exit-all on terminate",
214e1eca
JA
4604 .type = FIO_OPT_STR_SET,
4605 .cb = str_exitall_cb,
4606 .help = "Terminate all jobs when one exits",
e8b0e958 4607 .category = FIO_OPT_C_GENERAL,
a1f6afec 4608 .group = FIO_OPT_G_PROCESS,
214e1eca 4609 },
64402a8a
HW
4610 {
4611 .name = "exit_what",
4612 .lname = "What jobs to quit on terminate",
4613 .type = FIO_OPT_STR,
4614 .off1 = offsetof(struct thread_options, exit_what),
4615 .help = "Fine-grained control for exitall",
4616 .def = "group",
4617 .category = FIO_OPT_C_GENERAL,
4618 .group = FIO_OPT_G_PROCESS,
4619 .posval = {
4620 { .ival = "group",
4621 .oval = TERMINATE_GROUP,
4622 .help = "exit_all=1 default behaviour",
4623 },
4624 { .ival = "stonewall",
4625 .oval = TERMINATE_STONEWALL,
4626 .help = "quit all currently running jobs; continue with next stonewall",
4627 },
4628 { .ival = "all",
4629 .oval = TERMINATE_ALL,
4630 .help = "Quit everything",
4631 },
4632 },
4633 },
f9cafb12
JA
4634 {
4635 .name = "exitall_on_error",
4636 .lname = "Exit-all on terminate in error",
78abcf9b 4637 .type = FIO_OPT_STR_SET,
a609f12a 4638 .off1 = offsetof(struct thread_options, exitall_error),
f9cafb12
JA
4639 .help = "Terminate all jobs when one exits in error",
4640 .category = FIO_OPT_C_GENERAL,
4641 .group = FIO_OPT_G_PROCESS,
4642 },
214e1eca
JA
4643 {
4644 .name = "stonewall",
e8b0e958 4645 .lname = "Wait for previous",
d392365e 4646 .alias = "wait_for_previous",
214e1eca 4647 .type = FIO_OPT_STR_SET,
a609f12a 4648 .off1 = offsetof(struct thread_options, stonewall),
214e1eca 4649 .help = "Insert a hard barrier between this job and previous",
e8b0e958 4650 .category = FIO_OPT_C_GENERAL,
a1f6afec 4651 .group = FIO_OPT_G_PROCESS,
214e1eca 4652 },
b3d62a75
JA
4653 {
4654 .name = "new_group",
e8b0e958 4655 .lname = "New group",
b3d62a75 4656 .type = FIO_OPT_STR_SET,
a609f12a 4657 .off1 = offsetof(struct thread_options, new_group),
b3d62a75 4658 .help = "Mark the start of a new group (for reporting)",
e8b0e958 4659 .category = FIO_OPT_C_GENERAL,
a1f6afec 4660 .group = FIO_OPT_G_PROCESS,
b3d62a75 4661 },
214e1eca
JA
4662 {
4663 .name = "thread",
e8b0e958 4664 .lname = "Thread",
214e1eca 4665 .type = FIO_OPT_STR_SET,
a609f12a 4666 .off1 = offsetof(struct thread_options, use_thread),
20eb06bd 4667 .help = "Use threads instead of processes",
c8931876
JA
4668#ifdef CONFIG_NO_SHM
4669 .def = "1",
4670 .no_warn_def = 1,
4671#endif
e8b0e958 4672 .category = FIO_OPT_C_GENERAL,
a1f6afec 4673 .group = FIO_OPT_G_PROCESS,
214e1eca 4674 },
3a5db920
JA
4675 {
4676 .name = "per_job_logs",
cce2fdfe 4677 .lname = "Per Job Logs",
3a5db920 4678 .type = FIO_OPT_BOOL,
a609f12a 4679 .off1 = offsetof(struct thread_options, per_job_logs),
3a5db920
JA
4680 .help = "Include job number in generated log files or not",
4681 .def = "1",
4682 .category = FIO_OPT_C_LOG,
4683 .group = FIO_OPT_G_INVALID,
4684 },
214e1eca
JA
4685 {
4686 .name = "write_bw_log",
e8b0e958 4687 .lname = "Write bandwidth log",
dded427c 4688 .type = FIO_OPT_STR,
a609f12a 4689 .off1 = offsetof(struct thread_options, bw_log_file),
dded427c 4690 .cb = str_write_bw_log_cb,
214e1eca 4691 .help = "Write log of bandwidth during run",
e8b0e958
JA
4692 .category = FIO_OPT_C_LOG,
4693 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4694 },
4695 {
4696 .name = "write_lat_log",
e8b0e958 4697 .lname = "Write latency log",
dded427c 4698 .type = FIO_OPT_STR,
a609f12a 4699 .off1 = offsetof(struct thread_options, lat_log_file),
dded427c 4700 .cb = str_write_lat_log_cb,
214e1eca 4701 .help = "Write log of latency during run",
e8b0e958
JA
4702 .category = FIO_OPT_C_LOG,
4703 .group = FIO_OPT_G_INVALID,
214e1eca 4704 },
c8eeb9df
JA
4705 {
4706 .name = "write_iops_log",
e8b0e958 4707 .lname = "Write IOPS log",
dded427c 4708 .type = FIO_OPT_STR,
a609f12a 4709 .off1 = offsetof(struct thread_options, iops_log_file),
dded427c 4710 .cb = str_write_iops_log_cb,
c8eeb9df 4711 .help = "Write log of IOPS during run",
e8b0e958
JA
4712 .category = FIO_OPT_C_LOG,
4713 .group = FIO_OPT_G_INVALID,
c8eeb9df 4714 },
0a852a50
DLM
4715 {
4716 .name = "log_entries",
4717 .lname = "Log entries",
4718 .type = FIO_OPT_INT,
4719 .off1 = offsetof(struct thread_options, log_entries),
4720 .help = "Initial number of entries in a job IO log",
4721 .def = __fio_stringify(DEF_LOG_ENTRIES),
4722 .minval = DEF_LOG_ENTRIES,
4723 .maxval = MAX_LOG_ENTRIES,
4724 .category = FIO_OPT_C_LOG,
4725 .group = FIO_OPT_G_INVALID,
4726 },
b8bc8cba
JA
4727 {
4728 .name = "log_avg_msec",
e8b0e958 4729 .lname = "Log averaging (msec)",
b8bc8cba 4730 .type = FIO_OPT_INT,
a609f12a 4731 .off1 = offsetof(struct thread_options, log_avg_msec),
b8bc8cba
JA
4732 .help = "Average bw/iops/lat logs over this period of time",
4733 .def = "0",
e8b0e958 4734 .category = FIO_OPT_C_LOG,
1e613c9c
KC
4735 .group = FIO_OPT_G_INVALID,
4736 },
4737 {
4738 .name = "log_hist_msec",
4739 .lname = "Log histograms (msec)",
4740 .type = FIO_OPT_INT,
a609f12a 4741 .off1 = offsetof(struct thread_options, log_hist_msec),
1e613c9c
KC
4742 .help = "Dump completion latency histograms at frequency of this time value",
4743 .def = "0",
4744 .category = FIO_OPT_C_LOG,
4745 .group = FIO_OPT_G_INVALID,
4746 },
4747 {
4748 .name = "log_hist_coarseness",
4749 .lname = "Histogram logs coarseness",
4750 .type = FIO_OPT_INT,
a609f12a 4751 .off1 = offsetof(struct thread_options, log_hist_coarseness),
1e613c9c
KC
4752 .help = "Integer in range [0,6]. Higher coarseness outputs"
4753 " fewer histogram bins per sample. The number of bins for"
4754 " these are [1216, 608, 304, 152, 76, 38, 19] respectively.",
4755 .def = "0",
4756 .category = FIO_OPT_C_LOG,
4757 .group = FIO_OPT_G_INVALID,
4758 },
4759 {
4760 .name = "write_hist_log",
4761 .lname = "Write latency histogram logs",
dded427c 4762 .type = FIO_OPT_STR,
a609f12a 4763 .off1 = offsetof(struct thread_options, hist_log_file),
dded427c 4764 .cb = str_write_hist_log_cb,
1e613c9c
KC
4765 .help = "Write log of latency histograms during run",
4766 .category = FIO_OPT_C_LOG,
e8b0e958 4767 .group = FIO_OPT_G_INVALID,
b8bc8cba 4768 },
e6989e10 4769 {
0e14633c
AK
4770 .name = "log_window_value",
4771 .alias = "log_max_value",
4772 .lname = "Log maximum, average or both values",
4773 .type = FIO_OPT_STR,
a609f12a 4774 .off1 = offsetof(struct thread_options, log_max),
0e14633c
AK
4775 .help = "Log max, average or both sample in a window",
4776 .def = "avg",
e6989e10
JA
4777 .category = FIO_OPT_C_LOG,
4778 .group = FIO_OPT_G_INVALID,
0e14633c
AK
4779 .posval = {
4780 { .ival = "avg",
4781 .oval = IO_LOG_SAMPLE_AVG,
4782 .help = "Log average value over the window",
4783 },
4784 { .ival = "max",
4785 .oval = IO_LOG_SAMPLE_MAX,
4786 .help = "Log maximum value in the window",
4787 },
4788 { .ival = "both",
4789 .oval = IO_LOG_SAMPLE_BOTH,
4790 .help = "Log both average and maximum values over the window"
4791 },
4792 /* Compatibility with former boolean values */
4793 { .ival = "0",
4794 .oval = IO_LOG_SAMPLE_AVG,
4795 .help = "Alias for 'avg'",
4796 },
4797 { .ival = "1",
4798 .oval = IO_LOG_SAMPLE_MAX,
4799 .help = "Alias for 'max'",
4800 },
4801 },
e6989e10 4802 },
ae588852
JA
4803 {
4804 .name = "log_offset",
4805 .lname = "Log offset of IO",
4806 .type = FIO_OPT_BOOL,
a609f12a 4807 .off1 = offsetof(struct thread_options, log_offset),
ae588852
JA
4808 .help = "Include offset of IO for each log entry",
4809 .def = "0",
4810 .category = FIO_OPT_C_LOG,
4811 .group = FIO_OPT_G_INVALID,
4812 },
03ec570f
DLM
4813 {
4814 .name = "log_prio",
4815 .lname = "Log priority of IO",
4816 .type = FIO_OPT_BOOL,
4817 .off1 = offsetof(struct thread_options, log_prio),
4818 .help = "Include priority value of IO for each log entry",
4819 .def = "0",
4820 .category = FIO_OPT_C_LOG,
4821 .group = FIO_OPT_G_INVALID,
4822 },
14d3134a
SK
4823 {
4824 .name = "log_issue_time",
4825 .lname = "Log IO issue time",
4826 .type = FIO_OPT_BOOL,
4827 .off1 = offsetof(struct thread_options, log_issue_time),
4828 .help = "Include IO issue time for each log entry",
4829 .def = "0",
4830 .category = FIO_OPT_C_LOG,
4831 .group = FIO_OPT_G_INVALID,
4832 },
aee2ab67
JA
4833#ifdef CONFIG_ZLIB
4834 {
4835 .name = "log_compression",
4836 .lname = "Log compression",
4837 .type = FIO_OPT_INT,
a609f12a 4838 .off1 = offsetof(struct thread_options, log_gz),
aee2ab67 4839 .help = "Log in compressed chunks of this size",
9919b27b 4840 .minval = 1024ULL,
aee2ab67
JA
4841 .maxval = 512 * 1024 * 1024ULL,
4842 .category = FIO_OPT_C_LOG,
4843 .group = FIO_OPT_G_INVALID,
4844 },
c08f9fe2
JA
4845#ifdef FIO_HAVE_CPU_AFFINITY
4846 {
4847 .name = "log_compression_cpus",
4848 .lname = "Log Compression CPUs",
4849 .type = FIO_OPT_STR,
4850 .cb = str_log_cpus_allowed_cb,
a609f12a 4851 .off1 = offsetof(struct thread_options, log_gz_cpumask),
c08f9fe2
JA
4852 .parent = "log_compression",
4853 .help = "Limit log compression to these CPUs",
4854 .category = FIO_OPT_C_LOG,
4855 .group = FIO_OPT_G_INVALID,
4856 },
a275c37a
JA
4857#else
4858 {
4859 .name = "log_compression_cpus",
4860 .lname = "Log Compression CPUs",
4861 .type = FIO_OPT_UNSUPPORTED,
4862 .help = "Your platform does not support CPU affinities",
4863 },
c08f9fe2 4864#endif
b26317c9
JA
4865 {
4866 .name = "log_store_compressed",
4867 .lname = "Log store compressed",
4868 .type = FIO_OPT_BOOL,
a609f12a 4869 .off1 = offsetof(struct thread_options, log_gz_store),
b26317c9
JA
4870 .help = "Store logs in a compressed format",
4871 .category = FIO_OPT_C_LOG,
4872 .group = FIO_OPT_G_INVALID,
4873 },
a275c37a
JA
4874#else
4875 {
4876 .name = "log_compression",
4877 .lname = "Log compression",
4878 .type = FIO_OPT_UNSUPPORTED,
4879 .help = "Install libz-dev(el) to get compression support",
4880 },
4881 {
4882 .name = "log_store_compressed",
4883 .lname = "Log store compressed",
4884 .type = FIO_OPT_UNSUPPORTED,
4885 .help = "Install libz-dev(el) to get compression support",
4886 },
aee2ab67 4887#endif
d5b3cfd4 4888 {
4889 .name = "log_alternate_epoch",
d252275b 4890 .alias = "log_unix_epoch",
d5b3cfd4 4891 .lname = "Log epoch alternate",
4892 .type = FIO_OPT_BOOL,
4893 .off1 = offsetof(struct thread_options, log_alternate_epoch),
4894 .help = "Use alternate epoch time in log files. Uses the same epoch as that is used by clock_gettime with specified log_alternate_epoch_clock_id.",
4895 .category = FIO_OPT_C_LOG,
4896 .group = FIO_OPT_G_INVALID,
4897 },
4898 {
4899 .name = "log_alternate_epoch_clock_id",
4900 .lname = "Log alternate epoch clock_id",
4901 .type = FIO_OPT_INT,
4902 .off1 = offsetof(struct thread_options, log_alternate_epoch_clock_id),
d252275b 4903 .help = "If log_alternate_epoch is true, this option specifies the clock_id from clock_gettime whose epoch should be used. If log_alternate_epoch is false, this option has no effect. Default value is 0, or CLOCK_REALTIME",
d5b3cfd4 4904 .category = FIO_OPT_C_LOG,
4905 .group = FIO_OPT_G_INVALID,
4906 },
66347cfa
DE
4907 {
4908 .name = "block_error_percentiles",
4909 .lname = "Block error percentiles",
4910 .type = FIO_OPT_BOOL,
a609f12a 4911 .off1 = offsetof(struct thread_options, block_error_hist),
66347cfa
DE
4912 .help = "Record trim block errors and make a histogram",
4913 .def = "0",
4914 .category = FIO_OPT_C_LOG,
4915 .group = FIO_OPT_G_INVALID,
4916 },
c504ee55
JA
4917 {
4918 .name = "bwavgtime",
4919 .lname = "Bandwidth average time",
4920 .type = FIO_OPT_INT,
a609f12a 4921 .off1 = offsetof(struct thread_options, bw_avg_time),
c504ee55
JA
4922 .help = "Time window over which to calculate bandwidth"
4923 " (msec)",
4924 .def = "500",
4925 .parent = "write_bw_log",
4926 .hide = 1,
4927 .interval = 100,
4928 .category = FIO_OPT_C_LOG,
4929 .group = FIO_OPT_G_INVALID,
4930 },
4931 {
4932 .name = "iopsavgtime",
4933 .lname = "IOPS average time",
4934 .type = FIO_OPT_INT,
a609f12a 4935 .off1 = offsetof(struct thread_options, iops_avg_time),
c504ee55
JA
4936 .help = "Time window over which to calculate IOPS (msec)",
4937 .def = "500",
4938 .parent = "write_iops_log",
4939 .hide = 1,
4940 .interval = 100,
4941 .category = FIO_OPT_C_LOG,
4942 .group = FIO_OPT_G_INVALID,
4943 },
214e1eca
JA
4944 {
4945 .name = "group_reporting",
e8b0e958 4946 .lname = "Group reporting",
d2507043 4947 .type = FIO_OPT_STR_SET,
a609f12a 4948 .off1 = offsetof(struct thread_options, group_reporting),
214e1eca 4949 .help = "Do reporting on a per-group basis",
10860056 4950 .category = FIO_OPT_C_STAT,
e8b0e958 4951 .group = FIO_OPT_G_INVALID,
214e1eca 4952 },
8243be59
JA
4953 {
4954 .name = "stats",
4955 .lname = "Stats",
4956 .type = FIO_OPT_BOOL,
4957 .off1 = offsetof(struct thread_options, stats),
4958 .help = "Enable collection of stats",
4959 .def = "1",
4960 .category = FIO_OPT_C_STAT,
4961 .group = FIO_OPT_G_INVALID,
4962 },
e9459e5a
JA
4963 {
4964 .name = "zero_buffers",
e8b0e958 4965 .lname = "Zero I/O buffers",
e9459e5a 4966 .type = FIO_OPT_STR_SET,
a609f12a 4967 .off1 = offsetof(struct thread_options, zero_buffers),
e9459e5a 4968 .help = "Init IO buffers to all zeroes",
e8b0e958 4969 .category = FIO_OPT_C_IO,
3ceb458f 4970 .group = FIO_OPT_G_IO_BUF,
e9459e5a 4971 },
5973cafb
JA
4972 {
4973 .name = "refill_buffers",
e8b0e958 4974 .lname = "Refill I/O buffers",
5973cafb 4975 .type = FIO_OPT_STR_SET,
a609f12a 4976 .off1 = offsetof(struct thread_options, refill_buffers),
5973cafb 4977 .help = "Refill IO buffers on every IO submit",
e8b0e958 4978 .category = FIO_OPT_C_IO,
3ceb458f 4979 .group = FIO_OPT_G_IO_BUF,
5973cafb 4980 },
fd68418e
JA
4981 {
4982 .name = "scramble_buffers",
e8b0e958 4983 .lname = "Scramble I/O buffers",
fd68418e 4984 .type = FIO_OPT_BOOL,
a609f12a 4985 .off1 = offsetof(struct thread_options, scramble_buffers),
fd68418e
JA
4986 .help = "Slightly scramble buffers on every IO submit",
4987 .def = "1",
e8b0e958 4988 .category = FIO_OPT_C_IO,
3ceb458f 4989 .group = FIO_OPT_G_IO_BUF,
fd68418e 4990 },
ce35b1ec
JA
4991 {
4992 .name = "buffer_pattern",
4993 .lname = "Buffer pattern",
4994 .type = FIO_OPT_STR,
4995 .cb = str_buffer_pattern_cb,
a609f12a 4996 .off1 = offsetof(struct thread_options, buffer_pattern),
ce35b1ec
JA
4997 .help = "Fill pattern for IO buffers",
4998 .category = FIO_OPT_C_IO,
4999 .group = FIO_OPT_G_IO_BUF,
5000 },
9c42684e
JA
5001 {
5002 .name = "buffer_compress_percentage",
e8b0e958 5003 .lname = "Buffer compression percentage",
9c42684e 5004 .type = FIO_OPT_INT,
bedc9dc2 5005 .cb = str_buffer_compress_cb,
a609f12a 5006 .off1 = offsetof(struct thread_options, compress_percentage),
9c42684e 5007 .maxval = 100,
e7f5de90 5008 .minval = 0,
9c42684e 5009 .help = "How compressible the buffer is (approximately)",
20eb06bd 5010 .interval = 5,
e8b0e958 5011 .category = FIO_OPT_C_IO,
3ceb458f 5012 .group = FIO_OPT_G_IO_BUF,
9c42684e 5013 },
f97a43a1
JA
5014 {
5015 .name = "buffer_compress_chunk",
e8b0e958 5016 .lname = "Buffer compression chunk size",
f97a43a1 5017 .type = FIO_OPT_INT,
a609f12a 5018 .off1 = offsetof(struct thread_options, compress_chunk),
207b18e4 5019 .parent = "buffer_compress_percentage",
d71c154c 5020 .hide = 1,
f97a43a1 5021 .help = "Size of compressible region in buffer",
1de80624 5022 .def = "512",
20eb06bd 5023 .interval = 256,
e8b0e958 5024 .category = FIO_OPT_C_IO,
3ceb458f 5025 .group = FIO_OPT_G_IO_BUF,
f97a43a1 5026 },
5c94b008
JA
5027 {
5028 .name = "dedupe_percentage",
5029 .lname = "Dedupe percentage",
5030 .type = FIO_OPT_INT,
5031 .cb = str_dedupe_cb,
a609f12a 5032 .off1 = offsetof(struct thread_options, dedupe_percentage),
5c94b008
JA
5033 .maxval = 100,
5034 .minval = 0,
5035 .help = "Percentage of buffers that are dedupable",
5036 .interval = 1,
5037 .category = FIO_OPT_C_IO,
5038 .group = FIO_OPT_G_IO_BUF,
5039 },
c49cfc76
BD
5040 {
5041 .name = "dedupe_global",
5042 .lname = "Global deduplication",
5043 .type = FIO_OPT_BOOL,
5044 .off1 = offsetof(struct thread_options, dedupe_global),
5045 .help = "Share deduplication buffers across jobs",
5046 .def = "0",
5047 .category = FIO_OPT_C_IO,
5048 .group = FIO_OPT_G_IO_BUF,
5049 },
0d71aa98
BD
5050 {
5051 .name = "dedupe_mode",
5052 .lname = "Dedupe mode",
5053 .help = "Mode for the deduplication buffer generation",
5054 .type = FIO_OPT_STR,
5055 .off1 = offsetof(struct thread_options, dedupe_mode),
5056 .parent = "dedupe_percentage",
5057 .def = "repeat",
5058 .category = FIO_OPT_C_IO,
5059 .group = FIO_OPT_G_IO_BUF,
5060 .posval = {
5061 { .ival = "repeat",
5062 .oval = DEDUPE_MODE_REPEAT,
5063 .help = "repeat previous page",
5064 },
5065 { .ival = "working_set",
5066 .oval = DEDUPE_MODE_WORKING_SET,
5067 .help = "choose a page randomly from limited working set defined in dedupe_working_set_percentage",
5068 },
5069 },
5070 },
5071 {
5072 .name = "dedupe_working_set_percentage",
5073 .lname = "Dedupe working set percentage",
5074 .help = "Dedupe working set size in percentages from file or device size used to generate dedupe patterns from",
5075 .type = FIO_OPT_INT,
5076 .off1 = offsetof(struct thread_options, dedupe_working_set_percentage),
5077 .parent = "dedupe_percentage",
5078 .def = "5",
5079 .maxval = 100,
5080 .minval = 0,
5081 .category = FIO_OPT_C_IO,
5082 .group = FIO_OPT_G_IO_BUF,
5083 },
83349190
YH
5084 {
5085 .name = "clat_percentiles",
e8b0e958 5086 .lname = "Completion latency percentiles",
83349190 5087 .type = FIO_OPT_BOOL,
a609f12a 5088 .off1 = offsetof(struct thread_options, clat_percentiles),
83349190 5089 .help = "Enable the reporting of completion latency percentiles",
467b35ed 5090 .def = "1",
b599759b
JA
5091 .category = FIO_OPT_C_STAT,
5092 .group = FIO_OPT_G_INVALID,
5093 },
5094 {
5095 .name = "lat_percentiles",
5096 .lname = "IO latency percentiles",
5097 .type = FIO_OPT_BOOL,
5098 .off1 = offsetof(struct thread_options, lat_percentiles),
5099 .help = "Enable the reporting of IO latency percentiles",
5100 .def = "0",
56440e63
VF
5101 .category = FIO_OPT_C_STAT,
5102 .group = FIO_OPT_G_INVALID,
5103 },
5104 {
5105 .name = "slat_percentiles",
5106 .lname = "Submission latency percentiles",
5107 .type = FIO_OPT_BOOL,
5108 .off1 = offsetof(struct thread_options, slat_percentiles),
5109 .help = "Enable the reporting of submission latency percentiles",
5110 .def = "0",
e8b0e958
JA
5111 .category = FIO_OPT_C_STAT,
5112 .group = FIO_OPT_G_INVALID,
83349190
YH
5113 },
5114 {
5115 .name = "percentile_list",
66347cfa 5116 .lname = "Percentile list",
83349190 5117 .type = FIO_OPT_FLOAT_LIST,
a609f12a
JA
5118 .off1 = offsetof(struct thread_options, percentile_list),
5119 .off2 = offsetof(struct thread_options, percentile_precision),
66347cfa
DE
5120 .help = "Specify a custom list of percentiles to report for "
5121 "completion latency and block errors",
fd112d34 5122 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
5123 .maxlen = FIO_IO_U_LIST_MAX_LEN,
5124 .minfp = 0.0,
5125 .maxfp = 100.0,
e8b0e958
JA
5126 .category = FIO_OPT_C_STAT,
5127 .group = FIO_OPT_G_INVALID,
e883cb35
JF
5128 },
5129 {
5130 .name = "significant_figures",
5131 .lname = "Significant figures",
5132 .type = FIO_OPT_INT,
5133 .off1 = offsetof(struct thread_options, sig_figs),
5134 .maxval = 10,
5135 .minval = 1,
5136 .help = "Significant figures for output-format set to normal",
5137 .def = "4",
5138 .interval = 1,
5139 .category = FIO_OPT_C_STAT,
5140 .group = FIO_OPT_G_INVALID,
83349190
YH
5141 },
5142
0a839f30
JA
5143#ifdef FIO_HAVE_DISK_UTIL
5144 {
5145 .name = "disk_util",
e8b0e958 5146 .lname = "Disk utilization",
0a839f30 5147 .type = FIO_OPT_BOOL,
a609f12a 5148 .off1 = offsetof(struct thread_options, do_disk_util),
f66ab3c8 5149 .help = "Log disk utilization statistics",
0a839f30 5150 .def = "1",
e8b0e958
JA
5151 .category = FIO_OPT_C_STAT,
5152 .group = FIO_OPT_G_INVALID,
0a839f30 5153 },
a275c37a
JA
5154#else
5155 {
5156 .name = "disk_util",
5157 .lname = "Disk utilization",
5158 .type = FIO_OPT_UNSUPPORTED,
5159 .help = "Your platform does not support disk utilization",
5160 },
0a839f30 5161#endif
993bf48b
JA
5162 {
5163 .name = "gtod_reduce",
e8b0e958 5164 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
5165 .type = FIO_OPT_BOOL,
5166 .help = "Greatly reduce number of gettimeofday() calls",
5167 .cb = str_gtod_reduce_cb,
5168 .def = "0",
a4ed77fe 5169 .hide_on_set = 1,
e8b0e958
JA
5170 .category = FIO_OPT_C_STAT,
5171 .group = FIO_OPT_G_INVALID,
993bf48b 5172 },
02af0988
JA
5173 {
5174 .name = "disable_lat",
e8b0e958 5175 .lname = "Disable all latency stats",
02af0988 5176 .type = FIO_OPT_BOOL,
a609f12a 5177 .off1 = offsetof(struct thread_options, disable_lat),
02af0988
JA
5178 .help = "Disable latency numbers",
5179 .parent = "gtod_reduce",
d71c154c 5180 .hide = 1,
02af0988 5181 .def = "0",
e8b0e958
JA
5182 .category = FIO_OPT_C_STAT,
5183 .group = FIO_OPT_G_INVALID,
02af0988 5184 },
9520ebb9
JA
5185 {
5186 .name = "disable_clat",
e8b0e958 5187 .lname = "Disable completion latency stats",
9520ebb9 5188 .type = FIO_OPT_BOOL,
a609f12a 5189 .off1 = offsetof(struct thread_options, disable_clat),
9520ebb9 5190 .help = "Disable completion latency numbers",
993bf48b 5191 .parent = "gtod_reduce",
d71c154c 5192 .hide = 1,
9520ebb9 5193 .def = "0",
e8b0e958
JA
5194 .category = FIO_OPT_C_STAT,
5195 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
5196 },
5197 {
5198 .name = "disable_slat",
e8b0e958 5199 .lname = "Disable submission latency stats",
9520ebb9 5200 .type = FIO_OPT_BOOL,
a609f12a 5201 .off1 = offsetof(struct thread_options, disable_slat),
03e20d68 5202 .help = "Disable submission latency numbers",
993bf48b 5203 .parent = "gtod_reduce",
d71c154c 5204 .hide = 1,
9520ebb9 5205 .def = "0",
e8b0e958
JA
5206 .category = FIO_OPT_C_STAT,
5207 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
5208 },
5209 {
5210 .name = "disable_bw_measurement",
afd2ceff 5211 .alias = "disable_bw",
e8b0e958 5212 .lname = "Disable bandwidth stats",
9520ebb9 5213 .type = FIO_OPT_BOOL,
a609f12a 5214 .off1 = offsetof(struct thread_options, disable_bw),
9520ebb9 5215 .help = "Disable bandwidth logging",
993bf48b 5216 .parent = "gtod_reduce",
d71c154c 5217 .hide = 1,
9520ebb9 5218 .def = "0",
e8b0e958
JA
5219 .category = FIO_OPT_C_STAT,
5220 .group = FIO_OPT_G_INVALID,
9520ebb9 5221 },
be4ecfdf
JA
5222 {
5223 .name = "gtod_cpu",
e8b0e958 5224 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 5225 .type = FIO_OPT_INT,
a609f12a 5226 .off1 = offsetof(struct thread_options, gtod_cpu),
03e20d68 5227 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 5228 .verify = gtod_cpu_verify,
e8b0e958 5229 .category = FIO_OPT_C_GENERAL,
10860056 5230 .group = FIO_OPT_G_CLOCK,
be4ecfdf 5231 },
12d325ca 5232 {
5233 .name = "job_start_clock_id",
5234 .lname = "Job start clock_id",
5235 .type = FIO_OPT_INT,
5236 .off1 = offsetof(struct thread_options, job_start_clock_id),
5237 .help = "The clock_id passed to the call to clock_gettime used to record job_start in the json output format. Default is 0, or CLOCK_REALTIME",
5238 .verify = gtod_cpu_verify,
5239 .category = FIO_OPT_C_GENERAL,
5240 .group = FIO_OPT_G_CLOCK,
5241 },
771e58be
JA
5242 {
5243 .name = "unified_rw_reporting",
cce2fdfe 5244 .lname = "Unified RW Reporting",
5cb8a8cd 5245 .type = FIO_OPT_STR,
a609f12a 5246 .off1 = offsetof(struct thread_options, unified_rw_rep),
771e58be 5247 .help = "Unify reporting across data direction",
5cb8a8cd 5248 .def = "none",
90b7a96d
JA
5249 .category = FIO_OPT_C_GENERAL,
5250 .group = FIO_OPT_G_INVALID,
5cb8a8cd
BP
5251 .posval = {
5252 { .ival = "none",
5253 .oval = UNIFIED_SPLIT,
5254 .help = "Normal statistics reporting",
5255 },
5256 { .ival = "mixed",
5257 .oval = UNIFIED_MIXED,
5258 .help = "Statistics are summed per data direction and reported together",
5259 },
5260 { .ival = "both",
5261 .oval = UNIFIED_BOTH,
5262 .help = "Statistics are reported normally, followed by the mixed statistics"
5263 },
5264 /* Compatibility with former boolean values */
5265 { .ival = "0",
5266 .oval = UNIFIED_SPLIT,
5267 .help = "Alias for 'none'",
5268 },
5269 { .ival = "1",
5270 .oval = UNIFIED_MIXED,
5271 .help = "Alias for 'mixed'",
5272 },
5273 { .ival = "2",
5274 .oval = UNIFIED_BOTH,
5275 .help = "Alias for 'both'",
5276 },
5277 },
771e58be 5278 },
f2bba182
RR
5279 {
5280 .name = "continue_on_error",
e8b0e958 5281 .lname = "Continue on error",
06842027 5282 .type = FIO_OPT_STR,
a609f12a 5283 .off1 = offsetof(struct thread_options, continue_on_error),
03e20d68 5284 .help = "Continue on non-fatal errors during IO",
06842027 5285 .def = "none",
e8b0e958 5286 .category = FIO_OPT_C_GENERAL,
bc3f552f 5287 .group = FIO_OPT_G_ERR,
06842027
SL
5288 .posval = {
5289 { .ival = "none",
5290 .oval = ERROR_TYPE_NONE,
5291 .help = "Exit when an error is encountered",
5292 },
5293 { .ival = "read",
5294 .oval = ERROR_TYPE_READ,
5295 .help = "Continue on read errors only",
5296 },
5297 { .ival = "write",
5298 .oval = ERROR_TYPE_WRITE,
5299 .help = "Continue on write errors only",
5300 },
5301 { .ival = "io",
5302 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
5303 .help = "Continue on any IO errors",
5304 },
5305 { .ival = "verify",
5306 .oval = ERROR_TYPE_VERIFY,
5307 .help = "Continue on verify errors only",
5308 },
5309 { .ival = "all",
5310 .oval = ERROR_TYPE_ANY,
5311 .help = "Continue on all io and verify errors",
5312 },
5313 { .ival = "0",
5314 .oval = ERROR_TYPE_NONE,
5315 .help = "Alias for 'none'",
5316 },
5317 { .ival = "1",
5318 .oval = ERROR_TYPE_ANY,
5319 .help = "Alias for 'all'",
5320 },
5321 },
f2bba182 5322 },
8b28bd41
DM
5323 {
5324 .name = "ignore_error",
cce2fdfe 5325 .lname = "Ignore Error",
8b28bd41
DM
5326 .type = FIO_OPT_STR,
5327 .cb = str_ignore_error_cb,
a609f12a 5328 .off1 = offsetof(struct thread_options, ignore_error_nr),
8b28bd41
DM
5329 .help = "Set a specific list of errors to ignore",
5330 .parent = "rw",
a94eb99a 5331 .category = FIO_OPT_C_GENERAL,
bc3f552f 5332 .group = FIO_OPT_G_ERR,
8b28bd41
DM
5333 },
5334 {
5335 .name = "error_dump",
cce2fdfe 5336 .lname = "Error Dump",
8b28bd41 5337 .type = FIO_OPT_BOOL,
a609f12a 5338 .off1 = offsetof(struct thread_options, error_dump),
8b28bd41
DM
5339 .def = "0",
5340 .help = "Dump info on each error",
a94eb99a 5341 .category = FIO_OPT_C_GENERAL,
bc3f552f 5342 .group = FIO_OPT_G_ERR,
8b28bd41 5343 },
9ac8a797
JA
5344 {
5345 .name = "profile",
e8b0e958 5346 .lname = "Profile",
79d16311 5347 .type = FIO_OPT_STR_STORE,
a609f12a 5348 .off1 = offsetof(struct thread_options, profile),
9ac8a797 5349 .help = "Select a specific builtin performance test",
13fca827 5350 .category = FIO_OPT_C_PROFILE,
e8b0e958 5351 .group = FIO_OPT_G_INVALID,
9ac8a797 5352 },
a696fa2a
JA
5353 {
5354 .name = "cgroup",
e8b0e958 5355 .lname = "Cgroup",
a696fa2a 5356 .type = FIO_OPT_STR_STORE,
a609f12a 5357 .off1 = offsetof(struct thread_options, cgroup),
a696fa2a 5358 .help = "Add job to cgroup of this name",
e8b0e958 5359 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
5360 .group = FIO_OPT_G_CGROUP,
5361 },
5362 {
5363 .name = "cgroup_nodelete",
5364 .lname = "Cgroup no-delete",
5365 .type = FIO_OPT_BOOL,
a609f12a 5366 .off1 = offsetof(struct thread_options, cgroup_nodelete),
a1f6afec
JA
5367 .help = "Do not delete cgroups after job completion",
5368 .def = "0",
5369 .parent = "cgroup",
5370 .category = FIO_OPT_C_GENERAL,
5371 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
5372 },
5373 {
5374 .name = "cgroup_weight",
e8b0e958 5375 .lname = "Cgroup weight",
a696fa2a 5376 .type = FIO_OPT_INT,
a609f12a 5377 .off1 = offsetof(struct thread_options, cgroup_weight),
a696fa2a
JA
5378 .help = "Use given weight for cgroup",
5379 .minval = 100,
5380 .maxval = 1000,
a1f6afec 5381 .parent = "cgroup",
e8b0e958 5382 .category = FIO_OPT_C_GENERAL,
a1f6afec 5383 .group = FIO_OPT_G_CGROUP,
7de87099 5384 },
e0b0d892
JA
5385 {
5386 .name = "uid",
e8b0e958 5387 .lname = "User ID",
e0b0d892 5388 .type = FIO_OPT_INT,
a609f12a 5389 .off1 = offsetof(struct thread_options, uid),
e0b0d892 5390 .help = "Run job with this user ID",
e8b0e958 5391 .category = FIO_OPT_C_GENERAL,
10860056 5392 .group = FIO_OPT_G_CRED,
e0b0d892
JA
5393 },
5394 {
5395 .name = "gid",
e8b0e958 5396 .lname = "Group ID",
e0b0d892 5397 .type = FIO_OPT_INT,
a609f12a 5398 .off1 = offsetof(struct thread_options, gid),
e0b0d892 5399 .help = "Run job with this group ID",
e8b0e958 5400 .category = FIO_OPT_C_GENERAL,
10860056 5401 .group = FIO_OPT_G_CRED,
e0b0d892 5402 },
a1f6afec
JA
5403 {
5404 .name = "kb_base",
5405 .lname = "KB Base",
41dd12d6 5406 .type = FIO_OPT_STR,
a609f12a 5407 .off1 = offsetof(struct thread_options, kb_base),
a1f6afec
JA
5408 .prio = 1,
5409 .def = "1024",
ba9c7219
JA
5410 .posval = {
5411 { .ival = "1024",
5412 .oval = 1024,
d694a6a7 5413 .help = "Inputs invert IEC and SI prefixes (for compatibility); outputs prefer binary",
ba9c7219
JA
5414 },
5415 { .ival = "1000",
5416 .oval = 1000,
d694a6a7 5417 .help = "Inputs use IEC and SI prefixes; outputs prefer SI",
ba9c7219
JA
5418 },
5419 },
d694a6a7 5420 .help = "Unit prefix interpretation for quantities of data (IEC and SI)",
a1f6afec
JA
5421 .category = FIO_OPT_C_GENERAL,
5422 .group = FIO_OPT_G_INVALID,
5423 },
cf3a0518
JA
5424 {
5425 .name = "unit_base",
d694a6a7 5426 .lname = "Unit for quantities of data (Bits or Bytes)",
92a1a1d7 5427 .type = FIO_OPT_STR,
a609f12a 5428 .off1 = offsetof(struct thread_options, unit_base),
cf3a0518 5429 .prio = 1,
71a08258
JA
5430 .posval = {
5431 { .ival = "0",
41a87019 5432 .oval = N2S_NONE,
71a08258
JA
5433 .help = "Auto-detect",
5434 },
5435 { .ival = "8",
41a87019 5436 .oval = N2S_BYTEPERSEC,
71a08258
JA
5437 .help = "Normal (byte based)",
5438 },
5439 { .ival = "1",
41a87019 5440 .oval = N2S_BITPERSEC,
71a08258
JA
5441 .help = "Bit based",
5442 },
5443 },
cf3a0518
JA
5444 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
5445 .category = FIO_OPT_C_GENERAL,
5446 .group = FIO_OPT_G_INVALID,
5447 },
3ceb458f
JA
5448 {
5449 .name = "hugepage-size",
5450 .lname = "Hugepage size",
5451 .type = FIO_OPT_INT,
a609f12a 5452 .off1 = offsetof(struct thread_options, hugepage_size),
3ceb458f
JA
5453 .help = "When using hugepages, specify size of each page",
5454 .def = __fio_stringify(FIO_HUGE_PAGE),
5455 .interval = 1024 * 1024,
5456 .category = FIO_OPT_C_GENERAL,
5457 .group = FIO_OPT_G_INVALID,
5458 },
9e684a49
DE
5459 {
5460 .name = "flow_id",
e8b0e958 5461 .lname = "I/O flow ID",
9e684a49 5462 .type = FIO_OPT_INT,
a609f12a 5463 .off1 = offsetof(struct thread_options, flow_id),
9e684a49
DE
5464 .help = "The flow index ID to use",
5465 .def = "0",
e8b0e958
JA
5466 .category = FIO_OPT_C_IO,
5467 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5468 },
5469 {
5470 .name = "flow",
e8b0e958 5471 .lname = "I/O flow weight",
20c7a244 5472 .type = FIO_OPT_INT,
a609f12a 5473 .off1 = offsetof(struct thread_options, flow),
9e684a49
DE
5474 .help = "Weight for flow control of this job",
5475 .parent = "flow_id",
d71c154c 5476 .hide = 1,
9e684a49 5477 .def = "0",
d4e74fda 5478 .maxval = FLOW_MAX_WEIGHT,
e8b0e958
JA
5479 .category = FIO_OPT_C_IO,
5480 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5481 },
5482 {
5483 .name = "flow_watermark",
e8b0e958 5484 .lname = "I/O flow watermark",
d4e74fda 5485 .type = FIO_OPT_SOFT_DEPRECATED,
e8b0e958
JA
5486 .category = FIO_OPT_C_IO,
5487 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5488 },
5489 {
5490 .name = "flow_sleep",
e8b0e958 5491 .lname = "I/O flow sleep",
9e684a49 5492 .type = FIO_OPT_INT,
a609f12a 5493 .off1 = offsetof(struct thread_options, flow_sleep),
9e684a49
DE
5494 .help = "How many microseconds to sleep after being held"
5495 " back by the flow control mechanism",
5496 .parent = "flow_id",
d71c154c 5497 .hide = 1,
9e684a49 5498 .def = "0",
e8b0e958
JA
5499 .category = FIO_OPT_C_IO,
5500 .group = FIO_OPT_G_IO_FLOW,
9e684a49 5501 },
16e56d25
VF
5502 {
5503 .name = "steadystate",
5504 .lname = "Steady state threshold",
5505 .alias = "ss",
5506 .type = FIO_OPT_STR,
2c5d94bc 5507 .off1 = offsetof(struct thread_options, ss_state),
16e56d25
VF
5508 .cb = str_steadystate_cb,
5509 .help = "Define the criterion and limit to judge when a job has reached steady state",
5510 .def = "iops_slope:0.01%",
5511 .posval = {
5512 { .ival = "iops",
f0c50c66 5513 .oval = FIO_SS_IOPS,
16e56d25
VF
5514 .help = "maximum mean deviation of IOPS measurements",
5515 },
5516 { .ival = "iops_slope",
f0c50c66 5517 .oval = FIO_SS_IOPS_SLOPE,
16e56d25
VF
5518 .help = "slope calculated from IOPS measurements",
5519 },
5520 { .ival = "bw",
f0c50c66 5521 .oval = FIO_SS_BW,
16e56d25
VF
5522 .help = "maximum mean deviation of bandwidth measurements",
5523 },
5524 {
5525 .ival = "bw_slope",
f0c50c66 5526 .oval = FIO_SS_BW_SLOPE,
16e56d25
VF
5527 .help = "slope calculated from bandwidth measurements",
5528 },
5529 },
5530 .category = FIO_OPT_C_GENERAL,
5531 .group = FIO_OPT_G_RUNTIME,
5532 },
5533 {
5534 .name = "steadystate_duration",
5535 .lname = "Steady state duration",
5536 .alias = "ss_dur",
915ca980 5537 .parent = "steadystate",
16e56d25
VF
5538 .type = FIO_OPT_STR_VAL_TIME,
5539 .off1 = offsetof(struct thread_options, ss_dur),
5540 .help = "Stop workload upon attaining steady state for specified duration",
5541 .def = "0",
5542 .is_seconds = 1,
5543 .is_time = 1,
5544 .category = FIO_OPT_C_GENERAL,
5545 .group = FIO_OPT_G_RUNTIME,
5546 },
5547 {
5548 .name = "steadystate_ramp_time",
5549 .lname = "Steady state ramp time",
5550 .alias = "ss_ramp",
915ca980 5551 .parent = "steadystate",
16e56d25
VF
5552 .type = FIO_OPT_STR_VAL_TIME,
5553 .off1 = offsetof(struct thread_options, ss_ramp_time),
5554 .help = "Delay before initiation of data collection for steady state job termination testing",
5555 .def = "0",
5556 .is_seconds = 1,
5557 .is_time = 1,
5558 .category = FIO_OPT_C_GENERAL,
5559 .group = FIO_OPT_G_RUNTIME,
5560 },
90e678ba
CL
5561 {
5562 .name = "steadystate_check_interval",
5563 .lname = "Steady state check interval",
5564 .alias = "ss_interval",
5565 .parent = "steadystate",
5566 .type = FIO_OPT_STR_VAL_TIME,
5567 .off1 = offsetof(struct thread_options, ss_check_interval),
5568 .help = "Polling interval for the steady state check (too low means steadystate will not converge)",
5569 .def = "1",
5570 .is_seconds = 1,
5571 .is_time = 1,
5572 .category = FIO_OPT_C_GENERAL,
5573 .group = FIO_OPT_G_RUNTIME,
5574 },
214e1eca
JA
5575 {
5576 .name = NULL,
5577 },
5578};
5579
17af15d4 5580static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 5581 const char *name, int val)
9f81736c 5582{
17af15d4 5583 lopt->name = (char *) name;
de890a1e 5584 lopt->val = val;
9f81736c 5585 if (o->type == FIO_OPT_STR_SET)
ff52be3d 5586 lopt->has_arg = optional_argument;
9f81736c
JA
5587 else
5588 lopt->has_arg = required_argument;
5589}
5590
de890a1e
SL
5591static void options_to_lopts(struct fio_option *opts,
5592 struct option *long_options,
5593 int i, int option_type)
214e1eca 5594{
de890a1e 5595 struct fio_option *o = &opts[0];
214e1eca 5596 while (o->name) {
de890a1e 5597 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
5598 if (o->alias) {
5599 i++;
de890a1e 5600 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 5601 }
214e1eca
JA
5602
5603 i++;
5604 o++;
5605 assert(i < FIO_NR_OPTIONS);
5606 }
5607}
5608
de890a1e
SL
5609void fio_options_set_ioengine_opts(struct option *long_options,
5610 struct thread_data *td)
5611{
5612 unsigned int i;
5613
5614 i = 0;
5615 while (long_options[i].name) {
5616 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
5617 memset(&long_options[i], 0, sizeof(*long_options));
5618 break;
5619 }
5620 i++;
5621 }
5622
5623 /*
5624 * Just clear out the prior ioengine options.
5625 */
5626 if (!td || !td->eo)
5627 return;
5628
5629 options_to_lopts(td->io_ops->options, long_options, i,
5630 FIO_GETOPT_IOENGINE);
5631}
5632
5633void fio_options_dup_and_init(struct option *long_options)
5634{
5635 unsigned int i;
5636
9af4a244 5637 options_init(fio_options);
de890a1e
SL
5638
5639 i = 0;
5640 while (long_options[i].name)
5641 i++;
5642
9af4a244 5643 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
5644}
5645
74929ac2
JA
5646struct fio_keyword {
5647 const char *word;
5648 const char *desc;
5649 char *replace;
5650};
5651
5652static struct fio_keyword fio_keywords[] = {
5653 {
5654 .word = "$pagesize",
5655 .desc = "Page size in the system",
5656 },
5657 {
5658 .word = "$mb_memory",
5659 .desc = "Megabytes of memory online",
5660 },
5661 {
5662 .word = "$ncpus",
5663 .desc = "Number of CPUs online in the system",
5664 },
5665 {
5666 .word = NULL,
5667 },
5668};
5669
af1dc266
JA
5670void fio_keywords_exit(void)
5671{
5672 struct fio_keyword *kw;
5673
5674 kw = &fio_keywords[0];
5675 while (kw->word) {
5676 free(kw->replace);
5677 kw->replace = NULL;
5678 kw++;
5679 }
5680}
5681
74929ac2
JA
5682void fio_keywords_init(void)
5683{
3b2e1464 5684 unsigned long long mb_memory;
74929ac2
JA
5685 char buf[128];
5686 long l;
5687
a4cfc477 5688 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
5689 fio_keywords[0].replace = strdup(buf);
5690
8eb016d3 5691 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 5692 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
5693 fio_keywords[1].replace = strdup(buf);
5694
40f61ec7 5695 l = cpus_configured();
74929ac2
JA
5696 sprintf(buf, "%lu", l);
5697 fio_keywords[2].replace = strdup(buf);
5698}
5699
892a6ffc
JA
5700#define BC_APP "bc"
5701
5702static char *bc_calc(char *str)
5703{
d0c814ec 5704 char buf[128], *tmp;
892a6ffc
JA
5705 FILE *f;
5706 int ret;
5707
5708 /*
5709 * No math, just return string
5710 */
d0c814ec
SL
5711 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
5712 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
5713 return str;
5714
5715 /*
5716 * Split option from value, we only need to calculate the value
5717 */
5718 tmp = strchr(str, '=');
5719 if (!tmp)
5720 return str;
5721
5722 tmp++;
892a6ffc 5723
d0c814ec
SL
5724 /*
5725 * Prevent buffer overflows; such a case isn't reasonable anyway
5726 */
5727 if (strlen(str) >= 128 || strlen(tmp) > 100)
5728 return str;
892a6ffc
JA
5729
5730 sprintf(buf, "which %s > /dev/null", BC_APP);
5731 if (system(buf)) {
5732 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
5733 return NULL;
5734 }
5735
d0c814ec 5736 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 5737 f = popen(buf, "r");
3c3ed070 5738 if (!f)
892a6ffc 5739 return NULL;
892a6ffc 5740
d0c814ec 5741 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
5742 if (ret <= 0) {
5743 pclose(f);
892a6ffc 5744 return NULL;
1d824f37 5745 }
892a6ffc 5746
892a6ffc 5747 pclose(f);
d0c814ec
SL
5748 buf[(tmp - str) + ret - 1] = '\0';
5749 memcpy(buf, str, tmp - str);
892a6ffc 5750 free(str);
d0c814ec
SL
5751 return strdup(buf);
5752}
5753
5754/*
5755 * Return a copy of the input string with substrings of the form ${VARNAME}
5756 * substituted with the value of the environment variable VARNAME. The
5757 * substitution always occurs, even if VARNAME is empty or the corresponding
5758 * environment variable undefined.
5759 */
b4f5e72f 5760char *fio_option_dup_subs(const char *opt)
d0c814ec
SL
5761{
5762 char out[OPT_LEN_MAX+1];
5763 char in[OPT_LEN_MAX+1];
5764 char *outptr = out;
5765 char *inptr = in;
5766 char *ch1, *ch2, *env;
5767 ssize_t nchr = OPT_LEN_MAX;
5768 size_t envlen;
5769
5770 if (strlen(opt) + 1 > OPT_LEN_MAX) {
5771 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
5772 return NULL;
5773 }
5774
36833fb0 5775 snprintf(in, sizeof(in), "%s", opt);
d0c814ec
SL
5776
5777 while (*inptr && nchr > 0) {
5778 if (inptr[0] == '$' && inptr[1] == '{') {
5779 ch2 = strchr(inptr, '}');
5780 if (ch2 && inptr+1 < ch2) {
5781 ch1 = inptr+2;
5782 inptr = ch2+1;
5783 *ch2 = '\0';
5784
5785 env = getenv(ch1);
5786 if (env) {
5787 envlen = strlen(env);
5788 if (envlen <= nchr) {
5789 memcpy(outptr, env, envlen);
5790 outptr += envlen;
5791 nchr -= envlen;
5792 }
5793 }
5794
5795 continue;
5796 }
5797 }
5798
5799 *outptr++ = *inptr++;
5800 --nchr;
5801 }
5802
5803 *outptr = '\0';
5804 return strdup(out);
892a6ffc
JA
5805}
5806
74929ac2
JA
5807/*
5808 * Look for reserved variable names and replace them with real values
5809 */
5810static char *fio_keyword_replace(char *opt)
5811{
5812 char *s;
5813 int i;
d0c814ec 5814 int docalc = 0;
74929ac2
JA
5815
5816 for (i = 0; fio_keywords[i].word != NULL; i++) {
5817 struct fio_keyword *kw = &fio_keywords[i];
5818
5819 while ((s = strstr(opt, kw->word)) != NULL) {
33153428 5820 char *new = calloc(strlen(opt) + 1, 1);
74929ac2
JA
5821 char *o_org = opt;
5822 int olen = s - opt;
5823 int len;
5824
5825 /*
5826 * Copy part of the string before the keyword and
5827 * sprintf() the replacement after it.
5828 */
5829 memcpy(new, opt, olen);
5830 len = sprintf(new + olen, "%s", kw->replace);
5831
5832 /*
5833 * If there's more in the original string, copy that
5834 * in too
5835 */
85b9ee7e 5836 opt += olen + strlen(kw->word);
33153428 5837 /* keeps final zero thanks to calloc */
74929ac2 5838 if (strlen(opt))
85b9ee7e 5839 memcpy(new + olen + len, opt, strlen(opt));
74929ac2
JA
5840
5841 /*
5842 * replace opt and free the old opt
5843 */
5844 opt = new;
d0c814ec 5845 free(o_org);
7a958bd5 5846
d0c814ec 5847 docalc = 1;
74929ac2
JA
5848 }
5849 }
5850
d0c814ec
SL
5851 /*
5852 * Check for potential math and invoke bc, if possible
5853 */
5854 if (docalc)
5855 opt = bc_calc(opt);
5856
7a958bd5 5857 return opt;
74929ac2
JA
5858}
5859
d0c814ec
SL
5860static char **dup_and_sub_options(char **opts, int num_opts)
5861{
5862 int i;
5863 char **opts_copy = malloc(num_opts * sizeof(*opts));
5864 for (i = 0; i < num_opts; i++) {
b4f5e72f 5865 opts_copy[i] = fio_option_dup_subs(opts[i]);
d0c814ec
SL
5866 if (!opts_copy[i])
5867 continue;
5868 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
5869 }
5870 return opts_copy;
5871}
5872
e15b023b 5873static void show_closest_option(const char *opt)
a2d027b9
JA
5874{
5875 int best_option, best_distance;
5876 int i, distance;
e15b023b
JA
5877 char *name;
5878
5879 if (!strlen(opt))
5880 return;
5881
5882 name = strdup(opt);
5883 i = 0;
5884 while (name[i] != '\0' && name[i] != '=')
5885 i++;
5886 name[i] = '\0';
a2d027b9
JA
5887
5888 best_option = -1;
5889 best_distance = INT_MAX;
5890 i = 0;
5891 while (fio_options[i].name) {
5892 distance = string_distance(name, fio_options[i].name);
5893 if (distance < best_distance) {
5894 best_distance = distance;
5895 best_option = i;
5896 }
5897 i++;
5898 }
5899
75e6bcba
JA
5900 if (best_option != -1 && string_distance_ok(name, best_distance) &&
5901 fio_options[best_option].type != FIO_OPT_UNSUPPORTED)
a2d027b9 5902 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
5903
5904 free(name);
a2d027b9
JA
5905}
5906
c2292325 5907int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 5908{
de890a1e 5909 int i, ret, unknown;
d0c814ec 5910 char **opts_copy;
3b8b7135 5911
9af4a244 5912 sort_options(opts, fio_options, num_opts);
d0c814ec 5913 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 5914
de890a1e 5915 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
9109883a 5916 const struct fio_option *o;
9af4a244 5917 int newret = parse_option(opts_copy[i], opts[i], fio_options,
a609f12a 5918 &o, &td->o, &td->opt_list);
d0c814ec 5919
a8523a6a
JA
5920 if (!newret && o)
5921 fio_option_mark_set(&td->o, o);
5922
de890a1e
SL
5923 if (opts_copy[i]) {
5924 if (newret && !o) {
5925 unknown++;
5926 continue;
5927 }
d0c814ec 5928 free(opts_copy[i]);
de890a1e
SL
5929 opts_copy[i] = NULL;
5930 }
5931
5932 ret |= newret;
5933 }
5934
5935 if (unknown) {
5936 ret |= ioengine_load(td);
5937 if (td->eo) {
5938 sort_options(opts_copy, td->io_ops->options, num_opts);
5939 opts = opts_copy;
5940 }
5941 for (i = 0; i < num_opts; i++) {
9109883a 5942 const struct fio_option *o = NULL;
de890a1e 5943 int newret = 1;
a2d027b9 5944
de890a1e
SL
5945 if (!opts_copy[i])
5946 continue;
5947
5948 if (td->eo)
5949 newret = parse_option(opts_copy[i], opts[i],
5950 td->io_ops->options, &o,
66e19a38 5951 td->eo, &td->opt_list);
de890a1e
SL
5952
5953 ret |= newret;
a2d027b9 5954 if (!o) {
de890a1e 5955 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
5956 show_closest_option(opts[i]);
5957 }
de890a1e
SL
5958 free(opts_copy[i]);
5959 opts_copy[i] = NULL;
5960 }
74929ac2 5961 }
3b8b7135 5962
d0c814ec 5963 free(opts_copy);
3b8b7135 5964 return ret;
214e1eca
JA
5965}
5966
5967int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
5968{
a8523a6a
JA
5969 int ret;
5970
a609f12a 5971 ret = parse_cmd_option(opt, val, fio_options, &td->o, &td->opt_list);
a8523a6a 5972 if (!ret) {
9109883a 5973 const struct fio_option *o;
a8523a6a 5974
9109883a 5975 o = find_option_c(fio_options, opt);
a8523a6a
JA
5976 if (o)
5977 fio_option_mark_set(&td->o, o);
5978 }
5979
5980 return ret;
214e1eca
JA
5981}
5982
de890a1e
SL
5983int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
5984 char *val)
5985{
d8b4f395
JA
5986 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
5987 &td->opt_list);
de890a1e
SL
5988}
5989
214e1eca
JA
5990void fio_fill_default_options(struct thread_data *td)
5991{
cb1402d6 5992 td->o.magic = OPT_MAGIC;
a609f12a 5993 fill_default_options(&td->o, fio_options);
214e1eca
JA
5994}
5995
5996int fio_show_option_help(const char *opt)
5997{
9af4a244 5998 return show_cmd_help(fio_options, opt);
214e1eca 5999}
d23bb327 6000
de890a1e
SL
6001/*
6002 * dupe FIO_OPT_STR_STORE options
6003 */
6004void fio_options_mem_dupe(struct thread_data *td)
6005{
53b5693d 6006 options_mem_dupe(fio_options, &td->o);
1647f592
JA
6007
6008 if (td->eo && td->io_ops) {
de890a1e 6009 void *oldeo = td->eo;
1647f592 6010
de890a1e
SL
6011 td->eo = malloc(td->io_ops->option_struct_size);
6012 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
53b5693d 6013 options_mem_dupe(td->io_ops->options, td->eo);
de890a1e
SL
6014 }
6015}
6016
d6978a32
JA
6017unsigned int fio_get_kb_base(void *data)
6018{
a609f12a
JA
6019 struct thread_data *td = cb_data_to_td(data);
6020 struct thread_options *o = &td->o;
d6978a32
JA
6021 unsigned int kb_base = 0;
6022
cb1402d6
JA
6023 /*
6024 * This is a hack... For private options, *data is not holding
6025 * a pointer to the thread_options, but to private data. This means
6026 * we can't safely dereference it, but magic is first so mem wise
6027 * it is valid. But this also means that if the job first sets
6028 * kb_base and expects that to be honored by private options,
6029 * it will be disappointed. We will return the global default
6030 * for this.
6031 */
6032 if (o && o->magic == OPT_MAGIC)
83ea422a 6033 kb_base = o->kb_base;
d6978a32
JA
6034 if (!kb_base)
6035 kb_base = 1024;
6036
6037 return kb_base;
6038}
9f988e2e 6039
9109883a 6040int add_option(const struct fio_option *o)
9f988e2e 6041{
07b3232d
JA
6042 struct fio_option *__o;
6043 int opt_index = 0;
6044
9af4a244 6045 __o = fio_options;
07b3232d
JA
6046 while (__o->name) {
6047 opt_index++;
6048 __o++;
6049 }
6050
7b504edd
JA
6051 if (opt_index + 1 == FIO_MAX_OPTS) {
6052 log_err("fio: FIO_MAX_OPTS is too small\n");
6053 return 1;
6054 }
6055
9af4a244 6056 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 6057 fio_options[opt_index + 1].name = NULL;
07b3232d 6058 return 0;
9f988e2e 6059}
e2de69da 6060
07b3232d 6061void invalidate_profile_options(const char *prof_name)
e2de69da 6062{
07b3232d 6063 struct fio_option *o;
e2de69da 6064
9af4a244 6065 o = fio_options;
07b3232d
JA
6066 while (o->name) {
6067 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
6068 o->type = FIO_OPT_INVALID;
6069 o->prof_name = NULL;
6070 }
6071 o++;
e2de69da
JA
6072 }
6073}
f5b6bb85
JA
6074
6075void add_opt_posval(const char *optname, const char *ival, const char *help)
6076{
6077 struct fio_option *o;
6078 unsigned int i;
6079
9af4a244 6080 o = find_option(fio_options, optname);
f5b6bb85
JA
6081 if (!o)
6082 return;
6083
6084 for (i = 0; i < PARSE_MAX_VP; i++) {
6085 if (o->posval[i].ival)
6086 continue;
6087
6088 o->posval[i].ival = ival;
6089 o->posval[i].help = help;
6090 break;
6091 }
6092}
6093
6094void del_opt_posval(const char *optname, const char *ival)
6095{
6096 struct fio_option *o;
6097 unsigned int i;
6098
9af4a244 6099 o = find_option(fio_options, optname);
f5b6bb85
JA
6100 if (!o)
6101 return;
6102
6103 for (i = 0; i < PARSE_MAX_VP; i++) {
6104 if (!o->posval[i].ival)
6105 continue;
6106 if (strcmp(o->posval[i].ival, ival))
6107 continue;
6108
6109 o->posval[i].ival = NULL;
6110 o->posval[i].help = NULL;
6111 }
6112}
7e356b2d
JA
6113
6114void fio_options_free(struct thread_data *td)
6115{
ca6336a8 6116 options_free(fio_options, &td->o);
de890a1e
SL
6117 if (td->eo && td->io_ops && td->io_ops->options) {
6118 options_free(td->io_ops->options, td->eo);
824912be
JA
6119 free(td->eo);
6120 td->eo = NULL;
de890a1e 6121 }
7e356b2d 6122}
c504ee55 6123
8009f543
NC
6124void fio_dump_options_free(struct thread_data *td)
6125{
6126 while (!flist_empty(&td->opt_list)) {
6127 struct print_option *p;
6128
6129 p = flist_first_entry(&td->opt_list, struct print_option, list);
6130 flist_del_init(&p->list);
6131 free(p->name);
6132 free(p->value);
6133 free(p);
6134 }
6135}
6136
c504ee55
JA
6137struct fio_option *fio_option_find(const char *name)
6138{
6139 return find_option(fio_options, name);
6140}
6141
517c9c72 6142static struct fio_option *find_next_opt(struct fio_option *from,
f0e7f45a 6143 unsigned int off1)
a8523a6a 6144{
f0e7f45a 6145 struct fio_option *opt;
a8523a6a 6146
f0e7f45a
JA
6147 if (!from)
6148 from = &fio_options[0];
6149 else
6150 from++;
6151
6152 opt = NULL;
6153 do {
6154 if (off1 == from->off1) {
6155 opt = from;
a8523a6a
JA
6156 break;
6157 }
f0e7f45a
JA
6158 from++;
6159 } while (from->name);
a8523a6a 6160
f0e7f45a
JA
6161 return opt;
6162}
6163
6164static int opt_is_set(struct thread_options *o, struct fio_option *opt)
6165{
6166 unsigned int opt_off, index, offset;
a8523a6a
JA
6167
6168 opt_off = opt - &fio_options[0];
6169 index = opt_off / (8 * sizeof(uint64_t));
6170 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 6171 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
6172}
6173
72f39748 6174bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
6175{
6176 struct fio_option *opt, *next;
6177
6178 next = NULL;
517c9c72 6179 while ((opt = find_next_opt(next, off1)) != NULL) {
f0e7f45a 6180 if (opt_is_set(o, opt))
72f39748 6181 return true;
f0e7f45a
JA
6182
6183 next = opt;
6184 }
6185
72f39748 6186 return false;
f0e7f45a
JA
6187}
6188
9109883a 6189void fio_option_mark_set(struct thread_options *o, const struct fio_option *opt)
a8523a6a
JA
6190{
6191 unsigned int opt_off, index, offset;
6192
6193 opt_off = opt - &fio_options[0];
6194 index = opt_off / (8 * sizeof(uint64_t));
6195 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 6196 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 6197}