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