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