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