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