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