Merge branch 'fix-randtrimwrite' of https://github.com/minwooim/fio
[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 },
90fef2d1 1957 {
e8b0e958
JA
1958 .name = "directory",
1959 .lname = "Directory",
1960 .type = FIO_OPT_STR_STORE,
a609f12a 1961 .off1 = offsetof(struct thread_options, directory),
e8b0e958
JA
1962 .cb = str_directory_cb,
1963 .help = "Directory to store files in",
1964 .category = FIO_OPT_C_FILE,
0626037e 1965 .group = FIO_OPT_G_FILENAME,
90fef2d1 1966 },
de98bd30
JA
1967 {
1968 .name = "filename_format",
922a5be8 1969 .lname = "Filename Format",
de98bd30 1970 .type = FIO_OPT_STR_STORE,
a609f12a 1971 .off1 = offsetof(struct thread_options, filename_format),
de98bd30
JA
1972 .prio = -1, /* must come after "directory" */
1973 .help = "Override default $jobname.$jobnum.$filenum naming",
1974 .def = "$jobname.$jobnum.$filenum",
93bb626a
JA
1975 .category = FIO_OPT_C_FILE,
1976 .group = FIO_OPT_G_FILENAME,
ad705bcb 1977 },
922a5be8
JA
1978 {
1979 .name = "unique_filename",
1980 .lname = "Unique Filename",
1981 .type = FIO_OPT_BOOL,
a609f12a 1982 .off1 = offsetof(struct thread_options, unique_filename),
922a5be8
JA
1983 .help = "For network clients, prefix file with source IP",
1984 .def = "1",
1985 .category = FIO_OPT_C_FILE,
1986 .group = FIO_OPT_G_FILENAME,
1987 },
29c1349f
JA
1988 {
1989 .name = "lockfile",
e8b0e958 1990 .lname = "Lockfile",
4d4e80f2 1991 .type = FIO_OPT_STR,
a609f12a 1992 .off1 = offsetof(struct thread_options, file_lock_mode),
29c1349f 1993 .help = "Lock file when doing IO to it",
bc6a0a5d 1994 .prio = 1,
29c1349f 1995 .parent = "filename",
d71c154c 1996 .hide = 0,
4d4e80f2 1997 .def = "none",
e8b0e958 1998 .category = FIO_OPT_C_FILE,
0626037e 1999 .group = FIO_OPT_G_FILENAME,
4d4e80f2
JA
2000 .posval = {
2001 { .ival = "none",
2002 .oval = FILE_LOCK_NONE,
2003 .help = "No file locking",
2004 },
2005 { .ival = "exclusive",
2006 .oval = FILE_LOCK_EXCLUSIVE,
2007 .help = "Exclusive file lock",
2008 },
2009 {
2010 .ival = "readwrite",
2011 .oval = FILE_LOCK_READWRITE,
2012 .help = "Read vs write lock",
2013 },
2014 },
29c1349f 2015 },
214e1eca
JA
2016 {
2017 .name = "opendir",
e8b0e958 2018 .lname = "Open directory",
214e1eca 2019 .type = FIO_OPT_STR_STORE,
a609f12a 2020 .off1 = offsetof(struct thread_options, opendir),
214e1eca
JA
2021 .cb = str_opendir_cb,
2022 .help = "Recursively add files from this directory and down",
e8b0e958 2023 .category = FIO_OPT_C_FILE,
0626037e 2024 .group = FIO_OPT_G_FILENAME,
214e1eca
JA
2025 },
2026 {
2027 .name = "rw",
e8b0e958 2028 .lname = "Read/write",
d3aad8f2 2029 .alias = "readwrite",
214e1eca 2030 .type = FIO_OPT_STR,
211097b2 2031 .cb = str_rw_cb,
a609f12a 2032 .off1 = offsetof(struct thread_options, td_ddir),
214e1eca
JA
2033 .help = "IO direction",
2034 .def = "read",
896cac2a 2035 .verify = rw_verify,
e8b0e958 2036 .category = FIO_OPT_C_IO,
0626037e 2037 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
2038 .posval = {
2039 { .ival = "read",
2040 .oval = TD_DDIR_READ,
2041 .help = "Sequential read",
2042 },
2043 { .ival = "write",
2044 .oval = TD_DDIR_WRITE,
2045 .help = "Sequential write",
2046 },
6eaf09d6
SL
2047 { .ival = "trim",
2048 .oval = TD_DDIR_TRIM,
2049 .help = "Sequential trim",
2050 },
214e1eca
JA
2051 { .ival = "randread",
2052 .oval = TD_DDIR_RANDREAD,
2053 .help = "Random read",
2054 },
2055 { .ival = "randwrite",
2056 .oval = TD_DDIR_RANDWRITE,
2057 .help = "Random write",
2058 },
6eaf09d6
SL
2059 { .ival = "randtrim",
2060 .oval = TD_DDIR_RANDTRIM,
2061 .help = "Random trim",
2062 },
214e1eca
JA
2063 { .ival = "rw",
2064 .oval = TD_DDIR_RW,
2065 .help = "Sequential read and write mix",
2066 },
10b023db
JA
2067 { .ival = "readwrite",
2068 .oval = TD_DDIR_RW,
2069 .help = "Sequential read and write mix",
2070 },
214e1eca
JA
2071 { .ival = "randrw",
2072 .oval = TD_DDIR_RANDRW,
2073 .help = "Random read and write mix"
2074 },
82a90686
JA
2075 { .ival = "trimwrite",
2076 .oval = TD_DDIR_TRIMWRITE,
2077 .help = "Trim and write mix, trims preceding writes"
0e4dd95c 2078 },
c16dc793
JA
2079 { .ival = "randtrimwrite",
2080 .oval = TD_DDIR_RANDTRIMWRITE,
2081 .help = "Randomly trim and write mix, trims preceding writes"
2082 },
214e1eca
JA
2083 },
2084 },
38dad62d
JA
2085 {
2086 .name = "rw_sequencer",
e8b0e958 2087 .lname = "RW Sequencer",
38dad62d 2088 .type = FIO_OPT_STR,
a609f12a 2089 .off1 = offsetof(struct thread_options, rw_seq),
38dad62d
JA
2090 .help = "IO offset generator modifier",
2091 .def = "sequential",
e8b0e958 2092 .category = FIO_OPT_C_IO,
0626037e 2093 .group = FIO_OPT_G_IO_BASIC,
38dad62d
JA
2094 .posval = {
2095 { .ival = "sequential",
2096 .oval = RW_SEQ_SEQ,
2097 .help = "Generate sequential offsets",
2098 },
2099 { .ival = "identical",
2100 .oval = RW_SEQ_IDENT,
2101 .help = "Generate identical offsets",
2102 },
2103 },
2104 },
2105
214e1eca
JA
2106 {
2107 .name = "ioengine",
e8b0e958 2108 .lname = "IO Engine",
214e1eca 2109 .type = FIO_OPT_STR_STORE,
a609f12a 2110 .off1 = offsetof(struct thread_options, ioengine),
214e1eca 2111 .help = "IO engine to use",
58483fa4 2112 .def = FIO_PREFERRED_ENGINE,
e8b0e958 2113 .category = FIO_OPT_C_IO,
0626037e 2114 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
2115 .posval = {
2116 { .ival = "sync",
2117 .help = "Use read/write",
2118 },
a31041ea 2119 { .ival = "psync",
2120 .help = "Use pread/pwrite",
2121 },
1d2af02a 2122 { .ival = "vsync",
03e20d68 2123 .help = "Use readv/writev",
1d2af02a 2124 },
07fc0acd
JA
2125#ifdef CONFIG_PWRITEV
2126 { .ival = "pvsync",
2127 .help = "Use preadv/pwritev",
2128 },
2129#endif
6562685f 2130#ifdef FIO_HAVE_PWRITEV2
2cafffbe
JA
2131 { .ival = "pvsync2",
2132 .help = "Use preadv2/pwritev2",
2133 },
2134#endif
67bf9823 2135#ifdef CONFIG_LIBAIO
214e1eca
JA
2136 { .ival = "libaio",
2137 .help = "Linux native asynchronous IO",
2138 },
2139#endif
bffad86f
JA
2140#ifdef ARCH_HAVE_IOURING
2141 { .ival = "io_uring",
2142 .help = "Fast Linux native aio",
52885fa2
JA
2143 },
2144#endif
67bf9823 2145#ifdef CONFIG_POSIXAIO
214e1eca
JA
2146 { .ival = "posixaio",
2147 .help = "POSIX asynchronous IO",
2148 },
417f0068 2149#endif
997843cb 2150#ifdef CONFIG_SOLARISAIO
417f0068
JA
2151 { .ival = "solarisaio",
2152 .help = "Solaris native asynchronous IO",
2153 },
214e1eca 2154#endif
4700b234 2155#ifdef CONFIG_WINDOWSAIO
03e20d68 2156 { .ival = "windowsaio",
3be80071 2157 .help = "Windows native asynchronous IO"
de890a1e 2158 },
fc5c0345
DG
2159#endif
2160#ifdef CONFIG_RBD
2161 { .ival = "rbd",
2162 .help = "Rados Block Device asynchronous IO"
2163 },
3be80071 2164#endif
214e1eca 2165 { .ival = "mmap",
03e20d68 2166 .help = "Memory mapped IO"
214e1eca 2167 },
67bf9823 2168#ifdef CONFIG_LINUX_SPLICE
214e1eca
JA
2169 { .ival = "splice",
2170 .help = "splice/vmsplice based IO",
2171 },
9cce02e8
JA
2172 { .ival = "netsplice",
2173 .help = "splice/vmsplice to/from the network",
2174 },
214e1eca
JA
2175#endif
2176#ifdef FIO_HAVE_SGIO
2177 { .ival = "sg",
2178 .help = "SCSI generic v3 IO",
2179 },
2180#endif
2181 { .ival = "null",
2182 .help = "Testing engine (no data transfer)",
2183 },
2184 { .ival = "net",
2185 .help = "Network IO",
2186 },
214e1eca 2187 { .ival = "cpuio",
03e20d68 2188 .help = "CPU cycle burner engine",
214e1eca 2189 },
67bf9823 2190#ifdef CONFIG_RDMA
21b8aee8 2191 { .ival = "rdma",
2192 .help = "RDMA IO engine",
2193 },
8200b8c7 2194#endif
997843cb 2195#ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
1ecc95ca
JA
2196 { .ival = "e4defrag",
2197 .help = "ext4 defrag engine",
2198 },
2199#endif
997843cb 2200#ifdef CONFIG_LINUX_FALLOCATE
1ecc95ca
JA
2201 { .ival = "falloc",
2202 .help = "fallocate() file based engine",
2203 },
b8c82a46 2204#endif
a7c386f4 2205#ifdef CONFIG_GFAPI
2206 { .ival = "gfapi",
cc47f094 2207 .help = "Glusterfs libgfapi(sync) based engine"
2208 },
2209 { .ival = "gfapi_async",
2210 .help = "Glusterfs libgfapi(async) based engine"
a7c386f4 2211 },
2212#endif
1b10477b 2213#ifdef CONFIG_LIBHDFS
b74e419e 2214 { .ival = "libhdfs",
1b10477b
MM
2215 .help = "Hadoop Distributed Filesystem (HDFS) engine"
2216 },
5c4ef02e 2217#endif
a40e7a59
GB
2218#ifdef CONFIG_IME
2219 { .ival = "ime_psync",
2220 .help = "DDN's IME synchronous IO engine",
2221 },
2222 { .ival = "ime_psyncv",
2223 .help = "DDN's IME synchronous IO engine using iovecs",
2224 },
2225 { .ival = "ime_aio",
2226 .help = "DDN's IME asynchronous IO engine",
2227 },
2228#endif
104ee4de
DJ
2229#ifdef CONFIG_LINUX_DEVDAX
2230 { .ival = "dev-dax",
2231 .help = "DAX Device based IO engine",
2232 },
1b10477b 2233#endif
edc5fa12
JA
2234 {
2235 .ival = "filecreate",
2236 .help = "File creation engine",
2237 },
214e1eca
JA
2238 { .ival = "external",
2239 .help = "Load external engine (append name)",
6730b40f 2240 .cb = str_ioengine_external_cb,
214e1eca 2241 },
ae0db592
TI
2242#ifdef CONFIG_LIBPMEM
2243 { .ival = "libpmem",
363a5f65 2244 .help = "PMDK libpmem based IO engine",
ae0db592 2245 },
c2f6a13d
LMB
2246#endif
2247#ifdef CONFIG_HTTP
2248 { .ival = "http",
2249 .help = "HTTP (WebDAV/S3) IO engine",
2250 },
ae0db592 2251#endif
d643a1e2
RJ
2252 { .ival = "nbd",
2253 .help = "Network Block Device (NBD) IO engine"
2254 },
c363fdd7
JL
2255#ifdef CONFIG_DFS
2256 { .ival = "dfs",
2257 .help = "DAOS File System (dfs) IO engine",
2258 },
9326926b 2259#endif
98ab1262 2260#ifdef CONFIG_LIBNFS
9326926b
TG
2261 { .ival = "nfs",
2262 .help = "NFS IO engine",
2263 },
a3ff873e
AK
2264#endif
2265#ifdef CONFIG_LIBXNVME
2266 { .ival = "xnvme",
2267 .help = "XNVME IO engine",
2268 },
c363fdd7 2269#endif
214e1eca
JA
2270 },
2271 },
2272 {
2273 .name = "iodepth",
e8b0e958 2274 .lname = "IO Depth",
214e1eca 2275 .type = FIO_OPT_INT,
a609f12a 2276 .off1 = offsetof(struct thread_options, iodepth),
03e20d68 2277 .help = "Number of IO buffers to keep in flight",
757aff4f 2278 .minval = 1,
20eb06bd 2279 .interval = 1,
214e1eca 2280 .def = "1",
e8b0e958 2281 .category = FIO_OPT_C_IO,
0626037e 2282 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
2283 },
2284 {
2285 .name = "iodepth_batch",
e8b0e958 2286 .lname = "IO Depth batch",
4950421a 2287 .alias = "iodepth_batch_submit",
214e1eca 2288 .type = FIO_OPT_INT,
a609f12a 2289 .off1 = offsetof(struct thread_options, iodepth_batch),
d65db441 2290 .help = "Number of IO buffers to submit in one go",
afdf9352 2291 .parent = "iodepth",
d71c154c 2292 .hide = 1,
20eb06bd 2293 .interval = 1,
a2e6f8ac 2294 .def = "1",
e8b0e958 2295 .category = FIO_OPT_C_IO,
0626037e 2296 .group = FIO_OPT_G_IO_BASIC,
4950421a
JA
2297 },
2298 {
82407585
RP
2299 .name = "iodepth_batch_complete_min",
2300 .lname = "Min IO depth batch complete",
2301 .alias = "iodepth_batch_complete",
4950421a 2302 .type = FIO_OPT_INT,
a609f12a 2303 .off1 = offsetof(struct thread_options, iodepth_batch_complete_min),
82407585 2304 .help = "Min number of IO buffers to retrieve in one go",
4950421a 2305 .parent = "iodepth",
d71c154c 2306 .hide = 1,
4950421a 2307 .minval = 0,
20eb06bd 2308 .interval = 1,
4950421a 2309 .def = "1",
e8b0e958 2310 .category = FIO_OPT_C_IO,
0626037e 2311 .group = FIO_OPT_G_IO_BASIC,
214e1eca 2312 },
82407585
RP
2313 {
2314 .name = "iodepth_batch_complete_max",
2315 .lname = "Max IO depth batch complete",
2316 .type = FIO_OPT_INT,
a609f12a 2317 .off1 = offsetof(struct thread_options, iodepth_batch_complete_max),
82407585
RP
2318 .help = "Max number of IO buffers to retrieve in one go",
2319 .parent = "iodepth",
2320 .hide = 1,
2321 .minval = 0,
2322 .interval = 1,
2323 .category = FIO_OPT_C_IO,
2324 .group = FIO_OPT_G_IO_BASIC,
2325 },
214e1eca
JA
2326 {
2327 .name = "iodepth_low",
e8b0e958 2328 .lname = "IO Depth batch low",
214e1eca 2329 .type = FIO_OPT_INT,
a609f12a 2330 .off1 = offsetof(struct thread_options, iodepth_low),
214e1eca 2331 .help = "Low water mark for queuing depth",
afdf9352 2332 .parent = "iodepth",
d71c154c 2333 .hide = 1,
20eb06bd 2334 .interval = 1,
e8b0e958 2335 .category = FIO_OPT_C_IO,
0626037e 2336 .group = FIO_OPT_G_IO_BASIC,
214e1eca 2337 },
997b5680
SW
2338 {
2339 .name = "serialize_overlap",
2340 .lname = "Serialize overlap",
2341 .off1 = offsetof(struct thread_options, serialize_overlap),
2342 .type = FIO_OPT_BOOL,
2343 .help = "Wait for in-flight IOs that collide to complete",
2344 .parent = "iodepth",
2345 .def = "0",
2346 .category = FIO_OPT_C_IO,
2347 .group = FIO_OPT_G_IO_BASIC,
2348 },
a9da8ab2
JA
2349 {
2350 .name = "io_submit_mode",
2351 .lname = "IO submit mode",
2352 .type = FIO_OPT_STR,
a609f12a 2353 .off1 = offsetof(struct thread_options, io_submit_mode),
a9da8ab2
JA
2354 .help = "How IO submissions and completions are done",
2355 .def = "inline",
2356 .category = FIO_OPT_C_IO,
2357 .group = FIO_OPT_G_IO_BASIC,
2358 .posval = {
2359 { .ival = "inline",
2360 .oval = IO_MODE_INLINE,
2361 .help = "Submit and complete IO inline",
2362 },
2363 { .ival = "offload",
2364 .oval = IO_MODE_OFFLOAD,
2365 .help = "Offload submit and complete to threads",
2366 },
2367 },
2368 },
214e1eca
JA
2369 {
2370 .name = "size",
e8b0e958 2371 .lname = "Size",
8f39afa7 2372 .type = FIO_OPT_STR_VAL_ZONE,
7bb59102 2373 .cb = str_size_cb,
a609f12a 2374 .off1 = offsetof(struct thread_options, size),
214e1eca 2375 .help = "Total size of device or files",
e8b0e958
JA
2376 .category = FIO_OPT_C_IO,
2377 .group = FIO_OPT_G_INVALID,
214e1eca 2378 },
77731b29 2379 {
a4d3b4db
JA
2380 .name = "io_size",
2381 .alias = "io_limit",
2382 .lname = "IO Size",
8f39afa7 2383 .type = FIO_OPT_STR_VAL_ZONE,
8b38f401 2384 .cb = str_io_size_cb,
5be9bf09 2385 .off1 = offsetof(struct thread_options, io_size),
1684f7fd 2386 .help = "Total size of I/O to be performed",
77731b29
JA
2387 .category = FIO_OPT_C_IO,
2388 .group = FIO_OPT_G_INVALID,
2389 },
aa31f1f1
SL
2390 {
2391 .name = "fill_device",
e8b0e958 2392 .lname = "Fill device",
74586c1e 2393 .alias = "fill_fs",
aa31f1f1 2394 .type = FIO_OPT_BOOL,
a609f12a 2395 .off1 = offsetof(struct thread_options, fill_device),
aa31f1f1
SL
2396 .help = "Write until an ENOSPC error occurs",
2397 .def = "0",
e8b0e958
JA
2398 .category = FIO_OPT_C_FILE,
2399 .group = FIO_OPT_G_INVALID,
aa31f1f1 2400 },
214e1eca
JA
2401 {
2402 .name = "filesize",
e8b0e958 2403 .lname = "File size",
214e1eca 2404 .type = FIO_OPT_STR_VAL,
a609f12a
JA
2405 .off1 = offsetof(struct thread_options, file_size_low),
2406 .off2 = offsetof(struct thread_options, file_size_high),
c3edbdba 2407 .minval = 1,
214e1eca 2408 .help = "Size of individual files",
20eb06bd 2409 .interval = 1024 * 1024,
e8b0e958
JA
2410 .category = FIO_OPT_C_FILE,
2411 .group = FIO_OPT_G_INVALID,
214e1eca 2412 },
bedc9dc2
JA
2413 {
2414 .name = "file_append",
2415 .lname = "File append",
2416 .type = FIO_OPT_BOOL,
a609f12a 2417 .off1 = offsetof(struct thread_options, file_append),
bedc9dc2
JA
2418 .help = "IO will start at the end of the file(s)",
2419 .def = "0",
2420 .category = FIO_OPT_C_FILE,
2421 .group = FIO_OPT_G_INVALID,
2422 },
67a1000f
JA
2423 {
2424 .name = "offset",
e8b0e958 2425 .lname = "IO offset",
67a1000f 2426 .alias = "fileoffset",
8f39afa7 2427 .type = FIO_OPT_STR_VAL_ZONE,
89978a6b 2428 .cb = str_offset_cb,
a609f12a 2429 .off1 = offsetof(struct thread_options, start_offset),
67a1000f
JA
2430 .help = "Start IO from this offset",
2431 .def = "0",
e8b0e958
JA
2432 .category = FIO_OPT_C_IO,
2433 .group = FIO_OPT_G_INVALID,
67a1000f 2434 },
83c8b093
JF
2435 {
2436 .name = "offset_align",
2437 .lname = "IO offset alignment",
2438 .type = FIO_OPT_INT,
2439 .off1 = offsetof(struct thread_options, start_offset_align),
2440 .help = "Start IO from this offset alignment",
2441 .def = "0",
2442 .interval = 512,
2443 .category = FIO_OPT_C_IO,
2444 .group = FIO_OPT_G_INVALID,
2445 },
2d7cd868
JA
2446 {
2447 .name = "offset_increment",
e8b0e958 2448 .lname = "IO offset increment",
8f39afa7 2449 .type = FIO_OPT_STR_VAL_ZONE,
0b288ba1 2450 .cb = str_offset_increment_cb,
a609f12a 2451 .off1 = offsetof(struct thread_options, offset_increment),
2d7cd868
JA
2452 .help = "What is the increment from one offset to the next",
2453 .parent = "offset",
d71c154c 2454 .hide = 1,
2d7cd868 2455 .def = "0",
e8b0e958
JA
2456 .category = FIO_OPT_C_IO,
2457 .group = FIO_OPT_G_INVALID,
2d7cd868 2458 },
ddf24e42
JA
2459 {
2460 .name = "number_ios",
2461 .lname = "Number of IOs to perform",
2462 .type = FIO_OPT_STR_VAL,
a609f12a 2463 .off1 = offsetof(struct thread_options, number_ios),
be3fec7d 2464 .help = "Force job completion after this number of IOs",
ddf24e42
JA
2465 .def = "0",
2466 .category = FIO_OPT_C_IO,
2467 .group = FIO_OPT_G_INVALID,
2468 },
b3251e31
AK
2469 {
2470 .name = "num_range",
2471 .lname = "Number of ranges",
2472 .type = FIO_OPT_INT,
2473 .off1 = offsetof(struct thread_options, num_range),
2474 .maxval = MAX_TRIM_RANGE,
2475 .help = "Number of ranges for trim command",
2476 .def = "1",
2477 .category = FIO_OPT_C_IO,
2478 .group = FIO_OPT_G_INVALID,
2479 },
214e1eca
JA
2480 {
2481 .name = "bs",
e8b0e958 2482 .lname = "Block size",
d3aad8f2 2483 .alias = "blocksize",
5fff9543 2484 .type = FIO_OPT_ULL,
a609f12a
JA
2485 .off1 = offsetof(struct thread_options, bs[DDIR_READ]),
2486 .off2 = offsetof(struct thread_options, bs[DDIR_WRITE]),
2487 .off3 = offsetof(struct thread_options, bs[DDIR_TRIM]),
c3edbdba 2488 .minval = 1,
214e1eca 2489 .help = "Block size unit",
2b9136a3 2490 .def = "4096",
67a1000f 2491 .parent = "rw",
d71c154c 2492 .hide = 1,
20eb06bd 2493 .interval = 512,
e8b0e958
JA
2494 .category = FIO_OPT_C_IO,
2495 .group = FIO_OPT_G_INVALID,
214e1eca 2496 },
2b7a01d0
JA
2497 {
2498 .name = "ba",
e8b0e958 2499 .lname = "Block size align",
2b7a01d0 2500 .alias = "blockalign",
5fff9543 2501 .type = FIO_OPT_ULL,
a609f12a
JA
2502 .off1 = offsetof(struct thread_options, ba[DDIR_READ]),
2503 .off2 = offsetof(struct thread_options, ba[DDIR_WRITE]),
2504 .off3 = offsetof(struct thread_options, ba[DDIR_TRIM]),
2b7a01d0
JA
2505 .minval = 1,
2506 .help = "IO block offset alignment",
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,
2b7a01d0 2512 },
214e1eca
JA
2513 {
2514 .name = "bsrange",
e8b0e958 2515 .lname = "Block size range",
d3aad8f2 2516 .alias = "blocksize_range",
214e1eca 2517 .type = FIO_OPT_RANGE,
a609f12a
JA
2518 .off1 = offsetof(struct thread_options, min_bs[DDIR_READ]),
2519 .off2 = offsetof(struct thread_options, max_bs[DDIR_READ]),
2520 .off3 = offsetof(struct thread_options, min_bs[DDIR_WRITE]),
2521 .off4 = offsetof(struct thread_options, max_bs[DDIR_WRITE]),
2522 .off5 = offsetof(struct thread_options, min_bs[DDIR_TRIM]),
2523 .off6 = offsetof(struct thread_options, max_bs[DDIR_TRIM]),
c3edbdba 2524 .minval = 1,
214e1eca 2525 .help = "Set block size range (in more detail than bs)",
67a1000f 2526 .parent = "rw",
d71c154c 2527 .hide = 1,
20eb06bd 2528 .interval = 4096,
e8b0e958
JA
2529 .category = FIO_OPT_C_IO,
2530 .group = FIO_OPT_G_INVALID,
214e1eca 2531 },
564ca972
JA
2532 {
2533 .name = "bssplit",
e8b0e958 2534 .lname = "Block size split",
5fff9543 2535 .type = FIO_OPT_STR_ULL,
564ca972 2536 .cb = str_bssplit_cb,
a609f12a 2537 .off1 = offsetof(struct thread_options, bssplit),
564ca972
JA
2538 .help = "Set a specific mix of block sizes",
2539 .parent = "rw",
d71c154c 2540 .hide = 1,
e8b0e958
JA
2541 .category = FIO_OPT_C_IO,
2542 .group = FIO_OPT_G_INVALID,
564ca972 2543 },
214e1eca
JA
2544 {
2545 .name = "bs_unaligned",
e8b0e958 2546 .lname = "Block size unaligned",
d3aad8f2 2547 .alias = "blocksize_unaligned",
214e1eca 2548 .type = FIO_OPT_STR_SET,
a609f12a 2549 .off1 = offsetof(struct thread_options, bs_unaligned),
214e1eca 2550 .help = "Don't sector align IO buffer sizes",
67a1000f 2551 .parent = "rw",
d71c154c 2552 .hide = 1,
e8b0e958
JA
2553 .category = FIO_OPT_C_IO,
2554 .group = FIO_OPT_G_INVALID,
214e1eca 2555 },
6aca9b3d
JA
2556 {
2557 .name = "bs_is_seq_rand",
2558 .lname = "Block size division is seq/random (not read/write)",
2559 .type = FIO_OPT_BOOL,
a609f12a 2560 .off1 = offsetof(struct thread_options, bs_is_seq_rand),
86d59660 2561 .help = "Consider any blocksize setting to be sequential,random",
6aca9b3d
JA
2562 .def = "0",
2563 .parent = "blocksize",
2564 .category = FIO_OPT_C_IO,
2565 .group = FIO_OPT_G_INVALID,
2566 },
214e1eca
JA
2567 {
2568 .name = "randrepeat",
95282650 2569 .alias = "allrandrepeat",
e8b0e958 2570 .lname = "Random repeatable",
214e1eca 2571 .type = FIO_OPT_BOOL,
a609f12a 2572 .off1 = offsetof(struct thread_options, rand_repeatable),
214e1eca
JA
2573 .help = "Use repeatable random IO pattern",
2574 .def = "1",
67a1000f 2575 .parent = "rw",
d71c154c 2576 .hide = 1,
e8b0e958 2577 .category = FIO_OPT_C_IO,
3ceb458f 2578 .group = FIO_OPT_G_RANDOM,
214e1eca 2579 },
04778baf
JA
2580 {
2581 .name = "randseed",
2582 .lname = "The random generator seed",
363cffa7 2583 .type = FIO_OPT_STR_VAL,
a609f12a 2584 .off1 = offsetof(struct thread_options, rand_seed),
04778baf 2585 .help = "Set the random generator seed value",
40fe5e7b 2586 .def = "0x89",
04778baf
JA
2587 .parent = "rw",
2588 .category = FIO_OPT_C_IO,
2589 .group = FIO_OPT_G_RANDOM,
2590 },
214e1eca
JA
2591 {
2592 .name = "norandommap",
e8b0e958 2593 .lname = "No randommap",
214e1eca 2594 .type = FIO_OPT_STR_SET,
a609f12a 2595 .off1 = offsetof(struct thread_options, norandommap),
214e1eca 2596 .help = "Accept potential duplicate random blocks",
67a1000f 2597 .parent = "rw",
d71c154c 2598 .hide = 1,
b2452a43 2599 .hide_on_set = 1,
e8b0e958 2600 .category = FIO_OPT_C_IO,
3ceb458f 2601 .group = FIO_OPT_G_RANDOM,
214e1eca 2602 },
2b386d25
JA
2603 {
2604 .name = "softrandommap",
e8b0e958 2605 .lname = "Soft randommap",
2b386d25 2606 .type = FIO_OPT_BOOL,
a609f12a 2607 .off1 = offsetof(struct thread_options, softrandommap),
f66ab3c8 2608 .help = "Set norandommap if randommap allocation fails",
2b386d25 2609 .parent = "norandommap",
d71c154c 2610 .hide = 1,
2b386d25 2611 .def = "0",
e8b0e958 2612 .category = FIO_OPT_C_IO,
3ceb458f 2613 .group = FIO_OPT_G_RANDOM,
2b386d25 2614 },
8055e41d
JA
2615 {
2616 .name = "random_generator",
cce2fdfe 2617 .lname = "Random Generator",
8055e41d 2618 .type = FIO_OPT_STR,
a609f12a 2619 .off1 = offsetof(struct thread_options, random_generator),
8055e41d
JA
2620 .help = "Type of random number generator to use",
2621 .def = "tausworthe",
2622 .posval = {
2623 { .ival = "tausworthe",
2624 .oval = FIO_RAND_GEN_TAUSWORTHE,
2625 .help = "Strong Tausworthe generator",
2626 },
2627 { .ival = "lfsr",
2628 .oval = FIO_RAND_GEN_LFSR,
2629 .help = "Variable length LFSR",
2630 },
c3546b53
JA
2631 {
2632 .ival = "tausworthe64",
2633 .oval = FIO_RAND_GEN_TAUSWORTHE64,
2634 .help = "64-bit Tausworthe variant",
2635 },
8055e41d 2636 },
48107598
JA
2637 .category = FIO_OPT_C_IO,
2638 .group = FIO_OPT_G_RANDOM,
8055e41d 2639 },
e25839d4
JA
2640 {
2641 .name = "random_distribution",
cce2fdfe 2642 .lname = "Random Distribution",
e25839d4 2643 .type = FIO_OPT_STR,
a609f12a 2644 .off1 = offsetof(struct thread_options, random_distribution),
e25839d4
JA
2645 .cb = str_random_distribution_cb,
2646 .help = "Random offset distribution generator",
2647 .def = "random",
2648 .posval = {
2649 { .ival = "random",
2650 .oval = FIO_RAND_DIST_RANDOM,
2651 .help = "Completely random",
2652 },
2653 { .ival = "zipf",
2654 .oval = FIO_RAND_DIST_ZIPF,
2655 .help = "Zipf distribution",
2656 },
925fee33
JA
2657 { .ival = "pareto",
2658 .oval = FIO_RAND_DIST_PARETO,
2659 .help = "Pareto distribution",
2660 },
56d9fa4b
JA
2661 { .ival = "normal",
2662 .oval = FIO_RAND_DIST_GAUSS,
ba2b3b07 2663 .help = "Normal (Gaussian) distribution",
56d9fa4b 2664 },
e0a04ac1
JA
2665 { .ival = "zoned",
2666 .oval = FIO_RAND_DIST_ZONED,
2667 .help = "Zoned random distribution",
2668 },
59466396
JA
2669 { .ival = "zoned_abs",
2670 .oval = FIO_RAND_DIST_ZONED_ABS,
2671 .help = "Zoned absolute random distribution",
2672 },
e25839d4 2673 },
48107598
JA
2674 .category = FIO_OPT_C_IO,
2675 .group = FIO_OPT_G_RANDOM,
e25839d4 2676 },
211c9b89
JA
2677 {
2678 .name = "percentage_random",
2679 .lname = "Percentage Random",
2680 .type = FIO_OPT_INT,
a609f12a
JA
2681 .off1 = offsetof(struct thread_options, perc_rand[DDIR_READ]),
2682 .off2 = offsetof(struct thread_options, perc_rand[DDIR_WRITE]),
2683 .off3 = offsetof(struct thread_options, perc_rand[DDIR_TRIM]),
211c9b89
JA
2684 .maxval = 100,
2685 .help = "Percentage of seq/random mix that should be random",
d9472271 2686 .def = "100,100,100",
211c9b89
JA
2687 .interval = 5,
2688 .inverse = "percentage_sequential",
2689 .category = FIO_OPT_C_IO,
2690 .group = FIO_OPT_G_RANDOM,
2691 },
2692 {
2693 .name = "percentage_sequential",
2694 .lname = "Percentage Sequential",
d9472271 2695 .type = FIO_OPT_DEPRECATED,
211c9b89
JA
2696 .category = FIO_OPT_C_IO,
2697 .group = FIO_OPT_G_RANDOM,
2698 },
214e1eca
JA
2699 {
2700 .name = "nrfiles",
e8b0e958 2701 .lname = "Number of files",
d7c8be03 2702 .alias = "nr_files",
214e1eca 2703 .type = FIO_OPT_INT,
a609f12a 2704 .off1 = offsetof(struct thread_options, nr_files),
214e1eca
JA
2705 .help = "Split job workload between this number of files",
2706 .def = "1",
20eb06bd 2707 .interval = 1,
e8b0e958
JA
2708 .category = FIO_OPT_C_FILE,
2709 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2710 },
2711 {
2712 .name = "openfiles",
e8b0e958 2713 .lname = "Number of open files",
214e1eca 2714 .type = FIO_OPT_INT,
a609f12a 2715 .off1 = offsetof(struct thread_options, open_files),
214e1eca 2716 .help = "Number of files to keep open at the same time",
e8b0e958
JA
2717 .category = FIO_OPT_C_FILE,
2718 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2719 },
2720 {
2721 .name = "file_service_type",
e8b0e958 2722 .lname = "File service type",
214e1eca
JA
2723 .type = FIO_OPT_STR,
2724 .cb = str_fst_cb,
a609f12a 2725 .off1 = offsetof(struct thread_options, file_service_type),
214e1eca
JA
2726 .help = "How to select which file to service next",
2727 .def = "roundrobin",
e8b0e958
JA
2728 .category = FIO_OPT_C_FILE,
2729 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2730 .posval = {
2731 { .ival = "random",
2732 .oval = FIO_FSERVICE_RANDOM,
8c07860d
JA
2733 .help = "Choose a file at random (uniform)",
2734 },
2735 { .ival = "zipf",
2736 .oval = FIO_FSERVICE_ZIPF,
2737 .help = "Zipf randomized",
2738 },
2739 { .ival = "pareto",
2740 .oval = FIO_FSERVICE_PARETO,
2741 .help = "Pareto randomized",
2742 },
dd3503d3
SW
2743 { .ival = "normal",
2744 .oval = FIO_FSERVICE_GAUSS,
2745 .help = "Normal (Gaussian) randomized",
2746 },
8c07860d
JA
2747 { .ival = "gauss",
2748 .oval = FIO_FSERVICE_GAUSS,
dd3503d3 2749 .help = "Alias for normal",
214e1eca
JA
2750 },
2751 { .ival = "roundrobin",
2752 .oval = FIO_FSERVICE_RR,
2753 .help = "Round robin select files",
2754 },
a086c257
JA
2755 { .ival = "sequential",
2756 .oval = FIO_FSERVICE_SEQ,
2757 .help = "Finish one file before moving to the next",
2758 },
214e1eca 2759 },
67a1000f 2760 .parent = "nrfiles",
d71c154c 2761 .hide = 1,
67a1000f 2762 },
7bc8c2cf
JA
2763 {
2764 .name = "fallocate",
e8b0e958 2765 .lname = "Fallocate",
a596f047 2766 .type = FIO_OPT_STR,
a609f12a 2767 .off1 = offsetof(struct thread_options, fallocate_mode),
a596f047 2768 .help = "Whether pre-allocation is performed when laying out files",
38ca5f03 2769#ifdef FIO_HAVE_DEFAULT_FALLOCATE
2c3e17be 2770 .def = "native",
38ca5f03
TV
2771#else
2772 .def = "none",
2773#endif
e8b0e958
JA
2774 .category = FIO_OPT_C_FILE,
2775 .group = FIO_OPT_G_INVALID,
a596f047
EG
2776 .posval = {
2777 { .ival = "none",
2778 .oval = FIO_FALLOCATE_NONE,
2779 .help = "Do not pre-allocate space",
2780 },
2c3e17be
SW
2781 { .ival = "native",
2782 .oval = FIO_FALLOCATE_NATIVE,
2783 .help = "Use native pre-allocation if possible",
2784 },
2785#ifdef CONFIG_POSIX_FALLOCATE
a596f047
EG
2786 { .ival = "posix",
2787 .oval = FIO_FALLOCATE_POSIX,
2788 .help = "Use posix_fallocate()",
2789 },
2c3e17be 2790#endif
97ac992c 2791#ifdef CONFIG_LINUX_FALLOCATE
a596f047
EG
2792 { .ival = "keep",
2793 .oval = FIO_FALLOCATE_KEEP_SIZE,
2794 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
2795 },
7bc8c2cf 2796#endif
38ca5f03
TV
2797 { .ival = "truncate",
2798 .oval = FIO_FALLOCATE_TRUNCATE,
2799 .help = "Truncate file to final size instead of allocating"
2800 },
a596f047
EG
2801 /* Compatibility with former boolean values */
2802 { .ival = "0",
2803 .oval = FIO_FALLOCATE_NONE,
2804 .help = "Alias for 'none'",
2805 },
2c3e17be 2806#ifdef CONFIG_POSIX_FALLOCATE
a596f047
EG
2807 { .ival = "1",
2808 .oval = FIO_FALLOCATE_POSIX,
2809 .help = "Alias for 'posix'",
2810 },
2c3e17be 2811#endif
a596f047
EG
2812 },
2813 },
67a1000f
JA
2814 {
2815 .name = "fadvise_hint",
e8b0e958 2816 .lname = "Fadvise hint",
ecb2083d 2817 .type = FIO_OPT_STR,
a609f12a 2818 .off1 = offsetof(struct thread_options, fadvise_hint),
ecb2083d
JA
2819 .posval = {
2820 { .ival = "0",
2821 .oval = F_ADV_NONE,
c712c97a 2822 .help = "Don't issue fadvise/madvise",
ecb2083d
JA
2823 },
2824 { .ival = "1",
2825 .oval = F_ADV_TYPE,
2826 .help = "Advise using fio IO pattern",
2827 },
2828 { .ival = "random",
2829 .oval = F_ADV_RANDOM,
2830 .help = "Advise using FADV_RANDOM",
2831 },
2832 { .ival = "sequential",
2833 .oval = F_ADV_SEQUENTIAL,
2834 .help = "Advise using FADV_SEQUENTIAL",
2835 },
638689b1 2836#ifdef POSIX_FADV_NOREUSE
eb314e70
YX
2837 { .ival = "noreuse",
2838 .oval = F_ADV_NOREUSE,
2839 .help = "Advise using FADV_NOREUSE",
2840 },
638689b1 2841#endif
ecb2083d 2842 },
67a1000f
JA
2843 .help = "Use fadvise() to advise the kernel on IO pattern",
2844 .def = "1",
e8b0e958
JA
2845 .category = FIO_OPT_C_FILE,
2846 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2847 },
2848 {
2849 .name = "fsync",
e8b0e958 2850 .lname = "Fsync",
214e1eca 2851 .type = FIO_OPT_INT,
a609f12a 2852 .off1 = offsetof(struct thread_options, fsync_blocks),
214e1eca
JA
2853 .help = "Issue fsync for writes every given number of blocks",
2854 .def = "0",
20eb06bd 2855 .interval = 1,
e8b0e958
JA
2856 .category = FIO_OPT_C_FILE,
2857 .group = FIO_OPT_G_INVALID,
214e1eca 2858 },
5f9099ea
JA
2859 {
2860 .name = "fdatasync",
e8b0e958 2861 .lname = "Fdatasync",
5f9099ea 2862 .type = FIO_OPT_INT,
a609f12a 2863 .off1 = offsetof(struct thread_options, fdatasync_blocks),
5f9099ea
JA
2864 .help = "Issue fdatasync for writes every given number of blocks",
2865 .def = "0",
20eb06bd 2866 .interval = 1,
e8b0e958
JA
2867 .category = FIO_OPT_C_FILE,
2868 .group = FIO_OPT_G_INVALID,
5f9099ea 2869 },
1ef2b6be
JA
2870 {
2871 .name = "write_barrier",
e8b0e958 2872 .lname = "Write barrier",
1ef2b6be 2873 .type = FIO_OPT_INT,
a609f12a 2874 .off1 = offsetof(struct thread_options, barrier_blocks),
1ef2b6be
JA
2875 .help = "Make every Nth write a barrier write",
2876 .def = "0",
20eb06bd 2877 .interval = 1,
e8b0e958
JA
2878 .category = FIO_OPT_C_IO,
2879 .group = FIO_OPT_G_INVALID,
1ef2b6be 2880 },
67bf9823 2881#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
2882 {
2883 .name = "sync_file_range",
e8b0e958 2884 .lname = "Sync file range",
44f29692
JA
2885 .posval = {
2886 { .ival = "wait_before",
2887 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
2888 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
ebadc0ce 2889 .orval = 1,
44f29692
JA
2890 },
2891 { .ival = "write",
2892 .oval = SYNC_FILE_RANGE_WRITE,
2893 .help = "SYNC_FILE_RANGE_WRITE",
ebadc0ce 2894 .orval = 1,
44f29692
JA
2895 },
2896 {
2897 .ival = "wait_after",
2898 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
2899 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
ebadc0ce 2900 .orval = 1,
44f29692
JA
2901 },
2902 },
3843deb3 2903 .type = FIO_OPT_STR_MULTI,
44f29692 2904 .cb = str_sfr_cb,
a609f12a 2905 .off1 = offsetof(struct thread_options, sync_file_range),
44f29692 2906 .help = "Use sync_file_range()",
e8b0e958
JA
2907 .category = FIO_OPT_C_FILE,
2908 .group = FIO_OPT_G_INVALID,
44f29692 2909 },
a275c37a 2910#else
54d0a315 2911 {
a275c37a
JA
2912 .name = "sync_file_range",
2913 .lname = "Sync file range",
2914 .type = FIO_OPT_UNSUPPORTED,
2915 .help = "Your platform does not support sync_file_range",
2916 },
44f29692 2917#endif
214e1eca
JA
2918 {
2919 .name = "direct",
e8b0e958 2920 .lname = "Direct I/O",
214e1eca 2921 .type = FIO_OPT_BOOL,
a609f12a 2922 .off1 = offsetof(struct thread_options, odirect),
214e1eca
JA
2923 .help = "Use O_DIRECT IO (negates buffered)",
2924 .def = "0",
a01a1bc5 2925 .inverse = "buffered",
e8b0e958 2926 .category = FIO_OPT_C_IO,
3ceb458f 2927 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2928 },
40f1fc11 2929#ifdef FIO_HAVE_RWF_ATOMIC
d01612f3
CM
2930 {
2931 .name = "atomic",
2932 .lname = "Atomic I/O",
2933 .type = FIO_OPT_BOOL,
a609f12a 2934 .off1 = offsetof(struct thread_options, oatomic),
d01612f3
CM
2935 .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
2936 .def = "0",
2937 .category = FIO_OPT_C_IO,
2938 .group = FIO_OPT_G_IO_TYPE,
2939 },
40f1fc11 2940#endif
214e1eca
JA
2941 {
2942 .name = "buffered",
e8b0e958 2943 .lname = "Buffered I/O",
214e1eca 2944 .type = FIO_OPT_BOOL,
a609f12a 2945 .off1 = offsetof(struct thread_options, odirect),
214e1eca
JA
2946 .neg = 1,
2947 .help = "Use buffered IO (negates direct)",
2948 .def = "1",
a01a1bc5 2949 .inverse = "direct",
e8b0e958 2950 .category = FIO_OPT_C_IO,
3ceb458f 2951 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2952 },
2953 {
2954 .name = "overwrite",
e8b0e958 2955 .lname = "Overwrite",
214e1eca 2956 .type = FIO_OPT_BOOL,
a609f12a 2957 .off1 = offsetof(struct thread_options, overwrite),
214e1eca
JA
2958 .help = "When writing, set whether to overwrite current data",
2959 .def = "0",
e8b0e958
JA
2960 .category = FIO_OPT_C_FILE,
2961 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2962 },
2963 {
2964 .name = "loops",
e8b0e958 2965 .lname = "Loops",
214e1eca 2966 .type = FIO_OPT_INT,
a609f12a 2967 .off1 = offsetof(struct thread_options, loops),
214e1eca
JA
2968 .help = "Number of times to run the job",
2969 .def = "1",
20eb06bd 2970 .interval = 1,
e8b0e958 2971 .category = FIO_OPT_C_GENERAL,
a1f6afec 2972 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2973 },
2974 {
2975 .name = "numjobs",
e8b0e958 2976 .lname = "Number of jobs",
214e1eca 2977 .type = FIO_OPT_INT,
a609f12a 2978 .off1 = offsetof(struct thread_options, numjobs),
214e1eca
JA
2979 .help = "Duplicate this job this many times",
2980 .def = "1",
20eb06bd 2981 .interval = 1,
e8b0e958 2982 .category = FIO_OPT_C_GENERAL,
a1f6afec 2983 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2984 },
2985 {
2986 .name = "startdelay",
e8b0e958 2987 .lname = "Start delay",
a5737c93 2988 .type = FIO_OPT_STR_VAL_TIME,
a609f12a
JA
2989 .off1 = offsetof(struct thread_options, start_delay),
2990 .off2 = offsetof(struct thread_options, start_delay_high),
214e1eca
JA
2991 .help = "Only start job when this period has passed",
2992 .def = "0",
0de5b26f 2993 .is_seconds = 1,
88038bc7 2994 .is_time = 1,
e8b0e958 2995 .category = FIO_OPT_C_GENERAL,
a1f6afec 2996 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2997 },
2998 {
2999 .name = "runtime",
e8b0e958 3000 .lname = "Runtime",
214e1eca
JA
3001 .alias = "timeout",
3002 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3003 .off1 = offsetof(struct thread_options, timeout),
214e1eca
JA
3004 .help = "Stop workload when this amount of time has passed",
3005 .def = "0",
0de5b26f 3006 .is_seconds = 1,
88038bc7 3007 .is_time = 1,
e8b0e958 3008 .category = FIO_OPT_C_GENERAL,
a1f6afec 3009 .group = FIO_OPT_G_RUNTIME,
214e1eca 3010 },
cf4464ca
JA
3011 {
3012 .name = "time_based",
e8b0e958 3013 .lname = "Time based",
cf4464ca 3014 .type = FIO_OPT_STR_SET,
a609f12a 3015 .off1 = offsetof(struct thread_options, time_based),
cf4464ca 3016 .help = "Keep running until runtime/timeout is met",
e8b0e958 3017 .category = FIO_OPT_C_GENERAL,
a1f6afec 3018 .group = FIO_OPT_G_RUNTIME,
cf4464ca 3019 },
62167762
JC
3020 {
3021 .name = "verify_only",
3022 .lname = "Verify only",
3023 .type = FIO_OPT_STR_SET,
a609f12a 3024 .off1 = offsetof(struct thread_options, verify_only),
62167762
JC
3025 .help = "Verifies previously written data is still valid",
3026 .category = FIO_OPT_C_GENERAL,
3027 .group = FIO_OPT_G_RUNTIME,
3028 },
721938ae
JA
3029 {
3030 .name = "ramp_time",
e8b0e958 3031 .lname = "Ramp time",
721938ae 3032 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3033 .off1 = offsetof(struct thread_options, ramp_time),
721938ae 3034 .help = "Ramp up time before measuring performance",
0de5b26f 3035 .is_seconds = 1,
88038bc7 3036 .is_time = 1,
e8b0e958 3037 .category = FIO_OPT_C_GENERAL,
a1f6afec 3038 .group = FIO_OPT_G_RUNTIME,
721938ae 3039 },
c223da83
JA
3040 {
3041 .name = "clocksource",
e8b0e958 3042 .lname = "Clock source",
c223da83
JA
3043 .type = FIO_OPT_STR,
3044 .cb = fio_clock_source_cb,
a609f12a 3045 .off1 = offsetof(struct thread_options, clocksource),
c223da83 3046 .help = "What type of timing source to use",
e8b0e958 3047 .category = FIO_OPT_C_GENERAL,
10860056 3048 .group = FIO_OPT_G_CLOCK,
c223da83 3049 .posval = {
67bf9823 3050#ifdef CONFIG_GETTIMEOFDAY
c223da83
JA
3051 { .ival = "gettimeofday",
3052 .oval = CS_GTOD,
3053 .help = "Use gettimeofday(2) for timing",
3054 },
67bf9823
JA
3055#endif
3056#ifdef CONFIG_CLOCK_GETTIME
c223da83
JA
3057 { .ival = "clock_gettime",
3058 .oval = CS_CGETTIME,
3059 .help = "Use clock_gettime(2) for timing",
3060 },
67bf9823 3061#endif
c223da83
JA
3062#ifdef ARCH_HAVE_CPU_CLOCK
3063 { .ival = "cpu",
3064 .oval = CS_CPUCLOCK,
3065 .help = "Use CPU private clock",
3066 },
3067#endif
3068 },
3069 },
214e1eca
JA
3070 {
3071 .name = "mem",
d3aad8f2 3072 .alias = "iomem",
e8b0e958 3073 .lname = "I/O Memory",
214e1eca
JA
3074 .type = FIO_OPT_STR,
3075 .cb = str_mem_cb,
a609f12a 3076 .off1 = offsetof(struct thread_options, mem_type),
214e1eca
JA
3077 .help = "Backing type for IO buffers",
3078 .def = "malloc",
e8b0e958
JA
3079 .category = FIO_OPT_C_IO,
3080 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3081 .posval = {
3082 { .ival = "malloc",
3083 .oval = MEM_MALLOC,
3084 .help = "Use malloc(3) for IO buffers",
3085 },
c8931876 3086#ifndef CONFIG_NO_SHM
37c8cdfe
JA
3087 { .ival = "shm",
3088 .oval = MEM_SHM,
3089 .help = "Use shared memory segments for IO buffers",
3090 },
214e1eca
JA
3091#ifdef FIO_HAVE_HUGETLB
3092 { .ival = "shmhuge",
3093 .oval = MEM_SHMHUGE,
3094 .help = "Like shm, but use huge pages",
3095 },
c8931876 3096#endif
b370e46a 3097#endif
37c8cdfe
JA
3098 { .ival = "mmap",
3099 .oval = MEM_MMAP,
3100 .help = "Use mmap(2) (file or anon) for IO buffers",
3101 },
217b0f1d
LG
3102 { .ival = "mmapshared",
3103 .oval = MEM_MMAPSHARED,
3104 .help = "Like mmap, but use the shared flag",
3105 },
214e1eca
JA
3106#ifdef FIO_HAVE_HUGETLB
3107 { .ival = "mmaphuge",
3108 .oval = MEM_MMAPHUGE,
3109 .help = "Like mmap, but use huge pages",
3110 },
03553853
YR
3111#endif
3112#ifdef CONFIG_CUDA
3113 { .ival = "cudamalloc",
3114 .oval = MEM_CUDA_MALLOC,
3115 .help = "Allocate GPU device memory for GPUDirect RDMA",
3116 },
214e1eca
JA
3117#endif
3118 },
3119 },
d529ee19
JA
3120 {
3121 .name = "iomem_align",
3122 .alias = "mem_align",
e8b0e958 3123 .lname = "I/O memory alignment",
d529ee19 3124 .type = FIO_OPT_INT,
a609f12a 3125 .off1 = offsetof(struct thread_options, mem_align),
d529ee19
JA
3126 .minval = 0,
3127 .help = "IO memory buffer offset alignment",
3128 .def = "0",
3129 .parent = "iomem",
d71c154c 3130 .hide = 1,
e8b0e958
JA
3131 .category = FIO_OPT_C_IO,
3132 .group = FIO_OPT_G_INVALID,
d529ee19 3133 },
214e1eca
JA
3134 {
3135 .name = "verify",
e8b0e958 3136 .lname = "Verify",
214e1eca 3137 .type = FIO_OPT_STR,
a609f12a 3138 .off1 = offsetof(struct thread_options, verify),
214e1eca
JA
3139 .help = "Verify data written",
3140 .def = "0",
e8b0e958 3141 .category = FIO_OPT_C_IO,
3ceb458f 3142 .group = FIO_OPT_G_VERIFY,
214e1eca
JA
3143 .posval = {
3144 { .ival = "0",
3145 .oval = VERIFY_NONE,
3146 .help = "Don't do IO verification",
3147 },
fcca4b58
JA
3148 { .ival = "md5",
3149 .oval = VERIFY_MD5,
3150 .help = "Use md5 checksums for verification",
3151 },
d77a7af3
JA
3152 { .ival = "crc64",
3153 .oval = VERIFY_CRC64,
3154 .help = "Use crc64 checksums for verification",
3155 },
214e1eca
JA
3156 { .ival = "crc32",
3157 .oval = VERIFY_CRC32,
3158 .help = "Use crc32 checksums for verification",
3159 },
af497e6a 3160 { .ival = "crc32c-intel",
e3aaafc4
JA
3161 .oval = VERIFY_CRC32C,
3162 .help = "Use crc32c checksums for verification (hw assisted, if available)",
af497e6a 3163 },
bac39e0e
JA
3164 { .ival = "crc32c",
3165 .oval = VERIFY_CRC32C,
e3aaafc4 3166 .help = "Use crc32c checksums for verification (hw assisted, if available)",
bac39e0e 3167 },
969f7ed3
JA
3168 { .ival = "crc16",
3169 .oval = VERIFY_CRC16,
3170 .help = "Use crc16 checksums for verification",
3171 },
1e154bdb
JA
3172 { .ival = "crc7",
3173 .oval = VERIFY_CRC7,
3174 .help = "Use crc7 checksums for verification",
3175 },
7c353ceb
JA
3176 { .ival = "sha1",
3177 .oval = VERIFY_SHA1,
3178 .help = "Use sha1 checksums for verification",
3179 },
cd14cc10
JA
3180 { .ival = "sha256",
3181 .oval = VERIFY_SHA256,
3182 .help = "Use sha256 checksums for verification",
3183 },
3184 { .ival = "sha512",
3185 .oval = VERIFY_SHA512,
3186 .help = "Use sha512 checksums for verification",
ae3a5acc
JA
3187 },
3188 { .ival = "sha3-224",
3189 .oval = VERIFY_SHA3_224,
3190 .help = "Use sha3-224 checksums for verification",
3191 },
3192 { .ival = "sha3-256",
3193 .oval = VERIFY_SHA3_256,
3194 .help = "Use sha3-256 checksums for verification",
3195 },
3196 { .ival = "sha3-384",
3197 .oval = VERIFY_SHA3_384,
3198 .help = "Use sha3-384 checksums for verification",
3199 },
3200 { .ival = "sha3-512",
3201 .oval = VERIFY_SHA3_512,
3202 .help = "Use sha3-512 checksums for verification",
cd14cc10 3203 },
844ea602
JA
3204 { .ival = "xxhash",
3205 .oval = VERIFY_XXHASH,
3206 .help = "Use xxhash checksums for verification",
3207 },
b638d82f
RP
3208 /* Meta information was included into verify_header,
3209 * 'meta' verification is implied by default. */
7437ee87 3210 { .ival = "meta",
b638d82f
RP
3211 .oval = VERIFY_HDR_ONLY,
3212 .help = "Use io information for verification. "
3213 "Now is implied by default, thus option is obsolete, "
3214 "don't use it",
7437ee87 3215 },
59245381
JA
3216 { .ival = "pattern",
3217 .oval = VERIFY_PATTERN_NO_HDR,
3218 .help = "Verify strict pattern",
3219 },
ab4e5b72
VF
3220 { .ival = "pattern_hdr",
3221 .oval = VERIFY_PATTERN,
3222 .help = "Verify pattern with header",
3223 },
36690c9b
JA
3224 {
3225 .ival = "null",
3226 .oval = VERIFY_NULL,
3227 .help = "Pretend to verify",
3228 },
214e1eca
JA
3229 },
3230 },
005c565a
JA
3231 {
3232 .name = "do_verify",
e8b0e958 3233 .lname = "Perform verify step",
68e1f29a 3234 .type = FIO_OPT_BOOL,
a609f12a 3235 .off1 = offsetof(struct thread_options, do_verify),
005c565a
JA
3236 .help = "Run verification stage after write",
3237 .def = "1",
3238 .parent = "verify",
d71c154c 3239 .hide = 1,
e8b0e958
JA
3240 .category = FIO_OPT_C_IO,
3241 .group = FIO_OPT_G_VERIFY,
005c565a 3242 },
160b966d
JA
3243 {
3244 .name = "verifysort",
e8b0e958 3245 .lname = "Verify sort",
f31feaa2 3246 .type = FIO_OPT_SOFT_DEPRECATED,
e8b0e958
JA
3247 .category = FIO_OPT_C_IO,
3248 .group = FIO_OPT_G_VERIFY,
160b966d 3249 },
1ae83d45
JA
3250 {
3251 .name = "verifysort_nr",
cce2fdfe 3252 .lname = "Verify Sort Nr",
f31feaa2 3253 .type = FIO_OPT_SOFT_DEPRECATED,
836fcc0f
JA
3254 .category = FIO_OPT_C_IO,
3255 .group = FIO_OPT_G_VERIFY,
1ae83d45 3256 },
3f9f4e26 3257 {
a59e170d 3258 .name = "verify_interval",
e8b0e958 3259 .lname = "Verify interval",
e01b22b8 3260 .type = FIO_OPT_INT,
a609f12a 3261 .off1 = offsetof(struct thread_options, verify_interval),
819a9680 3262 .minval = 2 * sizeof(struct verify_header),
a59e170d 3263 .help = "Store verify buffer header every N bytes",
afdf9352 3264 .parent = "verify",
d71c154c 3265 .hide = 1,
20eb06bd 3266 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
3267 .category = FIO_OPT_C_IO,
3268 .group = FIO_OPT_G_VERIFY,
3f9f4e26 3269 },
546a9142 3270 {
a59e170d 3271 .name = "verify_offset",
e8b0e958 3272 .lname = "Verify offset",
e01b22b8 3273 .type = FIO_OPT_INT,
a59e170d 3274 .help = "Offset verify header location by N bytes",
a609f12a 3275 .off1 = offsetof(struct thread_options, verify_offset),
203160d5 3276 .minval = sizeof(struct verify_header),
afdf9352 3277 .parent = "verify",
d71c154c 3278 .hide = 1,
e8b0e958
JA
3279 .category = FIO_OPT_C_IO,
3280 .group = FIO_OPT_G_VERIFY,
546a9142 3281 },
e28218f3
SL
3282 {
3283 .name = "verify_pattern",
e8b0e958 3284 .lname = "Verify pattern",
0e92f873 3285 .type = FIO_OPT_STR,
e28218f3 3286 .cb = str_verify_pattern_cb,
a609f12a 3287 .off1 = offsetof(struct thread_options, verify_pattern),
e28218f3
SL
3288 .help = "Fill pattern for IO buffers",
3289 .parent = "verify",
d71c154c 3290 .hide = 1,
e8b0e958
JA
3291 .category = FIO_OPT_C_IO,
3292 .group = FIO_OPT_G_VERIFY,
e28218f3 3293 },
79330c25
VF
3294 {
3295 .name = "verify_pattern_interval",
3296 .lname = "Running verify pattern",
3297 .type = FIO_OPT_INT,
3298 .off1 = offsetof(struct thread_options, verify_pattern_interval),
3299 .def = "0",
3300 .help = "Re-create verify pattern every N bytes",
3301 .parent = "verify",
3302 .hide = 1,
3303 .category = FIO_OPT_C_IO,
3304 .group = FIO_OPT_G_VERIFY,
3305 },
a12a3b4d
JA
3306 {
3307 .name = "verify_fatal",
e8b0e958 3308 .lname = "Verify fatal",
68e1f29a 3309 .type = FIO_OPT_BOOL,
a609f12a 3310 .off1 = offsetof(struct thread_options, verify_fatal),
a12a3b4d
JA
3311 .def = "0",
3312 .help = "Exit on a single verify failure, don't continue",
3313 .parent = "verify",
d71c154c 3314 .hide = 1,
e8b0e958
JA
3315 .category = FIO_OPT_C_IO,
3316 .group = FIO_OPT_G_VERIFY,
a12a3b4d 3317 },
b463e936
JA
3318 {
3319 .name = "verify_dump",
e8b0e958 3320 .lname = "Verify dump",
b463e936 3321 .type = FIO_OPT_BOOL,
a609f12a 3322 .off1 = offsetof(struct thread_options, verify_dump),
ef71e317 3323 .def = "0",
b463e936
JA
3324 .help = "Dump contents of good and bad blocks on failure",
3325 .parent = "verify",
d71c154c 3326 .hide = 1,
e8b0e958
JA
3327 .category = FIO_OPT_C_IO,
3328 .group = FIO_OPT_G_VERIFY,
b463e936 3329 },
e8462bd8
JA
3330 {
3331 .name = "verify_async",
e8b0e958 3332 .lname = "Verify asynchronously",
e8462bd8 3333 .type = FIO_OPT_INT,
a609f12a 3334 .off1 = offsetof(struct thread_options, verify_async),
e8462bd8
JA
3335 .def = "0",
3336 .help = "Number of async verifier threads to use",
3337 .parent = "verify",
d71c154c 3338 .hide = 1,
e8b0e958
JA
3339 .category = FIO_OPT_C_IO,
3340 .group = FIO_OPT_G_VERIFY,
e8462bd8 3341 },
9e144189
JA
3342 {
3343 .name = "verify_backlog",
e8b0e958 3344 .lname = "Verify backlog",
9e144189 3345 .type = FIO_OPT_STR_VAL,
a609f12a 3346 .off1 = offsetof(struct thread_options, verify_backlog),
9e144189
JA
3347 .help = "Verify after this number of blocks are written",
3348 .parent = "verify",
d71c154c 3349 .hide = 1,
e8b0e958
JA
3350 .category = FIO_OPT_C_IO,
3351 .group = FIO_OPT_G_VERIFY,
9e144189
JA
3352 },
3353 {
3354 .name = "verify_backlog_batch",
e8b0e958 3355 .lname = "Verify backlog batch",
9e144189 3356 .type = FIO_OPT_INT,
a609f12a 3357 .off1 = offsetof(struct thread_options, verify_batch),
9e144189 3358 .help = "Verify this number of IO blocks",
0d29de83 3359 .parent = "verify",
d71c154c 3360 .hide = 1,
e8b0e958
JA
3361 .category = FIO_OPT_C_IO,
3362 .group = FIO_OPT_G_VERIFY,
9e144189 3363 },
e8462bd8
JA
3364#ifdef FIO_HAVE_CPU_AFFINITY
3365 {
3366 .name = "verify_async_cpus",
e8b0e958 3367 .lname = "Async verify CPUs",
e8462bd8
JA
3368 .type = FIO_OPT_STR,
3369 .cb = str_verify_cpus_allowed_cb,
a609f12a 3370 .off1 = offsetof(struct thread_options, verify_cpumask),
e8462bd8
JA
3371 .help = "Set CPUs allowed for async verify threads",
3372 .parent = "verify_async",
d71c154c 3373 .hide = 1,
e8b0e958
JA
3374 .category = FIO_OPT_C_IO,
3375 .group = FIO_OPT_G_VERIFY,
e8462bd8 3376 },
a275c37a
JA
3377#else
3378 {
3379 .name = "verify_async_cpus",
3380 .lname = "Async verify CPUs",
3381 .type = FIO_OPT_UNSUPPORTED,
54d0a315 3382 .help = "Your platform does not support CPU affinities",
a275c37a 3383 },
0d29de83 3384#endif
51aa2da8
JA
3385 {
3386 .name = "experimental_verify",
cce2fdfe 3387 .lname = "Experimental Verify",
a609f12a 3388 .off1 = offsetof(struct thread_options, experimental_verify),
51aa2da8 3389 .type = FIO_OPT_BOOL,
b31eaac9 3390 .help = "Enable experimental verification",
ca09be4b
JA
3391 .parent = "verify",
3392 .category = FIO_OPT_C_IO,
3393 .group = FIO_OPT_G_VERIFY,
3394 },
3395 {
3396 .name = "verify_state_load",
3397 .lname = "Load verify state",
a609f12a 3398 .off1 = offsetof(struct thread_options, verify_state),
ca09be4b
JA
3399 .type = FIO_OPT_BOOL,
3400 .help = "Load verify termination state",
3401 .parent = "verify",
3402 .category = FIO_OPT_C_IO,
3403 .group = FIO_OPT_G_VERIFY,
3404 },
3405 {
3406 .name = "verify_state_save",
3407 .lname = "Save verify state",
a609f12a 3408 .off1 = offsetof(struct thread_options, verify_state_save),
ca09be4b
JA
3409 .type = FIO_OPT_BOOL,
3410 .def = "1",
3411 .help = "Save verify state on termination",
3412 .parent = "verify",
836fcc0f
JA
3413 .category = FIO_OPT_C_IO,
3414 .group = FIO_OPT_G_VERIFY,
51aa2da8 3415 },
2dd80ee4
JG
3416 {
3417 .name = "verify_write_sequence",
3418 .lname = "Verify write sequence number",
3419 .off1 = offsetof(struct thread_options, verify_write_sequence),
3420 .type = FIO_OPT_BOOL,
3421 .def = "1",
3422 .help = "Verify header write sequence number",
3423 .parent = "verify",
3424 .category = FIO_OPT_C_IO,
3425 .group = FIO_OPT_G_VERIFY,
3426 },
703d04e7
AK
3427 {
3428 .name = "verify_header_seed",
3429 .lname = "Verify header seed",
3430 .off1 = offsetof(struct thread_options, verify_header_seed),
3431 .type = FIO_OPT_BOOL,
3432 .def = "1",
3433 .help = "Verify the header seed used to generate the buffer contents",
3434 .parent = "verify",
3435 .category = FIO_OPT_C_IO,
3436 .group = FIO_OPT_G_VERIFY,
3437 },
0d29de83
JA
3438#ifdef FIO_HAVE_TRIM
3439 {
3440 .name = "trim_percentage",
e8b0e958 3441 .lname = "Trim percentage",
0d29de83 3442 .type = FIO_OPT_INT,
a609f12a 3443 .off1 = offsetof(struct thread_options, trim_percentage),
20eb06bd 3444 .minval = 0,
0d29de83 3445 .maxval = 100,
169c098d 3446 .help = "Number of verify blocks to trim (i.e., discard)",
0d29de83
JA
3447 .parent = "verify",
3448 .def = "0",
20eb06bd 3449 .interval = 1,
d71c154c 3450 .hide = 1,
e8b0e958
JA
3451 .category = FIO_OPT_C_IO,
3452 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3453 },
3454 {
3455 .name = "trim_verify_zero",
e8b0e958 3456 .lname = "Verify trim zero",
20eb06bd 3457 .type = FIO_OPT_BOOL,
169c098d 3458 .help = "Verify that trimmed (i.e., discarded) blocks are returned as zeroes",
a609f12a 3459 .off1 = offsetof(struct thread_options, trim_zero),
0d29de83 3460 .parent = "trim_percentage",
d71c154c 3461 .hide = 1,
0d29de83 3462 .def = "1",
e8b0e958
JA
3463 .category = FIO_OPT_C_IO,
3464 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3465 },
3466 {
3467 .name = "trim_backlog",
e8b0e958 3468 .lname = "Trim backlog",
0d29de83 3469 .type = FIO_OPT_STR_VAL,
a609f12a 3470 .off1 = offsetof(struct thread_options, trim_backlog),
0d29de83
JA
3471 .help = "Trim after this number of blocks are written",
3472 .parent = "trim_percentage",
d71c154c 3473 .hide = 1,
20eb06bd 3474 .interval = 1,
e8b0e958
JA
3475 .category = FIO_OPT_C_IO,
3476 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3477 },
3478 {
3479 .name = "trim_backlog_batch",
e8b0e958 3480 .lname = "Trim backlog batch",
0d29de83 3481 .type = FIO_OPT_INT,
a609f12a 3482 .off1 = offsetof(struct thread_options, trim_batch),
0d29de83
JA
3483 .help = "Trim this number of IO blocks",
3484 .parent = "trim_percentage",
d71c154c 3485 .hide = 1,
20eb06bd 3486 .interval = 1,
e8b0e958
JA
3487 .category = FIO_OPT_C_IO,
3488 .group = FIO_OPT_G_TRIM,
0d29de83 3489 },
a275c37a
JA
3490#else
3491 {
3492 .name = "trim_percentage",
3493 .lname = "Trim percentage",
3494 .type = FIO_OPT_UNSUPPORTED,
3495 .help = "Fio does not support TRIM on your platform",
3496 },
3497 {
3498 .name = "trim_verify_zero",
3499 .lname = "Verify trim zero",
3500 .type = FIO_OPT_UNSUPPORTED,
3501 .help = "Fio does not support TRIM on your platform",
3502 },
3503 {
3504 .name = "trim_backlog",
3505 .lname = "Trim backlog",
3506 .type = FIO_OPT_UNSUPPORTED,
3507 .help = "Fio does not support TRIM on your platform",
3508 },
3509 {
3510 .name = "trim_backlog_batch",
3511 .lname = "Trim backlog batch",
3512 .type = FIO_OPT_UNSUPPORTED,
3513 .help = "Fio does not support TRIM on your platform",
3514 },
e8462bd8 3515#endif
214e1eca
JA
3516 {
3517 .name = "write_iolog",
e8b0e958 3518 .lname = "Write I/O log",
214e1eca 3519 .type = FIO_OPT_STR_STORE,
a609f12a 3520 .off1 = offsetof(struct thread_options, write_iolog_file),
214e1eca 3521 .help = "Store IO pattern to file",
e8b0e958
JA
3522 .category = FIO_OPT_C_IO,
3523 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
3524 },
3525 {
3526 .name = "read_iolog",
e8b0e958 3527 .lname = "Read I/O log",
214e1eca 3528 .type = FIO_OPT_STR_STORE,
a609f12a 3529 .off1 = offsetof(struct thread_options, read_iolog_file),
214e1eca 3530 .help = "Playback IO pattern from file",
e8b0e958
JA
3531 .category = FIO_OPT_C_IO,
3532 .group = FIO_OPT_G_IOLOG,
214e1eca 3533 },
98e7161c
AK
3534 {
3535 .name = "read_iolog_chunked",
3536 .lname = "Read I/O log in parts",
3537 .type = FIO_OPT_BOOL,
3538 .off1 = offsetof(struct thread_options, read_iolog_chunked),
3539 .def = "0",
3540 .parent = "read_iolog",
3541 .help = "Parse IO pattern in chunks",
3542 .category = FIO_OPT_C_IO,
3543 .group = FIO_OPT_G_IOLOG,
3544 },
64bbb865
DN
3545 {
3546 .name = "replay_no_stall",
e8b0e958 3547 .lname = "Don't stall on replay",
20eb06bd 3548 .type = FIO_OPT_BOOL,
a609f12a 3549 .off1 = offsetof(struct thread_options, no_stall),
64bbb865 3550 .def = "0",
87e7a972 3551 .parent = "read_iolog",
d71c154c 3552 .hide = 1,
64bbb865 3553 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
3554 .category = FIO_OPT_C_IO,
3555 .group = FIO_OPT_G_IOLOG,
64bbb865 3556 },
d1c46c04
DN
3557 {
3558 .name = "replay_redirect",
e8b0e958 3559 .lname = "Redirect device for replay",
d1c46c04 3560 .type = FIO_OPT_STR_STORE,
a609f12a 3561 .off1 = offsetof(struct thread_options, replay_redirect),
d1c46c04 3562 .parent = "read_iolog",
d71c154c 3563 .hide = 1,
d1c46c04 3564 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
3565 .category = FIO_OPT_C_IO,
3566 .group = FIO_OPT_G_IOLOG,
d1c46c04 3567 },
0c63576e
JA
3568 {
3569 .name = "replay_scale",
3570 .lname = "Replace offset scale factor",
3571 .type = FIO_OPT_INT,
a609f12a 3572 .off1 = offsetof(struct thread_options, replay_scale),
0c63576e
JA
3573 .parent = "read_iolog",
3574 .def = "1",
3575 .help = "Align offsets to this blocksize",
3576 .category = FIO_OPT_C_IO,
3577 .group = FIO_OPT_G_IOLOG,
3578 },
3579 {
3580 .name = "replay_align",
3581 .lname = "Replace alignment",
3582 .type = FIO_OPT_INT,
a609f12a 3583 .off1 = offsetof(struct thread_options, replay_align),
0c63576e
JA
3584 .parent = "read_iolog",
3585 .help = "Scale offset down by this factor",
3586 .category = FIO_OPT_C_IO,
3587 .group = FIO_OPT_G_IOLOG,
3588 .pow2 = 1,
3589 },
6dd7fa77
JA
3590 {
3591 .name = "replay_time_scale",
3592 .lname = "Replay Time Scale",
3593 .type = FIO_OPT_INT,
3594 .off1 = offsetof(struct thread_options, replay_time_scale),
3595 .def = "100",
3596 .minval = 1,
3597 .parent = "read_iolog",
3598 .hide = 1,
3599 .help = "Scale time for replay events",
3600 .category = FIO_OPT_C_IO,
3601 .group = FIO_OPT_G_IOLOG,
3602 },
d7235efb
JA
3603 {
3604 .name = "replay_skip",
3605 .lname = "Replay Skip",
3606 .type = FIO_OPT_STR,
3607 .cb = str_replay_skip_cb,
3608 .off1 = offsetof(struct thread_options, replay_skip),
3609 .parent = "read_iolog",
3610 .help = "Skip certain IO types (read,write,trim,flush)",
3611 .category = FIO_OPT_C_IO,
3612 .group = FIO_OPT_G_IOLOG,
3613 },
b9921d1a
DZ
3614 {
3615 .name = "merge_blktrace_file",
3616 .lname = "Merged blktrace output filename",
3617 .type = FIO_OPT_STR_STORE,
3618 .off1 = offsetof(struct thread_options, merge_blktrace_file),
3619 .help = "Merged blktrace output filename",
3620 .category = FIO_OPT_C_IO,
3621 .group = FIO_OPT_G_IOLOG,
3622 },
87a48ada
DZ
3623 {
3624 .name = "merge_blktrace_scalars",
3625 .lname = "Percentage to scale each trace",
3626 .type = FIO_OPT_FLOAT_LIST,
3627 .off1 = offsetof(struct thread_options, merge_blktrace_scalars),
3628 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3629 .help = "Percentage to scale each trace",
3630 .category = FIO_OPT_C_IO,
3631 .group = FIO_OPT_G_IOLOG,
3632 },
55bfd8c8
DZ
3633 {
3634 .name = "merge_blktrace_iters",
3635 .lname = "Number of iterations to run per trace",
3636 .type = FIO_OPT_FLOAT_LIST,
3637 .off1 = offsetof(struct thread_options, merge_blktrace_iters),
3638 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3639 .help = "Number of iterations to run per trace",
3640 .category = FIO_OPT_C_IO,
3641 .group = FIO_OPT_G_IOLOG,
3642 },
214e1eca
JA
3643 {
3644 .name = "exec_prerun",
e8b0e958 3645 .lname = "Pre-execute runnable",
214e1eca 3646 .type = FIO_OPT_STR_STORE,
a609f12a 3647 .off1 = offsetof(struct thread_options, exec_prerun),
214e1eca 3648 .help = "Execute this file prior to running job",
e8b0e958
JA
3649 .category = FIO_OPT_C_GENERAL,
3650 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3651 },
3652 {
3653 .name = "exec_postrun",
e8b0e958 3654 .lname = "Post-execute runnable",
214e1eca 3655 .type = FIO_OPT_STR_STORE,
a609f12a 3656 .off1 = offsetof(struct thread_options, exec_postrun),
214e1eca 3657 .help = "Execute this file after running job",
e8b0e958
JA
3658 .category = FIO_OPT_C_GENERAL,
3659 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3660 },
3661#ifdef FIO_HAVE_IOSCHED_SWITCH
3662 {
3663 .name = "ioscheduler",
e8b0e958 3664 .lname = "I/O scheduler",
214e1eca 3665 .type = FIO_OPT_STR_STORE,
a609f12a 3666 .off1 = offsetof(struct thread_options, ioscheduler),
214e1eca 3667 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
3668 .category = FIO_OPT_C_FILE,
3669 .group = FIO_OPT_G_INVALID,
214e1eca 3670 },
a275c37a
JA
3671#else
3672 {
3673 .name = "ioscheduler",
3674 .lname = "I/O scheduler",
3675 .type = FIO_OPT_UNSUPPORTED,
3676 .help = "Your platform does not support IO scheduler switching",
3677 },
214e1eca 3678#endif
7b865a2f
BVA
3679 {
3680 .name = "zonemode",
3681 .lname = "Zone mode",
3682 .help = "Mode for the zonesize, zonerange and zoneskip parameters",
3683 .type = FIO_OPT_STR,
3684 .off1 = offsetof(struct thread_options, zone_mode),
3685 .def = "none",
3686 .category = FIO_OPT_C_IO,
3687 .group = FIO_OPT_G_ZONE,
3688 .posval = {
3689 { .ival = "none",
3690 .oval = ZONE_MODE_NONE,
3691 .help = "no zoning",
3692 },
3693 { .ival = "strided",
3694 .oval = ZONE_MODE_STRIDED,
3695 .help = "strided mode - random I/O is restricted to a single zone",
3696 },
3697 { .ival = "zbd",
3698 .oval = ZONE_MODE_ZBD,
3699 .help = "zoned block device mode - random I/O selects one of multiple zones randomly",
3700 },
3701 },
3702 },
214e1eca
JA
3703 {
3704 .name = "zonesize",
e8b0e958 3705 .lname = "Zone size",
214e1eca 3706 .type = FIO_OPT_STR_VAL,
a609f12a 3707 .off1 = offsetof(struct thread_options, zone_size),
ed335855
SN
3708 .help = "Amount of data to read per zone",
3709 .def = "0",
20eb06bd 3710 .interval = 1024 * 1024,
e8b0e958
JA
3711 .category = FIO_OPT_C_IO,
3712 .group = FIO_OPT_G_ZONE,
ed335855 3713 },
b8dd9750
HH
3714 {
3715 .name = "zonecapacity",
3716 .lname = "Zone capacity",
3717 .type = FIO_OPT_STR_VAL,
3718 .off1 = offsetof(struct thread_options, zone_capacity),
3719 .help = "Capacity per zone",
3720 .def = "0",
3721 .interval = 1024 * 1024,
3722 .category = FIO_OPT_C_IO,
3723 .group = FIO_OPT_G_ZONE,
3724 },
ed335855
SN
3725 {
3726 .name = "zonerange",
e8b0e958 3727 .lname = "Zone range",
ed335855 3728 .type = FIO_OPT_STR_VAL,
a609f12a 3729 .off1 = offsetof(struct thread_options, zone_range),
214e1eca
JA
3730 .help = "Give size of an IO zone",
3731 .def = "0",
20eb06bd 3732 .interval = 1024 * 1024,
e8b0e958
JA
3733 .category = FIO_OPT_C_IO,
3734 .group = FIO_OPT_G_ZONE,
214e1eca
JA
3735 },
3736 {
3737 .name = "zoneskip",
e8b0e958 3738 .lname = "Zone skip",
8f39afa7
AD
3739 .type = FIO_OPT_STR_VAL_ZONE,
3740 .cb = str_zoneskip_cb,
a609f12a 3741 .off1 = offsetof(struct thread_options, zone_skip),
214e1eca
JA
3742 .help = "Space between IO zones",
3743 .def = "0",
e8b0e958
JA
3744 .category = FIO_OPT_C_IO,
3745 .group = FIO_OPT_G_ZONE,
214e1eca 3746 },
bfbdd35b
BVA
3747 {
3748 .name = "read_beyond_wp",
3749 .lname = "Allow reads beyond the zone write pointer",
3750 .type = FIO_OPT_BOOL,
3751 .off1 = offsetof(struct thread_options, read_beyond_wp),
3752 .help = "Allow reads beyond the zone write pointer",
3753 .def = "0",
3754 .category = FIO_OPT_C_IO,
3755 .group = FIO_OPT_G_INVALID,
3756 },
59b07544
BVA
3757 {
3758 .name = "max_open_zones",
219c662d 3759 .lname = "Per device/file maximum number of open zones",
59b07544
BVA
3760 .type = FIO_OPT_INT,
3761 .off1 = offsetof(struct thread_options, max_open_zones),
a4807046 3762 .maxval = ZBD_MAX_WRITE_ZONES,
219c662d
AD
3763 .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd",
3764 .def = "0",
3765 .category = FIO_OPT_C_IO,
3766 .group = FIO_OPT_G_INVALID,
3767 },
3768 {
3769 .name = "job_max_open_zones",
3770 .lname = "Job maximum number of open zones",
3771 .type = FIO_OPT_INT,
3772 .off1 = offsetof(struct thread_options, job_max_open_zones),
a4807046 3773 .maxval = ZBD_MAX_WRITE_ZONES,
219c662d 3774 .help = "Limit on the number of simultaneously opened sequential write zones with zonemode=zbd by one thread/process",
59b07544
BVA
3775 .def = "0",
3776 .category = FIO_OPT_C_IO,
3777 .group = FIO_OPT_G_INVALID,
3778 },
575686bb
NC
3779 {
3780 .name = "ignore_zone_limits",
3781 .lname = "Ignore zone resource limits",
3782 .type = FIO_OPT_BOOL,
3783 .off1 = offsetof(struct thread_options, ignore_zone_limits),
3784 .def = "0",
3785 .help = "Ignore the zone resource limits (max open/active zones) reported by the device",
3786 .category = FIO_OPT_C_IO,
3787 .group = FIO_OPT_G_INVALID,
3788 },
a7c2b6fc
BVA
3789 {
3790 .name = "zone_reset_threshold",
3791 .lname = "Zone reset threshold",
3792 .help = "Zoned block device reset threshold",
3793 .type = FIO_OPT_FLOAT_LIST,
3794 .maxlen = 1,
3795 .off1 = offsetof(struct thread_options, zrt),
3796 .minfp = 0,
3797 .maxfp = 1,
3798 .category = FIO_OPT_C_IO,
3799 .group = FIO_OPT_G_ZONE,
3800 },
3801 {
3802 .name = "zone_reset_frequency",
3803 .lname = "Zone reset frequency",
3804 .help = "Zoned block device zone reset frequency in HZ",
3805 .type = FIO_OPT_FLOAT_LIST,
3806 .maxlen = 1,
3807 .off1 = offsetof(struct thread_options, zrf),
3808 .minfp = 0,
3809 .maxfp = 1,
3810 .category = FIO_OPT_C_IO,
3811 .group = FIO_OPT_G_ZONE,
3812 },
650c4ad3
SK
3813 {
3814 .name = "recover_zbd_write_error",
3815 .lname = "Recover write errors when zonemode=zbd is set",
3816 .type = FIO_OPT_BOOL,
3817 .off1 = offsetof(struct thread_options, recover_zbd_write_error),
3818 .def = 0,
3819 .help = "Continue writes for sequential write required zones after recovering write errors with care for partial write pointer move",
3820 .category = FIO_OPT_C_IO,
3821 .group = FIO_OPT_G_ZONE,
3822 },
a7e8aae0
KB
3823 {
3824 .name = "fdp",
3825 .lname = "Flexible data placement",
3826 .type = FIO_OPT_BOOL,
3827 .off1 = offsetof(struct thread_options, fdp),
3828 .help = "Use Data placement directive (FDP)",
3829 .def = "0",
3830 .category = FIO_OPT_C_IO,
3831 .group = FIO_OPT_G_INVALID,
3832 },
d3e310c5 3833 {
65ca6791
VF
3834 .name = "dataplacement",
3835 .alias = "data_placement",
3836 .lname = "Data Placement interface",
d3e310c5 3837 .type = FIO_OPT_STR,
65ca6791
VF
3838 .off1 = offsetof(struct thread_options, dp_type),
3839 .help = "Data Placement interface to use",
3840 .def = "none",
3841 .category = FIO_OPT_C_IO,
3842 .group = FIO_OPT_G_INVALID,
3843 .posval = {
3844 { .ival = "none",
3845 .oval = FIO_DP_NONE,
3846 .help = "Do not specify a data placement interface",
3847 },
3848 { .ival = "fdp",
3849 .oval = FIO_DP_FDP,
3850 .help = "Use Flexible Data Placement interface",
3851 },
3852 { .ival = "streams",
3853 .oval = FIO_DP_STREAMS,
3854 .help = "Use Streams interface",
3855 },
3856 },
3857 },
3858 {
3859 .name = "plid_select",
3860 .alias = "fdp_pli_select",
3861 .lname = "Data Placement ID selection strategy",
3862 .type = FIO_OPT_STR,
3863 .off1 = offsetof(struct thread_options, dp_id_select),
3864 .help = "Strategy for selecting next Data Placement ID",
d3e310c5
AK
3865 .def = "roundrobin",
3866 .category = FIO_OPT_C_IO,
3867 .group = FIO_OPT_G_INVALID,
3868 .posval = {
3869 { .ival = "random",
65ca6791 3870 .oval = FIO_DP_RANDOM,
d3e310c5
AK
3871 .help = "Choose a Placement ID at random (uniform)",
3872 },
3873 { .ival = "roundrobin",
65ca6791 3874 .oval = FIO_DP_RR,
d3e310c5
AK
3875 .help = "Round robin select Placement IDs",
3876 },
04d5add8
HP
3877 { .ival = "scheme",
3878 .oval = FIO_DP_SCHEME,
3879 .help = "Use a scheme(based on LBA) to select Placement IDs",
3880 },
d3e310c5
AK
3881 },
3882 },
a7e8aae0 3883 {
65ca6791
VF
3884 .name = "plids",
3885 .alias = "fdp_pli",
3886 .lname = "Stream IDs/Data Placement ID indices",
a7e8aae0
KB
3887 .type = FIO_OPT_STR,
3888 .cb = str_fdp_pli_cb,
65ca6791
VF
3889 .off1 = offsetof(struct thread_options, dp_ids),
3890 .help = "Sets which Data Placement ids to use (defaults to all for FDP)",
a7e8aae0
KB
3891 .hide = 1,
3892 .category = FIO_OPT_C_IO,
3893 .group = FIO_OPT_G_INVALID,
3894 },
04d5add8
HP
3895 {
3896 .name = "dp_scheme",
3897 .lname = "Data Placement Scheme",
3898 .type = FIO_OPT_STR_STORE,
3899 .cb = str_dp_scheme_cb,
3900 .off1 = offsetof(struct thread_options, dp_scheme_file),
3901 .maxlen = PATH_MAX,
3902 .help = "scheme file that specifies offset-RUH mapping",
3903 .category = FIO_OPT_C_IO,
3904 .group = FIO_OPT_G_INVALID,
3905 },
214e1eca
JA
3906 {
3907 .name = "lockmem",
e8b0e958 3908 .lname = "Lock memory",
214e1eca 3909 .type = FIO_OPT_STR_VAL,
a609f12a 3910 .off1 = offsetof(struct thread_options, lockmem),
81c6b6cd 3911 .help = "Lock down this amount of memory (per worker)",
214e1eca 3912 .def = "0",
20eb06bd 3913 .interval = 1024 * 1024,
e8b0e958
JA
3914 .category = FIO_OPT_C_GENERAL,
3915 .group = FIO_OPT_G_INVALID,
214e1eca 3916 },
214e1eca
JA
3917 {
3918 .name = "rwmixread",
e8b0e958 3919 .lname = "Read/write mix read",
214e1eca 3920 .type = FIO_OPT_INT,
cb499fc4 3921 .cb = str_rwmix_read_cb,
a609f12a 3922 .off1 = offsetof(struct thread_options, rwmix[DDIR_READ]),
214e1eca
JA
3923 .maxval = 100,
3924 .help = "Percentage of mixed workload that is reads",
3925 .def = "50",
20eb06bd 3926 .interval = 5,
90265353 3927 .inverse = "rwmixwrite",
e8b0e958
JA
3928 .category = FIO_OPT_C_IO,
3929 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
3930 },
3931 {
3932 .name = "rwmixwrite",
e8b0e958 3933 .lname = "Read/write mix write",
214e1eca 3934 .type = FIO_OPT_INT,
cb499fc4 3935 .cb = str_rwmix_write_cb,
a609f12a 3936 .off1 = offsetof(struct thread_options, rwmix[DDIR_WRITE]),
214e1eca
JA
3937 .maxval = 100,
3938 .help = "Percentage of mixed workload that is writes",
3939 .def = "50",
20eb06bd 3940 .interval = 5,
90265353 3941 .inverse = "rwmixread",
e8b0e958
JA
3942 .category = FIO_OPT_C_IO,
3943 .group = FIO_OPT_G_RWMIX,
214e1eca 3944 },
afdf9352
JA
3945 {
3946 .name = "rwmixcycle",
e8b0e958 3947 .lname = "Read/write mix cycle",
15ca150e 3948 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
3949 .category = FIO_OPT_C_IO,
3950 .group = FIO_OPT_G_RWMIX,
afdf9352 3951 },
214e1eca
JA
3952 {
3953 .name = "nice",
e8b0e958 3954 .lname = "Nice",
214e1eca 3955 .type = FIO_OPT_INT,
a609f12a 3956 .off1 = offsetof(struct thread_options, nice),
214e1eca 3957 .help = "Set job CPU nice value",
11fd6aa8
RC
3958 .minval = -20,
3959 .maxval = 19,
214e1eca 3960 .def = "0",
20eb06bd 3961 .interval = 1,
e8b0e958 3962 .category = FIO_OPT_C_GENERAL,
10860056 3963 .group = FIO_OPT_G_CRED,
214e1eca
JA
3964 },
3965#ifdef FIO_HAVE_IOPRIO
3966 {
3967 .name = "prio",
e8b0e958 3968 .lname = "I/O nice priority",
214e1eca 3969 .type = FIO_OPT_INT,
a609f12a 3970 .off1 = offsetof(struct thread_options, ioprio),
214e1eca 3971 .help = "Set job IO priority value",
1767bd34
TK
3972 .minval = IOPRIO_MIN_PRIO,
3973 .maxval = IOPRIO_MAX_PRIO,
20eb06bd 3974 .interval = 1,
e8b0e958 3975 .category = FIO_OPT_C_GENERAL,
10860056 3976 .group = FIO_OPT_G_CRED,
214e1eca 3977 },
32ef447a
TK
3978#else
3979 {
3980 .name = "prio",
3981 .lname = "I/O nice priority",
3982 .type = FIO_OPT_UNSUPPORTED,
3983 .help = "Your platform does not support IO priorities",
3984 },
3985#endif
3986#ifdef FIO_HAVE_IOPRIO_CLASS
3987#ifndef FIO_HAVE_IOPRIO
3988#error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
3989#endif
214e1eca
JA
3990 {
3991 .name = "prioclass",
e8b0e958 3992 .lname = "I/O nice priority class",
214e1eca 3993 .type = FIO_OPT_INT,
a609f12a 3994 .off1 = offsetof(struct thread_options, ioprio_class),
214e1eca 3995 .help = "Set job IO priority class",
1767bd34
TK
3996 .minval = IOPRIO_MIN_PRIO_CLASS,
3997 .maxval = IOPRIO_MAX_PRIO_CLASS,
20eb06bd 3998 .interval = 1,
e8b0e958 3999 .category = FIO_OPT_C_GENERAL,
10860056 4000 .group = FIO_OPT_G_CRED,
214e1eca 4001 },
860462da
DLM
4002 {
4003 .name = "priohint",
4004 .lname = "I/O nice priority hint",
4005 .type = FIO_OPT_INT,
4006 .off1 = offsetof(struct thread_options, ioprio_hint),
4007 .help = "Set job IO priority hint",
4008 .minval = IOPRIO_MIN_PRIO_HINT,
4009 .maxval = IOPRIO_MAX_PRIO_HINT,
4010 .interval = 1,
4011 .category = FIO_OPT_C_GENERAL,
4012 .group = FIO_OPT_G_CRED,
4013 },
a275c37a 4014#else
a275c37a
JA
4015 {
4016 .name = "prioclass",
4017 .lname = "I/O nice priority class",
4018 .type = FIO_OPT_UNSUPPORTED,
32ef447a 4019 .help = "Your platform does not support IO priority classes",
a275c37a 4020 },
860462da
DLM
4021 {
4022 .name = "priohint",
4023 .lname = "I/O nice priority hint",
4024 .type = FIO_OPT_UNSUPPORTED,
4025 .help = "Your platform does not support IO priority hints",
4026 },
214e1eca
JA
4027#endif
4028 {
4029 .name = "thinktime",
e8b0e958 4030 .lname = "Thinktime",
214e1eca 4031 .type = FIO_OPT_INT,
a609f12a 4032 .off1 = offsetof(struct thread_options, thinktime),
214e1eca
JA
4033 .help = "Idle time between IO buffers (usec)",
4034 .def = "0",
88038bc7 4035 .is_time = 1,
e8b0e958 4036 .category = FIO_OPT_C_IO,
3ceb458f 4037 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
4038 },
4039 {
4040 .name = "thinktime_spin",
e8b0e958 4041 .lname = "Thinktime spin",
214e1eca 4042 .type = FIO_OPT_INT,
a609f12a 4043 .off1 = offsetof(struct thread_options, thinktime_spin),
214e1eca
JA
4044 .help = "Start think time by spinning this amount (usec)",
4045 .def = "0",
88038bc7 4046 .is_time = 1,
afdf9352 4047 .parent = "thinktime",
d71c154c 4048 .hide = 1,
e8b0e958 4049 .category = FIO_OPT_C_IO,
3ceb458f 4050 .group = FIO_OPT_G_THINKTIME,
214e1eca 4051 },
0d8cc753
CL
4052 {
4053 .name = "thinkcycles",
4054 .lname = "Think cycles",
4055 .type = FIO_OPT_INT,
4056 .off1 = offsetof(struct thread_options, thinkcycles),
4057 .help = "Spin for a constant amount of cycles between requests",
4058 .def = "0",
4059 .parent = "thinktime",
4060 .hide = 1,
4061 .category = FIO_OPT_C_IO,
4062 .group = FIO_OPT_G_THINKTIME,
4063 },
214e1eca
JA
4064 {
4065 .name = "thinktime_blocks",
e8b0e958 4066 .lname = "Thinktime blocks",
214e1eca 4067 .type = FIO_OPT_INT,
a609f12a 4068 .off1 = offsetof(struct thread_options, thinktime_blocks),
214e1eca
JA
4069 .help = "IO buffer period between 'thinktime'",
4070 .def = "1",
afdf9352 4071 .parent = "thinktime",
d71c154c 4072 .hide = 1,
e8b0e958 4073 .category = FIO_OPT_C_IO,
3ceb458f 4074 .group = FIO_OPT_G_THINKTIME,
214e1eca 4075 },
33f42c20
HQ
4076 {
4077 .name = "thinktime_blocks_type",
4078 .lname = "Thinktime blocks type",
4079 .type = FIO_OPT_STR,
4080 .off1 = offsetof(struct thread_options, thinktime_blocks_type),
4081 .help = "How thinktime_blocks takes effect",
4082 .def = "complete",
4083 .category = FIO_OPT_C_IO,
4084 .group = FIO_OPT_G_THINKTIME,
4085 .posval = {
4086 { .ival = "complete",
4087 .oval = THINKTIME_BLOCKS_TYPE_COMPLETE,
4088 .help = "thinktime_blocks takes effect at the completion side",
4089 },
4090 {
4091 .ival = "issue",
4092 .oval = THINKTIME_BLOCKS_TYPE_ISSUE,
4093 .help = "thinktime_blocks takes effect at the issue side",
4094 },
4095 },
4096 .parent = "thinktime",
4097 },
f7942acd
SK
4098 {
4099 .name = "thinktime_iotime",
4100 .lname = "Thinktime interval",
4101 .type = FIO_OPT_INT,
4102 .off1 = offsetof(struct thread_options, thinktime_iotime),
4103 .help = "IO time interval between 'thinktime'",
4104 .def = "0",
4105 .parent = "thinktime",
4106 .hide = 1,
4107 .is_seconds = 1,
4108 .is_time = 1,
4109 .category = FIO_OPT_C_IO,
4110 .group = FIO_OPT_G_THINKTIME,
4111 },
214e1eca
JA
4112 {
4113 .name = "rate",
e8b0e958 4114 .lname = "I/O rate",
140a6888 4115 .type = FIO_OPT_ULL,
a609f12a
JA
4116 .off1 = offsetof(struct thread_options, rate[DDIR_READ]),
4117 .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]),
4118 .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]),
214e1eca 4119 .help = "Set bandwidth rate",
e8b0e958
JA
4120 .category = FIO_OPT_C_IO,
4121 .group = FIO_OPT_G_RATE,
214e1eca
JA
4122 },
4123 {
6d428bcd
JA
4124 .name = "rate_min",
4125 .alias = "ratemin",
e8b0e958 4126 .lname = "I/O min rate",
140a6888 4127 .type = FIO_OPT_ULL,
a609f12a
JA
4128 .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]),
4129 .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]),
4130 .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]),
4e991c23 4131 .help = "Job must meet this rate or it will be shutdown",
afdf9352 4132 .parent = "rate",
d71c154c 4133 .hide = 1,
e8b0e958
JA
4134 .category = FIO_OPT_C_IO,
4135 .group = FIO_OPT_G_RATE,
4e991c23
JA
4136 },
4137 {
4138 .name = "rate_iops",
e8b0e958 4139 .lname = "I/O rate IOPS",
e01b22b8 4140 .type = FIO_OPT_INT,
a609f12a
JA
4141 .off1 = offsetof(struct thread_options, rate_iops[DDIR_READ]),
4142 .off2 = offsetof(struct thread_options, rate_iops[DDIR_WRITE]),
4143 .off3 = offsetof(struct thread_options, rate_iops[DDIR_TRIM]),
4e991c23 4144 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 4145 .hide = 1,
e8b0e958
JA
4146 .category = FIO_OPT_C_IO,
4147 .group = FIO_OPT_G_RATE,
4e991c23
JA
4148 },
4149 {
4150 .name = "rate_iops_min",
e8b0e958 4151 .lname = "I/O min rate IOPS",
e01b22b8 4152 .type = FIO_OPT_INT,
a609f12a
JA
4153 .off1 = offsetof(struct thread_options, rate_iops_min[DDIR_READ]),
4154 .off2 = offsetof(struct thread_options, rate_iops_min[DDIR_WRITE]),
4155 .off3 = offsetof(struct thread_options, rate_iops_min[DDIR_TRIM]),
03e20d68 4156 .help = "Job must meet this rate or it will be shut down",
afdf9352 4157 .parent = "rate_iops",
d71c154c 4158 .hide = 1,
e8b0e958
JA
4159 .category = FIO_OPT_C_IO,
4160 .group = FIO_OPT_G_RATE,
214e1eca 4161 },
ff6bb260 4162 {
6de65959
JA
4163 .name = "rate_process",
4164 .lname = "Rate Process",
4165 .type = FIO_OPT_STR,
a609f12a 4166 .off1 = offsetof(struct thread_options, rate_process),
6de65959
JA
4167 .help = "What process controls how rated IO is managed",
4168 .def = "linear",
ff6bb260
SL
4169 .category = FIO_OPT_C_IO,
4170 .group = FIO_OPT_G_RATE,
6de65959
JA
4171 .posval = {
4172 { .ival = "linear",
4173 .oval = RATE_PROCESS_LINEAR,
4174 .help = "Linear rate of IO",
4175 },
4176 {
4177 .ival = "poisson",
4178 .oval = RATE_PROCESS_POISSON,
4179 .help = "Rate follows Poisson process",
4180 },
4181 },
4182 .parent = "rate",
ff6bb260 4183 },
214e1eca 4184 {
6d428bcd
JA
4185 .name = "rate_cycle",
4186 .alias = "ratecycle",
e8b0e958 4187 .lname = "I/O rate cycle",
214e1eca 4188 .type = FIO_OPT_INT,
a609f12a 4189 .off1 = offsetof(struct thread_options, ratecycle),
214e1eca
JA
4190 .help = "Window average for rate limits (msec)",
4191 .def = "1000",
afdf9352 4192 .parent = "rate",
d71c154c 4193 .hide = 1,
e8b0e958
JA
4194 .category = FIO_OPT_C_IO,
4195 .group = FIO_OPT_G_RATE,
214e1eca 4196 },
1a9bf814
JA
4197 {
4198 .name = "rate_ignore_thinktime",
4199 .lname = "Rate ignore thinktime",
4200 .type = FIO_OPT_BOOL,
4201 .off1 = offsetof(struct thread_options, rate_ign_think),
4202 .help = "Rated IO ignores thinktime settings",
4203 .parent = "rate",
4204 .category = FIO_OPT_C_IO,
4205 .group = FIO_OPT_G_RATE,
4206 },
15501535
JA
4207 {
4208 .name = "max_latency",
dd97d866 4209 .lname = "Max Latency (usec)",
f7cf63bf
VR
4210 .type = FIO_OPT_ULL,
4211 .off1 = offsetof(struct thread_options, max_latency[DDIR_READ]),
4212 .off2 = offsetof(struct thread_options, max_latency[DDIR_WRITE]),
4213 .off3 = offsetof(struct thread_options, max_latency[DDIR_TRIM]),
15501535 4214 .help = "Maximum tolerated IO latency (usec)",
88038bc7 4215 .is_time = 1,
1e5324e7 4216 .category = FIO_OPT_C_IO,
3e260a46
JA
4217 .group = FIO_OPT_G_LATPROF,
4218 },
4219 {
4220 .name = "latency_target",
4221 .lname = "Latency Target (usec)",
4222 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 4223 .off1 = offsetof(struct thread_options, latency_target),
3e260a46 4224 .help = "Ramp to max queue depth supporting this latency",
88038bc7 4225 .is_time = 1,
3e260a46
JA
4226 .category = FIO_OPT_C_IO,
4227 .group = FIO_OPT_G_LATPROF,
4228 },
4229 {
4230 .name = "latency_window",
4231 .lname = "Latency Window (usec)",
4232 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 4233 .off1 = offsetof(struct thread_options, latency_window),
3e260a46 4234 .help = "Time to sustain latency_target",
88038bc7 4235 .is_time = 1,
3e260a46
JA
4236 .category = FIO_OPT_C_IO,
4237 .group = FIO_OPT_G_LATPROF,
4238 },
4239 {
4240 .name = "latency_percentile",
4241 .lname = "Latency Percentile",
4242 .type = FIO_OPT_FLOAT_LIST,
a609f12a 4243 .off1 = offsetof(struct thread_options, latency_percentile),
3e260a46
JA
4244 .help = "Percentile of IOs must be below latency_target",
4245 .def = "100",
4246 .maxlen = 1,
4247 .minfp = 0.0,
4248 .maxfp = 100.0,
4249 .category = FIO_OPT_C_IO,
4250 .group = FIO_OPT_G_LATPROF,
15501535 4251 },
e1bcd541
SL
4252 {
4253 .name = "latency_run",
4254 .lname = "Latency Run",
4255 .type = FIO_OPT_BOOL,
4256 .off1 = offsetof(struct thread_options, latency_run),
4257 .help = "Keep adjusting queue depth to match latency_target",
4258 .def = "0",
4259 .category = FIO_OPT_C_IO,
4260 .group = FIO_OPT_G_LATPROF,
4261 },
214e1eca
JA
4262 {
4263 .name = "invalidate",
e8b0e958 4264 .lname = "Cache invalidate",
214e1eca 4265 .type = FIO_OPT_BOOL,
a609f12a 4266 .off1 = offsetof(struct thread_options, invalidate_cache),
214e1eca
JA
4267 .help = "Invalidate buffer/page cache prior to running job",
4268 .def = "1",
e8b0e958 4269 .category = FIO_OPT_C_IO,
3ceb458f 4270 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
4271 },
4272 {
4273 .name = "sync",
e8b0e958 4274 .lname = "Synchronous I/O",
eb9f8d7f 4275 .type = FIO_OPT_STR,
a609f12a 4276 .off1 = offsetof(struct thread_options, sync_io),
eb9f8d7f
AF
4277 .help = "Use synchronous write IO",
4278 .def = "none",
d71c154c 4279 .hide = 1,
e8b0e958 4280 .category = FIO_OPT_C_IO,
3ceb458f 4281 .group = FIO_OPT_G_IO_TYPE,
eb9f8d7f
AF
4282 .posval = {
4283 { .ival = "none",
4284 .oval = 0,
4285 },
4286 { .ival = "0",
4287 .oval = 0,
4288 },
4289 { .ival = "sync",
4290 .oval = O_SYNC,
4291 },
4292 { .ival = "1",
4293 .oval = O_SYNC,
4294 },
4295#ifdef O_DSYNC
4296 { .ival = "dsync",
4297 .oval = O_DSYNC,
4298 },
4299#endif
4300 },
214e1eca 4301 },
ae8e559e
JA
4302#ifdef FIO_HAVE_WRITE_HINT
4303 {
4304 .name = "write_hint",
4305 .lname = "Write hint",
4306 .type = FIO_OPT_STR,
4307 .off1 = offsetof(struct thread_options, write_hint),
4308 .help = "Set expected write life time",
4309 .category = FIO_OPT_C_ENGINE,
4310 .group = FIO_OPT_G_INVALID,
4311 .posval = {
4312 { .ival = "none",
4313 .oval = RWH_WRITE_LIFE_NONE,
4314 },
4315 { .ival = "short",
4316 .oval = RWH_WRITE_LIFE_SHORT,
4317 },
4318 { .ival = "medium",
4319 .oval = RWH_WRITE_LIFE_MEDIUM,
4320 },
4321 { .ival = "long",
4322 .oval = RWH_WRITE_LIFE_LONG,
4323 },
4324 { .ival = "extreme",
4325 .oval = RWH_WRITE_LIFE_EXTREME,
4326 },
4327 },
4328 },
4329#endif
214e1eca
JA
4330 {
4331 .name = "create_serialize",
e8b0e958 4332 .lname = "Create serialize",
214e1eca 4333 .type = FIO_OPT_BOOL,
a609f12a 4334 .off1 = offsetof(struct thread_options, create_serialize),
c2b8035f 4335 .help = "Serialize creation of job files",
214e1eca 4336 .def = "1",
e8b0e958
JA
4337 .category = FIO_OPT_C_FILE,
4338 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4339 },
4340 {
4341 .name = "create_fsync",
e8b0e958 4342 .lname = "Create fsync",
214e1eca 4343 .type = FIO_OPT_BOOL,
a609f12a 4344 .off1 = offsetof(struct thread_options, create_fsync),
03e20d68 4345 .help = "fsync file after creation",
214e1eca 4346 .def = "1",
e8b0e958
JA
4347 .category = FIO_OPT_C_FILE,
4348 .group = FIO_OPT_G_INVALID,
214e1eca 4349 },
814452bd
JA
4350 {
4351 .name = "create_on_open",
e8b0e958 4352 .lname = "Create on open",
814452bd 4353 .type = FIO_OPT_BOOL,
a609f12a 4354 .off1 = offsetof(struct thread_options, create_on_open),
814452bd
JA
4355 .help = "Create files when they are opened for IO",
4356 .def = "0",
e8b0e958
JA
4357 .category = FIO_OPT_C_FILE,
4358 .group = FIO_OPT_G_INVALID,
814452bd 4359 },
25460cf6
JA
4360 {
4361 .name = "create_only",
cce2fdfe 4362 .lname = "Create Only",
25460cf6 4363 .type = FIO_OPT_BOOL,
a609f12a 4364 .off1 = offsetof(struct thread_options, create_only),
25460cf6 4365 .help = "Only perform file creation phase",
d17fda71 4366 .category = FIO_OPT_C_FILE,
25460cf6
JA
4367 .def = "0",
4368 },
2378826d
JA
4369 {
4370 .name = "allow_file_create",
e81ecca3 4371 .lname = "Allow file create",
2378826d 4372 .type = FIO_OPT_BOOL,
a609f12a 4373 .off1 = offsetof(struct thread_options, allow_create),
2378826d
JA
4374 .help = "Permit fio to create files, if they don't exist",
4375 .def = "1",
4376 .category = FIO_OPT_C_FILE,
4377 .group = FIO_OPT_G_FILENAME,
4378 },
e81ecca3
JA
4379 {
4380 .name = "allow_mounted_write",
4381 .lname = "Allow mounted write",
4382 .type = FIO_OPT_BOOL,
a609f12a 4383 .off1 = offsetof(struct thread_options, allow_mounted_write),
e81ecca3
JA
4384 .help = "Allow writes to a mounted partition",
4385 .def = "0",
4386 .category = FIO_OPT_C_FILE,
4387 .group = FIO_OPT_G_FILENAME,
4388 },
0b9d69ec 4389 {
afad68f7 4390 .name = "pre_read",
e8b0e958 4391 .lname = "Pre-read files",
afad68f7 4392 .type = FIO_OPT_BOOL,
a609f12a 4393 .off1 = offsetof(struct thread_options, pre_read),
03e20d68 4394 .help = "Pre-read files before starting official testing",
afad68f7 4395 .def = "0",
e8b0e958
JA
4396 .category = FIO_OPT_C_FILE,
4397 .group = FIO_OPT_G_INVALID,
afad68f7 4398 },
214e1eca
JA
4399#ifdef FIO_HAVE_CPU_AFFINITY
4400 {
4401 .name = "cpumask",
e8b0e958 4402 .lname = "CPU mask",
214e1eca
JA
4403 .type = FIO_OPT_INT,
4404 .cb = str_cpumask_cb,
a609f12a 4405 .off1 = offsetof(struct thread_options, cpumask),
214e1eca 4406 .help = "CPU affinity mask",
e8b0e958 4407 .category = FIO_OPT_C_GENERAL,
10860056 4408 .group = FIO_OPT_G_CRED,
214e1eca 4409 },
d2e268b0
JA
4410 {
4411 .name = "cpus_allowed",
e8b0e958 4412 .lname = "CPUs allowed",
d2e268b0
JA
4413 .type = FIO_OPT_STR,
4414 .cb = str_cpus_allowed_cb,
a609f12a 4415 .off1 = offsetof(struct thread_options, cpumask),
d2e268b0 4416 .help = "Set CPUs allowed",
e8b0e958 4417 .category = FIO_OPT_C_GENERAL,
10860056 4418 .group = FIO_OPT_G_CRED,
d2e268b0 4419 },
c2acfbac
JA
4420 {
4421 .name = "cpus_allowed_policy",
4422 .lname = "CPUs allowed distribution policy",
4423 .type = FIO_OPT_STR,
a609f12a 4424 .off1 = offsetof(struct thread_options, cpus_allowed_policy),
c2acfbac
JA
4425 .help = "Distribution policy for cpus_allowed",
4426 .parent = "cpus_allowed",
4427 .prio = 1,
4428 .posval = {
4429 { .ival = "shared",
4430 .oval = FIO_CPUS_SHARED,
4431 .help = "Mask shared between threads",
4432 },
4433 { .ival = "split",
4434 .oval = FIO_CPUS_SPLIT,
4435 .help = "Mask split between threads",
4436 },
4437 },
4438 .category = FIO_OPT_C_GENERAL,
4439 .group = FIO_OPT_G_CRED,
4440 },
a275c37a
JA
4441#else
4442 {
4443 .name = "cpumask",
4444 .lname = "CPU mask",
4445 .type = FIO_OPT_UNSUPPORTED,
4446 .help = "Your platform does not support CPU affinities",
4447 },
4448 {
4449 .name = "cpus_allowed",
4450 .lname = "CPUs allowed",
4451 .type = FIO_OPT_UNSUPPORTED,
4452 .help = "Your platform does not support CPU affinities",
4453 },
4454 {
4455 .name = "cpus_allowed_policy",
4456 .lname = "CPUs allowed distribution policy",
4457 .type = FIO_OPT_UNSUPPORTED,
4458 .help = "Your platform does not support CPU affinities",
4459 },
d0b937ed 4460#endif
67bf9823 4461#ifdef CONFIG_LIBNUMA
d0b937ed
YR
4462 {
4463 .name = "numa_cpu_nodes",
cce2fdfe 4464 .lname = "NUMA CPU Nodes",
d0b937ed
YR
4465 .type = FIO_OPT_STR,
4466 .cb = str_numa_cpunodes_cb,
a609f12a 4467 .off1 = offsetof(struct thread_options, numa_cpunodes),
d0b937ed 4468 .help = "NUMA CPU nodes bind",
6be54b2d
JA
4469 .category = FIO_OPT_C_GENERAL,
4470 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
4471 },
4472 {
4473 .name = "numa_mem_policy",
cce2fdfe 4474 .lname = "NUMA Memory Policy",
d0b937ed
YR
4475 .type = FIO_OPT_STR,
4476 .cb = str_numa_mpol_cb,
a609f12a 4477 .off1 = offsetof(struct thread_options, numa_memnodes),
d0b937ed 4478 .help = "NUMA memory policy setup",
6be54b2d
JA
4479 .category = FIO_OPT_C_GENERAL,
4480 .group = FIO_OPT_G_INVALID,
d0b937ed 4481 },
a275c37a
JA
4482#else
4483 {
4484 .name = "numa_cpu_nodes",
4485 .lname = "NUMA CPU Nodes",
4486 .type = FIO_OPT_UNSUPPORTED,
4487 .help = "Build fio with libnuma-dev(el) to enable this option",
4488 },
4489 {
4490 .name = "numa_mem_policy",
4491 .lname = "NUMA Memory Policy",
4492 .type = FIO_OPT_UNSUPPORTED,
4493 .help = "Build fio with libnuma-dev(el) to enable this option",
4494 },
03553853
YR
4495#endif
4496#ifdef CONFIG_CUDA
4497 {
4498 .name = "gpu_dev_id",
4499 .lname = "GPU device ID",
4500 .type = FIO_OPT_INT,
4501 .off1 = offsetof(struct thread_options, gpu_dev_id),
4502 .help = "Set GPU device ID for GPUDirect RDMA",
4503 .def = "0",
4504 .category = FIO_OPT_C_GENERAL,
4505 .group = FIO_OPT_G_INVALID,
4506 },
214e1eca
JA
4507#endif
4508 {
4509 .name = "end_fsync",
e8b0e958 4510 .lname = "End fsync",
214e1eca 4511 .type = FIO_OPT_BOOL,
a609f12a 4512 .off1 = offsetof(struct thread_options, end_fsync),
214e1eca
JA
4513 .help = "Include fsync at the end of job",
4514 .def = "0",
e8b0e958
JA
4515 .category = FIO_OPT_C_FILE,
4516 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4517 },
4518 {
4519 .name = "fsync_on_close",
e8b0e958 4520 .lname = "Fsync on close",
214e1eca 4521 .type = FIO_OPT_BOOL,
a609f12a 4522 .off1 = offsetof(struct thread_options, fsync_on_close),
214e1eca
JA
4523 .help = "fsync files on close",
4524 .def = "0",
e8b0e958
JA
4525 .category = FIO_OPT_C_FILE,
4526 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4527 },
4528 {
4529 .name = "unlink",
e8b0e958 4530 .lname = "Unlink file",
214e1eca 4531 .type = FIO_OPT_BOOL,
a609f12a 4532 .off1 = offsetof(struct thread_options, unlink),
214e1eca
JA
4533 .help = "Unlink created files after job has completed",
4534 .def = "0",
e8b0e958
JA
4535 .category = FIO_OPT_C_FILE,
4536 .group = FIO_OPT_G_INVALID,
214e1eca 4537 },
39c1c323 4538 {
4539 .name = "unlink_each_loop",
4540 .lname = "Unlink file after each loop of a job",
4541 .type = FIO_OPT_BOOL,
a609f12a 4542 .off1 = offsetof(struct thread_options, unlink_each_loop),
39c1c323 4543 .help = "Unlink created files after each loop in a job has completed",
4544 .def = "0",
4545 .category = FIO_OPT_C_FILE,
4546 .group = FIO_OPT_G_INVALID,
4547 },
214e1eca
JA
4548 {
4549 .name = "exitall",
e8b0e958 4550 .lname = "Exit-all on terminate",
214e1eca
JA
4551 .type = FIO_OPT_STR_SET,
4552 .cb = str_exitall_cb,
4553 .help = "Terminate all jobs when one exits",
e8b0e958 4554 .category = FIO_OPT_C_GENERAL,
a1f6afec 4555 .group = FIO_OPT_G_PROCESS,
214e1eca 4556 },
64402a8a
HW
4557 {
4558 .name = "exit_what",
4559 .lname = "What jobs to quit on terminate",
4560 .type = FIO_OPT_STR,
4561 .off1 = offsetof(struct thread_options, exit_what),
4562 .help = "Fine-grained control for exitall",
4563 .def = "group",
4564 .category = FIO_OPT_C_GENERAL,
4565 .group = FIO_OPT_G_PROCESS,
4566 .posval = {
4567 { .ival = "group",
4568 .oval = TERMINATE_GROUP,
4569 .help = "exit_all=1 default behaviour",
4570 },
4571 { .ival = "stonewall",
4572 .oval = TERMINATE_STONEWALL,
4573 .help = "quit all currently running jobs; continue with next stonewall",
4574 },
4575 { .ival = "all",
4576 .oval = TERMINATE_ALL,
4577 .help = "Quit everything",
4578 },
4579 },
4580 },
f9cafb12
JA
4581 {
4582 .name = "exitall_on_error",
4583 .lname = "Exit-all on terminate in error",
78abcf9b 4584 .type = FIO_OPT_STR_SET,
a609f12a 4585 .off1 = offsetof(struct thread_options, exitall_error),
f9cafb12
JA
4586 .help = "Terminate all jobs when one exits in error",
4587 .category = FIO_OPT_C_GENERAL,
4588 .group = FIO_OPT_G_PROCESS,
4589 },
214e1eca
JA
4590 {
4591 .name = "stonewall",
e8b0e958 4592 .lname = "Wait for previous",
d392365e 4593 .alias = "wait_for_previous",
214e1eca 4594 .type = FIO_OPT_STR_SET,
a609f12a 4595 .off1 = offsetof(struct thread_options, stonewall),
214e1eca 4596 .help = "Insert a hard barrier between this job and previous",
e8b0e958 4597 .category = FIO_OPT_C_GENERAL,
a1f6afec 4598 .group = FIO_OPT_G_PROCESS,
214e1eca 4599 },
b3d62a75
JA
4600 {
4601 .name = "new_group",
e8b0e958 4602 .lname = "New group",
b3d62a75 4603 .type = FIO_OPT_STR_SET,
a609f12a 4604 .off1 = offsetof(struct thread_options, new_group),
b3d62a75 4605 .help = "Mark the start of a new group (for reporting)",
e8b0e958 4606 .category = FIO_OPT_C_GENERAL,
a1f6afec 4607 .group = FIO_OPT_G_PROCESS,
b3d62a75 4608 },
214e1eca
JA
4609 {
4610 .name = "thread",
e8b0e958 4611 .lname = "Thread",
214e1eca 4612 .type = FIO_OPT_STR_SET,
a609f12a 4613 .off1 = offsetof(struct thread_options, use_thread),
20eb06bd 4614 .help = "Use threads instead of processes",
c8931876
JA
4615#ifdef CONFIG_NO_SHM
4616 .def = "1",
4617 .no_warn_def = 1,
4618#endif
e8b0e958 4619 .category = FIO_OPT_C_GENERAL,
a1f6afec 4620 .group = FIO_OPT_G_PROCESS,
214e1eca 4621 },
3a5db920
JA
4622 {
4623 .name = "per_job_logs",
cce2fdfe 4624 .lname = "Per Job Logs",
3a5db920 4625 .type = FIO_OPT_BOOL,
a609f12a 4626 .off1 = offsetof(struct thread_options, per_job_logs),
3a5db920
JA
4627 .help = "Include job number in generated log files or not",
4628 .def = "1",
4629 .category = FIO_OPT_C_LOG,
4630 .group = FIO_OPT_G_INVALID,
4631 },
214e1eca
JA
4632 {
4633 .name = "write_bw_log",
e8b0e958 4634 .lname = "Write bandwidth log",
dded427c 4635 .type = FIO_OPT_STR,
a609f12a 4636 .off1 = offsetof(struct thread_options, bw_log_file),
dded427c 4637 .cb = str_write_bw_log_cb,
214e1eca 4638 .help = "Write log of bandwidth during run",
e8b0e958
JA
4639 .category = FIO_OPT_C_LOG,
4640 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4641 },
4642 {
4643 .name = "write_lat_log",
e8b0e958 4644 .lname = "Write latency log",
dded427c 4645 .type = FIO_OPT_STR,
a609f12a 4646 .off1 = offsetof(struct thread_options, lat_log_file),
dded427c 4647 .cb = str_write_lat_log_cb,
214e1eca 4648 .help = "Write log of latency during run",
e8b0e958
JA
4649 .category = FIO_OPT_C_LOG,
4650 .group = FIO_OPT_G_INVALID,
214e1eca 4651 },
c8eeb9df
JA
4652 {
4653 .name = "write_iops_log",
e8b0e958 4654 .lname = "Write IOPS log",
dded427c 4655 .type = FIO_OPT_STR,
a609f12a 4656 .off1 = offsetof(struct thread_options, iops_log_file),
dded427c 4657 .cb = str_write_iops_log_cb,
c8eeb9df 4658 .help = "Write log of IOPS during run",
e8b0e958
JA
4659 .category = FIO_OPT_C_LOG,
4660 .group = FIO_OPT_G_INVALID,
c8eeb9df 4661 },
0a852a50
DLM
4662 {
4663 .name = "log_entries",
4664 .lname = "Log entries",
4665 .type = FIO_OPT_INT,
4666 .off1 = offsetof(struct thread_options, log_entries),
4667 .help = "Initial number of entries in a job IO log",
4668 .def = __fio_stringify(DEF_LOG_ENTRIES),
4669 .minval = DEF_LOG_ENTRIES,
4670 .maxval = MAX_LOG_ENTRIES,
4671 .category = FIO_OPT_C_LOG,
4672 .group = FIO_OPT_G_INVALID,
4673 },
b8bc8cba
JA
4674 {
4675 .name = "log_avg_msec",
e8b0e958 4676 .lname = "Log averaging (msec)",
b8bc8cba 4677 .type = FIO_OPT_INT,
a609f12a 4678 .off1 = offsetof(struct thread_options, log_avg_msec),
b8bc8cba
JA
4679 .help = "Average bw/iops/lat logs over this period of time",
4680 .def = "0",
e8b0e958 4681 .category = FIO_OPT_C_LOG,
1e613c9c
KC
4682 .group = FIO_OPT_G_INVALID,
4683 },
4684 {
4685 .name = "log_hist_msec",
4686 .lname = "Log histograms (msec)",
4687 .type = FIO_OPT_INT,
a609f12a 4688 .off1 = offsetof(struct thread_options, log_hist_msec),
1e613c9c
KC
4689 .help = "Dump completion latency histograms at frequency of this time value",
4690 .def = "0",
4691 .category = FIO_OPT_C_LOG,
4692 .group = FIO_OPT_G_INVALID,
4693 },
4694 {
4695 .name = "log_hist_coarseness",
4696 .lname = "Histogram logs coarseness",
4697 .type = FIO_OPT_INT,
a609f12a 4698 .off1 = offsetof(struct thread_options, log_hist_coarseness),
1e613c9c
KC
4699 .help = "Integer in range [0,6]. Higher coarseness outputs"
4700 " fewer histogram bins per sample. The number of bins for"
4701 " these are [1216, 608, 304, 152, 76, 38, 19] respectively.",
4702 .def = "0",
4703 .category = FIO_OPT_C_LOG,
4704 .group = FIO_OPT_G_INVALID,
4705 },
4706 {
4707 .name = "write_hist_log",
4708 .lname = "Write latency histogram logs",
dded427c 4709 .type = FIO_OPT_STR,
a609f12a 4710 .off1 = offsetof(struct thread_options, hist_log_file),
dded427c 4711 .cb = str_write_hist_log_cb,
1e613c9c
KC
4712 .help = "Write log of latency histograms during run",
4713 .category = FIO_OPT_C_LOG,
e8b0e958 4714 .group = FIO_OPT_G_INVALID,
b8bc8cba 4715 },
e6989e10 4716 {
0e14633c
AK
4717 .name = "log_window_value",
4718 .alias = "log_max_value",
4719 .lname = "Log maximum, average or both values",
4720 .type = FIO_OPT_STR,
a609f12a 4721 .off1 = offsetof(struct thread_options, log_max),
0e14633c
AK
4722 .help = "Log max, average or both sample in a window",
4723 .def = "avg",
e6989e10
JA
4724 .category = FIO_OPT_C_LOG,
4725 .group = FIO_OPT_G_INVALID,
0e14633c
AK
4726 .posval = {
4727 { .ival = "avg",
4728 .oval = IO_LOG_SAMPLE_AVG,
4729 .help = "Log average value over the window",
4730 },
4731 { .ival = "max",
4732 .oval = IO_LOG_SAMPLE_MAX,
4733 .help = "Log maximum value in the window",
4734 },
4735 { .ival = "both",
4736 .oval = IO_LOG_SAMPLE_BOTH,
4737 .help = "Log both average and maximum values over the window"
4738 },
4739 /* Compatibility with former boolean values */
4740 { .ival = "0",
4741 .oval = IO_LOG_SAMPLE_AVG,
4742 .help = "Alias for 'avg'",
4743 },
4744 { .ival = "1",
4745 .oval = IO_LOG_SAMPLE_MAX,
4746 .help = "Alias for 'max'",
4747 },
4748 },
e6989e10 4749 },
ae588852
JA
4750 {
4751 .name = "log_offset",
4752 .lname = "Log offset of IO",
4753 .type = FIO_OPT_BOOL,
a609f12a 4754 .off1 = offsetof(struct thread_options, log_offset),
ae588852
JA
4755 .help = "Include offset of IO for each log entry",
4756 .def = "0",
4757 .category = FIO_OPT_C_LOG,
4758 .group = FIO_OPT_G_INVALID,
4759 },
03ec570f
DLM
4760 {
4761 .name = "log_prio",
4762 .lname = "Log priority of IO",
4763 .type = FIO_OPT_BOOL,
4764 .off1 = offsetof(struct thread_options, log_prio),
4765 .help = "Include priority value of IO for each log entry",
4766 .def = "0",
4767 .category = FIO_OPT_C_LOG,
4768 .group = FIO_OPT_G_INVALID,
4769 },
14d3134a
SK
4770 {
4771 .name = "log_issue_time",
4772 .lname = "Log IO issue time",
4773 .type = FIO_OPT_BOOL,
4774 .off1 = offsetof(struct thread_options, log_issue_time),
4775 .help = "Include IO issue time for each log entry",
4776 .def = "0",
4777 .category = FIO_OPT_C_LOG,
4778 .group = FIO_OPT_G_INVALID,
4779 },
aee2ab67
JA
4780#ifdef CONFIG_ZLIB
4781 {
4782 .name = "log_compression",
4783 .lname = "Log compression",
4784 .type = FIO_OPT_INT,
a609f12a 4785 .off1 = offsetof(struct thread_options, log_gz),
aee2ab67 4786 .help = "Log in compressed chunks of this size",
9919b27b 4787 .minval = 1024ULL,
aee2ab67
JA
4788 .maxval = 512 * 1024 * 1024ULL,
4789 .category = FIO_OPT_C_LOG,
4790 .group = FIO_OPT_G_INVALID,
4791 },
c08f9fe2
JA
4792#ifdef FIO_HAVE_CPU_AFFINITY
4793 {
4794 .name = "log_compression_cpus",
4795 .lname = "Log Compression CPUs",
4796 .type = FIO_OPT_STR,
4797 .cb = str_log_cpus_allowed_cb,
a609f12a 4798 .off1 = offsetof(struct thread_options, log_gz_cpumask),
c08f9fe2
JA
4799 .parent = "log_compression",
4800 .help = "Limit log compression to these CPUs",
4801 .category = FIO_OPT_C_LOG,
4802 .group = FIO_OPT_G_INVALID,
4803 },
a275c37a
JA
4804#else
4805 {
4806 .name = "log_compression_cpus",
4807 .lname = "Log Compression CPUs",
4808 .type = FIO_OPT_UNSUPPORTED,
4809 .help = "Your platform does not support CPU affinities",
4810 },
c08f9fe2 4811#endif
b26317c9
JA
4812 {
4813 .name = "log_store_compressed",
4814 .lname = "Log store compressed",
4815 .type = FIO_OPT_BOOL,
a609f12a 4816 .off1 = offsetof(struct thread_options, log_gz_store),
b26317c9
JA
4817 .help = "Store logs in a compressed format",
4818 .category = FIO_OPT_C_LOG,
4819 .group = FIO_OPT_G_INVALID,
4820 },
a275c37a
JA
4821#else
4822 {
4823 .name = "log_compression",
4824 .lname = "Log compression",
4825 .type = FIO_OPT_UNSUPPORTED,
4826 .help = "Install libz-dev(el) to get compression support",
4827 },
4828 {
4829 .name = "log_store_compressed",
4830 .lname = "Log store compressed",
4831 .type = FIO_OPT_UNSUPPORTED,
4832 .help = "Install libz-dev(el) to get compression support",
4833 },
aee2ab67 4834#endif
d5b3cfd4 4835 {
4836 .name = "log_alternate_epoch",
d252275b 4837 .alias = "log_unix_epoch",
d5b3cfd4 4838 .lname = "Log epoch alternate",
4839 .type = FIO_OPT_BOOL,
4840 .off1 = offsetof(struct thread_options, log_alternate_epoch),
4841 .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.",
4842 .category = FIO_OPT_C_LOG,
4843 .group = FIO_OPT_G_INVALID,
4844 },
4845 {
4846 .name = "log_alternate_epoch_clock_id",
4847 .lname = "Log alternate epoch clock_id",
4848 .type = FIO_OPT_INT,
4849 .off1 = offsetof(struct thread_options, log_alternate_epoch_clock_id),
d252275b 4850 .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 4851 .category = FIO_OPT_C_LOG,
4852 .group = FIO_OPT_G_INVALID,
4853 },
66347cfa
DE
4854 {
4855 .name = "block_error_percentiles",
4856 .lname = "Block error percentiles",
4857 .type = FIO_OPT_BOOL,
a609f12a 4858 .off1 = offsetof(struct thread_options, block_error_hist),
66347cfa
DE
4859 .help = "Record trim block errors and make a histogram",
4860 .def = "0",
4861 .category = FIO_OPT_C_LOG,
4862 .group = FIO_OPT_G_INVALID,
4863 },
c504ee55
JA
4864 {
4865 .name = "bwavgtime",
4866 .lname = "Bandwidth average time",
4867 .type = FIO_OPT_INT,
a609f12a 4868 .off1 = offsetof(struct thread_options, bw_avg_time),
c504ee55
JA
4869 .help = "Time window over which to calculate bandwidth"
4870 " (msec)",
4871 .def = "500",
4872 .parent = "write_bw_log",
4873 .hide = 1,
4874 .interval = 100,
4875 .category = FIO_OPT_C_LOG,
4876 .group = FIO_OPT_G_INVALID,
4877 },
4878 {
4879 .name = "iopsavgtime",
4880 .lname = "IOPS average time",
4881 .type = FIO_OPT_INT,
a609f12a 4882 .off1 = offsetof(struct thread_options, iops_avg_time),
c504ee55
JA
4883 .help = "Time window over which to calculate IOPS (msec)",
4884 .def = "500",
4885 .parent = "write_iops_log",
4886 .hide = 1,
4887 .interval = 100,
4888 .category = FIO_OPT_C_LOG,
4889 .group = FIO_OPT_G_INVALID,
4890 },
214e1eca
JA
4891 {
4892 .name = "group_reporting",
e8b0e958 4893 .lname = "Group reporting",
d2507043 4894 .type = FIO_OPT_STR_SET,
a609f12a 4895 .off1 = offsetof(struct thread_options, group_reporting),
214e1eca 4896 .help = "Do reporting on a per-group basis",
10860056 4897 .category = FIO_OPT_C_STAT,
e8b0e958 4898 .group = FIO_OPT_G_INVALID,
214e1eca 4899 },
8243be59
JA
4900 {
4901 .name = "stats",
4902 .lname = "Stats",
4903 .type = FIO_OPT_BOOL,
4904 .off1 = offsetof(struct thread_options, stats),
4905 .help = "Enable collection of stats",
4906 .def = "1",
4907 .category = FIO_OPT_C_STAT,
4908 .group = FIO_OPT_G_INVALID,
4909 },
e9459e5a
JA
4910 {
4911 .name = "zero_buffers",
e8b0e958 4912 .lname = "Zero I/O buffers",
e9459e5a 4913 .type = FIO_OPT_STR_SET,
a609f12a 4914 .off1 = offsetof(struct thread_options, zero_buffers),
e9459e5a 4915 .help = "Init IO buffers to all zeroes",
e8b0e958 4916 .category = FIO_OPT_C_IO,
3ceb458f 4917 .group = FIO_OPT_G_IO_BUF,
e9459e5a 4918 },
5973cafb
JA
4919 {
4920 .name = "refill_buffers",
e8b0e958 4921 .lname = "Refill I/O buffers",
5973cafb 4922 .type = FIO_OPT_STR_SET,
a609f12a 4923 .off1 = offsetof(struct thread_options, refill_buffers),
5973cafb 4924 .help = "Refill IO buffers on every IO submit",
e8b0e958 4925 .category = FIO_OPT_C_IO,
3ceb458f 4926 .group = FIO_OPT_G_IO_BUF,
5973cafb 4927 },
fd68418e
JA
4928 {
4929 .name = "scramble_buffers",
e8b0e958 4930 .lname = "Scramble I/O buffers",
fd68418e 4931 .type = FIO_OPT_BOOL,
a609f12a 4932 .off1 = offsetof(struct thread_options, scramble_buffers),
fd68418e
JA
4933 .help = "Slightly scramble buffers on every IO submit",
4934 .def = "1",
e8b0e958 4935 .category = FIO_OPT_C_IO,
3ceb458f 4936 .group = FIO_OPT_G_IO_BUF,
fd68418e 4937 },
ce35b1ec
JA
4938 {
4939 .name = "buffer_pattern",
4940 .lname = "Buffer pattern",
4941 .type = FIO_OPT_STR,
4942 .cb = str_buffer_pattern_cb,
a609f12a 4943 .off1 = offsetof(struct thread_options, buffer_pattern),
ce35b1ec
JA
4944 .help = "Fill pattern for IO buffers",
4945 .category = FIO_OPT_C_IO,
4946 .group = FIO_OPT_G_IO_BUF,
4947 },
9c42684e
JA
4948 {
4949 .name = "buffer_compress_percentage",
e8b0e958 4950 .lname = "Buffer compression percentage",
9c42684e 4951 .type = FIO_OPT_INT,
bedc9dc2 4952 .cb = str_buffer_compress_cb,
a609f12a 4953 .off1 = offsetof(struct thread_options, compress_percentage),
9c42684e 4954 .maxval = 100,
e7f5de90 4955 .minval = 0,
9c42684e 4956 .help = "How compressible the buffer is (approximately)",
20eb06bd 4957 .interval = 5,
e8b0e958 4958 .category = FIO_OPT_C_IO,
3ceb458f 4959 .group = FIO_OPT_G_IO_BUF,
9c42684e 4960 },
f97a43a1
JA
4961 {
4962 .name = "buffer_compress_chunk",
e8b0e958 4963 .lname = "Buffer compression chunk size",
f97a43a1 4964 .type = FIO_OPT_INT,
a609f12a 4965 .off1 = offsetof(struct thread_options, compress_chunk),
207b18e4 4966 .parent = "buffer_compress_percentage",
d71c154c 4967 .hide = 1,
f97a43a1 4968 .help = "Size of compressible region in buffer",
1de80624 4969 .def = "512",
20eb06bd 4970 .interval = 256,
e8b0e958 4971 .category = FIO_OPT_C_IO,
3ceb458f 4972 .group = FIO_OPT_G_IO_BUF,
f97a43a1 4973 },
5c94b008
JA
4974 {
4975 .name = "dedupe_percentage",
4976 .lname = "Dedupe percentage",
4977 .type = FIO_OPT_INT,
4978 .cb = str_dedupe_cb,
a609f12a 4979 .off1 = offsetof(struct thread_options, dedupe_percentage),
5c94b008
JA
4980 .maxval = 100,
4981 .minval = 0,
4982 .help = "Percentage of buffers that are dedupable",
4983 .interval = 1,
4984 .category = FIO_OPT_C_IO,
4985 .group = FIO_OPT_G_IO_BUF,
4986 },
c49cfc76
BD
4987 {
4988 .name = "dedupe_global",
4989 .lname = "Global deduplication",
4990 .type = FIO_OPT_BOOL,
4991 .off1 = offsetof(struct thread_options, dedupe_global),
4992 .help = "Share deduplication buffers across jobs",
4993 .def = "0",
4994 .category = FIO_OPT_C_IO,
4995 .group = FIO_OPT_G_IO_BUF,
4996 },
0d71aa98
BD
4997 {
4998 .name = "dedupe_mode",
4999 .lname = "Dedupe mode",
5000 .help = "Mode for the deduplication buffer generation",
5001 .type = FIO_OPT_STR,
5002 .off1 = offsetof(struct thread_options, dedupe_mode),
5003 .parent = "dedupe_percentage",
5004 .def = "repeat",
5005 .category = FIO_OPT_C_IO,
5006 .group = FIO_OPT_G_IO_BUF,
5007 .posval = {
5008 { .ival = "repeat",
5009 .oval = DEDUPE_MODE_REPEAT,
5010 .help = "repeat previous page",
5011 },
5012 { .ival = "working_set",
5013 .oval = DEDUPE_MODE_WORKING_SET,
5014 .help = "choose a page randomly from limited working set defined in dedupe_working_set_percentage",
5015 },
5016 },
5017 },
5018 {
5019 .name = "dedupe_working_set_percentage",
5020 .lname = "Dedupe working set percentage",
5021 .help = "Dedupe working set size in percentages from file or device size used to generate dedupe patterns from",
5022 .type = FIO_OPT_INT,
5023 .off1 = offsetof(struct thread_options, dedupe_working_set_percentage),
5024 .parent = "dedupe_percentage",
5025 .def = "5",
5026 .maxval = 100,
5027 .minval = 0,
5028 .category = FIO_OPT_C_IO,
5029 .group = FIO_OPT_G_IO_BUF,
5030 },
83349190
YH
5031 {
5032 .name = "clat_percentiles",
e8b0e958 5033 .lname = "Completion latency percentiles",
83349190 5034 .type = FIO_OPT_BOOL,
a609f12a 5035 .off1 = offsetof(struct thread_options, clat_percentiles),
83349190 5036 .help = "Enable the reporting of completion latency percentiles",
467b35ed 5037 .def = "1",
b599759b
JA
5038 .category = FIO_OPT_C_STAT,
5039 .group = FIO_OPT_G_INVALID,
5040 },
5041 {
5042 .name = "lat_percentiles",
5043 .lname = "IO latency percentiles",
5044 .type = FIO_OPT_BOOL,
5045 .off1 = offsetof(struct thread_options, lat_percentiles),
5046 .help = "Enable the reporting of IO latency percentiles",
5047 .def = "0",
56440e63
VF
5048 .category = FIO_OPT_C_STAT,
5049 .group = FIO_OPT_G_INVALID,
5050 },
5051 {
5052 .name = "slat_percentiles",
5053 .lname = "Submission latency percentiles",
5054 .type = FIO_OPT_BOOL,
5055 .off1 = offsetof(struct thread_options, slat_percentiles),
5056 .help = "Enable the reporting of submission latency percentiles",
5057 .def = "0",
e8b0e958
JA
5058 .category = FIO_OPT_C_STAT,
5059 .group = FIO_OPT_G_INVALID,
83349190
YH
5060 },
5061 {
5062 .name = "percentile_list",
66347cfa 5063 .lname = "Percentile list",
83349190 5064 .type = FIO_OPT_FLOAT_LIST,
a609f12a
JA
5065 .off1 = offsetof(struct thread_options, percentile_list),
5066 .off2 = offsetof(struct thread_options, percentile_precision),
66347cfa
DE
5067 .help = "Specify a custom list of percentiles to report for "
5068 "completion latency and block errors",
fd112d34 5069 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
5070 .maxlen = FIO_IO_U_LIST_MAX_LEN,
5071 .minfp = 0.0,
5072 .maxfp = 100.0,
e8b0e958
JA
5073 .category = FIO_OPT_C_STAT,
5074 .group = FIO_OPT_G_INVALID,
e883cb35
JF
5075 },
5076 {
5077 .name = "significant_figures",
5078 .lname = "Significant figures",
5079 .type = FIO_OPT_INT,
5080 .off1 = offsetof(struct thread_options, sig_figs),
5081 .maxval = 10,
5082 .minval = 1,
5083 .help = "Significant figures for output-format set to normal",
5084 .def = "4",
5085 .interval = 1,
5086 .category = FIO_OPT_C_STAT,
5087 .group = FIO_OPT_G_INVALID,
83349190
YH
5088 },
5089
0a839f30
JA
5090#ifdef FIO_HAVE_DISK_UTIL
5091 {
5092 .name = "disk_util",
e8b0e958 5093 .lname = "Disk utilization",
0a839f30 5094 .type = FIO_OPT_BOOL,
a609f12a 5095 .off1 = offsetof(struct thread_options, do_disk_util),
f66ab3c8 5096 .help = "Log disk utilization statistics",
0a839f30 5097 .def = "1",
e8b0e958
JA
5098 .category = FIO_OPT_C_STAT,
5099 .group = FIO_OPT_G_INVALID,
0a839f30 5100 },
a275c37a
JA
5101#else
5102 {
5103 .name = "disk_util",
5104 .lname = "Disk utilization",
5105 .type = FIO_OPT_UNSUPPORTED,
5106 .help = "Your platform does not support disk utilization",
5107 },
0a839f30 5108#endif
993bf48b
JA
5109 {
5110 .name = "gtod_reduce",
e8b0e958 5111 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
5112 .type = FIO_OPT_BOOL,
5113 .help = "Greatly reduce number of gettimeofday() calls",
5114 .cb = str_gtod_reduce_cb,
5115 .def = "0",
a4ed77fe 5116 .hide_on_set = 1,
e8b0e958
JA
5117 .category = FIO_OPT_C_STAT,
5118 .group = FIO_OPT_G_INVALID,
993bf48b 5119 },
02af0988
JA
5120 {
5121 .name = "disable_lat",
e8b0e958 5122 .lname = "Disable all latency stats",
02af0988 5123 .type = FIO_OPT_BOOL,
a609f12a 5124 .off1 = offsetof(struct thread_options, disable_lat),
02af0988
JA
5125 .help = "Disable latency numbers",
5126 .parent = "gtod_reduce",
d71c154c 5127 .hide = 1,
02af0988 5128 .def = "0",
e8b0e958
JA
5129 .category = FIO_OPT_C_STAT,
5130 .group = FIO_OPT_G_INVALID,
02af0988 5131 },
9520ebb9
JA
5132 {
5133 .name = "disable_clat",
e8b0e958 5134 .lname = "Disable completion latency stats",
9520ebb9 5135 .type = FIO_OPT_BOOL,
a609f12a 5136 .off1 = offsetof(struct thread_options, disable_clat),
9520ebb9 5137 .help = "Disable completion latency numbers",
993bf48b 5138 .parent = "gtod_reduce",
d71c154c 5139 .hide = 1,
9520ebb9 5140 .def = "0",
e8b0e958
JA
5141 .category = FIO_OPT_C_STAT,
5142 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
5143 },
5144 {
5145 .name = "disable_slat",
e8b0e958 5146 .lname = "Disable submission latency stats",
9520ebb9 5147 .type = FIO_OPT_BOOL,
a609f12a 5148 .off1 = offsetof(struct thread_options, disable_slat),
03e20d68 5149 .help = "Disable submission latency numbers",
993bf48b 5150 .parent = "gtod_reduce",
d71c154c 5151 .hide = 1,
9520ebb9 5152 .def = "0",
e8b0e958
JA
5153 .category = FIO_OPT_C_STAT,
5154 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
5155 },
5156 {
5157 .name = "disable_bw_measurement",
afd2ceff 5158 .alias = "disable_bw",
e8b0e958 5159 .lname = "Disable bandwidth stats",
9520ebb9 5160 .type = FIO_OPT_BOOL,
a609f12a 5161 .off1 = offsetof(struct thread_options, disable_bw),
9520ebb9 5162 .help = "Disable bandwidth logging",
993bf48b 5163 .parent = "gtod_reduce",
d71c154c 5164 .hide = 1,
9520ebb9 5165 .def = "0",
e8b0e958
JA
5166 .category = FIO_OPT_C_STAT,
5167 .group = FIO_OPT_G_INVALID,
9520ebb9 5168 },
be4ecfdf
JA
5169 {
5170 .name = "gtod_cpu",
e8b0e958 5171 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 5172 .type = FIO_OPT_INT,
a609f12a 5173 .off1 = offsetof(struct thread_options, gtod_cpu),
03e20d68 5174 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 5175 .verify = gtod_cpu_verify,
e8b0e958 5176 .category = FIO_OPT_C_GENERAL,
10860056 5177 .group = FIO_OPT_G_CLOCK,
be4ecfdf 5178 },
12d325ca 5179 {
5180 .name = "job_start_clock_id",
5181 .lname = "Job start clock_id",
5182 .type = FIO_OPT_INT,
5183 .off1 = offsetof(struct thread_options, job_start_clock_id),
5184 .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",
5185 .verify = gtod_cpu_verify,
5186 .category = FIO_OPT_C_GENERAL,
5187 .group = FIO_OPT_G_CLOCK,
5188 },
771e58be
JA
5189 {
5190 .name = "unified_rw_reporting",
cce2fdfe 5191 .lname = "Unified RW Reporting",
5cb8a8cd 5192 .type = FIO_OPT_STR,
a609f12a 5193 .off1 = offsetof(struct thread_options, unified_rw_rep),
771e58be 5194 .help = "Unify reporting across data direction",
5cb8a8cd 5195 .def = "none",
90b7a96d
JA
5196 .category = FIO_OPT_C_GENERAL,
5197 .group = FIO_OPT_G_INVALID,
5cb8a8cd
BP
5198 .posval = {
5199 { .ival = "none",
5200 .oval = UNIFIED_SPLIT,
5201 .help = "Normal statistics reporting",
5202 },
5203 { .ival = "mixed",
5204 .oval = UNIFIED_MIXED,
5205 .help = "Statistics are summed per data direction and reported together",
5206 },
5207 { .ival = "both",
5208 .oval = UNIFIED_BOTH,
5209 .help = "Statistics are reported normally, followed by the mixed statistics"
5210 },
5211 /* Compatibility with former boolean values */
5212 { .ival = "0",
5213 .oval = UNIFIED_SPLIT,
5214 .help = "Alias for 'none'",
5215 },
5216 { .ival = "1",
5217 .oval = UNIFIED_MIXED,
5218 .help = "Alias for 'mixed'",
5219 },
5220 { .ival = "2",
5221 .oval = UNIFIED_BOTH,
5222 .help = "Alias for 'both'",
5223 },
5224 },
771e58be 5225 },
f2bba182
RR
5226 {
5227 .name = "continue_on_error",
e8b0e958 5228 .lname = "Continue on error",
06842027 5229 .type = FIO_OPT_STR,
a609f12a 5230 .off1 = offsetof(struct thread_options, continue_on_error),
03e20d68 5231 .help = "Continue on non-fatal errors during IO",
06842027 5232 .def = "none",
e8b0e958 5233 .category = FIO_OPT_C_GENERAL,
bc3f552f 5234 .group = FIO_OPT_G_ERR,
06842027
SL
5235 .posval = {
5236 { .ival = "none",
5237 .oval = ERROR_TYPE_NONE,
5238 .help = "Exit when an error is encountered",
5239 },
5240 { .ival = "read",
5241 .oval = ERROR_TYPE_READ,
5242 .help = "Continue on read errors only",
5243 },
5244 { .ival = "write",
5245 .oval = ERROR_TYPE_WRITE,
5246 .help = "Continue on write errors only",
5247 },
5248 { .ival = "io",
5249 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
5250 .help = "Continue on any IO errors",
5251 },
5252 { .ival = "verify",
5253 .oval = ERROR_TYPE_VERIFY,
5254 .help = "Continue on verify errors only",
5255 },
5256 { .ival = "all",
5257 .oval = ERROR_TYPE_ANY,
5258 .help = "Continue on all io and verify errors",
5259 },
5260 { .ival = "0",
5261 .oval = ERROR_TYPE_NONE,
5262 .help = "Alias for 'none'",
5263 },
5264 { .ival = "1",
5265 .oval = ERROR_TYPE_ANY,
5266 .help = "Alias for 'all'",
5267 },
5268 },
f2bba182 5269 },
8b28bd41
DM
5270 {
5271 .name = "ignore_error",
cce2fdfe 5272 .lname = "Ignore Error",
8b28bd41
DM
5273 .type = FIO_OPT_STR,
5274 .cb = str_ignore_error_cb,
a609f12a 5275 .off1 = offsetof(struct thread_options, ignore_error_nr),
8b28bd41
DM
5276 .help = "Set a specific list of errors to ignore",
5277 .parent = "rw",
a94eb99a 5278 .category = FIO_OPT_C_GENERAL,
bc3f552f 5279 .group = FIO_OPT_G_ERR,
8b28bd41
DM
5280 },
5281 {
5282 .name = "error_dump",
cce2fdfe 5283 .lname = "Error Dump",
8b28bd41 5284 .type = FIO_OPT_BOOL,
a609f12a 5285 .off1 = offsetof(struct thread_options, error_dump),
8b28bd41
DM
5286 .def = "0",
5287 .help = "Dump info on each error",
a94eb99a 5288 .category = FIO_OPT_C_GENERAL,
bc3f552f 5289 .group = FIO_OPT_G_ERR,
8b28bd41 5290 },
9ac8a797
JA
5291 {
5292 .name = "profile",
e8b0e958 5293 .lname = "Profile",
79d16311 5294 .type = FIO_OPT_STR_STORE,
a609f12a 5295 .off1 = offsetof(struct thread_options, profile),
9ac8a797 5296 .help = "Select a specific builtin performance test",
13fca827 5297 .category = FIO_OPT_C_PROFILE,
e8b0e958 5298 .group = FIO_OPT_G_INVALID,
9ac8a797 5299 },
a696fa2a
JA
5300 {
5301 .name = "cgroup",
e8b0e958 5302 .lname = "Cgroup",
a696fa2a 5303 .type = FIO_OPT_STR_STORE,
a609f12a 5304 .off1 = offsetof(struct thread_options, cgroup),
a696fa2a 5305 .help = "Add job to cgroup of this name",
e8b0e958 5306 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
5307 .group = FIO_OPT_G_CGROUP,
5308 },
5309 {
5310 .name = "cgroup_nodelete",
5311 .lname = "Cgroup no-delete",
5312 .type = FIO_OPT_BOOL,
a609f12a 5313 .off1 = offsetof(struct thread_options, cgroup_nodelete),
a1f6afec
JA
5314 .help = "Do not delete cgroups after job completion",
5315 .def = "0",
5316 .parent = "cgroup",
5317 .category = FIO_OPT_C_GENERAL,
5318 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
5319 },
5320 {
5321 .name = "cgroup_weight",
e8b0e958 5322 .lname = "Cgroup weight",
a696fa2a 5323 .type = FIO_OPT_INT,
a609f12a 5324 .off1 = offsetof(struct thread_options, cgroup_weight),
a696fa2a
JA
5325 .help = "Use given weight for cgroup",
5326 .minval = 100,
5327 .maxval = 1000,
a1f6afec 5328 .parent = "cgroup",
e8b0e958 5329 .category = FIO_OPT_C_GENERAL,
a1f6afec 5330 .group = FIO_OPT_G_CGROUP,
7de87099 5331 },
e0b0d892
JA
5332 {
5333 .name = "uid",
e8b0e958 5334 .lname = "User ID",
e0b0d892 5335 .type = FIO_OPT_INT,
a609f12a 5336 .off1 = offsetof(struct thread_options, uid),
e0b0d892 5337 .help = "Run job with this user ID",
e8b0e958 5338 .category = FIO_OPT_C_GENERAL,
10860056 5339 .group = FIO_OPT_G_CRED,
e0b0d892
JA
5340 },
5341 {
5342 .name = "gid",
e8b0e958 5343 .lname = "Group ID",
e0b0d892 5344 .type = FIO_OPT_INT,
a609f12a 5345 .off1 = offsetof(struct thread_options, gid),
e0b0d892 5346 .help = "Run job with this group ID",
e8b0e958 5347 .category = FIO_OPT_C_GENERAL,
10860056 5348 .group = FIO_OPT_G_CRED,
e0b0d892 5349 },
a1f6afec
JA
5350 {
5351 .name = "kb_base",
5352 .lname = "KB Base",
41dd12d6 5353 .type = FIO_OPT_STR,
a609f12a 5354 .off1 = offsetof(struct thread_options, kb_base),
a1f6afec
JA
5355 .prio = 1,
5356 .def = "1024",
ba9c7219
JA
5357 .posval = {
5358 { .ival = "1024",
5359 .oval = 1024,
d694a6a7 5360 .help = "Inputs invert IEC and SI prefixes (for compatibility); outputs prefer binary",
ba9c7219
JA
5361 },
5362 { .ival = "1000",
5363 .oval = 1000,
d694a6a7 5364 .help = "Inputs use IEC and SI prefixes; outputs prefer SI",
ba9c7219
JA
5365 },
5366 },
d694a6a7 5367 .help = "Unit prefix interpretation for quantities of data (IEC and SI)",
a1f6afec
JA
5368 .category = FIO_OPT_C_GENERAL,
5369 .group = FIO_OPT_G_INVALID,
5370 },
cf3a0518
JA
5371 {
5372 .name = "unit_base",
d694a6a7 5373 .lname = "Unit for quantities of data (Bits or Bytes)",
92a1a1d7 5374 .type = FIO_OPT_STR,
a609f12a 5375 .off1 = offsetof(struct thread_options, unit_base),
cf3a0518 5376 .prio = 1,
71a08258
JA
5377 .posval = {
5378 { .ival = "0",
41a87019 5379 .oval = N2S_NONE,
71a08258
JA
5380 .help = "Auto-detect",
5381 },
5382 { .ival = "8",
41a87019 5383 .oval = N2S_BYTEPERSEC,
71a08258
JA
5384 .help = "Normal (byte based)",
5385 },
5386 { .ival = "1",
41a87019 5387 .oval = N2S_BITPERSEC,
71a08258
JA
5388 .help = "Bit based",
5389 },
5390 },
cf3a0518
JA
5391 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
5392 .category = FIO_OPT_C_GENERAL,
5393 .group = FIO_OPT_G_INVALID,
5394 },
3ceb458f
JA
5395 {
5396 .name = "hugepage-size",
5397 .lname = "Hugepage size",
5398 .type = FIO_OPT_INT,
a609f12a 5399 .off1 = offsetof(struct thread_options, hugepage_size),
3ceb458f
JA
5400 .help = "When using hugepages, specify size of each page",
5401 .def = __fio_stringify(FIO_HUGE_PAGE),
5402 .interval = 1024 * 1024,
5403 .category = FIO_OPT_C_GENERAL,
5404 .group = FIO_OPT_G_INVALID,
5405 },
9e684a49
DE
5406 {
5407 .name = "flow_id",
e8b0e958 5408 .lname = "I/O flow ID",
9e684a49 5409 .type = FIO_OPT_INT,
a609f12a 5410 .off1 = offsetof(struct thread_options, flow_id),
9e684a49
DE
5411 .help = "The flow index ID to use",
5412 .def = "0",
e8b0e958
JA
5413 .category = FIO_OPT_C_IO,
5414 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5415 },
5416 {
5417 .name = "flow",
e8b0e958 5418 .lname = "I/O flow weight",
20c7a244 5419 .type = FIO_OPT_INT,
a609f12a 5420 .off1 = offsetof(struct thread_options, flow),
9e684a49
DE
5421 .help = "Weight for flow control of this job",
5422 .parent = "flow_id",
d71c154c 5423 .hide = 1,
9e684a49 5424 .def = "0",
d4e74fda 5425 .maxval = FLOW_MAX_WEIGHT,
e8b0e958
JA
5426 .category = FIO_OPT_C_IO,
5427 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5428 },
5429 {
5430 .name = "flow_watermark",
e8b0e958 5431 .lname = "I/O flow watermark",
d4e74fda 5432 .type = FIO_OPT_SOFT_DEPRECATED,
e8b0e958
JA
5433 .category = FIO_OPT_C_IO,
5434 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5435 },
5436 {
5437 .name = "flow_sleep",
e8b0e958 5438 .lname = "I/O flow sleep",
9e684a49 5439 .type = FIO_OPT_INT,
a609f12a 5440 .off1 = offsetof(struct thread_options, flow_sleep),
9e684a49
DE
5441 .help = "How many microseconds to sleep after being held"
5442 " back by the flow control mechanism",
5443 .parent = "flow_id",
d71c154c 5444 .hide = 1,
9e684a49 5445 .def = "0",
e8b0e958
JA
5446 .category = FIO_OPT_C_IO,
5447 .group = FIO_OPT_G_IO_FLOW,
9e684a49 5448 },
16e56d25
VF
5449 {
5450 .name = "steadystate",
5451 .lname = "Steady state threshold",
5452 .alias = "ss",
5453 .type = FIO_OPT_STR,
2c5d94bc 5454 .off1 = offsetof(struct thread_options, ss_state),
16e56d25
VF
5455 .cb = str_steadystate_cb,
5456 .help = "Define the criterion and limit to judge when a job has reached steady state",
5457 .def = "iops_slope:0.01%",
5458 .posval = {
5459 { .ival = "iops",
f0c50c66 5460 .oval = FIO_SS_IOPS,
16e56d25
VF
5461 .help = "maximum mean deviation of IOPS measurements",
5462 },
5463 { .ival = "iops_slope",
f0c50c66 5464 .oval = FIO_SS_IOPS_SLOPE,
16e56d25
VF
5465 .help = "slope calculated from IOPS measurements",
5466 },
5467 { .ival = "bw",
f0c50c66 5468 .oval = FIO_SS_BW,
16e56d25
VF
5469 .help = "maximum mean deviation of bandwidth measurements",
5470 },
5471 {
5472 .ival = "bw_slope",
f0c50c66 5473 .oval = FIO_SS_BW_SLOPE,
16e56d25
VF
5474 .help = "slope calculated from bandwidth measurements",
5475 },
5476 },
5477 .category = FIO_OPT_C_GENERAL,
5478 .group = FIO_OPT_G_RUNTIME,
5479 },
5480 {
5481 .name = "steadystate_duration",
5482 .lname = "Steady state duration",
5483 .alias = "ss_dur",
915ca980 5484 .parent = "steadystate",
16e56d25
VF
5485 .type = FIO_OPT_STR_VAL_TIME,
5486 .off1 = offsetof(struct thread_options, ss_dur),
5487 .help = "Stop workload upon attaining steady state for specified duration",
5488 .def = "0",
5489 .is_seconds = 1,
5490 .is_time = 1,
5491 .category = FIO_OPT_C_GENERAL,
5492 .group = FIO_OPT_G_RUNTIME,
5493 },
5494 {
5495 .name = "steadystate_ramp_time",
5496 .lname = "Steady state ramp time",
5497 .alias = "ss_ramp",
915ca980 5498 .parent = "steadystate",
16e56d25
VF
5499 .type = FIO_OPT_STR_VAL_TIME,
5500 .off1 = offsetof(struct thread_options, ss_ramp_time),
5501 .help = "Delay before initiation of data collection for steady state job termination testing",
5502 .def = "0",
5503 .is_seconds = 1,
5504 .is_time = 1,
5505 .category = FIO_OPT_C_GENERAL,
5506 .group = FIO_OPT_G_RUNTIME,
5507 },
90e678ba
CL
5508 {
5509 .name = "steadystate_check_interval",
5510 .lname = "Steady state check interval",
5511 .alias = "ss_interval",
5512 .parent = "steadystate",
5513 .type = FIO_OPT_STR_VAL_TIME,
5514 .off1 = offsetof(struct thread_options, ss_check_interval),
5515 .help = "Polling interval for the steady state check (too low means steadystate will not converge)",
5516 .def = "1",
5517 .is_seconds = 1,
5518 .is_time = 1,
5519 .category = FIO_OPT_C_GENERAL,
5520 .group = FIO_OPT_G_RUNTIME,
5521 },
214e1eca
JA
5522 {
5523 .name = NULL,
5524 },
5525};
5526
17af15d4 5527static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 5528 const char *name, int val)
9f81736c 5529{
17af15d4 5530 lopt->name = (char *) name;
de890a1e 5531 lopt->val = val;
9f81736c 5532 if (o->type == FIO_OPT_STR_SET)
ff52be3d 5533 lopt->has_arg = optional_argument;
9f81736c
JA
5534 else
5535 lopt->has_arg = required_argument;
5536}
5537
de890a1e
SL
5538static void options_to_lopts(struct fio_option *opts,
5539 struct option *long_options,
5540 int i, int option_type)
214e1eca 5541{
de890a1e 5542 struct fio_option *o = &opts[0];
214e1eca 5543 while (o->name) {
de890a1e 5544 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
5545 if (o->alias) {
5546 i++;
de890a1e 5547 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 5548 }
214e1eca
JA
5549
5550 i++;
5551 o++;
5552 assert(i < FIO_NR_OPTIONS);
5553 }
5554}
5555
de890a1e
SL
5556void fio_options_set_ioengine_opts(struct option *long_options,
5557 struct thread_data *td)
5558{
5559 unsigned int i;
5560
5561 i = 0;
5562 while (long_options[i].name) {
5563 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
5564 memset(&long_options[i], 0, sizeof(*long_options));
5565 break;
5566 }
5567 i++;
5568 }
5569
5570 /*
5571 * Just clear out the prior ioengine options.
5572 */
5573 if (!td || !td->eo)
5574 return;
5575
5576 options_to_lopts(td->io_ops->options, long_options, i,
5577 FIO_GETOPT_IOENGINE);
5578}
5579
5580void fio_options_dup_and_init(struct option *long_options)
5581{
5582 unsigned int i;
5583
9af4a244 5584 options_init(fio_options);
de890a1e
SL
5585
5586 i = 0;
5587 while (long_options[i].name)
5588 i++;
5589
9af4a244 5590 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
5591}
5592
74929ac2
JA
5593struct fio_keyword {
5594 const char *word;
5595 const char *desc;
5596 char *replace;
5597};
5598
5599static struct fio_keyword fio_keywords[] = {
5600 {
5601 .word = "$pagesize",
5602 .desc = "Page size in the system",
5603 },
5604 {
5605 .word = "$mb_memory",
5606 .desc = "Megabytes of memory online",
5607 },
5608 {
5609 .word = "$ncpus",
5610 .desc = "Number of CPUs online in the system",
5611 },
5612 {
5613 .word = NULL,
5614 },
5615};
5616
af1dc266
JA
5617void fio_keywords_exit(void)
5618{
5619 struct fio_keyword *kw;
5620
5621 kw = &fio_keywords[0];
5622 while (kw->word) {
5623 free(kw->replace);
5624 kw->replace = NULL;
5625 kw++;
5626 }
5627}
5628
74929ac2
JA
5629void fio_keywords_init(void)
5630{
3b2e1464 5631 unsigned long long mb_memory;
74929ac2
JA
5632 char buf[128];
5633 long l;
5634
a4cfc477 5635 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
5636 fio_keywords[0].replace = strdup(buf);
5637
8eb016d3 5638 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 5639 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
5640 fio_keywords[1].replace = strdup(buf);
5641
40f61ec7 5642 l = cpus_configured();
74929ac2
JA
5643 sprintf(buf, "%lu", l);
5644 fio_keywords[2].replace = strdup(buf);
5645}
5646
892a6ffc
JA
5647#define BC_APP "bc"
5648
5649static char *bc_calc(char *str)
5650{
d0c814ec 5651 char buf[128], *tmp;
892a6ffc
JA
5652 FILE *f;
5653 int ret;
5654
5655 /*
5656 * No math, just return string
5657 */
d0c814ec
SL
5658 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
5659 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
5660 return str;
5661
5662 /*
5663 * Split option from value, we only need to calculate the value
5664 */
5665 tmp = strchr(str, '=');
5666 if (!tmp)
5667 return str;
5668
5669 tmp++;
892a6ffc 5670
d0c814ec
SL
5671 /*
5672 * Prevent buffer overflows; such a case isn't reasonable anyway
5673 */
5674 if (strlen(str) >= 128 || strlen(tmp) > 100)
5675 return str;
892a6ffc
JA
5676
5677 sprintf(buf, "which %s > /dev/null", BC_APP);
5678 if (system(buf)) {
5679 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
5680 return NULL;
5681 }
5682
d0c814ec 5683 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 5684 f = popen(buf, "r");
3c3ed070 5685 if (!f)
892a6ffc 5686 return NULL;
892a6ffc 5687
d0c814ec 5688 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
5689 if (ret <= 0) {
5690 pclose(f);
892a6ffc 5691 return NULL;
1d824f37 5692 }
892a6ffc 5693
892a6ffc 5694 pclose(f);
d0c814ec
SL
5695 buf[(tmp - str) + ret - 1] = '\0';
5696 memcpy(buf, str, tmp - str);
892a6ffc 5697 free(str);
d0c814ec
SL
5698 return strdup(buf);
5699}
5700
5701/*
5702 * Return a copy of the input string with substrings of the form ${VARNAME}
5703 * substituted with the value of the environment variable VARNAME. The
5704 * substitution always occurs, even if VARNAME is empty or the corresponding
5705 * environment variable undefined.
5706 */
b4f5e72f 5707char *fio_option_dup_subs(const char *opt)
d0c814ec
SL
5708{
5709 char out[OPT_LEN_MAX+1];
5710 char in[OPT_LEN_MAX+1];
5711 char *outptr = out;
5712 char *inptr = in;
5713 char *ch1, *ch2, *env;
5714 ssize_t nchr = OPT_LEN_MAX;
5715 size_t envlen;
5716
5717 if (strlen(opt) + 1 > OPT_LEN_MAX) {
5718 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
5719 return NULL;
5720 }
5721
36833fb0 5722 snprintf(in, sizeof(in), "%s", opt);
d0c814ec
SL
5723
5724 while (*inptr && nchr > 0) {
5725 if (inptr[0] == '$' && inptr[1] == '{') {
5726 ch2 = strchr(inptr, '}');
5727 if (ch2 && inptr+1 < ch2) {
5728 ch1 = inptr+2;
5729 inptr = ch2+1;
5730 *ch2 = '\0';
5731
5732 env = getenv(ch1);
5733 if (env) {
5734 envlen = strlen(env);
5735 if (envlen <= nchr) {
5736 memcpy(outptr, env, envlen);
5737 outptr += envlen;
5738 nchr -= envlen;
5739 }
5740 }
5741
5742 continue;
5743 }
5744 }
5745
5746 *outptr++ = *inptr++;
5747 --nchr;
5748 }
5749
5750 *outptr = '\0';
5751 return strdup(out);
892a6ffc
JA
5752}
5753
74929ac2
JA
5754/*
5755 * Look for reserved variable names and replace them with real values
5756 */
5757static char *fio_keyword_replace(char *opt)
5758{
5759 char *s;
5760 int i;
d0c814ec 5761 int docalc = 0;
74929ac2
JA
5762
5763 for (i = 0; fio_keywords[i].word != NULL; i++) {
5764 struct fio_keyword *kw = &fio_keywords[i];
5765
5766 while ((s = strstr(opt, kw->word)) != NULL) {
33153428 5767 char *new = calloc(strlen(opt) + 1, 1);
74929ac2
JA
5768 char *o_org = opt;
5769 int olen = s - opt;
5770 int len;
5771
5772 /*
5773 * Copy part of the string before the keyword and
5774 * sprintf() the replacement after it.
5775 */
5776 memcpy(new, opt, olen);
5777 len = sprintf(new + olen, "%s", kw->replace);
5778
5779 /*
5780 * If there's more in the original string, copy that
5781 * in too
5782 */
85b9ee7e 5783 opt += olen + strlen(kw->word);
33153428 5784 /* keeps final zero thanks to calloc */
74929ac2 5785 if (strlen(opt))
85b9ee7e 5786 memcpy(new + olen + len, opt, strlen(opt));
74929ac2
JA
5787
5788 /*
5789 * replace opt and free the old opt
5790 */
5791 opt = new;
d0c814ec 5792 free(o_org);
7a958bd5 5793
d0c814ec 5794 docalc = 1;
74929ac2
JA
5795 }
5796 }
5797
d0c814ec
SL
5798 /*
5799 * Check for potential math and invoke bc, if possible
5800 */
5801 if (docalc)
5802 opt = bc_calc(opt);
5803
7a958bd5 5804 return opt;
74929ac2
JA
5805}
5806
d0c814ec
SL
5807static char **dup_and_sub_options(char **opts, int num_opts)
5808{
5809 int i;
5810 char **opts_copy = malloc(num_opts * sizeof(*opts));
5811 for (i = 0; i < num_opts; i++) {
b4f5e72f 5812 opts_copy[i] = fio_option_dup_subs(opts[i]);
d0c814ec
SL
5813 if (!opts_copy[i])
5814 continue;
5815 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
5816 }
5817 return opts_copy;
5818}
5819
e15b023b 5820static void show_closest_option(const char *opt)
a2d027b9
JA
5821{
5822 int best_option, best_distance;
5823 int i, distance;
e15b023b
JA
5824 char *name;
5825
5826 if (!strlen(opt))
5827 return;
5828
5829 name = strdup(opt);
5830 i = 0;
5831 while (name[i] != '\0' && name[i] != '=')
5832 i++;
5833 name[i] = '\0';
a2d027b9
JA
5834
5835 best_option = -1;
5836 best_distance = INT_MAX;
5837 i = 0;
5838 while (fio_options[i].name) {
5839 distance = string_distance(name, fio_options[i].name);
5840 if (distance < best_distance) {
5841 best_distance = distance;
5842 best_option = i;
5843 }
5844 i++;
5845 }
5846
75e6bcba
JA
5847 if (best_option != -1 && string_distance_ok(name, best_distance) &&
5848 fio_options[best_option].type != FIO_OPT_UNSUPPORTED)
a2d027b9 5849 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
5850
5851 free(name);
a2d027b9
JA
5852}
5853
c2292325 5854int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 5855{
de890a1e 5856 int i, ret, unknown;
d0c814ec 5857 char **opts_copy;
3b8b7135 5858
9af4a244 5859 sort_options(opts, fio_options, num_opts);
d0c814ec 5860 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 5861
de890a1e 5862 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
9109883a 5863 const struct fio_option *o;
9af4a244 5864 int newret = parse_option(opts_copy[i], opts[i], fio_options,
a609f12a 5865 &o, &td->o, &td->opt_list);
d0c814ec 5866
a8523a6a
JA
5867 if (!newret && o)
5868 fio_option_mark_set(&td->o, o);
5869
de890a1e
SL
5870 if (opts_copy[i]) {
5871 if (newret && !o) {
5872 unknown++;
5873 continue;
5874 }
d0c814ec 5875 free(opts_copy[i]);
de890a1e
SL
5876 opts_copy[i] = NULL;
5877 }
5878
5879 ret |= newret;
5880 }
5881
5882 if (unknown) {
5883 ret |= ioengine_load(td);
5884 if (td->eo) {
5885 sort_options(opts_copy, td->io_ops->options, num_opts);
5886 opts = opts_copy;
5887 }
5888 for (i = 0; i < num_opts; i++) {
9109883a 5889 const struct fio_option *o = NULL;
de890a1e 5890 int newret = 1;
a2d027b9 5891
de890a1e
SL
5892 if (!opts_copy[i])
5893 continue;
5894
5895 if (td->eo)
5896 newret = parse_option(opts_copy[i], opts[i],
5897 td->io_ops->options, &o,
66e19a38 5898 td->eo, &td->opt_list);
de890a1e
SL
5899
5900 ret |= newret;
a2d027b9 5901 if (!o) {
de890a1e 5902 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
5903 show_closest_option(opts[i]);
5904 }
de890a1e
SL
5905 free(opts_copy[i]);
5906 opts_copy[i] = NULL;
5907 }
74929ac2 5908 }
3b8b7135 5909
d0c814ec 5910 free(opts_copy);
3b8b7135 5911 return ret;
214e1eca
JA
5912}
5913
5914int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
5915{
a8523a6a
JA
5916 int ret;
5917
a609f12a 5918 ret = parse_cmd_option(opt, val, fio_options, &td->o, &td->opt_list);
a8523a6a 5919 if (!ret) {
9109883a 5920 const struct fio_option *o;
a8523a6a 5921
9109883a 5922 o = find_option_c(fio_options, opt);
a8523a6a
JA
5923 if (o)
5924 fio_option_mark_set(&td->o, o);
5925 }
5926
5927 return ret;
214e1eca
JA
5928}
5929
de890a1e
SL
5930int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
5931 char *val)
5932{
d8b4f395
JA
5933 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
5934 &td->opt_list);
de890a1e
SL
5935}
5936
214e1eca
JA
5937void fio_fill_default_options(struct thread_data *td)
5938{
cb1402d6 5939 td->o.magic = OPT_MAGIC;
a609f12a 5940 fill_default_options(&td->o, fio_options);
214e1eca
JA
5941}
5942
5943int fio_show_option_help(const char *opt)
5944{
9af4a244 5945 return show_cmd_help(fio_options, opt);
214e1eca 5946}
d23bb327 5947
de890a1e
SL
5948/*
5949 * dupe FIO_OPT_STR_STORE options
5950 */
5951void fio_options_mem_dupe(struct thread_data *td)
5952{
53b5693d 5953 options_mem_dupe(fio_options, &td->o);
1647f592
JA
5954
5955 if (td->eo && td->io_ops) {
de890a1e 5956 void *oldeo = td->eo;
1647f592 5957
de890a1e
SL
5958 td->eo = malloc(td->io_ops->option_struct_size);
5959 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
53b5693d 5960 options_mem_dupe(td->io_ops->options, td->eo);
de890a1e
SL
5961 }
5962}
5963
d6978a32
JA
5964unsigned int fio_get_kb_base(void *data)
5965{
a609f12a
JA
5966 struct thread_data *td = cb_data_to_td(data);
5967 struct thread_options *o = &td->o;
d6978a32
JA
5968 unsigned int kb_base = 0;
5969
cb1402d6
JA
5970 /*
5971 * This is a hack... For private options, *data is not holding
5972 * a pointer to the thread_options, but to private data. This means
5973 * we can't safely dereference it, but magic is first so mem wise
5974 * it is valid. But this also means that if the job first sets
5975 * kb_base and expects that to be honored by private options,
5976 * it will be disappointed. We will return the global default
5977 * for this.
5978 */
5979 if (o && o->magic == OPT_MAGIC)
83ea422a 5980 kb_base = o->kb_base;
d6978a32
JA
5981 if (!kb_base)
5982 kb_base = 1024;
5983
5984 return kb_base;
5985}
9f988e2e 5986
9109883a 5987int add_option(const struct fio_option *o)
9f988e2e 5988{
07b3232d
JA
5989 struct fio_option *__o;
5990 int opt_index = 0;
5991
9af4a244 5992 __o = fio_options;
07b3232d
JA
5993 while (__o->name) {
5994 opt_index++;
5995 __o++;
5996 }
5997
7b504edd
JA
5998 if (opt_index + 1 == FIO_MAX_OPTS) {
5999 log_err("fio: FIO_MAX_OPTS is too small\n");
6000 return 1;
6001 }
6002
9af4a244 6003 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 6004 fio_options[opt_index + 1].name = NULL;
07b3232d 6005 return 0;
9f988e2e 6006}
e2de69da 6007
07b3232d 6008void invalidate_profile_options(const char *prof_name)
e2de69da 6009{
07b3232d 6010 struct fio_option *o;
e2de69da 6011
9af4a244 6012 o = fio_options;
07b3232d
JA
6013 while (o->name) {
6014 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
6015 o->type = FIO_OPT_INVALID;
6016 o->prof_name = NULL;
6017 }
6018 o++;
e2de69da
JA
6019 }
6020}
f5b6bb85
JA
6021
6022void add_opt_posval(const char *optname, const char *ival, const char *help)
6023{
6024 struct fio_option *o;
6025 unsigned int i;
6026
9af4a244 6027 o = find_option(fio_options, optname);
f5b6bb85
JA
6028 if (!o)
6029 return;
6030
6031 for (i = 0; i < PARSE_MAX_VP; i++) {
6032 if (o->posval[i].ival)
6033 continue;
6034
6035 o->posval[i].ival = ival;
6036 o->posval[i].help = help;
6037 break;
6038 }
6039}
6040
6041void del_opt_posval(const char *optname, const char *ival)
6042{
6043 struct fio_option *o;
6044 unsigned int i;
6045
9af4a244 6046 o = find_option(fio_options, optname);
f5b6bb85
JA
6047 if (!o)
6048 return;
6049
6050 for (i = 0; i < PARSE_MAX_VP; i++) {
6051 if (!o->posval[i].ival)
6052 continue;
6053 if (strcmp(o->posval[i].ival, ival))
6054 continue;
6055
6056 o->posval[i].ival = NULL;
6057 o->posval[i].help = NULL;
6058 }
6059}
7e356b2d
JA
6060
6061void fio_options_free(struct thread_data *td)
6062{
ca6336a8 6063 options_free(fio_options, &td->o);
de890a1e
SL
6064 if (td->eo && td->io_ops && td->io_ops->options) {
6065 options_free(td->io_ops->options, td->eo);
824912be
JA
6066 free(td->eo);
6067 td->eo = NULL;
de890a1e 6068 }
7e356b2d 6069}
c504ee55 6070
8009f543
NC
6071void fio_dump_options_free(struct thread_data *td)
6072{
6073 while (!flist_empty(&td->opt_list)) {
6074 struct print_option *p;
6075
6076 p = flist_first_entry(&td->opt_list, struct print_option, list);
6077 flist_del_init(&p->list);
6078 free(p->name);
6079 free(p->value);
6080 free(p);
6081 }
6082}
6083
c504ee55
JA
6084struct fio_option *fio_option_find(const char *name)
6085{
6086 return find_option(fio_options, name);
6087}
6088
517c9c72 6089static struct fio_option *find_next_opt(struct fio_option *from,
f0e7f45a 6090 unsigned int off1)
a8523a6a 6091{
f0e7f45a 6092 struct fio_option *opt;
a8523a6a 6093
f0e7f45a
JA
6094 if (!from)
6095 from = &fio_options[0];
6096 else
6097 from++;
6098
6099 opt = NULL;
6100 do {
6101 if (off1 == from->off1) {
6102 opt = from;
a8523a6a
JA
6103 break;
6104 }
f0e7f45a
JA
6105 from++;
6106 } while (from->name);
a8523a6a 6107
f0e7f45a
JA
6108 return opt;
6109}
6110
6111static int opt_is_set(struct thread_options *o, struct fio_option *opt)
6112{
6113 unsigned int opt_off, index, offset;
a8523a6a
JA
6114
6115 opt_off = opt - &fio_options[0];
6116 index = opt_off / (8 * sizeof(uint64_t));
6117 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 6118 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
6119}
6120
72f39748 6121bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
6122{
6123 struct fio_option *opt, *next;
6124
6125 next = NULL;
517c9c72 6126 while ((opt = find_next_opt(next, off1)) != NULL) {
f0e7f45a 6127 if (opt_is_set(o, opt))
72f39748 6128 return true;
f0e7f45a
JA
6129
6130 next = opt;
6131 }
6132
72f39748 6133 return false;
f0e7f45a
JA
6134}
6135
9109883a 6136void fio_option_mark_set(struct thread_options *o, const struct fio_option *opt)
a8523a6a
JA
6137{
6138 unsigned int opt_off, index, offset;
6139
6140 opt_off = opt - &fio_options[0];
6141 index = opt_off / (8 * sizeof(uint64_t));
6142 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 6143 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 6144}