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