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