lib/rand: make __init_randX() static
[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>
921c766f 7#include <libgen.h>
5921e80c
JA
8#include <fcntl.h>
9#include <sys/types.h>
10#include <sys/stat.h>
e13c3b50 11#include <netinet/in.h>
214e1eca
JA
12
13#include "fio.h"
4f5af7b2 14#include "verify.h"
214e1eca 15#include "parse.h"
eef32359 16#include "lib/fls.h"
61b9861d 17#include "lib/pattern.h"
9f988e2e 18#include "options.h"
d220c761 19#include "optgroup.h"
214e1eca 20
e13c3b50 21char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 };
72a703da 22
214e1eca
JA
23/*
24 * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
25 */
26static char *get_opt_postfix(const char *str)
27{
28 char *p = strstr(str, ":");
29
30 if (!p)
31 return NULL;
32
33 p++;
34 strip_blank_front(&p);
35 strip_blank_end(p);
36 return strdup(p);
37}
38
564ca972
JA
39static int bs_cmp(const void *p1, const void *p2)
40{
41 const struct bssplit *bsp1 = p1;
42 const struct bssplit *bsp2 = p2;
43
a7cd478d 44 return (int) bsp1->perc - (int) bsp2->perc;
564ca972
JA
45}
46
d2835319
JA
47struct split {
48 unsigned int nr;
49 unsigned int val1[100];
50 unsigned int val2[100];
51};
52
53static int split_parse_ddir(struct thread_options *o, struct split *split,
54 enum fio_ddir ddir, char *str)
564ca972 55{
d2835319 56 unsigned int i, perc;
564ca972 57 long long val;
720e84ad 58 char *fname;
564ca972 59
d2835319 60 split->nr = 0;
564ca972
JA
61
62 i = 0;
564ca972
JA
63 while ((fname = strsep(&str, ":")) != NULL) {
64 char *perc_str;
65
66 if (!strlen(fname))
67 break;
68
564ca972
JA
69 perc_str = strstr(fname, "/");
70 if (perc_str) {
71 *perc_str = '\0';
72 perc_str++;
73 perc = atoi(perc_str);
74 if (perc > 100)
75 perc = 100;
76 else if (!perc)
d711cce5 77 perc = -1U;
564ca972 78 } else
d711cce5 79 perc = -1U;
564ca972 80
88038bc7 81 if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
564ca972 82 log_err("fio: bssplit conversion failed\n");
564ca972
JA
83 return 1;
84 }
85
d2835319
JA
86 split->val1[i] = val;
87 split->val2[i] = perc;
564ca972 88 i++;
d2835319
JA
89 if (i == 100)
90 break;
564ca972
JA
91 }
92
d2835319
JA
93 split->nr = i;
94 return 0;
95}
96
97static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str)
98{
99 unsigned int i, perc, perc_missing;
100 unsigned int max_bs, min_bs;
101 struct split split;
102
103 memset(&split, 0, sizeof(split));
104
105 if (split_parse_ddir(o, &split, ddir, str))
106 return 1;
107 if (!split.nr)
108 return 0;
109
110 max_bs = 0;
111 min_bs = -1;
112 o->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
113 o->bssplit_nr[ddir] = split.nr;
114 for (i = 0; i < split.nr; i++) {
115 if (split.val1[i] > max_bs)
116 max_bs = split.val1[i];
117 if (split.val1[i] < min_bs)
118 min_bs = split.val1[i];
119
120 o->bssplit[ddir][i].bs = split.val1[i];
121 o->bssplit[ddir][i].perc =split.val2[i];
122 }
564ca972
JA
123
124 /*
125 * Now check if the percentages add up, and how much is missing
126 */
127 perc = perc_missing = 0;
83ea422a 128 for (i = 0; i < o->bssplit_nr[ddir]; i++) {
d2835319 129 struct bssplit *bsp = &o->bssplit[ddir][i];
564ca972 130
d711cce5 131 if (bsp->perc == -1U)
564ca972
JA
132 perc_missing++;
133 else
134 perc += bsp->perc;
135 }
136
40bafa33 137 if (perc > 100 && perc_missing > 1) {
564ca972 138 log_err("fio: bssplit percentages add to more than 100%%\n");
d2835319
JA
139 free(o->bssplit[ddir]);
140 o->bssplit[ddir] = NULL;
564ca972
JA
141 return 1;
142 }
d711cce5 143
564ca972
JA
144 /*
145 * If values didn't have a percentage set, divide the remains between
146 * them.
147 */
148 if (perc_missing) {
d711cce5 149 if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
40bafa33 150 perc = 100;
83ea422a 151 for (i = 0; i < o->bssplit_nr[ddir]; i++) {
d2835319 152 struct bssplit *bsp = &o->bssplit[ddir][i];
564ca972 153
d711cce5 154 if (bsp->perc == -1U)
564ca972
JA
155 bsp->perc = (100 - perc) / perc_missing;
156 }
157 }
158
83ea422a
JA
159 o->min_bs[ddir] = min_bs;
160 o->max_bs[ddir] = max_bs;
564ca972
JA
161
162 /*
163 * now sort based on percentages, for ease of lookup
164 */
d2835319 165 qsort(o->bssplit[ddir], o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
720e84ad 166 return 0;
720e84ad
JA
167}
168
764593c0
JA
169typedef int (split_parse_fn)(struct thread_options *, enum fio_ddir, char *);
170
171static int str_split_parse(struct thread_data *td, char *str, split_parse_fn *fn)
720e84ad 172{
764593c0 173 char *odir, *ddir;
720e84ad
JA
174 int ret = 0;
175
720e84ad
JA
176 odir = strchr(str, ',');
177 if (odir) {
6eaf09d6
SL
178 ddir = strchr(odir + 1, ',');
179 if (ddir) {
764593c0 180 ret = fn(&td->o, DDIR_TRIM, ddir + 1);
6eaf09d6
SL
181 if (!ret)
182 *ddir = '\0';
183 } else {
184 char *op;
185
186 op = strdup(odir + 1);
764593c0 187 ret = fn(&td->o, DDIR_TRIM, op);
6eaf09d6
SL
188
189 free(op);
190 }
d79db122 191 if (!ret)
764593c0 192 ret = fn(&td->o, DDIR_WRITE, odir + 1);
720e84ad
JA
193 if (!ret) {
194 *odir = '\0';
764593c0 195 ret = fn(&td->o, DDIR_READ, str);
720e84ad
JA
196 }
197 } else {
198 char *op;
199
200 op = strdup(str);
764593c0 201 ret = fn(&td->o, DDIR_WRITE, op);
6eaf09d6 202 free(op);
720e84ad 203
6eaf09d6
SL
204 if (!ret) {
205 op = strdup(str);
764593c0 206 ret = fn(&td->o, DDIR_TRIM, op);
6eaf09d6
SL
207 free(op);
208 }
f0c9c217 209 if (!ret)
764593c0 210 ret = fn(&td->o, DDIR_READ, str);
720e84ad 211 }
564ca972 212
764593c0
JA
213 return ret;
214}
215
216static int str_bssplit_cb(void *data, const char *input)
217{
218 struct thread_data *td = data;
219 char *str, *p;
220 int ret = 0;
221
764593c0
JA
222 p = str = strdup(input);
223
224 strip_blank_front(&str);
225 strip_blank_end(str);
226
227 ret = str_split_parse(td, str, bssplit_ddir);
228
55baca06
JA
229 if (parse_dryrun()) {
230 int i;
231
232 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
233 free(td->o.bssplit[i]);
234 td->o.bssplit[i] = NULL;
235 td->o.bssplit_nr[i] = 0;
236 }
237 }
238
564ca972 239 free(p);
720e84ad 240 return ret;
564ca972
JA
241}
242
8b28bd41
DM
243static int str2error(char *str)
244{
a94eb99a 245 const char *err[] = { "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
8b28bd41
DM
246 "ENXIO", "E2BIG", "ENOEXEC", "EBADF",
247 "ECHILD", "EAGAIN", "ENOMEM", "EACCES",
248 "EFAULT", "ENOTBLK", "EBUSY", "EEXIST",
249 "EXDEV", "ENODEV", "ENOTDIR", "EISDIR",
250 "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
251 "ETXTBSY","EFBIG", "ENOSPC", "ESPIPE",
a94eb99a 252 "EROFS","EMLINK", "EPIPE", "EDOM", "ERANGE" };
8b28bd41
DM
253 int i = 0, num = sizeof(err) / sizeof(void *);
254
a94eb99a 255 while (i < num) {
8b28bd41
DM
256 if (!strcmp(err[i], str))
257 return i + 1;
258 i++;
259 }
260 return 0;
261}
262
263static int ignore_error_type(struct thread_data *td, int etype, char *str)
264{
265 unsigned int i;
266 int *error;
267 char *fname;
268
269 if (etype >= ERROR_TYPE_CNT) {
270 log_err("Illegal error type\n");
271 return 1;
272 }
273
274 td->o.ignore_error_nr[etype] = 4;
275 error = malloc(4 * sizeof(struct bssplit));
276
277 i = 0;
278 while ((fname = strsep(&str, ":")) != NULL) {
279
280 if (!strlen(fname))
281 break;
282
283 /*
284 * grow struct buffer, if needed
285 */
286 if (i == td->o.ignore_error_nr[etype]) {
287 td->o.ignore_error_nr[etype] <<= 1;
288 error = realloc(error, td->o.ignore_error_nr[etype]
289 * sizeof(int));
290 }
291 if (fname[0] == 'E') {
292 error[i] = str2error(fname);
293 } else {
294 error[i] = atoi(fname);
295 if (error[i] < 0)
1616e025 296 error[i] = -error[i];
8b28bd41
DM
297 }
298 if (!error[i]) {
299 log_err("Unknown error %s, please use number value \n",
300 fname);
0fddbf7a 301 free(error);
8b28bd41
DM
302 return 1;
303 }
304 i++;
305 }
306 if (i) {
307 td->o.continue_on_error |= 1 << etype;
308 td->o.ignore_error_nr[etype] = i;
309 td->o.ignore_error[etype] = error;
c7b086be
JA
310 } else
311 free(error);
312
8b28bd41
DM
313 return 0;
314
315}
316
317static int str_ignore_error_cb(void *data, const char *input)
318{
319 struct thread_data *td = data;
320 char *str, *p, *n;
321 int type = 0, ret = 1;
52c0cea3
JA
322
323 if (parse_dryrun())
324 return 0;
325
8b28bd41
DM
326 p = str = strdup(input);
327
328 strip_blank_front(&str);
329 strip_blank_end(str);
330
331 while (p) {
332 n = strchr(p, ',');
333 if (n)
334 *n++ = '\0';
335 ret = ignore_error_type(td, type, p);
336 if (ret)
337 break;
338 p = n;
339 type++;
340 }
341 free(str);
342 return ret;
343}
344
211097b2
JA
345static int str_rw_cb(void *data, const char *str)
346{
347 struct thread_data *td = data;
83ea422a 348 struct thread_options *o = &td->o;
27ca949f 349 char *nr;
211097b2 350
52c0cea3
JA
351 if (parse_dryrun())
352 return 0;
353
83ea422a
JA
354 o->ddir_seq_nr = 1;
355 o->ddir_seq_add = 0;
059b0802 356
27ca949f 357 nr = get_opt_postfix(str);
059b0802
JA
358 if (!nr)
359 return 0;
360
361 if (td_random(td))
83ea422a 362 o->ddir_seq_nr = atoi(nr);
059b0802
JA
363 else {
364 long long val;
365
88038bc7 366 if (str_to_decimal(nr, &val, 1, o, 0, 0)) {
059b0802
JA
367 log_err("fio: rw postfix parsing failed\n");
368 free(nr);
369 return 1;
370 }
371
83ea422a 372 o->ddir_seq_add = val;
182ec6ee 373 }
211097b2 374
059b0802 375 free(nr);
211097b2
JA
376 return 0;
377}
378
214e1eca
JA
379static int str_mem_cb(void *data, const char *mem)
380{
381 struct thread_data *td = data;
382
217b0f1d
LG
383 if (td->o.mem_type == MEM_MMAPHUGE || td->o.mem_type == MEM_MMAP ||
384 td->o.mem_type == MEM_MMAPSHARED)
836fcc0f 385 td->o.mmapfile = get_opt_postfix(mem);
214e1eca
JA
386
387 return 0;
388}
389
c223da83
JA
390static int fio_clock_source_cb(void *data, const char *str)
391{
392 struct thread_data *td = data;
393
394 fio_clock_source = td->o.clocksource;
fa80feae 395 fio_clock_source_set = 1;
01423eae 396 fio_clock_init();
c223da83
JA
397 return 0;
398}
399
85bc833b 400static int str_rwmix_read_cb(void *data, unsigned long long *val)
cb499fc4
JA
401{
402 struct thread_data *td = data;
403
404 td->o.rwmix[DDIR_READ] = *val;
405 td->o.rwmix[DDIR_WRITE] = 100 - *val;
406 return 0;
407}
408
85bc833b 409static int str_rwmix_write_cb(void *data, unsigned long long *val)
cb499fc4
JA
410{
411 struct thread_data *td = data;
412
413 td->o.rwmix[DDIR_WRITE] = *val;
414 td->o.rwmix[DDIR_READ] = 100 - *val;
415 return 0;
416}
417
214e1eca
JA
418static int str_exitall_cb(void)
419{
420 exitall_on_terminate = 1;
421 return 0;
422}
423
214e1eca 424#ifdef FIO_HAVE_CPU_AFFINITY
50b5860b 425int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu_index)
c2acfbac 426{
50b5860b 427 unsigned int i, index, cpus_in_mask;
c2acfbac 428 const long max_cpu = cpus_online();
c2acfbac 429
50b5860b
JA
430 cpus_in_mask = fio_cpu_count(mask);
431 cpu_index = cpu_index % cpus_in_mask;
432
433 index = 0;
c2acfbac 434 for (i = 0; i < max_cpu; i++) {
50b5860b 435 if (!fio_cpu_isset(mask, i))
c2acfbac 436 continue;
50b5860b
JA
437
438 if (cpu_index != index)
439 fio_cpu_clear(mask, i);
440
441 index++;
c2acfbac
JA
442 }
443
444 return fio_cpu_count(mask);
445}
446
85bc833b 447static int str_cpumask_cb(void *data, unsigned long long *val)
d2e268b0
JA
448{
449 struct thread_data *td = data;
214e1eca 450 unsigned int i;
b03daafb 451 long max_cpu;
d2ce18b5
JA
452 int ret;
453
52c0cea3
JA
454 if (parse_dryrun())
455 return 0;
456
d2ce18b5
JA
457 ret = fio_cpuset_init(&td->o.cpumask);
458 if (ret < 0) {
459 log_err("fio: cpuset_init failed\n");
460 td_verror(td, ret, "fio_cpuset_init");
461 return 1;
462 }
214e1eca 463
c00a2289 464 max_cpu = cpus_online();
214e1eca 465
62a7273d
JA
466 for (i = 0; i < sizeof(int) * 8; i++) {
467 if ((1 << i) & *val) {
b8411399 468 if (i >= max_cpu) {
b03daafb 469 log_err("fio: CPU %d too large (max=%ld)\n", i,
b8411399 470 max_cpu - 1);
b03daafb
JA
471 return 1;
472 }
62a7273d 473 dprint(FD_PARSE, "set cpu allowed %d\n", i);
6d459ee7 474 fio_cpu_set(&td->o.cpumask, i);
62a7273d
JA
475 }
476 }
d2e268b0 477
d2e268b0 478 return 0;
214e1eca
JA
479}
480
e8462bd8
JA
481static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask,
482 const char *input)
214e1eca 483{
d2e268b0 484 char *cpu, *str, *p;
b03daafb 485 long max_cpu;
19608d6c 486 int ret = 0;
d2e268b0 487
e8462bd8 488 ret = fio_cpuset_init(mask);
d2ce18b5
JA
489 if (ret < 0) {
490 log_err("fio: cpuset_init failed\n");
491 td_verror(td, ret, "fio_cpuset_init");
492 return 1;
493 }
d2e268b0
JA
494
495 p = str = strdup(input);
214e1eca 496
d2e268b0
JA
497 strip_blank_front(&str);
498 strip_blank_end(str);
499
c00a2289 500 max_cpu = cpus_online();
b03daafb 501
d2e268b0 502 while ((cpu = strsep(&str, ",")) != NULL) {
62a7273d
JA
503 char *str2, *cpu2;
504 int icpu, icpu2;
505
d2e268b0
JA
506 if (!strlen(cpu))
507 break;
62a7273d
JA
508
509 str2 = cpu;
510 icpu2 = -1;
511 while ((cpu2 = strsep(&str2, "-")) != NULL) {
512 if (!strlen(cpu2))
513 break;
514
515 icpu2 = atoi(cpu2);
516 }
517
518 icpu = atoi(cpu);
519 if (icpu2 == -1)
520 icpu2 = icpu;
521 while (icpu <= icpu2) {
6d459ee7 522 if (icpu >= FIO_MAX_CPUS) {
19608d6c 523 log_err("fio: your OS only supports up to"
6d459ee7 524 " %d CPUs\n", (int) FIO_MAX_CPUS);
19608d6c
JA
525 ret = 1;
526 break;
527 }
9e986889 528 if (icpu >= max_cpu) {
b03daafb 529 log_err("fio: CPU %d too large (max=%ld)\n",
9e986889 530 icpu, max_cpu - 1);
b03daafb
JA
531 ret = 1;
532 break;
533 }
0b9d69ec 534
62a7273d 535 dprint(FD_PARSE, "set cpu allowed %d\n", icpu);
e8462bd8 536 fio_cpu_set(mask, icpu);
62a7273d
JA
537 icpu++;
538 }
19608d6c
JA
539 if (ret)
540 break;
d2e268b0
JA
541 }
542
543 free(p);
19608d6c 544 return ret;
214e1eca 545}
e8462bd8
JA
546
547static int str_cpus_allowed_cb(void *data, const char *input)
548{
549 struct thread_data *td = data;
e8462bd8 550
52c0cea3
JA
551 if (parse_dryrun())
552 return 0;
553
b2a9e649 554 return set_cpus_allowed(td, &td->o.cpumask, input);
e8462bd8
JA
555}
556
557static int str_verify_cpus_allowed_cb(void *data, const char *input)
558{
559 struct thread_data *td = data;
e8462bd8 560
466155e2
JA
561 if (parse_dryrun())
562 return 0;
563
b2a9e649 564 return set_cpus_allowed(td, &td->o.verify_cpumask, input);
e8462bd8 565}
c08f9fe2 566
105157ad 567#ifdef CONFIG_ZLIB
c08f9fe2
JA
568static int str_log_cpus_allowed_cb(void *data, const char *input)
569{
570 struct thread_data *td = data;
571
572 if (parse_dryrun())
573 return 0;
574
575 return set_cpus_allowed(td, &td->o.log_gz_cpumask, input);
576}
105157ad 577#endif /* CONFIG_ZLIB */
c08f9fe2 578
105157ad 579#endif /* FIO_HAVE_CPU_AFFINITY */
214e1eca 580
67bf9823 581#ifdef CONFIG_LIBNUMA
d0b937ed
YR
582static int str_numa_cpunodes_cb(void *data, char *input)
583{
584 struct thread_data *td = data;
43522848 585 struct bitmask *verify_bitmask;
d0b937ed 586
52c0cea3
JA
587 if (parse_dryrun())
588 return 0;
589
d0b937ed
YR
590 /* numa_parse_nodestring() parses a character string list
591 * of nodes into a bit mask. The bit mask is allocated by
592 * numa_allocate_nodemask(), so it should be freed by
593 * numa_free_nodemask().
594 */
43522848
DG
595 verify_bitmask = numa_parse_nodestring(input);
596 if (verify_bitmask == NULL) {
d0b937ed
YR
597 log_err("fio: numa_parse_nodestring failed\n");
598 td_verror(td, 1, "str_numa_cpunodes_cb");
599 return 1;
600 }
43522848 601 numa_free_nodemask(verify_bitmask);
d0b937ed 602
43522848 603 td->o.numa_cpunodes = strdup(input);
d0b937ed
YR
604 return 0;
605}
606
607static int str_numa_mpol_cb(void *data, char *input)
608{
609 struct thread_data *td = data;
610 const char * const policy_types[] =
05d6f44b 611 { "default", "prefer", "bind", "interleave", "local", NULL };
d0b937ed 612 int i;
52c0cea3 613 char *nodelist;
43522848 614 struct bitmask *verify_bitmask;
52c0cea3
JA
615
616 if (parse_dryrun())
617 return 0;
d0b937ed 618
52c0cea3 619 nodelist = strchr(input, ':');
d0b937ed
YR
620 if (nodelist) {
621 /* NUL-terminate mode */
622 *nodelist++ = '\0';
623 }
624
625 for (i = 0; i <= MPOL_LOCAL; i++) {
626 if (!strcmp(input, policy_types[i])) {
627 td->o.numa_mem_mode = i;
628 break;
629 }
630 }
631 if (i > MPOL_LOCAL) {
632 log_err("fio: memory policy should be: default, prefer, bind, interleave, local\n");
633 goto out;
634 }
635
636 switch (td->o.numa_mem_mode) {
637 case MPOL_PREFERRED:
638 /*
639 * Insist on a nodelist of one node only
640 */
641 if (nodelist) {
642 char *rest = nodelist;
643 while (isdigit(*rest))
644 rest++;
645 if (*rest) {
646 log_err("fio: one node only for \'prefer\'\n");
647 goto out;
648 }
649 } else {
650 log_err("fio: one node is needed for \'prefer\'\n");
651 goto out;
652 }
653 break;
654 case MPOL_INTERLEAVE:
655 /*
656 * Default to online nodes with memory if no nodelist
657 */
658 if (!nodelist)
659 nodelist = strdup("all");
660 break;
661 case MPOL_LOCAL:
662 case MPOL_DEFAULT:
663 /*
664 * Don't allow a nodelist
665 */
666 if (nodelist) {
667 log_err("fio: NO nodelist for \'local\'\n");
668 goto out;
669 }
670 break;
671 case MPOL_BIND:
672 /*
673 * Insist on a nodelist
674 */
675 if (!nodelist) {
676 log_err("fio: a nodelist is needed for \'bind\'\n");
677 goto out;
678 }
679 break;
680 }
681
682
683 /* numa_parse_nodestring() parses a character string list
684 * of nodes into a bit mask. The bit mask is allocated by
685 * numa_allocate_nodemask(), so it should be freed by
686 * numa_free_nodemask().
687 */
688 switch (td->o.numa_mem_mode) {
689 case MPOL_PREFERRED:
690 td->o.numa_mem_prefer_node = atoi(nodelist);
691 break;
692 case MPOL_INTERLEAVE:
693 case MPOL_BIND:
43522848
DG
694 verify_bitmask = numa_parse_nodestring(nodelist);
695 if (verify_bitmask == NULL) {
d0b937ed
YR
696 log_err("fio: numa_parse_nodestring failed\n");
697 td_verror(td, 1, "str_numa_memnodes_cb");
698 return 1;
699 }
43522848
DG
700 td->o.numa_memnodes = strdup(nodelist);
701 numa_free_nodemask(verify_bitmask);
b74e419e 702
d0b937ed
YR
703 break;
704 case MPOL_LOCAL:
705 case MPOL_DEFAULT:
706 default:
707 break;
708 }
709
d0b937ed 710 return 0;
d0b937ed
YR
711out:
712 return 1;
713}
714#endif
715
214e1eca
JA
716static int str_fst_cb(void *data, const char *str)
717{
718 struct thread_data *td = data;
719 char *nr = get_opt_postfix(str);
720
721 td->file_service_nr = 1;
182ec6ee 722 if (nr) {
214e1eca 723 td->file_service_nr = atoi(nr);
182ec6ee
JA
724 free(nr);
725 }
214e1eca
JA
726
727 return 0;
728}
729
67bf9823 730#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
731static int str_sfr_cb(void *data, const char *str)
732{
733 struct thread_data *td = data;
734 char *nr = get_opt_postfix(str);
735
736 td->sync_file_range_nr = 1;
737 if (nr) {
738 td->sync_file_range_nr = atoi(nr);
739 free(nr);
740 }
741
742 return 0;
743}
3ae06371 744#endif
44f29692 745
e0a04ac1
JA
746static int zone_cmp(const void *p1, const void *p2)
747{
748 const struct zone_split *zsp1 = p1;
749 const struct zone_split *zsp2 = p2;
750
751 return (int) zsp2->access_perc - (int) zsp1->access_perc;
752}
753
764593c0
JA
754static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
755 char *str)
e0a04ac1 756{
e0a04ac1 757 unsigned int i, perc, perc_missing, sperc, sperc_missing;
d2835319 758 struct split split;
e0a04ac1 759
d2835319 760 memset(&split, 0, sizeof(split));
e0a04ac1 761
d2835319
JA
762 if (split_parse_ddir(o, &split, ddir, str))
763 return 1;
764 if (!split.nr)
765 return 0;
e0a04ac1 766
d2835319
JA
767 o->zone_split[ddir] = malloc(split.nr * sizeof(struct zone_split));
768 o->zone_split_nr[ddir] = split.nr;
769 for (i = 0; i < split.nr; i++) {
770 o->zone_split[ddir][i].access_perc = split.val1[i];
771 o->zone_split[ddir][i].size_perc = split.val2[i];
e0a04ac1
JA
772 }
773
e0a04ac1
JA
774 /*
775 * Now check if the percentages add up, and how much is missing
776 */
777 perc = perc_missing = 0;
778 sperc = sperc_missing = 0;
779 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
d2835319 780 struct zone_split *zsp = &o->zone_split[ddir][i];
e0a04ac1
JA
781
782 if (zsp->access_perc == (uint8_t) -1U)
783 perc_missing++;
784 else
785 perc += zsp->access_perc;
786
787 if (zsp->size_perc == (uint8_t) -1U)
788 sperc_missing++;
789 else
790 sperc += zsp->size_perc;
791
792 }
793
794 if (perc > 100 || sperc > 100) {
795 log_err("fio: zone_split percentages add to more than 100%%\n");
d2835319
JA
796 free(o->zone_split[ddir]);
797 o->zone_split[ddir] = NULL;
e0a04ac1
JA
798 return 1;
799 }
800 if (perc < 100) {
801 log_err("fio: access percentage don't add up to 100 for zoned "
802 "random distribution (got=%u)\n", perc);
d2835319
JA
803 free(o->zone_split[ddir]);
804 o->zone_split[ddir] = NULL;
e0a04ac1
JA
805 return 1;
806 }
807
808 /*
809 * If values didn't have a percentage set, divide the remains between
810 * them.
811 */
812 if (perc_missing) {
813 if (perc_missing == 1 && o->zone_split_nr[ddir] == 1)
814 perc = 100;
815 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
d2835319 816 struct zone_split *zsp = &o->zone_split[ddir][i];
e0a04ac1
JA
817
818 if (zsp->access_perc == (uint8_t) -1U)
819 zsp->access_perc = (100 - perc) / perc_missing;
820 }
821 }
822 if (sperc_missing) {
823 if (sperc_missing == 1 && o->zone_split_nr[ddir] == 1)
824 sperc = 100;
825 for (i = 0; i < o->zone_split_nr[ddir]; i++) {
d2835319 826 struct zone_split *zsp = &o->zone_split[ddir][i];
e0a04ac1
JA
827
828 if (zsp->size_perc == (uint8_t) -1U)
829 zsp->size_perc = (100 - sperc) / sperc_missing;
830 }
831 }
832
833 /*
834 * now sort based on percentages, for ease of lookup
835 */
d2835319 836 qsort(o->zone_split[ddir], o->zone_split_nr[ddir], sizeof(struct zone_split), zone_cmp);
e0a04ac1
JA
837 return 0;
838}
839
840static void __td_zone_gen_index(struct thread_data *td, enum fio_ddir ddir)
841{
842 unsigned int i, j, sprev, aprev;
843
844 td->zone_state_index[ddir] = malloc(sizeof(struct zone_split_index) * 100);
845
846 sprev = aprev = 0;
847 for (i = 0; i < td->o.zone_split_nr[ddir]; i++) {
848 struct zone_split *zsp = &td->o.zone_split[ddir][i];
849
850 for (j = aprev; j < aprev + zsp->access_perc; j++) {
851 struct zone_split_index *zsi = &td->zone_state_index[ddir][j];
852
853 zsi->size_perc = sprev + zsp->size_perc;
854 zsi->size_perc_prev = sprev;
855 }
856
857 aprev += zsp->access_perc;
858 sprev += zsp->size_perc;
859 }
860}
861
862/*
863 * Generate state table for indexes, so we don't have to do it inline from
864 * the hot IO path
865 */
866static void td_zone_gen_index(struct thread_data *td)
867{
868 int i;
869
870 td->zone_state_index = malloc(DDIR_RWDIR_CNT *
871 sizeof(struct zone_split_index *));
872
873 for (i = 0; i < DDIR_RWDIR_CNT; i++)
874 __td_zone_gen_index(td, i);
875}
876
e0a04ac1
JA
877static int parse_zoned_distribution(struct thread_data *td, const char *input)
878{
764593c0 879 char *str, *p;
e0a04ac1
JA
880 int i, ret = 0;
881
882 p = str = strdup(input);
883
884 strip_blank_front(&str);
885 strip_blank_end(str);
886
887 /* We expect it to start like that, bail if not */
888 if (strncmp(str, "zoned:", 6)) {
889 log_err("fio: mismatch in zoned input <%s>\n", str);
890 free(p);
891 return 1;
892 }
893 str += strlen("zoned:");
894
764593c0 895 ret = str_split_parse(td, str, zone_split_ddir);
e0a04ac1
JA
896
897 free(p);
898
899 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
900 int j;
901
902 dprint(FD_PARSE, "zone ddir %d (nr=%u): \n", i, td->o.zone_split_nr[i]);
903
904 for (j = 0; j < td->o.zone_split_nr[i]; j++) {
905 struct zone_split *zsp = &td->o.zone_split[i][j];
906
907 dprint(FD_PARSE, "\t%d: %u/%u\n", j, zsp->access_perc,
908 zsp->size_perc);
909 }
910 }
911
55baca06
JA
912 if (parse_dryrun()) {
913 int i;
914
915 for (i = 0; i < DDIR_RWDIR_CNT; i++) {
916 free(td->o.zone_split[i]);
917 td->o.zone_split[i] = NULL;
918 td->o.zone_split_nr[i] = 0;
919 }
920
921 return ret;
922 }
923
e0a04ac1
JA
924 if (!ret)
925 td_zone_gen_index(td);
dc4bffb8
JA
926 else {
927 for (i = 0; i < DDIR_RWDIR_CNT; i++)
928 td->o.zone_split_nr[i] = 0;
929 }
e0a04ac1
JA
930
931 return ret;
932}
933
e25839d4
JA
934static int str_random_distribution_cb(void *data, const char *str)
935{
936 struct thread_data *td = data;
937 double val;
938 char *nr;
939
925fee33 940 if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
c95f9404 941 val = FIO_DEF_ZIPF;
925fee33 942 else if (td->o.random_distribution == FIO_RAND_DIST_PARETO)
c95f9404 943 val = FIO_DEF_PARETO;
56d9fa4b
JA
944 else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
945 val = 0.0;
e0a04ac1
JA
946 else if (td->o.random_distribution == FIO_RAND_DIST_ZONED)
947 return parse_zoned_distribution(td, str);
925fee33 948 else
e25839d4
JA
949 return 0;
950
951 nr = get_opt_postfix(str);
88038bc7 952 if (nr && !str_to_float(nr, &val, 0)) {
e25839d4
JA
953 log_err("fio: random postfix parsing failed\n");
954 free(nr);
955 return 1;
956 }
957
078189c1
JA
958 free(nr);
959
18ded917
JA
960 if (td->o.random_distribution == FIO_RAND_DIST_ZIPF) {
961 if (val == 1.00) {
962 log_err("fio: zipf theta must different than 1.0\n");
963 return 1;
964 }
55baca06
JA
965 if (parse_dryrun())
966 return 0;
1e5324e7 967 td->o.zipf_theta.u.f = val;
56d9fa4b 968 } else if (td->o.random_distribution == FIO_RAND_DIST_PARETO) {
078189c1
JA
969 if (val <= 0.00 || val >= 1.00) {
970 log_err("fio: pareto input out of range (0 < input < 1.0)\n");
971 return 1;
972 }
55baca06
JA
973 if (parse_dryrun())
974 return 0;
1e5324e7 975 td->o.pareto_h.u.f = val;
3cdb8cf3
JA
976 } else {
977 if (val <= 0.00 || val >= 100.0) {
978 log_err("fio: normal deviation out of range (0 < input < 100.0)\n");
979 return 1;
980 }
55baca06
JA
981 if (parse_dryrun())
982 return 0;
f88cd222 983 td->o.gauss_dev.u.f = val;
3cdb8cf3 984 }
921c766f
JA
985
986 return 0;
987}
988
8e827d35 989/*
bcbfeefa 990 * Return next name in the string. Files are separated with ':'. If the ':'
8e827d35
JA
991 * is escaped with a '\', then that ':' is part of the filename and does not
992 * indicate a new file.
993 */
bcbfeefa 994static char *get_next_name(char **ptr)
8e827d35
JA
995{
996 char *str = *ptr;
997 char *p, *start;
998
999 if (!str || !strlen(str))
1000 return NULL;
1001
1002 start = str;
1003 do {
1004 /*
1005 * No colon, we are done
1006 */
1007 p = strchr(str, ':');
1008 if (!p) {
1009 *ptr = NULL;
1010 break;
1011 }
1012
1013 /*
1014 * We got a colon, but it's the first character. Skip and
1015 * continue
1016 */
1017 if (p == start) {
1018 str = ++start;
1019 continue;
1020 }
1021
1022 if (*(p - 1) != '\\') {
1023 *p = '\0';
1024 *ptr = p + 1;
1025 break;
1026 }
1027
1028 memmove(p - 1, p, strlen(p) + 1);
1029 str = p;
1030 } while (1);
1031
1032 return start;
1033}
1034
bcbfeefa
CE
1035
1036static int get_max_name_idx(char *input)
1037{
1038 unsigned int cur_idx;
1039 char *str, *p;
1040
1041 p = str = strdup(input);
1042 for (cur_idx = 0; ; cur_idx++)
1043 if (get_next_name(&str) == NULL)
1044 break;
1045
1046 free(p);
1047 return cur_idx;
1048}
1049
1050/*
1051 * Returns the directory at the index, indexes > entires will be
1052 * assigned via modulo division of the index
1053 */
e13c3b50 1054int set_name_idx(char *target, size_t tlen, char *input, int index)
bcbfeefa
CE
1055{
1056 unsigned int cur_idx;
1057 int len;
1058 char *fname, *str, *p;
1059
1060 p = str = strdup(input);
1061
1062 index %= get_max_name_idx(input);
1063 for (cur_idx = 0; cur_idx <= index; cur_idx++)
1064 fname = get_next_name(&str);
1065
72a703da 1066 if (client_sockaddr_str[0]) {
e13c3b50
JA
1067 len = snprintf(target, tlen, "%s/%s.", fname,
1068 client_sockaddr_str);
1069 } else
1070 len = snprintf(target, tlen, "%s/", fname);
72a703da 1071
e13c3b50 1072 target[tlen - 1] = '\0';
bcbfeefa
CE
1073 free(p);
1074
1075 return len;
1076}
1077
214e1eca
JA
1078static int str_filename_cb(void *data, const char *input)
1079{
1080 struct thread_data *td = data;
1081 char *fname, *str, *p;
1082
1083 p = str = strdup(input);
1084
1085 strip_blank_front(&str);
1086 strip_blank_end(str);
1087
1088 if (!td->files_index)
2dc1bbeb 1089 td->o.nr_files = 0;
214e1eca 1090
bcbfeefa 1091 while ((fname = get_next_name(&str)) != NULL) {
214e1eca
JA
1092 if (!strlen(fname))
1093 break;
5903e7b7 1094 add_file(td, fname, 0, 1);
214e1eca
JA
1095 }
1096
1097 free(p);
1098 return 0;
1099}
1100
bcbfeefa 1101static int str_directory_cb(void *data, const char fio_unused *unused)
214e1eca
JA
1102{
1103 struct thread_data *td = data;
1104 struct stat sb;
bcbfeefa
CE
1105 char *dirname, *str, *p;
1106 int ret = 0;
214e1eca 1107
f9633d72
JA
1108 if (parse_dryrun())
1109 return 0;
1110
bcbfeefa
CE
1111 p = str = strdup(td->o.directory);
1112 while ((dirname = get_next_name(&str)) != NULL) {
1113 if (lstat(dirname, &sb) < 0) {
1114 ret = errno;
921c766f 1115
bcbfeefa
CE
1116 log_err("fio: %s is not a directory\n", dirname);
1117 td_verror(td, ret, "lstat");
1118 goto out;
1119 }
1120 if (!S_ISDIR(sb.st_mode)) {
1121 log_err("fio: %s is not a directory\n", dirname);
1122 ret = 1;
1123 goto out;
1124 }
214e1eca
JA
1125 }
1126
bcbfeefa
CE
1127out:
1128 free(p);
1129 return ret;
214e1eca
JA
1130}
1131
1132static int str_opendir_cb(void *data, const char fio_unused *str)
1133{
1134 struct thread_data *td = data;
1135
52c0cea3
JA
1136 if (parse_dryrun())
1137 return 0;
1138
214e1eca 1139 if (!td->files_index)
2dc1bbeb 1140 td->o.nr_files = 0;
214e1eca 1141
2dc1bbeb 1142 return add_dir_files(td, td->o.opendir);
214e1eca
JA
1143}
1144
ce35b1ec
JA
1145static int str_buffer_pattern_cb(void *data, const char *input)
1146{
1147 struct thread_data *td = data;
1148 int ret;
1149
61b9861d
RP
1150 /* FIXME: for now buffer pattern does not support formats */
1151 ret = parse_and_fill_pattern(input, strlen(input), td->o.buffer_pattern,
1152 MAX_PATTERN_SIZE, NULL, 0, NULL, NULL);
1153 if (ret < 0)
1154 return 1;
ce35b1ec 1155
61b9861d
RP
1156 assert(ret != 0);
1157 td->o.buffer_pattern_bytes = ret;
1158 if (!td->o.compress_percentage)
1159 td->o.refill_buffers = 0;
1160 td->o.scramble_buffers = 0;
1161 td->o.zero_buffers = 0;
efcd9dcc 1162
61b9861d 1163 return 0;
ce35b1ec
JA
1164}
1165
bedc9dc2
JA
1166static int str_buffer_compress_cb(void *data, unsigned long long *il)
1167{
1168 struct thread_data *td = data;
1169
1170 td->flags |= TD_F_COMPRESS;
1171 td->o.compress_percentage = *il;
1172 return 0;
1173}
1174
5c94b008
JA
1175static int str_dedupe_cb(void *data, unsigned long long *il)
1176{
1177 struct thread_data *td = data;
1178
1179 td->flags |= TD_F_COMPRESS;
1180 td->o.dedupe_percentage = *il;
1181 td->o.refill_buffers = 1;
1182 return 0;
1183}
1184
ce35b1ec
JA
1185static int str_verify_pattern_cb(void *data, const char *input)
1186{
5f3bd0fd
JA
1187 struct pattern_fmt_desc fmt_desc[] = {
1188 {
1189 .fmt = "%o",
1190 .len = FIELD_SIZE(struct io_u *, offset),
1191 .paste = paste_blockoff
1192 }
1193 };
ce35b1ec
JA
1194 struct thread_data *td = data;
1195 int ret;
1196
61b9861d
RP
1197 td->o.verify_fmt_sz = ARRAY_SIZE(td->o.verify_fmt);
1198 ret = parse_and_fill_pattern(input, strlen(input), td->o.verify_pattern,
5f3bd0fd
JA
1199 MAX_PATTERN_SIZE, fmt_desc, sizeof(fmt_desc),
1200 td->o.verify_fmt, &td->o.verify_fmt_sz);
61b9861d
RP
1201 if (ret < 0)
1202 return 1;
efcd9dcc 1203
61b9861d
RP
1204 assert(ret != 0);
1205 td->o.verify_pattern_bytes = ret;
92bf48d5 1206 /*
b638d82f 1207 * VERIFY_* could already be set
92bf48d5 1208 */
61b9861d 1209 if (!fio_option_is_set(&td->o, verify))
92bf48d5 1210 td->o.verify = VERIFY_PATTERN;
efcd9dcc 1211
61b9861d 1212 return 0;
90059d65 1213}
214e1eca 1214
993bf48b
JA
1215static int str_gtod_reduce_cb(void *data, int *il)
1216{
1217 struct thread_data *td = data;
1218 int val = *il;
1219
02af0988 1220 td->o.disable_lat = !!val;
993bf48b
JA
1221 td->o.disable_clat = !!val;
1222 td->o.disable_slat = !!val;
1223 td->o.disable_bw = !!val;
0dc1bc03 1224 td->o.clat_percentiles = !val;
993bf48b
JA
1225 if (val)
1226 td->tv_cache_mask = 63;
1227
1228 return 0;
1229}
1230
7bb59102
JA
1231static int str_size_cb(void *data, unsigned long long *__val)
1232{
1233 struct thread_data *td = data;
1234 unsigned long long v = *__val;
1235
1236 if (parse_is_percent(v)) {
1237 td->o.size = 0;
1238 td->o.size_percent = -1ULL - v;
1239 } else
1240 td->o.size = v;
1241
1242 return 0;
1243}
1244
896cac2a
JA
1245static int rw_verify(struct fio_option *o, void *data)
1246{
1247 struct thread_data *td = data;
1248
1249 if (read_only && td_write(td)) {
1250 log_err("fio: job <%s> has write bit set, but fio is in"
1251 " read-only mode\n", td->o.name);
1252 return 1;
1253 }
1254
1255 return 0;
1256}
1257
276ca4f7 1258static int gtod_cpu_verify(struct fio_option *o, void *data)
29d43ff9 1259{
276ca4f7 1260#ifndef FIO_HAVE_CPU_AFFINITY
29d43ff9
JA
1261 struct thread_data *td = data;
1262
29d43ff9
JA
1263 if (td->o.gtod_cpu) {
1264 log_err("fio: platform must support CPU affinity for"
1265 "gettimeofday() offloading\n");
1266 return 1;
1267 }
1268#endif
1269
1270 return 0;
1271}
1272
214e1eca
JA
1273/*
1274 * Map of job/command line options
1275 */
9af4a244 1276struct fio_option fio_options[FIO_MAX_OPTS] = {
214e1eca
JA
1277 {
1278 .name = "description",
e8b0e958 1279 .lname = "Description of job",
214e1eca
JA
1280 .type = FIO_OPT_STR_STORE,
1281 .off1 = td_var_offset(description),
1282 .help = "Text job description",
e8b0e958 1283 .category = FIO_OPT_C_GENERAL,
0626037e 1284 .group = FIO_OPT_G_DESC,
214e1eca
JA
1285 },
1286 {
1287 .name = "name",
e8b0e958 1288 .lname = "Job name",
214e1eca
JA
1289 .type = FIO_OPT_STR_STORE,
1290 .off1 = td_var_offset(name),
1291 .help = "Name of this job",
e8b0e958 1292 .category = FIO_OPT_C_GENERAL,
0626037e 1293 .group = FIO_OPT_G_DESC,
214e1eca 1294 },
9cc8cb91
AK
1295 {
1296 .name = "wait_for",
1297 .lname = "Waitee name",
1298 .type = FIO_OPT_STR_STORE,
1299 .off1 = td_var_offset(wait_for),
1300 .help = "Name of the job this one wants to wait for before starting",
1301 .category = FIO_OPT_C_GENERAL,
1302 .group = FIO_OPT_G_DESC,
1303 },
214e1eca
JA
1304 {
1305 .name = "filename",
e8b0e958 1306 .lname = "Filename(s)",
214e1eca
JA
1307 .type = FIO_OPT_STR_STORE,
1308 .off1 = td_var_offset(filename),
1309 .cb = str_filename_cb,
f0d524b0 1310 .prio = -1, /* must come after "directory" */
214e1eca 1311 .help = "File(s) to use for the workload",
e8b0e958 1312 .category = FIO_OPT_C_FILE,
0626037e 1313 .group = FIO_OPT_G_FILENAME,
214e1eca 1314 },
90fef2d1 1315 {
e8b0e958
JA
1316 .name = "directory",
1317 .lname = "Directory",
1318 .type = FIO_OPT_STR_STORE,
1319 .off1 = td_var_offset(directory),
1320 .cb = str_directory_cb,
1321 .help = "Directory to store files in",
1322 .category = FIO_OPT_C_FILE,
0626037e 1323 .group = FIO_OPT_G_FILENAME,
90fef2d1 1324 },
de98bd30
JA
1325 {
1326 .name = "filename_format",
1327 .type = FIO_OPT_STR_STORE,
1328 .off1 = td_var_offset(filename_format),
1329 .prio = -1, /* must come after "directory" */
1330 .help = "Override default $jobname.$jobnum.$filenum naming",
1331 .def = "$jobname.$jobnum.$filenum",
93bb626a
JA
1332 .category = FIO_OPT_C_FILE,
1333 .group = FIO_OPT_G_FILENAME,
ad705bcb 1334 },
29c1349f
JA
1335 {
1336 .name = "lockfile",
e8b0e958 1337 .lname = "Lockfile",
4d4e80f2 1338 .type = FIO_OPT_STR,
4d4e80f2 1339 .off1 = td_var_offset(file_lock_mode),
29c1349f 1340 .help = "Lock file when doing IO to it",
bc6a0a5d 1341 .prio = 1,
29c1349f 1342 .parent = "filename",
d71c154c 1343 .hide = 0,
4d4e80f2 1344 .def = "none",
e8b0e958 1345 .category = FIO_OPT_C_FILE,
0626037e 1346 .group = FIO_OPT_G_FILENAME,
4d4e80f2
JA
1347 .posval = {
1348 { .ival = "none",
1349 .oval = FILE_LOCK_NONE,
1350 .help = "No file locking",
1351 },
1352 { .ival = "exclusive",
1353 .oval = FILE_LOCK_EXCLUSIVE,
1354 .help = "Exclusive file lock",
1355 },
1356 {
1357 .ival = "readwrite",
1358 .oval = FILE_LOCK_READWRITE,
1359 .help = "Read vs write lock",
1360 },
1361 },
29c1349f 1362 },
214e1eca
JA
1363 {
1364 .name = "opendir",
e8b0e958 1365 .lname = "Open directory",
214e1eca
JA
1366 .type = FIO_OPT_STR_STORE,
1367 .off1 = td_var_offset(opendir),
1368 .cb = str_opendir_cb,
1369 .help = "Recursively add files from this directory and down",
e8b0e958 1370 .category = FIO_OPT_C_FILE,
0626037e 1371 .group = FIO_OPT_G_FILENAME,
214e1eca
JA
1372 },
1373 {
1374 .name = "rw",
e8b0e958 1375 .lname = "Read/write",
d3aad8f2 1376 .alias = "readwrite",
214e1eca 1377 .type = FIO_OPT_STR,
211097b2 1378 .cb = str_rw_cb,
214e1eca
JA
1379 .off1 = td_var_offset(td_ddir),
1380 .help = "IO direction",
1381 .def = "read",
896cac2a 1382 .verify = rw_verify,
e8b0e958 1383 .category = FIO_OPT_C_IO,
0626037e 1384 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1385 .posval = {
1386 { .ival = "read",
1387 .oval = TD_DDIR_READ,
1388 .help = "Sequential read",
1389 },
1390 { .ival = "write",
1391 .oval = TD_DDIR_WRITE,
1392 .help = "Sequential write",
1393 },
6eaf09d6
SL
1394 { .ival = "trim",
1395 .oval = TD_DDIR_TRIM,
1396 .help = "Sequential trim",
1397 },
214e1eca
JA
1398 { .ival = "randread",
1399 .oval = TD_DDIR_RANDREAD,
1400 .help = "Random read",
1401 },
1402 { .ival = "randwrite",
1403 .oval = TD_DDIR_RANDWRITE,
1404 .help = "Random write",
1405 },
6eaf09d6
SL
1406 { .ival = "randtrim",
1407 .oval = TD_DDIR_RANDTRIM,
1408 .help = "Random trim",
1409 },
214e1eca
JA
1410 { .ival = "rw",
1411 .oval = TD_DDIR_RW,
1412 .help = "Sequential read and write mix",
1413 },
10b023db
JA
1414 { .ival = "readwrite",
1415 .oval = TD_DDIR_RW,
1416 .help = "Sequential read and write mix",
1417 },
214e1eca
JA
1418 { .ival = "randrw",
1419 .oval = TD_DDIR_RANDRW,
1420 .help = "Random read and write mix"
1421 },
82a90686
JA
1422 { .ival = "trimwrite",
1423 .oval = TD_DDIR_TRIMWRITE,
1424 .help = "Trim and write mix, trims preceding writes"
0e4dd95c 1425 },
214e1eca
JA
1426 },
1427 },
38dad62d
JA
1428 {
1429 .name = "rw_sequencer",
e8b0e958 1430 .lname = "RW Sequencer",
38dad62d
JA
1431 .type = FIO_OPT_STR,
1432 .off1 = td_var_offset(rw_seq),
1433 .help = "IO offset generator modifier",
1434 .def = "sequential",
e8b0e958 1435 .category = FIO_OPT_C_IO,
0626037e 1436 .group = FIO_OPT_G_IO_BASIC,
38dad62d
JA
1437 .posval = {
1438 { .ival = "sequential",
1439 .oval = RW_SEQ_SEQ,
1440 .help = "Generate sequential offsets",
1441 },
1442 { .ival = "identical",
1443 .oval = RW_SEQ_IDENT,
1444 .help = "Generate identical offsets",
1445 },
1446 },
1447 },
1448
214e1eca
JA
1449 {
1450 .name = "ioengine",
e8b0e958 1451 .lname = "IO Engine",
214e1eca
JA
1452 .type = FIO_OPT_STR_STORE,
1453 .off1 = td_var_offset(ioengine),
1454 .help = "IO engine to use",
58483fa4 1455 .def = FIO_PREFERRED_ENGINE,
e8b0e958 1456 .category = FIO_OPT_C_IO,
0626037e 1457 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1458 .posval = {
1459 { .ival = "sync",
1460 .help = "Use read/write",
1461 },
a31041ea 1462 { .ival = "psync",
1463 .help = "Use pread/pwrite",
1464 },
1d2af02a 1465 { .ival = "vsync",
03e20d68 1466 .help = "Use readv/writev",
1d2af02a 1467 },
07fc0acd
JA
1468#ifdef CONFIG_PWRITEV
1469 { .ival = "pvsync",
1470 .help = "Use preadv/pwritev",
1471 },
1472#endif
2cafffbe
JA
1473#ifdef CONFIG_PWRITEV
1474 { .ival = "pvsync2",
1475 .help = "Use preadv2/pwritev2",
1476 },
1477#endif
67bf9823 1478#ifdef CONFIG_LIBAIO
214e1eca
JA
1479 { .ival = "libaio",
1480 .help = "Linux native asynchronous IO",
1481 },
1482#endif
67bf9823 1483#ifdef CONFIG_POSIXAIO
214e1eca
JA
1484 { .ival = "posixaio",
1485 .help = "POSIX asynchronous IO",
1486 },
417f0068 1487#endif
997843cb 1488#ifdef CONFIG_SOLARISAIO
417f0068
JA
1489 { .ival = "solarisaio",
1490 .help = "Solaris native asynchronous IO",
1491 },
214e1eca 1492#endif
4700b234 1493#ifdef CONFIG_WINDOWSAIO
03e20d68 1494 { .ival = "windowsaio",
3be80071 1495 .help = "Windows native asynchronous IO"
de890a1e 1496 },
fc5c0345
DG
1497#endif
1498#ifdef CONFIG_RBD
1499 { .ival = "rbd",
1500 .help = "Rados Block Device asynchronous IO"
1501 },
3be80071 1502#endif
214e1eca 1503 { .ival = "mmap",
03e20d68 1504 .help = "Memory mapped IO"
214e1eca 1505 },
67bf9823 1506#ifdef CONFIG_LINUX_SPLICE
214e1eca
JA
1507 { .ival = "splice",
1508 .help = "splice/vmsplice based IO",
1509 },
9cce02e8
JA
1510 { .ival = "netsplice",
1511 .help = "splice/vmsplice to/from the network",
1512 },
214e1eca
JA
1513#endif
1514#ifdef FIO_HAVE_SGIO
1515 { .ival = "sg",
1516 .help = "SCSI generic v3 IO",
1517 },
1518#endif
1519 { .ival = "null",
1520 .help = "Testing engine (no data transfer)",
1521 },
1522 { .ival = "net",
1523 .help = "Network IO",
1524 },
214e1eca 1525 { .ival = "cpuio",
03e20d68 1526 .help = "CPU cycle burner engine",
214e1eca 1527 },
67bf9823 1528#ifdef CONFIG_GUASI
b8c82a46
JA
1529 { .ival = "guasi",
1530 .help = "GUASI IO engine",
1531 },
79a43187
JA
1532#endif
1533#ifdef FIO_HAVE_BINJECT
1534 { .ival = "binject",
1535 .help = "binject direct inject block engine",
1536 },
21b8aee8 1537#endif
67bf9823 1538#ifdef CONFIG_RDMA
21b8aee8 1539 { .ival = "rdma",
1540 .help = "RDMA IO engine",
1541 },
8200b8c7 1542#endif
67bf9823 1543#ifdef CONFIG_FUSION_AW
8200b8c7
JA
1544 { .ival = "fusion-aw-sync",
1545 .help = "Fusion-io atomic write engine",
1546 },
1ecc95ca 1547#endif
997843cb 1548#ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
1ecc95ca
JA
1549 { .ival = "e4defrag",
1550 .help = "ext4 defrag engine",
1551 },
1552#endif
997843cb 1553#ifdef CONFIG_LINUX_FALLOCATE
1ecc95ca
JA
1554 { .ival = "falloc",
1555 .help = "fallocate() file based engine",
1556 },
b8c82a46 1557#endif
a7c386f4 1558#ifdef CONFIG_GFAPI
1559 { .ival = "gfapi",
cc47f094 1560 .help = "Glusterfs libgfapi(sync) based engine"
1561 },
1562 { .ival = "gfapi_async",
1563 .help = "Glusterfs libgfapi(async) based engine"
a7c386f4 1564 },
1565#endif
1b10477b 1566#ifdef CONFIG_LIBHDFS
b74e419e 1567 { .ival = "libhdfs",
1b10477b
MM
1568 .help = "Hadoop Distributed Filesystem (HDFS) engine"
1569 },
1570#endif
214e1eca
JA
1571 { .ival = "external",
1572 .help = "Load external engine (append name)",
1573 },
1574 },
1575 },
1576 {
1577 .name = "iodepth",
e8b0e958 1578 .lname = "IO Depth",
214e1eca
JA
1579 .type = FIO_OPT_INT,
1580 .off1 = td_var_offset(iodepth),
03e20d68 1581 .help = "Number of IO buffers to keep in flight",
757aff4f 1582 .minval = 1,
20eb06bd 1583 .interval = 1,
214e1eca 1584 .def = "1",
e8b0e958 1585 .category = FIO_OPT_C_IO,
0626037e 1586 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1587 },
1588 {
1589 .name = "iodepth_batch",
e8b0e958 1590 .lname = "IO Depth batch",
4950421a 1591 .alias = "iodepth_batch_submit",
214e1eca
JA
1592 .type = FIO_OPT_INT,
1593 .off1 = td_var_offset(iodepth_batch),
d65db441 1594 .help = "Number of IO buffers to submit in one go",
afdf9352 1595 .parent = "iodepth",
d71c154c 1596 .hide = 1,
a2e6f8ac 1597 .minval = 1,
20eb06bd 1598 .interval = 1,
a2e6f8ac 1599 .def = "1",
e8b0e958 1600 .category = FIO_OPT_C_IO,
0626037e 1601 .group = FIO_OPT_G_IO_BASIC,
4950421a
JA
1602 },
1603 {
82407585
RP
1604 .name = "iodepth_batch_complete_min",
1605 .lname = "Min IO depth batch complete",
1606 .alias = "iodepth_batch_complete",
4950421a 1607 .type = FIO_OPT_INT,
82407585
RP
1608 .off1 = td_var_offset(iodepth_batch_complete_min),
1609 .help = "Min number of IO buffers to retrieve in one go",
4950421a 1610 .parent = "iodepth",
d71c154c 1611 .hide = 1,
4950421a 1612 .minval = 0,
20eb06bd 1613 .interval = 1,
4950421a 1614 .def = "1",
e8b0e958 1615 .category = FIO_OPT_C_IO,
0626037e 1616 .group = FIO_OPT_G_IO_BASIC,
214e1eca 1617 },
82407585
RP
1618 {
1619 .name = "iodepth_batch_complete_max",
1620 .lname = "Max IO depth batch complete",
1621 .type = FIO_OPT_INT,
1622 .off1 = td_var_offset(iodepth_batch_complete_max),
1623 .help = "Max number of IO buffers to retrieve in one go",
1624 .parent = "iodepth",
1625 .hide = 1,
1626 .minval = 0,
1627 .interval = 1,
1628 .category = FIO_OPT_C_IO,
1629 .group = FIO_OPT_G_IO_BASIC,
1630 },
214e1eca
JA
1631 {
1632 .name = "iodepth_low",
e8b0e958 1633 .lname = "IO Depth batch low",
214e1eca
JA
1634 .type = FIO_OPT_INT,
1635 .off1 = td_var_offset(iodepth_low),
1636 .help = "Low water mark for queuing depth",
afdf9352 1637 .parent = "iodepth",
d71c154c 1638 .hide = 1,
20eb06bd 1639 .interval = 1,
e8b0e958 1640 .category = FIO_OPT_C_IO,
0626037e 1641 .group = FIO_OPT_G_IO_BASIC,
214e1eca 1642 },
a9da8ab2
JA
1643 {
1644 .name = "io_submit_mode",
1645 .lname = "IO submit mode",
1646 .type = FIO_OPT_STR,
1647 .off1 = td_var_offset(io_submit_mode),
1648 .help = "How IO submissions and completions are done",
1649 .def = "inline",
1650 .category = FIO_OPT_C_IO,
1651 .group = FIO_OPT_G_IO_BASIC,
1652 .posval = {
1653 { .ival = "inline",
1654 .oval = IO_MODE_INLINE,
1655 .help = "Submit and complete IO inline",
1656 },
1657 { .ival = "offload",
1658 .oval = IO_MODE_OFFLOAD,
1659 .help = "Offload submit and complete to threads",
1660 },
1661 },
1662 },
214e1eca
JA
1663 {
1664 .name = "size",
e8b0e958 1665 .lname = "Size",
214e1eca 1666 .type = FIO_OPT_STR_VAL,
7bb59102 1667 .cb = str_size_cb,
a8523a6a 1668 .off1 = td_var_offset(size),
214e1eca 1669 .help = "Total size of device or files",
20eb06bd 1670 .interval = 1024 * 1024,
e8b0e958
JA
1671 .category = FIO_OPT_C_IO,
1672 .group = FIO_OPT_G_INVALID,
214e1eca 1673 },
77731b29 1674 {
a4d3b4db
JA
1675 .name = "io_size",
1676 .alias = "io_limit",
1677 .lname = "IO Size",
77731b29
JA
1678 .type = FIO_OPT_STR_VAL,
1679 .off1 = td_var_offset(io_limit),
1680 .interval = 1024 * 1024,
1681 .category = FIO_OPT_C_IO,
1682 .group = FIO_OPT_G_INVALID,
1683 },
aa31f1f1
SL
1684 {
1685 .name = "fill_device",
e8b0e958 1686 .lname = "Fill device",
74586c1e 1687 .alias = "fill_fs",
aa31f1f1
SL
1688 .type = FIO_OPT_BOOL,
1689 .off1 = td_var_offset(fill_device),
1690 .help = "Write until an ENOSPC error occurs",
1691 .def = "0",
e8b0e958
JA
1692 .category = FIO_OPT_C_FILE,
1693 .group = FIO_OPT_G_INVALID,
aa31f1f1 1694 },
214e1eca
JA
1695 {
1696 .name = "filesize",
e8b0e958 1697 .lname = "File size",
214e1eca
JA
1698 .type = FIO_OPT_STR_VAL,
1699 .off1 = td_var_offset(file_size_low),
1700 .off2 = td_var_offset(file_size_high),
c3edbdba 1701 .minval = 1,
214e1eca 1702 .help = "Size of individual files",
20eb06bd 1703 .interval = 1024 * 1024,
e8b0e958
JA
1704 .category = FIO_OPT_C_FILE,
1705 .group = FIO_OPT_G_INVALID,
214e1eca 1706 },
bedc9dc2
JA
1707 {
1708 .name = "file_append",
1709 .lname = "File append",
1710 .type = FIO_OPT_BOOL,
1711 .off1 = td_var_offset(file_append),
1712 .help = "IO will start at the end of the file(s)",
1713 .def = "0",
1714 .category = FIO_OPT_C_FILE,
1715 .group = FIO_OPT_G_INVALID,
1716 },
67a1000f
JA
1717 {
1718 .name = "offset",
e8b0e958 1719 .lname = "IO offset",
67a1000f
JA
1720 .alias = "fileoffset",
1721 .type = FIO_OPT_STR_VAL,
1722 .off1 = td_var_offset(start_offset),
1723 .help = "Start IO from this offset",
1724 .def = "0",
20eb06bd 1725 .interval = 1024 * 1024,
e8b0e958
JA
1726 .category = FIO_OPT_C_IO,
1727 .group = FIO_OPT_G_INVALID,
67a1000f 1728 },
2d7cd868
JA
1729 {
1730 .name = "offset_increment",
e8b0e958 1731 .lname = "IO offset increment",
2d7cd868
JA
1732 .type = FIO_OPT_STR_VAL,
1733 .off1 = td_var_offset(offset_increment),
1734 .help = "What is the increment from one offset to the next",
1735 .parent = "offset",
d71c154c 1736 .hide = 1,
2d7cd868 1737 .def = "0",
20eb06bd 1738 .interval = 1024 * 1024,
e8b0e958
JA
1739 .category = FIO_OPT_C_IO,
1740 .group = FIO_OPT_G_INVALID,
2d7cd868 1741 },
ddf24e42
JA
1742 {
1743 .name = "number_ios",
1744 .lname = "Number of IOs to perform",
1745 .type = FIO_OPT_STR_VAL,
1746 .off1 = td_var_offset(number_ios),
be3fec7d 1747 .help = "Force job completion after this number of IOs",
ddf24e42
JA
1748 .def = "0",
1749 .category = FIO_OPT_C_IO,
1750 .group = FIO_OPT_G_INVALID,
1751 },
214e1eca
JA
1752 {
1753 .name = "bs",
e8b0e958 1754 .lname = "Block size",
d3aad8f2 1755 .alias = "blocksize",
e01b22b8 1756 .type = FIO_OPT_INT,
214e1eca
JA
1757 .off1 = td_var_offset(bs[DDIR_READ]),
1758 .off2 = td_var_offset(bs[DDIR_WRITE]),
6eaf09d6 1759 .off3 = td_var_offset(bs[DDIR_TRIM]),
c3edbdba 1760 .minval = 1,
214e1eca
JA
1761 .help = "Block size unit",
1762 .def = "4k",
67a1000f 1763 .parent = "rw",
d71c154c 1764 .hide = 1,
20eb06bd 1765 .interval = 512,
e8b0e958
JA
1766 .category = FIO_OPT_C_IO,
1767 .group = FIO_OPT_G_INVALID,
214e1eca 1768 },
2b7a01d0
JA
1769 {
1770 .name = "ba",
e8b0e958 1771 .lname = "Block size align",
2b7a01d0 1772 .alias = "blockalign",
e01b22b8 1773 .type = FIO_OPT_INT,
2b7a01d0
JA
1774 .off1 = td_var_offset(ba[DDIR_READ]),
1775 .off2 = td_var_offset(ba[DDIR_WRITE]),
6eaf09d6 1776 .off3 = td_var_offset(ba[DDIR_TRIM]),
2b7a01d0
JA
1777 .minval = 1,
1778 .help = "IO block offset alignment",
1779 .parent = "rw",
d71c154c 1780 .hide = 1,
20eb06bd 1781 .interval = 512,
e8b0e958
JA
1782 .category = FIO_OPT_C_IO,
1783 .group = FIO_OPT_G_INVALID,
2b7a01d0 1784 },
214e1eca
JA
1785 {
1786 .name = "bsrange",
e8b0e958 1787 .lname = "Block size range",
d3aad8f2 1788 .alias = "blocksize_range",
214e1eca
JA
1789 .type = FIO_OPT_RANGE,
1790 .off1 = td_var_offset(min_bs[DDIR_READ]),
1791 .off2 = td_var_offset(max_bs[DDIR_READ]),
1792 .off3 = td_var_offset(min_bs[DDIR_WRITE]),
1793 .off4 = td_var_offset(max_bs[DDIR_WRITE]),
6eaf09d6
SL
1794 .off5 = td_var_offset(min_bs[DDIR_TRIM]),
1795 .off6 = td_var_offset(max_bs[DDIR_TRIM]),
c3edbdba 1796 .minval = 1,
214e1eca 1797 .help = "Set block size range (in more detail than bs)",
67a1000f 1798 .parent = "rw",
d71c154c 1799 .hide = 1,
20eb06bd 1800 .interval = 4096,
e8b0e958
JA
1801 .category = FIO_OPT_C_IO,
1802 .group = FIO_OPT_G_INVALID,
214e1eca 1803 },
564ca972
JA
1804 {
1805 .name = "bssplit",
e8b0e958 1806 .lname = "Block size split",
564ca972
JA
1807 .type = FIO_OPT_STR,
1808 .cb = str_bssplit_cb,
a8523a6a 1809 .off1 = td_var_offset(bssplit),
564ca972
JA
1810 .help = "Set a specific mix of block sizes",
1811 .parent = "rw",
d71c154c 1812 .hide = 1,
e8b0e958
JA
1813 .category = FIO_OPT_C_IO,
1814 .group = FIO_OPT_G_INVALID,
564ca972 1815 },
214e1eca
JA
1816 {
1817 .name = "bs_unaligned",
e8b0e958 1818 .lname = "Block size unaligned",
d3aad8f2 1819 .alias = "blocksize_unaligned",
214e1eca
JA
1820 .type = FIO_OPT_STR_SET,
1821 .off1 = td_var_offset(bs_unaligned),
1822 .help = "Don't sector align IO buffer sizes",
67a1000f 1823 .parent = "rw",
d71c154c 1824 .hide = 1,
e8b0e958
JA
1825 .category = FIO_OPT_C_IO,
1826 .group = FIO_OPT_G_INVALID,
214e1eca 1827 },
6aca9b3d
JA
1828 {
1829 .name = "bs_is_seq_rand",
1830 .lname = "Block size division is seq/random (not read/write)",
1831 .type = FIO_OPT_BOOL,
1832 .off1 = td_var_offset(bs_is_seq_rand),
86d59660 1833 .help = "Consider any blocksize setting to be sequential,random",
6aca9b3d
JA
1834 .def = "0",
1835 .parent = "blocksize",
1836 .category = FIO_OPT_C_IO,
1837 .group = FIO_OPT_G_INVALID,
1838 },
214e1eca
JA
1839 {
1840 .name = "randrepeat",
e8b0e958 1841 .lname = "Random repeatable",
214e1eca
JA
1842 .type = FIO_OPT_BOOL,
1843 .off1 = td_var_offset(rand_repeatable),
1844 .help = "Use repeatable random IO pattern",
1845 .def = "1",
67a1000f 1846 .parent = "rw",
d71c154c 1847 .hide = 1,
e8b0e958 1848 .category = FIO_OPT_C_IO,
3ceb458f 1849 .group = FIO_OPT_G_RANDOM,
214e1eca 1850 },
04778baf
JA
1851 {
1852 .name = "randseed",
1853 .lname = "The random generator seed",
363cffa7 1854 .type = FIO_OPT_STR_VAL,
04778baf
JA
1855 .off1 = td_var_offset(rand_seed),
1856 .help = "Set the random generator seed value",
40fe5e7b 1857 .def = "0x89",
04778baf
JA
1858 .parent = "rw",
1859 .category = FIO_OPT_C_IO,
1860 .group = FIO_OPT_G_RANDOM,
1861 },
2615cc4b
JA
1862 {
1863 .name = "use_os_rand",
e8b0e958 1864 .lname = "Use OS random",
54a21917
JA
1865 .type = FIO_OPT_DEPRECATED,
1866 .off1 = td_var_offset(dep_use_os_rand),
e8b0e958 1867 .category = FIO_OPT_C_IO,
3ceb458f 1868 .group = FIO_OPT_G_RANDOM,
2615cc4b 1869 },
214e1eca
JA
1870 {
1871 .name = "norandommap",
e8b0e958 1872 .lname = "No randommap",
214e1eca
JA
1873 .type = FIO_OPT_STR_SET,
1874 .off1 = td_var_offset(norandommap),
1875 .help = "Accept potential duplicate random blocks",
67a1000f 1876 .parent = "rw",
d71c154c 1877 .hide = 1,
b2452a43 1878 .hide_on_set = 1,
e8b0e958 1879 .category = FIO_OPT_C_IO,
3ceb458f 1880 .group = FIO_OPT_G_RANDOM,
214e1eca 1881 },
2b386d25
JA
1882 {
1883 .name = "softrandommap",
e8b0e958 1884 .lname = "Soft randommap",
2b386d25
JA
1885 .type = FIO_OPT_BOOL,
1886 .off1 = td_var_offset(softrandommap),
f66ab3c8 1887 .help = "Set norandommap if randommap allocation fails",
2b386d25 1888 .parent = "norandommap",
d71c154c 1889 .hide = 1,
2b386d25 1890 .def = "0",
e8b0e958 1891 .category = FIO_OPT_C_IO,
3ceb458f 1892 .group = FIO_OPT_G_RANDOM,
2b386d25 1893 },
8055e41d
JA
1894 {
1895 .name = "random_generator",
1896 .type = FIO_OPT_STR,
1897 .off1 = td_var_offset(random_generator),
1898 .help = "Type of random number generator to use",
1899 .def = "tausworthe",
1900 .posval = {
1901 { .ival = "tausworthe",
1902 .oval = FIO_RAND_GEN_TAUSWORTHE,
1903 .help = "Strong Tausworthe generator",
1904 },
1905 { .ival = "lfsr",
1906 .oval = FIO_RAND_GEN_LFSR,
1907 .help = "Variable length LFSR",
1908 },
c3546b53
JA
1909 {
1910 .ival = "tausworthe64",
1911 .oval = FIO_RAND_GEN_TAUSWORTHE64,
1912 .help = "64-bit Tausworthe variant",
1913 },
8055e41d 1914 },
48107598
JA
1915 .category = FIO_OPT_C_IO,
1916 .group = FIO_OPT_G_RANDOM,
8055e41d 1917 },
e25839d4
JA
1918 {
1919 .name = "random_distribution",
1920 .type = FIO_OPT_STR,
1921 .off1 = td_var_offset(random_distribution),
1922 .cb = str_random_distribution_cb,
1923 .help = "Random offset distribution generator",
1924 .def = "random",
1925 .posval = {
1926 { .ival = "random",
1927 .oval = FIO_RAND_DIST_RANDOM,
1928 .help = "Completely random",
1929 },
1930 { .ival = "zipf",
1931 .oval = FIO_RAND_DIST_ZIPF,
1932 .help = "Zipf distribution",
1933 },
925fee33
JA
1934 { .ival = "pareto",
1935 .oval = FIO_RAND_DIST_PARETO,
1936 .help = "Pareto distribution",
1937 },
56d9fa4b
JA
1938 { .ival = "normal",
1939 .oval = FIO_RAND_DIST_GAUSS,
1940 .help = "Normal (gaussian) distribution",
1941 },
e0a04ac1
JA
1942 { .ival = "zoned",
1943 .oval = FIO_RAND_DIST_ZONED,
1944 .help = "Zoned random distribution",
1945 },
1946
e25839d4 1947 },
48107598
JA
1948 .category = FIO_OPT_C_IO,
1949 .group = FIO_OPT_G_RANDOM,
e25839d4 1950 },
211c9b89
JA
1951 {
1952 .name = "percentage_random",
1953 .lname = "Percentage Random",
1954 .type = FIO_OPT_INT,
d9472271
JA
1955 .off1 = td_var_offset(perc_rand[DDIR_READ]),
1956 .off2 = td_var_offset(perc_rand[DDIR_WRITE]),
1957 .off3 = td_var_offset(perc_rand[DDIR_TRIM]),
211c9b89
JA
1958 .maxval = 100,
1959 .help = "Percentage of seq/random mix that should be random",
d9472271 1960 .def = "100,100,100",
211c9b89
JA
1961 .interval = 5,
1962 .inverse = "percentage_sequential",
1963 .category = FIO_OPT_C_IO,
1964 .group = FIO_OPT_G_RANDOM,
1965 },
1966 {
1967 .name = "percentage_sequential",
1968 .lname = "Percentage Sequential",
d9472271 1969 .type = FIO_OPT_DEPRECATED,
211c9b89
JA
1970 .category = FIO_OPT_C_IO,
1971 .group = FIO_OPT_G_RANDOM,
1972 },
56e2a5fc
CE
1973 {
1974 .name = "allrandrepeat",
1975 .type = FIO_OPT_BOOL,
1976 .off1 = td_var_offset(allrand_repeatable),
1977 .help = "Use repeatable random numbers for everything",
1978 .def = "0",
a869d9c6
JA
1979 .category = FIO_OPT_C_IO,
1980 .group = FIO_OPT_G_RANDOM,
56e2a5fc 1981 },
214e1eca
JA
1982 {
1983 .name = "nrfiles",
e8b0e958 1984 .lname = "Number of files",
d7c8be03 1985 .alias = "nr_files",
214e1eca
JA
1986 .type = FIO_OPT_INT,
1987 .off1 = td_var_offset(nr_files),
1988 .help = "Split job workload between this number of files",
1989 .def = "1",
20eb06bd 1990 .interval = 1,
e8b0e958
JA
1991 .category = FIO_OPT_C_FILE,
1992 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1993 },
1994 {
1995 .name = "openfiles",
e8b0e958 1996 .lname = "Number of open files",
214e1eca
JA
1997 .type = FIO_OPT_INT,
1998 .off1 = td_var_offset(open_files),
1999 .help = "Number of files to keep open at the same time",
e8b0e958
JA
2000 .category = FIO_OPT_C_FILE,
2001 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2002 },
2003 {
2004 .name = "file_service_type",
e8b0e958 2005 .lname = "File service type",
214e1eca
JA
2006 .type = FIO_OPT_STR,
2007 .cb = str_fst_cb,
2008 .off1 = td_var_offset(file_service_type),
2009 .help = "How to select which file to service next",
2010 .def = "roundrobin",
e8b0e958
JA
2011 .category = FIO_OPT_C_FILE,
2012 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2013 .posval = {
2014 { .ival = "random",
2015 .oval = FIO_FSERVICE_RANDOM,
2016 .help = "Choose a file at random",
2017 },
2018 { .ival = "roundrobin",
2019 .oval = FIO_FSERVICE_RR,
2020 .help = "Round robin select files",
2021 },
a086c257
JA
2022 { .ival = "sequential",
2023 .oval = FIO_FSERVICE_SEQ,
2024 .help = "Finish one file before moving to the next",
2025 },
214e1eca 2026 },
67a1000f 2027 .parent = "nrfiles",
d71c154c 2028 .hide = 1,
67a1000f 2029 },
97ac992c 2030#ifdef CONFIG_POSIX_FALLOCATE
7bc8c2cf
JA
2031 {
2032 .name = "fallocate",
e8b0e958 2033 .lname = "Fallocate",
a596f047
EG
2034 .type = FIO_OPT_STR,
2035 .off1 = td_var_offset(fallocate_mode),
2036 .help = "Whether pre-allocation is performed when laying out files",
2037 .def = "posix",
e8b0e958
JA
2038 .category = FIO_OPT_C_FILE,
2039 .group = FIO_OPT_G_INVALID,
a596f047
EG
2040 .posval = {
2041 { .ival = "none",
2042 .oval = FIO_FALLOCATE_NONE,
2043 .help = "Do not pre-allocate space",
2044 },
2045 { .ival = "posix",
2046 .oval = FIO_FALLOCATE_POSIX,
2047 .help = "Use posix_fallocate()",
2048 },
97ac992c 2049#ifdef CONFIG_LINUX_FALLOCATE
a596f047
EG
2050 { .ival = "keep",
2051 .oval = FIO_FALLOCATE_KEEP_SIZE,
2052 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
2053 },
7bc8c2cf 2054#endif
a596f047
EG
2055 /* Compatibility with former boolean values */
2056 { .ival = "0",
2057 .oval = FIO_FALLOCATE_NONE,
2058 .help = "Alias for 'none'",
2059 },
2060 { .ival = "1",
2061 .oval = FIO_FALLOCATE_POSIX,
2062 .help = "Alias for 'posix'",
2063 },
2064 },
2065 },
97ac992c 2066#endif /* CONFIG_POSIX_FALLOCATE */
67a1000f
JA
2067 {
2068 .name = "fadvise_hint",
e8b0e958 2069 .lname = "Fadvise hint",
67a1000f
JA
2070 .type = FIO_OPT_BOOL,
2071 .off1 = td_var_offset(fadvise_hint),
2072 .help = "Use fadvise() to advise the kernel on IO pattern",
2073 .def = "1",
e8b0e958
JA
2074 .category = FIO_OPT_C_FILE,
2075 .group = FIO_OPT_G_INVALID,
214e1eca 2076 },
37659335
JA
2077#ifdef FIO_HAVE_STREAMID
2078 {
2079 .name = "fadvise_stream",
2080 .lname = "Fadvise stream",
2081 .type = FIO_OPT_INT,
2082 .off1 = td_var_offset(fadvise_stream),
2083 .help = "Use fadvise() to set stream ID",
2084 .category = FIO_OPT_C_FILE,
2085 .group = FIO_OPT_G_INVALID,
2086 },
2087#endif
214e1eca
JA
2088 {
2089 .name = "fsync",
e8b0e958 2090 .lname = "Fsync",
214e1eca
JA
2091 .type = FIO_OPT_INT,
2092 .off1 = td_var_offset(fsync_blocks),
2093 .help = "Issue fsync for writes every given number of blocks",
2094 .def = "0",
20eb06bd 2095 .interval = 1,
e8b0e958
JA
2096 .category = FIO_OPT_C_FILE,
2097 .group = FIO_OPT_G_INVALID,
214e1eca 2098 },
5f9099ea
JA
2099 {
2100 .name = "fdatasync",
e8b0e958 2101 .lname = "Fdatasync",
5f9099ea
JA
2102 .type = FIO_OPT_INT,
2103 .off1 = td_var_offset(fdatasync_blocks),
2104 .help = "Issue fdatasync for writes every given number of blocks",
2105 .def = "0",
20eb06bd 2106 .interval = 1,
e8b0e958
JA
2107 .category = FIO_OPT_C_FILE,
2108 .group = FIO_OPT_G_INVALID,
5f9099ea 2109 },
1ef2b6be
JA
2110 {
2111 .name = "write_barrier",
e8b0e958 2112 .lname = "Write barrier",
1ef2b6be
JA
2113 .type = FIO_OPT_INT,
2114 .off1 = td_var_offset(barrier_blocks),
2115 .help = "Make every Nth write a barrier write",
2116 .def = "0",
20eb06bd 2117 .interval = 1,
e8b0e958
JA
2118 .category = FIO_OPT_C_IO,
2119 .group = FIO_OPT_G_INVALID,
1ef2b6be 2120 },
67bf9823 2121#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
2122 {
2123 .name = "sync_file_range",
e8b0e958 2124 .lname = "Sync file range",
44f29692
JA
2125 .posval = {
2126 { .ival = "wait_before",
2127 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
2128 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
ebadc0ce 2129 .orval = 1,
44f29692
JA
2130 },
2131 { .ival = "write",
2132 .oval = SYNC_FILE_RANGE_WRITE,
2133 .help = "SYNC_FILE_RANGE_WRITE",
ebadc0ce 2134 .orval = 1,
44f29692
JA
2135 },
2136 {
2137 .ival = "wait_after",
2138 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
2139 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
ebadc0ce 2140 .orval = 1,
44f29692
JA
2141 },
2142 },
3843deb3 2143 .type = FIO_OPT_STR_MULTI,
44f29692
JA
2144 .cb = str_sfr_cb,
2145 .off1 = td_var_offset(sync_file_range),
2146 .help = "Use sync_file_range()",
e8b0e958
JA
2147 .category = FIO_OPT_C_FILE,
2148 .group = FIO_OPT_G_INVALID,
44f29692
JA
2149 },
2150#endif
214e1eca
JA
2151 {
2152 .name = "direct",
e8b0e958 2153 .lname = "Direct I/O",
214e1eca
JA
2154 .type = FIO_OPT_BOOL,
2155 .off1 = td_var_offset(odirect),
2156 .help = "Use O_DIRECT IO (negates buffered)",
2157 .def = "0",
a01a1bc5 2158 .inverse = "buffered",
e8b0e958 2159 .category = FIO_OPT_C_IO,
3ceb458f 2160 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2161 },
d01612f3
CM
2162 {
2163 .name = "atomic",
2164 .lname = "Atomic I/O",
2165 .type = FIO_OPT_BOOL,
2166 .off1 = td_var_offset(oatomic),
2167 .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
2168 .def = "0",
2169 .category = FIO_OPT_C_IO,
2170 .group = FIO_OPT_G_IO_TYPE,
2171 },
214e1eca
JA
2172 {
2173 .name = "buffered",
e8b0e958 2174 .lname = "Buffered I/O",
214e1eca
JA
2175 .type = FIO_OPT_BOOL,
2176 .off1 = td_var_offset(odirect),
2177 .neg = 1,
2178 .help = "Use buffered IO (negates direct)",
2179 .def = "1",
a01a1bc5 2180 .inverse = "direct",
e8b0e958 2181 .category = FIO_OPT_C_IO,
3ceb458f 2182 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2183 },
2184 {
2185 .name = "overwrite",
e8b0e958 2186 .lname = "Overwrite",
214e1eca
JA
2187 .type = FIO_OPT_BOOL,
2188 .off1 = td_var_offset(overwrite),
2189 .help = "When writing, set whether to overwrite current data",
2190 .def = "0",
e8b0e958
JA
2191 .category = FIO_OPT_C_FILE,
2192 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2193 },
2194 {
2195 .name = "loops",
e8b0e958 2196 .lname = "Loops",
214e1eca
JA
2197 .type = FIO_OPT_INT,
2198 .off1 = td_var_offset(loops),
2199 .help = "Number of times to run the job",
2200 .def = "1",
20eb06bd 2201 .interval = 1,
e8b0e958 2202 .category = FIO_OPT_C_GENERAL,
a1f6afec 2203 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2204 },
2205 {
2206 .name = "numjobs",
e8b0e958 2207 .lname = "Number of jobs",
214e1eca
JA
2208 .type = FIO_OPT_INT,
2209 .off1 = td_var_offset(numjobs),
2210 .help = "Duplicate this job this many times",
2211 .def = "1",
20eb06bd 2212 .interval = 1,
e8b0e958 2213 .category = FIO_OPT_C_GENERAL,
a1f6afec 2214 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2215 },
2216 {
2217 .name = "startdelay",
e8b0e958 2218 .lname = "Start delay",
a5737c93 2219 .type = FIO_OPT_STR_VAL_TIME,
214e1eca 2220 .off1 = td_var_offset(start_delay),
23ed19b0 2221 .off2 = td_var_offset(start_delay_high),
214e1eca
JA
2222 .help = "Only start job when this period has passed",
2223 .def = "0",
0de5b26f 2224 .is_seconds = 1,
88038bc7 2225 .is_time = 1,
e8b0e958 2226 .category = FIO_OPT_C_GENERAL,
a1f6afec 2227 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2228 },
2229 {
2230 .name = "runtime",
e8b0e958 2231 .lname = "Runtime",
214e1eca
JA
2232 .alias = "timeout",
2233 .type = FIO_OPT_STR_VAL_TIME,
2234 .off1 = td_var_offset(timeout),
2235 .help = "Stop workload when this amount of time has passed",
2236 .def = "0",
0de5b26f 2237 .is_seconds = 1,
88038bc7 2238 .is_time = 1,
e8b0e958 2239 .category = FIO_OPT_C_GENERAL,
a1f6afec 2240 .group = FIO_OPT_G_RUNTIME,
214e1eca 2241 },
cf4464ca
JA
2242 {
2243 .name = "time_based",
e8b0e958 2244 .lname = "Time based",
cf4464ca
JA
2245 .type = FIO_OPT_STR_SET,
2246 .off1 = td_var_offset(time_based),
2247 .help = "Keep running until runtime/timeout is met",
e8b0e958 2248 .category = FIO_OPT_C_GENERAL,
a1f6afec 2249 .group = FIO_OPT_G_RUNTIME,
cf4464ca 2250 },
62167762
JC
2251 {
2252 .name = "verify_only",
2253 .lname = "Verify only",
2254 .type = FIO_OPT_STR_SET,
2255 .off1 = td_var_offset(verify_only),
2256 .help = "Verifies previously written data is still valid",
2257 .category = FIO_OPT_C_GENERAL,
2258 .group = FIO_OPT_G_RUNTIME,
2259 },
721938ae
JA
2260 {
2261 .name = "ramp_time",
e8b0e958 2262 .lname = "Ramp time",
721938ae
JA
2263 .type = FIO_OPT_STR_VAL_TIME,
2264 .off1 = td_var_offset(ramp_time),
2265 .help = "Ramp up time before measuring performance",
0de5b26f 2266 .is_seconds = 1,
88038bc7 2267 .is_time = 1,
e8b0e958 2268 .category = FIO_OPT_C_GENERAL,
a1f6afec 2269 .group = FIO_OPT_G_RUNTIME,
721938ae 2270 },
c223da83
JA
2271 {
2272 .name = "clocksource",
e8b0e958 2273 .lname = "Clock source",
c223da83
JA
2274 .type = FIO_OPT_STR,
2275 .cb = fio_clock_source_cb,
2276 .off1 = td_var_offset(clocksource),
2277 .help = "What type of timing source to use",
e8b0e958 2278 .category = FIO_OPT_C_GENERAL,
10860056 2279 .group = FIO_OPT_G_CLOCK,
c223da83 2280 .posval = {
67bf9823 2281#ifdef CONFIG_GETTIMEOFDAY
c223da83
JA
2282 { .ival = "gettimeofday",
2283 .oval = CS_GTOD,
2284 .help = "Use gettimeofday(2) for timing",
2285 },
67bf9823
JA
2286#endif
2287#ifdef CONFIG_CLOCK_GETTIME
c223da83
JA
2288 { .ival = "clock_gettime",
2289 .oval = CS_CGETTIME,
2290 .help = "Use clock_gettime(2) for timing",
2291 },
67bf9823 2292#endif
c223da83
JA
2293#ifdef ARCH_HAVE_CPU_CLOCK
2294 { .ival = "cpu",
2295 .oval = CS_CPUCLOCK,
2296 .help = "Use CPU private clock",
2297 },
2298#endif
2299 },
2300 },
214e1eca
JA
2301 {
2302 .name = "mem",
d3aad8f2 2303 .alias = "iomem",
e8b0e958 2304 .lname = "I/O Memory",
214e1eca
JA
2305 .type = FIO_OPT_STR,
2306 .cb = str_mem_cb,
2307 .off1 = td_var_offset(mem_type),
2308 .help = "Backing type for IO buffers",
2309 .def = "malloc",
e8b0e958
JA
2310 .category = FIO_OPT_C_IO,
2311 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2312 .posval = {
2313 { .ival = "malloc",
2314 .oval = MEM_MALLOC,
2315 .help = "Use malloc(3) for IO buffers",
2316 },
c8931876 2317#ifndef CONFIG_NO_SHM
37c8cdfe
JA
2318 { .ival = "shm",
2319 .oval = MEM_SHM,
2320 .help = "Use shared memory segments for IO buffers",
2321 },
214e1eca
JA
2322#ifdef FIO_HAVE_HUGETLB
2323 { .ival = "shmhuge",
2324 .oval = MEM_SHMHUGE,
2325 .help = "Like shm, but use huge pages",
2326 },
c8931876 2327#endif
b370e46a 2328#endif
37c8cdfe
JA
2329 { .ival = "mmap",
2330 .oval = MEM_MMAP,
2331 .help = "Use mmap(2) (file or anon) for IO buffers",
2332 },
217b0f1d
LG
2333 { .ival = "mmapshared",
2334 .oval = MEM_MMAPSHARED,
2335 .help = "Like mmap, but use the shared flag",
2336 },
214e1eca
JA
2337#ifdef FIO_HAVE_HUGETLB
2338 { .ival = "mmaphuge",
2339 .oval = MEM_MMAPHUGE,
2340 .help = "Like mmap, but use huge pages",
2341 },
2342#endif
2343 },
2344 },
d529ee19
JA
2345 {
2346 .name = "iomem_align",
2347 .alias = "mem_align",
e8b0e958 2348 .lname = "I/O memory alignment",
d529ee19
JA
2349 .type = FIO_OPT_INT,
2350 .off1 = td_var_offset(mem_align),
2351 .minval = 0,
2352 .help = "IO memory buffer offset alignment",
2353 .def = "0",
2354 .parent = "iomem",
d71c154c 2355 .hide = 1,
e8b0e958
JA
2356 .category = FIO_OPT_C_IO,
2357 .group = FIO_OPT_G_INVALID,
d529ee19 2358 },
214e1eca
JA
2359 {
2360 .name = "verify",
e8b0e958 2361 .lname = "Verify",
214e1eca
JA
2362 .type = FIO_OPT_STR,
2363 .off1 = td_var_offset(verify),
2364 .help = "Verify data written",
2365 .def = "0",
e8b0e958 2366 .category = FIO_OPT_C_IO,
3ceb458f 2367 .group = FIO_OPT_G_VERIFY,
214e1eca
JA
2368 .posval = {
2369 { .ival = "0",
2370 .oval = VERIFY_NONE,
2371 .help = "Don't do IO verification",
2372 },
fcca4b58
JA
2373 { .ival = "md5",
2374 .oval = VERIFY_MD5,
2375 .help = "Use md5 checksums for verification",
2376 },
d77a7af3
JA
2377 { .ival = "crc64",
2378 .oval = VERIFY_CRC64,
2379 .help = "Use crc64 checksums for verification",
2380 },
214e1eca
JA
2381 { .ival = "crc32",
2382 .oval = VERIFY_CRC32,
2383 .help = "Use crc32 checksums for verification",
2384 },
af497e6a 2385 { .ival = "crc32c-intel",
e3aaafc4
JA
2386 .oval = VERIFY_CRC32C,
2387 .help = "Use crc32c checksums for verification (hw assisted, if available)",
af497e6a 2388 },
bac39e0e
JA
2389 { .ival = "crc32c",
2390 .oval = VERIFY_CRC32C,
e3aaafc4 2391 .help = "Use crc32c checksums for verification (hw assisted, if available)",
bac39e0e 2392 },
969f7ed3
JA
2393 { .ival = "crc16",
2394 .oval = VERIFY_CRC16,
2395 .help = "Use crc16 checksums for verification",
2396 },
1e154bdb
JA
2397 { .ival = "crc7",
2398 .oval = VERIFY_CRC7,
2399 .help = "Use crc7 checksums for verification",
2400 },
7c353ceb
JA
2401 { .ival = "sha1",
2402 .oval = VERIFY_SHA1,
2403 .help = "Use sha1 checksums for verification",
2404 },
cd14cc10
JA
2405 { .ival = "sha256",
2406 .oval = VERIFY_SHA256,
2407 .help = "Use sha256 checksums for verification",
2408 },
2409 { .ival = "sha512",
2410 .oval = VERIFY_SHA512,
2411 .help = "Use sha512 checksums for verification",
2412 },
844ea602
JA
2413 { .ival = "xxhash",
2414 .oval = VERIFY_XXHASH,
2415 .help = "Use xxhash checksums for verification",
2416 },
b638d82f
RP
2417 /* Meta information was included into verify_header,
2418 * 'meta' verification is implied by default. */
7437ee87 2419 { .ival = "meta",
b638d82f
RP
2420 .oval = VERIFY_HDR_ONLY,
2421 .help = "Use io information for verification. "
2422 "Now is implied by default, thus option is obsolete, "
2423 "don't use it",
7437ee87 2424 },
59245381
JA
2425 { .ival = "pattern",
2426 .oval = VERIFY_PATTERN_NO_HDR,
2427 .help = "Verify strict pattern",
2428 },
36690c9b
JA
2429 {
2430 .ival = "null",
2431 .oval = VERIFY_NULL,
2432 .help = "Pretend to verify",
2433 },
214e1eca
JA
2434 },
2435 },
005c565a
JA
2436 {
2437 .name = "do_verify",
e8b0e958 2438 .lname = "Perform verify step",
68e1f29a 2439 .type = FIO_OPT_BOOL,
005c565a
JA
2440 .off1 = td_var_offset(do_verify),
2441 .help = "Run verification stage after write",
2442 .def = "1",
2443 .parent = "verify",
d71c154c 2444 .hide = 1,
e8b0e958
JA
2445 .category = FIO_OPT_C_IO,
2446 .group = FIO_OPT_G_VERIFY,
005c565a 2447 },
160b966d
JA
2448 {
2449 .name = "verifysort",
e8b0e958 2450 .lname = "Verify sort",
160b966d
JA
2451 .type = FIO_OPT_BOOL,
2452 .off1 = td_var_offset(verifysort),
2453 .help = "Sort written verify blocks for read back",
2454 .def = "1",
c83f2df1 2455 .parent = "verify",
d71c154c 2456 .hide = 1,
e8b0e958
JA
2457 .category = FIO_OPT_C_IO,
2458 .group = FIO_OPT_G_VERIFY,
160b966d 2459 },
1ae83d45
JA
2460 {
2461 .name = "verifysort_nr",
2462 .type = FIO_OPT_INT,
2463 .off1 = td_var_offset(verifysort_nr),
2464 .help = "Pre-load and sort verify blocks for a read workload",
2465 .minval = 0,
2466 .maxval = 131072,
2467 .def = "1024",
2468 .parent = "verify",
836fcc0f
JA
2469 .category = FIO_OPT_C_IO,
2470 .group = FIO_OPT_G_VERIFY,
1ae83d45 2471 },
3f9f4e26 2472 {
a59e170d 2473 .name = "verify_interval",
e8b0e958 2474 .lname = "Verify interval",
e01b22b8 2475 .type = FIO_OPT_INT,
a59e170d 2476 .off1 = td_var_offset(verify_interval),
819a9680 2477 .minval = 2 * sizeof(struct verify_header),
a59e170d 2478 .help = "Store verify buffer header every N bytes",
afdf9352 2479 .parent = "verify",
d71c154c 2480 .hide = 1,
20eb06bd 2481 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
2482 .category = FIO_OPT_C_IO,
2483 .group = FIO_OPT_G_VERIFY,
3f9f4e26 2484 },
546a9142 2485 {
a59e170d 2486 .name = "verify_offset",
e8b0e958 2487 .lname = "Verify offset",
e01b22b8 2488 .type = FIO_OPT_INT,
a59e170d 2489 .help = "Offset verify header location by N bytes",
203160d5
JA
2490 .off1 = td_var_offset(verify_offset),
2491 .minval = sizeof(struct verify_header),
afdf9352 2492 .parent = "verify",
d71c154c 2493 .hide = 1,
e8b0e958
JA
2494 .category = FIO_OPT_C_IO,
2495 .group = FIO_OPT_G_VERIFY,
546a9142 2496 },
e28218f3
SL
2497 {
2498 .name = "verify_pattern",
e8b0e958 2499 .lname = "Verify pattern",
0e92f873 2500 .type = FIO_OPT_STR,
e28218f3 2501 .cb = str_verify_pattern_cb,
a8523a6a 2502 .off1 = td_var_offset(verify_pattern),
e28218f3
SL
2503 .help = "Fill pattern for IO buffers",
2504 .parent = "verify",
d71c154c 2505 .hide = 1,
e8b0e958
JA
2506 .category = FIO_OPT_C_IO,
2507 .group = FIO_OPT_G_VERIFY,
e28218f3 2508 },
a12a3b4d
JA
2509 {
2510 .name = "verify_fatal",
e8b0e958 2511 .lname = "Verify fatal",
68e1f29a 2512 .type = FIO_OPT_BOOL,
a12a3b4d
JA
2513 .off1 = td_var_offset(verify_fatal),
2514 .def = "0",
2515 .help = "Exit on a single verify failure, don't continue",
2516 .parent = "verify",
d71c154c 2517 .hide = 1,
e8b0e958
JA
2518 .category = FIO_OPT_C_IO,
2519 .group = FIO_OPT_G_VERIFY,
a12a3b4d 2520 },
b463e936
JA
2521 {
2522 .name = "verify_dump",
e8b0e958 2523 .lname = "Verify dump",
b463e936
JA
2524 .type = FIO_OPT_BOOL,
2525 .off1 = td_var_offset(verify_dump),
ef71e317 2526 .def = "0",
b463e936
JA
2527 .help = "Dump contents of good and bad blocks on failure",
2528 .parent = "verify",
d71c154c 2529 .hide = 1,
e8b0e958
JA
2530 .category = FIO_OPT_C_IO,
2531 .group = FIO_OPT_G_VERIFY,
b463e936 2532 },
e8462bd8
JA
2533 {
2534 .name = "verify_async",
e8b0e958 2535 .lname = "Verify asynchronously",
e8462bd8
JA
2536 .type = FIO_OPT_INT,
2537 .off1 = td_var_offset(verify_async),
2538 .def = "0",
2539 .help = "Number of async verifier threads to use",
2540 .parent = "verify",
d71c154c 2541 .hide = 1,
e8b0e958
JA
2542 .category = FIO_OPT_C_IO,
2543 .group = FIO_OPT_G_VERIFY,
e8462bd8 2544 },
9e144189
JA
2545 {
2546 .name = "verify_backlog",
e8b0e958 2547 .lname = "Verify backlog",
9e144189
JA
2548 .type = FIO_OPT_STR_VAL,
2549 .off1 = td_var_offset(verify_backlog),
2550 .help = "Verify after this number of blocks are written",
2551 .parent = "verify",
d71c154c 2552 .hide = 1,
e8b0e958
JA
2553 .category = FIO_OPT_C_IO,
2554 .group = FIO_OPT_G_VERIFY,
9e144189
JA
2555 },
2556 {
2557 .name = "verify_backlog_batch",
e8b0e958 2558 .lname = "Verify backlog batch",
9e144189
JA
2559 .type = FIO_OPT_INT,
2560 .off1 = td_var_offset(verify_batch),
2561 .help = "Verify this number of IO blocks",
0d29de83 2562 .parent = "verify",
d71c154c 2563 .hide = 1,
e8b0e958
JA
2564 .category = FIO_OPT_C_IO,
2565 .group = FIO_OPT_G_VERIFY,
9e144189 2566 },
e8462bd8
JA
2567#ifdef FIO_HAVE_CPU_AFFINITY
2568 {
2569 .name = "verify_async_cpus",
e8b0e958 2570 .lname = "Async verify CPUs",
e8462bd8
JA
2571 .type = FIO_OPT_STR,
2572 .cb = str_verify_cpus_allowed_cb,
a8523a6a 2573 .off1 = td_var_offset(verify_cpumask),
e8462bd8
JA
2574 .help = "Set CPUs allowed for async verify threads",
2575 .parent = "verify_async",
d71c154c 2576 .hide = 1,
e8b0e958
JA
2577 .category = FIO_OPT_C_IO,
2578 .group = FIO_OPT_G_VERIFY,
e8462bd8 2579 },
0d29de83 2580#endif
51aa2da8
JA
2581 {
2582 .name = "experimental_verify",
2583 .off1 = td_var_offset(experimental_verify),
2584 .type = FIO_OPT_BOOL,
b31eaac9 2585 .help = "Enable experimental verification",
ca09be4b
JA
2586 .parent = "verify",
2587 .category = FIO_OPT_C_IO,
2588 .group = FIO_OPT_G_VERIFY,
2589 },
2590 {
2591 .name = "verify_state_load",
2592 .lname = "Load verify state",
2593 .off1 = td_var_offset(verify_state),
2594 .type = FIO_OPT_BOOL,
2595 .help = "Load verify termination state",
2596 .parent = "verify",
2597 .category = FIO_OPT_C_IO,
2598 .group = FIO_OPT_G_VERIFY,
2599 },
2600 {
2601 .name = "verify_state_save",
2602 .lname = "Save verify state",
2603 .off1 = td_var_offset(verify_state_save),
2604 .type = FIO_OPT_BOOL,
2605 .def = "1",
2606 .help = "Save verify state on termination",
2607 .parent = "verify",
836fcc0f
JA
2608 .category = FIO_OPT_C_IO,
2609 .group = FIO_OPT_G_VERIFY,
51aa2da8 2610 },
0d29de83
JA
2611#ifdef FIO_HAVE_TRIM
2612 {
2613 .name = "trim_percentage",
e8b0e958 2614 .lname = "Trim percentage",
0d29de83 2615 .type = FIO_OPT_INT,
203160d5 2616 .off1 = td_var_offset(trim_percentage),
20eb06bd 2617 .minval = 0,
0d29de83
JA
2618 .maxval = 100,
2619 .help = "Number of verify blocks to discard/trim",
2620 .parent = "verify",
2621 .def = "0",
20eb06bd 2622 .interval = 1,
d71c154c 2623 .hide = 1,
e8b0e958
JA
2624 .category = FIO_OPT_C_IO,
2625 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2626 },
2627 {
2628 .name = "trim_verify_zero",
e8b0e958 2629 .lname = "Verify trim zero",
20eb06bd 2630 .type = FIO_OPT_BOOL,
0d29de83
JA
2631 .help = "Verify that trim/discarded blocks are returned as zeroes",
2632 .off1 = td_var_offset(trim_zero),
2633 .parent = "trim_percentage",
d71c154c 2634 .hide = 1,
0d29de83 2635 .def = "1",
e8b0e958
JA
2636 .category = FIO_OPT_C_IO,
2637 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2638 },
2639 {
2640 .name = "trim_backlog",
e8b0e958 2641 .lname = "Trim backlog",
0d29de83
JA
2642 .type = FIO_OPT_STR_VAL,
2643 .off1 = td_var_offset(trim_backlog),
2644 .help = "Trim after this number of blocks are written",
2645 .parent = "trim_percentage",
d71c154c 2646 .hide = 1,
20eb06bd 2647 .interval = 1,
e8b0e958
JA
2648 .category = FIO_OPT_C_IO,
2649 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2650 },
2651 {
2652 .name = "trim_backlog_batch",
e8b0e958 2653 .lname = "Trim backlog batch",
0d29de83
JA
2654 .type = FIO_OPT_INT,
2655 .off1 = td_var_offset(trim_batch),
2656 .help = "Trim this number of IO blocks",
2657 .parent = "trim_percentage",
d71c154c 2658 .hide = 1,
20eb06bd 2659 .interval = 1,
e8b0e958
JA
2660 .category = FIO_OPT_C_IO,
2661 .group = FIO_OPT_G_TRIM,
0d29de83 2662 },
e8462bd8 2663#endif
214e1eca
JA
2664 {
2665 .name = "write_iolog",
e8b0e958 2666 .lname = "Write I/O log",
214e1eca
JA
2667 .type = FIO_OPT_STR_STORE,
2668 .off1 = td_var_offset(write_iolog_file),
2669 .help = "Store IO pattern to file",
e8b0e958
JA
2670 .category = FIO_OPT_C_IO,
2671 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
2672 },
2673 {
2674 .name = "read_iolog",
e8b0e958 2675 .lname = "Read I/O log",
214e1eca
JA
2676 .type = FIO_OPT_STR_STORE,
2677 .off1 = td_var_offset(read_iolog_file),
2678 .help = "Playback IO pattern from file",
e8b0e958
JA
2679 .category = FIO_OPT_C_IO,
2680 .group = FIO_OPT_G_IOLOG,
214e1eca 2681 },
64bbb865
DN
2682 {
2683 .name = "replay_no_stall",
e8b0e958 2684 .lname = "Don't stall on replay",
20eb06bd 2685 .type = FIO_OPT_BOOL,
64bbb865
DN
2686 .off1 = td_var_offset(no_stall),
2687 .def = "0",
87e7a972 2688 .parent = "read_iolog",
d71c154c 2689 .hide = 1,
64bbb865 2690 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
2691 .category = FIO_OPT_C_IO,
2692 .group = FIO_OPT_G_IOLOG,
64bbb865 2693 },
d1c46c04
DN
2694 {
2695 .name = "replay_redirect",
e8b0e958 2696 .lname = "Redirect device for replay",
d1c46c04
DN
2697 .type = FIO_OPT_STR_STORE,
2698 .off1 = td_var_offset(replay_redirect),
2699 .parent = "read_iolog",
d71c154c 2700 .hide = 1,
d1c46c04 2701 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
2702 .category = FIO_OPT_C_IO,
2703 .group = FIO_OPT_G_IOLOG,
d1c46c04 2704 },
0c63576e
JA
2705 {
2706 .name = "replay_scale",
2707 .lname = "Replace offset scale factor",
2708 .type = FIO_OPT_INT,
2709 .off1 = td_var_offset(replay_scale),
2710 .parent = "read_iolog",
2711 .def = "1",
2712 .help = "Align offsets to this blocksize",
2713 .category = FIO_OPT_C_IO,
2714 .group = FIO_OPT_G_IOLOG,
2715 },
2716 {
2717 .name = "replay_align",
2718 .lname = "Replace alignment",
2719 .type = FIO_OPT_INT,
2720 .off1 = td_var_offset(replay_align),
2721 .parent = "read_iolog",
2722 .help = "Scale offset down by this factor",
2723 .category = FIO_OPT_C_IO,
2724 .group = FIO_OPT_G_IOLOG,
2725 .pow2 = 1,
2726 },
214e1eca
JA
2727 {
2728 .name = "exec_prerun",
e8b0e958 2729 .lname = "Pre-execute runnable",
214e1eca
JA
2730 .type = FIO_OPT_STR_STORE,
2731 .off1 = td_var_offset(exec_prerun),
2732 .help = "Execute this file prior to running job",
e8b0e958
JA
2733 .category = FIO_OPT_C_GENERAL,
2734 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2735 },
2736 {
2737 .name = "exec_postrun",
e8b0e958 2738 .lname = "Post-execute runnable",
214e1eca
JA
2739 .type = FIO_OPT_STR_STORE,
2740 .off1 = td_var_offset(exec_postrun),
2741 .help = "Execute this file after running job",
e8b0e958
JA
2742 .category = FIO_OPT_C_GENERAL,
2743 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2744 },
2745#ifdef FIO_HAVE_IOSCHED_SWITCH
2746 {
2747 .name = "ioscheduler",
e8b0e958 2748 .lname = "I/O scheduler",
214e1eca
JA
2749 .type = FIO_OPT_STR_STORE,
2750 .off1 = td_var_offset(ioscheduler),
2751 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
2752 .category = FIO_OPT_C_FILE,
2753 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2754 },
2755#endif
2756 {
2757 .name = "zonesize",
e8b0e958 2758 .lname = "Zone size",
214e1eca
JA
2759 .type = FIO_OPT_STR_VAL,
2760 .off1 = td_var_offset(zone_size),
ed335855
SN
2761 .help = "Amount of data to read per zone",
2762 .def = "0",
20eb06bd 2763 .interval = 1024 * 1024,
e8b0e958
JA
2764 .category = FIO_OPT_C_IO,
2765 .group = FIO_OPT_G_ZONE,
ed335855
SN
2766 },
2767 {
2768 .name = "zonerange",
e8b0e958 2769 .lname = "Zone range",
ed335855
SN
2770 .type = FIO_OPT_STR_VAL,
2771 .off1 = td_var_offset(zone_range),
214e1eca
JA
2772 .help = "Give size of an IO zone",
2773 .def = "0",
20eb06bd 2774 .interval = 1024 * 1024,
e8b0e958
JA
2775 .category = FIO_OPT_C_IO,
2776 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2777 },
2778 {
2779 .name = "zoneskip",
e8b0e958 2780 .lname = "Zone skip",
214e1eca
JA
2781 .type = FIO_OPT_STR_VAL,
2782 .off1 = td_var_offset(zone_skip),
2783 .help = "Space between IO zones",
2784 .def = "0",
20eb06bd 2785 .interval = 1024 * 1024,
e8b0e958
JA
2786 .category = FIO_OPT_C_IO,
2787 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2788 },
2789 {
2790 .name = "lockmem",
e8b0e958 2791 .lname = "Lock memory",
214e1eca 2792 .type = FIO_OPT_STR_VAL,
1b79a070 2793 .off1 = td_var_offset(lockmem),
81c6b6cd 2794 .help = "Lock down this amount of memory (per worker)",
214e1eca 2795 .def = "0",
20eb06bd 2796 .interval = 1024 * 1024,
e8b0e958
JA
2797 .category = FIO_OPT_C_GENERAL,
2798 .group = FIO_OPT_G_INVALID,
214e1eca 2799 },
214e1eca
JA
2800 {
2801 .name = "rwmixread",
e8b0e958 2802 .lname = "Read/write mix read",
214e1eca 2803 .type = FIO_OPT_INT,
cb499fc4 2804 .cb = str_rwmix_read_cb,
a8523a6a 2805 .off1 = td_var_offset(rwmix[DDIR_READ]),
214e1eca
JA
2806 .maxval = 100,
2807 .help = "Percentage of mixed workload that is reads",
2808 .def = "50",
20eb06bd 2809 .interval = 5,
90265353 2810 .inverse = "rwmixwrite",
e8b0e958
JA
2811 .category = FIO_OPT_C_IO,
2812 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
2813 },
2814 {
2815 .name = "rwmixwrite",
e8b0e958 2816 .lname = "Read/write mix write",
214e1eca 2817 .type = FIO_OPT_INT,
cb499fc4 2818 .cb = str_rwmix_write_cb,
a8523a6a 2819 .off1 = td_var_offset(rwmix[DDIR_WRITE]),
214e1eca
JA
2820 .maxval = 100,
2821 .help = "Percentage of mixed workload that is writes",
2822 .def = "50",
20eb06bd 2823 .interval = 5,
90265353 2824 .inverse = "rwmixread",
e8b0e958
JA
2825 .category = FIO_OPT_C_IO,
2826 .group = FIO_OPT_G_RWMIX,
214e1eca 2827 },
afdf9352
JA
2828 {
2829 .name = "rwmixcycle",
e8b0e958 2830 .lname = "Read/write mix cycle",
15ca150e 2831 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
2832 .category = FIO_OPT_C_IO,
2833 .group = FIO_OPT_G_RWMIX,
afdf9352 2834 },
214e1eca
JA
2835 {
2836 .name = "nice",
e8b0e958 2837 .lname = "Nice",
214e1eca
JA
2838 .type = FIO_OPT_INT,
2839 .off1 = td_var_offset(nice),
2840 .help = "Set job CPU nice value",
2841 .minval = -19,
2842 .maxval = 20,
2843 .def = "0",
20eb06bd 2844 .interval = 1,
e8b0e958 2845 .category = FIO_OPT_C_GENERAL,
10860056 2846 .group = FIO_OPT_G_CRED,
214e1eca
JA
2847 },
2848#ifdef FIO_HAVE_IOPRIO
2849 {
2850 .name = "prio",
e8b0e958 2851 .lname = "I/O nice priority",
214e1eca 2852 .type = FIO_OPT_INT,
28727df7 2853 .off1 = td_var_offset(ioprio),
214e1eca
JA
2854 .help = "Set job IO priority value",
2855 .minval = 0,
2856 .maxval = 7,
20eb06bd 2857 .interval = 1,
e8b0e958 2858 .category = FIO_OPT_C_GENERAL,
10860056 2859 .group = FIO_OPT_G_CRED,
214e1eca
JA
2860 },
2861 {
2862 .name = "prioclass",
e8b0e958 2863 .lname = "I/O nice priority class",
214e1eca 2864 .type = FIO_OPT_INT,
28727df7 2865 .off1 = td_var_offset(ioprio_class),
214e1eca
JA
2866 .help = "Set job IO priority class",
2867 .minval = 0,
2868 .maxval = 3,
20eb06bd 2869 .interval = 1,
e8b0e958 2870 .category = FIO_OPT_C_GENERAL,
10860056 2871 .group = FIO_OPT_G_CRED,
214e1eca
JA
2872 },
2873#endif
2874 {
2875 .name = "thinktime",
e8b0e958 2876 .lname = "Thinktime",
214e1eca
JA
2877 .type = FIO_OPT_INT,
2878 .off1 = td_var_offset(thinktime),
2879 .help = "Idle time between IO buffers (usec)",
2880 .def = "0",
88038bc7 2881 .is_time = 1,
e8b0e958 2882 .category = FIO_OPT_C_IO,
3ceb458f 2883 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2884 },
2885 {
2886 .name = "thinktime_spin",
e8b0e958 2887 .lname = "Thinktime spin",
214e1eca
JA
2888 .type = FIO_OPT_INT,
2889 .off1 = td_var_offset(thinktime_spin),
2890 .help = "Start think time by spinning this amount (usec)",
2891 .def = "0",
88038bc7 2892 .is_time = 1,
afdf9352 2893 .parent = "thinktime",
d71c154c 2894 .hide = 1,
e8b0e958 2895 .category = FIO_OPT_C_IO,
3ceb458f 2896 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2897 },
2898 {
2899 .name = "thinktime_blocks",
e8b0e958 2900 .lname = "Thinktime blocks",
214e1eca
JA
2901 .type = FIO_OPT_INT,
2902 .off1 = td_var_offset(thinktime_blocks),
2903 .help = "IO buffer period between 'thinktime'",
2904 .def = "1",
afdf9352 2905 .parent = "thinktime",
d71c154c 2906 .hide = 1,
e8b0e958 2907 .category = FIO_OPT_C_IO,
3ceb458f 2908 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2909 },
2910 {
2911 .name = "rate",
e8b0e958 2912 .lname = "I/O rate",
e01b22b8 2913 .type = FIO_OPT_INT,
6eaf09d6
SL
2914 .off1 = td_var_offset(rate[DDIR_READ]),
2915 .off2 = td_var_offset(rate[DDIR_WRITE]),
2916 .off3 = td_var_offset(rate[DDIR_TRIM]),
214e1eca 2917 .help = "Set bandwidth rate",
e8b0e958
JA
2918 .category = FIO_OPT_C_IO,
2919 .group = FIO_OPT_G_RATE,
214e1eca
JA
2920 },
2921 {
6d428bcd
JA
2922 .name = "rate_min",
2923 .alias = "ratemin",
e8b0e958 2924 .lname = "I/O min rate",
e01b22b8 2925 .type = FIO_OPT_INT,
6eaf09d6
SL
2926 .off1 = td_var_offset(ratemin[DDIR_READ]),
2927 .off2 = td_var_offset(ratemin[DDIR_WRITE]),
2928 .off3 = td_var_offset(ratemin[DDIR_TRIM]),
4e991c23 2929 .help = "Job must meet this rate or it will be shutdown",
afdf9352 2930 .parent = "rate",
d71c154c 2931 .hide = 1,
e8b0e958
JA
2932 .category = FIO_OPT_C_IO,
2933 .group = FIO_OPT_G_RATE,
4e991c23
JA
2934 },
2935 {
2936 .name = "rate_iops",
e8b0e958 2937 .lname = "I/O rate IOPS",
e01b22b8 2938 .type = FIO_OPT_INT,
6eaf09d6
SL
2939 .off1 = td_var_offset(rate_iops[DDIR_READ]),
2940 .off2 = td_var_offset(rate_iops[DDIR_WRITE]),
2941 .off3 = td_var_offset(rate_iops[DDIR_TRIM]),
4e991c23 2942 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 2943 .hide = 1,
e8b0e958
JA
2944 .category = FIO_OPT_C_IO,
2945 .group = FIO_OPT_G_RATE,
4e991c23
JA
2946 },
2947 {
2948 .name = "rate_iops_min",
e8b0e958 2949 .lname = "I/O min rate IOPS",
e01b22b8 2950 .type = FIO_OPT_INT,
6eaf09d6
SL
2951 .off1 = td_var_offset(rate_iops_min[DDIR_READ]),
2952 .off2 = td_var_offset(rate_iops_min[DDIR_WRITE]),
2953 .off3 = td_var_offset(rate_iops_min[DDIR_TRIM]),
03e20d68 2954 .help = "Job must meet this rate or it will be shut down",
afdf9352 2955 .parent = "rate_iops",
d71c154c 2956 .hide = 1,
e8b0e958
JA
2957 .category = FIO_OPT_C_IO,
2958 .group = FIO_OPT_G_RATE,
214e1eca 2959 },
ff6bb260 2960 {
6de65959
JA
2961 .name = "rate_process",
2962 .lname = "Rate Process",
2963 .type = FIO_OPT_STR,
2964 .off1 = td_var_offset(rate_process),
2965 .help = "What process controls how rated IO is managed",
2966 .def = "linear",
ff6bb260
SL
2967 .category = FIO_OPT_C_IO,
2968 .group = FIO_OPT_G_RATE,
6de65959
JA
2969 .posval = {
2970 { .ival = "linear",
2971 .oval = RATE_PROCESS_LINEAR,
2972 .help = "Linear rate of IO",
2973 },
2974 {
2975 .ival = "poisson",
2976 .oval = RATE_PROCESS_POISSON,
2977 .help = "Rate follows Poisson process",
2978 },
2979 },
2980 .parent = "rate",
ff6bb260 2981 },
214e1eca 2982 {
6d428bcd
JA
2983 .name = "rate_cycle",
2984 .alias = "ratecycle",
e8b0e958 2985 .lname = "I/O rate cycle",
214e1eca
JA
2986 .type = FIO_OPT_INT,
2987 .off1 = td_var_offset(ratecycle),
2988 .help = "Window average for rate limits (msec)",
2989 .def = "1000",
afdf9352 2990 .parent = "rate",
d71c154c 2991 .hide = 1,
e8b0e958
JA
2992 .category = FIO_OPT_C_IO,
2993 .group = FIO_OPT_G_RATE,
214e1eca 2994 },
15501535
JA
2995 {
2996 .name = "max_latency",
2997 .type = FIO_OPT_INT,
2998 .off1 = td_var_offset(max_latency),
2999 .help = "Maximum tolerated IO latency (usec)",
88038bc7 3000 .is_time = 1,
1e5324e7 3001 .category = FIO_OPT_C_IO,
3e260a46
JA
3002 .group = FIO_OPT_G_LATPROF,
3003 },
3004 {
3005 .name = "latency_target",
3006 .lname = "Latency Target (usec)",
3007 .type = FIO_OPT_STR_VAL_TIME,
3008 .off1 = td_var_offset(latency_target),
3009 .help = "Ramp to max queue depth supporting this latency",
88038bc7 3010 .is_time = 1,
3e260a46
JA
3011 .category = FIO_OPT_C_IO,
3012 .group = FIO_OPT_G_LATPROF,
3013 },
3014 {
3015 .name = "latency_window",
3016 .lname = "Latency Window (usec)",
3017 .type = FIO_OPT_STR_VAL_TIME,
3018 .off1 = td_var_offset(latency_window),
3019 .help = "Time to sustain latency_target",
88038bc7 3020 .is_time = 1,
3e260a46
JA
3021 .category = FIO_OPT_C_IO,
3022 .group = FIO_OPT_G_LATPROF,
3023 },
3024 {
3025 .name = "latency_percentile",
3026 .lname = "Latency Percentile",
3027 .type = FIO_OPT_FLOAT_LIST,
3028 .off1 = td_var_offset(latency_percentile),
3029 .help = "Percentile of IOs must be below latency_target",
3030 .def = "100",
3031 .maxlen = 1,
3032 .minfp = 0.0,
3033 .maxfp = 100.0,
3034 .category = FIO_OPT_C_IO,
3035 .group = FIO_OPT_G_LATPROF,
15501535 3036 },
214e1eca
JA
3037 {
3038 .name = "invalidate",
e8b0e958 3039 .lname = "Cache invalidate",
214e1eca
JA
3040 .type = FIO_OPT_BOOL,
3041 .off1 = td_var_offset(invalidate_cache),
3042 .help = "Invalidate buffer/page cache prior to running job",
3043 .def = "1",
e8b0e958 3044 .category = FIO_OPT_C_IO,
3ceb458f 3045 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
3046 },
3047 {
3048 .name = "sync",
e8b0e958 3049 .lname = "Synchronous I/O",
214e1eca
JA
3050 .type = FIO_OPT_BOOL,
3051 .off1 = td_var_offset(sync_io),
3052 .help = "Use O_SYNC for buffered writes",
3053 .def = "0",
67a1000f 3054 .parent = "buffered",
d71c154c 3055 .hide = 1,
e8b0e958 3056 .category = FIO_OPT_C_IO,
3ceb458f 3057 .group = FIO_OPT_G_IO_TYPE,
214e1eca 3058 },
214e1eca
JA
3059 {
3060 .name = "create_serialize",
e8b0e958 3061 .lname = "Create serialize",
214e1eca
JA
3062 .type = FIO_OPT_BOOL,
3063 .off1 = td_var_offset(create_serialize),
3064 .help = "Serialize creating of job files",
3065 .def = "1",
e8b0e958
JA
3066 .category = FIO_OPT_C_FILE,
3067 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3068 },
3069 {
3070 .name = "create_fsync",
e8b0e958 3071 .lname = "Create fsync",
214e1eca
JA
3072 .type = FIO_OPT_BOOL,
3073 .off1 = td_var_offset(create_fsync),
03e20d68 3074 .help = "fsync file after creation",
214e1eca 3075 .def = "1",
e8b0e958
JA
3076 .category = FIO_OPT_C_FILE,
3077 .group = FIO_OPT_G_INVALID,
214e1eca 3078 },
814452bd
JA
3079 {
3080 .name = "create_on_open",
e8b0e958 3081 .lname = "Create on open",
814452bd
JA
3082 .type = FIO_OPT_BOOL,
3083 .off1 = td_var_offset(create_on_open),
3084 .help = "Create files when they are opened for IO",
3085 .def = "0",
e8b0e958
JA
3086 .category = FIO_OPT_C_FILE,
3087 .group = FIO_OPT_G_INVALID,
814452bd 3088 },
25460cf6
JA
3089 {
3090 .name = "create_only",
3091 .type = FIO_OPT_BOOL,
3092 .off1 = td_var_offset(create_only),
3093 .help = "Only perform file creation phase",
d17fda71 3094 .category = FIO_OPT_C_FILE,
25460cf6
JA
3095 .def = "0",
3096 },
2378826d
JA
3097 {
3098 .name = "allow_file_create",
e81ecca3 3099 .lname = "Allow file create",
2378826d
JA
3100 .type = FIO_OPT_BOOL,
3101 .off1 = td_var_offset(allow_create),
3102 .help = "Permit fio to create files, if they don't exist",
3103 .def = "1",
3104 .category = FIO_OPT_C_FILE,
3105 .group = FIO_OPT_G_FILENAME,
3106 },
e81ecca3
JA
3107 {
3108 .name = "allow_mounted_write",
3109 .lname = "Allow mounted write",
3110 .type = FIO_OPT_BOOL,
3111 .off1 = td_var_offset(allow_mounted_write),
3112 .help = "Allow writes to a mounted partition",
3113 .def = "0",
3114 .category = FIO_OPT_C_FILE,
3115 .group = FIO_OPT_G_FILENAME,
3116 },
0b9d69ec 3117 {
afad68f7 3118 .name = "pre_read",
e8b0e958 3119 .lname = "Pre-read files",
afad68f7
ZY
3120 .type = FIO_OPT_BOOL,
3121 .off1 = td_var_offset(pre_read),
03e20d68 3122 .help = "Pre-read files before starting official testing",
afad68f7 3123 .def = "0",
e8b0e958
JA
3124 .category = FIO_OPT_C_FILE,
3125 .group = FIO_OPT_G_INVALID,
afad68f7 3126 },
214e1eca
JA
3127#ifdef FIO_HAVE_CPU_AFFINITY
3128 {
3129 .name = "cpumask",
e8b0e958 3130 .lname = "CPU mask",
214e1eca
JA
3131 .type = FIO_OPT_INT,
3132 .cb = str_cpumask_cb,
a8523a6a 3133 .off1 = td_var_offset(cpumask),
214e1eca 3134 .help = "CPU affinity mask",
e8b0e958 3135 .category = FIO_OPT_C_GENERAL,
10860056 3136 .group = FIO_OPT_G_CRED,
214e1eca 3137 },
d2e268b0
JA
3138 {
3139 .name = "cpus_allowed",
e8b0e958 3140 .lname = "CPUs allowed",
d2e268b0
JA
3141 .type = FIO_OPT_STR,
3142 .cb = str_cpus_allowed_cb,
a8523a6a 3143 .off1 = td_var_offset(cpumask),
d2e268b0 3144 .help = "Set CPUs allowed",
e8b0e958 3145 .category = FIO_OPT_C_GENERAL,
10860056 3146 .group = FIO_OPT_G_CRED,
d2e268b0 3147 },
c2acfbac
JA
3148 {
3149 .name = "cpus_allowed_policy",
3150 .lname = "CPUs allowed distribution policy",
3151 .type = FIO_OPT_STR,
3152 .off1 = td_var_offset(cpus_allowed_policy),
3153 .help = "Distribution policy for cpus_allowed",
3154 .parent = "cpus_allowed",
3155 .prio = 1,
3156 .posval = {
3157 { .ival = "shared",
3158 .oval = FIO_CPUS_SHARED,
3159 .help = "Mask shared between threads",
3160 },
3161 { .ival = "split",
3162 .oval = FIO_CPUS_SPLIT,
3163 .help = "Mask split between threads",
3164 },
3165 },
3166 .category = FIO_OPT_C_GENERAL,
3167 .group = FIO_OPT_G_CRED,
3168 },
d0b937ed 3169#endif
67bf9823 3170#ifdef CONFIG_LIBNUMA
d0b937ed
YR
3171 {
3172 .name = "numa_cpu_nodes",
3173 .type = FIO_OPT_STR,
3174 .cb = str_numa_cpunodes_cb,
b2a9e649 3175 .off1 = td_var_offset(numa_cpunodes),
d0b937ed 3176 .help = "NUMA CPU nodes bind",
6be54b2d
JA
3177 .category = FIO_OPT_C_GENERAL,
3178 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
3179 },
3180 {
3181 .name = "numa_mem_policy",
3182 .type = FIO_OPT_STR,
3183 .cb = str_numa_mpol_cb,
b2a9e649 3184 .off1 = td_var_offset(numa_memnodes),
d0b937ed 3185 .help = "NUMA memory policy setup",
6be54b2d
JA
3186 .category = FIO_OPT_C_GENERAL,
3187 .group = FIO_OPT_G_INVALID,
d0b937ed 3188 },
214e1eca
JA
3189#endif
3190 {
3191 .name = "end_fsync",
e8b0e958 3192 .lname = "End fsync",
214e1eca
JA
3193 .type = FIO_OPT_BOOL,
3194 .off1 = td_var_offset(end_fsync),
3195 .help = "Include fsync at the end of job",
3196 .def = "0",
e8b0e958
JA
3197 .category = FIO_OPT_C_FILE,
3198 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3199 },
3200 {
3201 .name = "fsync_on_close",
e8b0e958 3202 .lname = "Fsync on close",
214e1eca
JA
3203 .type = FIO_OPT_BOOL,
3204 .off1 = td_var_offset(fsync_on_close),
3205 .help = "fsync files on close",
3206 .def = "0",
e8b0e958
JA
3207 .category = FIO_OPT_C_FILE,
3208 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3209 },
3210 {
3211 .name = "unlink",
e8b0e958 3212 .lname = "Unlink file",
214e1eca
JA
3213 .type = FIO_OPT_BOOL,
3214 .off1 = td_var_offset(unlink),
3215 .help = "Unlink created files after job has completed",
3216 .def = "0",
e8b0e958
JA
3217 .category = FIO_OPT_C_FILE,
3218 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3219 },
3220 {
3221 .name = "exitall",
e8b0e958 3222 .lname = "Exit-all on terminate",
214e1eca
JA
3223 .type = FIO_OPT_STR_SET,
3224 .cb = str_exitall_cb,
3225 .help = "Terminate all jobs when one exits",
e8b0e958 3226 .category = FIO_OPT_C_GENERAL,
a1f6afec 3227 .group = FIO_OPT_G_PROCESS,
214e1eca 3228 },
f9cafb12
JA
3229 {
3230 .name = "exitall_on_error",
3231 .lname = "Exit-all on terminate in error",
3232 .type = FIO_OPT_BOOL,
3233 .off1 = td_var_offset(unlink),
3234 .help = "Terminate all jobs when one exits in error",
3235 .category = FIO_OPT_C_GENERAL,
3236 .group = FIO_OPT_G_PROCESS,
3237 },
214e1eca
JA
3238 {
3239 .name = "stonewall",
e8b0e958 3240 .lname = "Wait for previous",
d392365e 3241 .alias = "wait_for_previous",
214e1eca
JA
3242 .type = FIO_OPT_STR_SET,
3243 .off1 = td_var_offset(stonewall),
3244 .help = "Insert a hard barrier between this job and previous",
e8b0e958 3245 .category = FIO_OPT_C_GENERAL,
a1f6afec 3246 .group = FIO_OPT_G_PROCESS,
214e1eca 3247 },
b3d62a75
JA
3248 {
3249 .name = "new_group",
e8b0e958 3250 .lname = "New group",
b3d62a75
JA
3251 .type = FIO_OPT_STR_SET,
3252 .off1 = td_var_offset(new_group),
3253 .help = "Mark the start of a new group (for reporting)",
e8b0e958 3254 .category = FIO_OPT_C_GENERAL,
a1f6afec 3255 .group = FIO_OPT_G_PROCESS,
b3d62a75 3256 },
214e1eca
JA
3257 {
3258 .name = "thread",
e8b0e958 3259 .lname = "Thread",
214e1eca
JA
3260 .type = FIO_OPT_STR_SET,
3261 .off1 = td_var_offset(use_thread),
20eb06bd 3262 .help = "Use threads instead of processes",
c8931876
JA
3263#ifdef CONFIG_NO_SHM
3264 .def = "1",
3265 .no_warn_def = 1,
3266#endif
e8b0e958 3267 .category = FIO_OPT_C_GENERAL,
a1f6afec 3268 .group = FIO_OPT_G_PROCESS,
214e1eca 3269 },
3a5db920
JA
3270 {
3271 .name = "per_job_logs",
3272 .type = FIO_OPT_BOOL,
3273 .off1 = td_var_offset(per_job_logs),
3274 .help = "Include job number in generated log files or not",
3275 .def = "1",
3276 .category = FIO_OPT_C_LOG,
3277 .group = FIO_OPT_G_INVALID,
3278 },
214e1eca
JA
3279 {
3280 .name = "write_bw_log",
e8b0e958 3281 .lname = "Write bandwidth log",
203160d5
JA
3282 .type = FIO_OPT_STR_STORE,
3283 .off1 = td_var_offset(bw_log_file),
214e1eca 3284 .help = "Write log of bandwidth during run",
e8b0e958
JA
3285 .category = FIO_OPT_C_LOG,
3286 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3287 },
3288 {
3289 .name = "write_lat_log",
e8b0e958 3290 .lname = "Write latency log",
203160d5
JA
3291 .type = FIO_OPT_STR_STORE,
3292 .off1 = td_var_offset(lat_log_file),
214e1eca 3293 .help = "Write log of latency during run",
e8b0e958
JA
3294 .category = FIO_OPT_C_LOG,
3295 .group = FIO_OPT_G_INVALID,
214e1eca 3296 },
c8eeb9df
JA
3297 {
3298 .name = "write_iops_log",
e8b0e958 3299 .lname = "Write IOPS log",
577c83bd 3300 .type = FIO_OPT_STR_STORE,
203160d5 3301 .off1 = td_var_offset(iops_log_file),
c8eeb9df 3302 .help = "Write log of IOPS during run",
e8b0e958
JA
3303 .category = FIO_OPT_C_LOG,
3304 .group = FIO_OPT_G_INVALID,
c8eeb9df 3305 },
b8bc8cba
JA
3306 {
3307 .name = "log_avg_msec",
e8b0e958 3308 .lname = "Log averaging (msec)",
b8bc8cba
JA
3309 .type = FIO_OPT_INT,
3310 .off1 = td_var_offset(log_avg_msec),
3311 .help = "Average bw/iops/lat logs over this period of time",
3312 .def = "0",
e8b0e958
JA
3313 .category = FIO_OPT_C_LOG,
3314 .group = FIO_OPT_G_INVALID,
b8bc8cba 3315 },
e6989e10
JA
3316 {
3317 .name = "log_max_value",
3318 .lname = "Log maximum instead of average",
3319 .type = FIO_OPT_BOOL,
3320 .off1 = td_var_offset(log_max),
3321 .help = "Log max sample in a window instead of average",
3322 .def = "0",
3323 .category = FIO_OPT_C_LOG,
3324 .group = FIO_OPT_G_INVALID,
3325 },
ae588852
JA
3326 {
3327 .name = "log_offset",
3328 .lname = "Log offset of IO",
3329 .type = FIO_OPT_BOOL,
3330 .off1 = td_var_offset(log_offset),
3331 .help = "Include offset of IO for each log entry",
3332 .def = "0",
3333 .category = FIO_OPT_C_LOG,
3334 .group = FIO_OPT_G_INVALID,
3335 },
aee2ab67
JA
3336#ifdef CONFIG_ZLIB
3337 {
3338 .name = "log_compression",
3339 .lname = "Log compression",
3340 .type = FIO_OPT_INT,
3341 .off1 = td_var_offset(log_gz),
3342 .help = "Log in compressed chunks of this size",
9919b27b 3343 .minval = 1024ULL,
aee2ab67
JA
3344 .maxval = 512 * 1024 * 1024ULL,
3345 .category = FIO_OPT_C_LOG,
3346 .group = FIO_OPT_G_INVALID,
3347 },
c08f9fe2
JA
3348#ifdef FIO_HAVE_CPU_AFFINITY
3349 {
3350 .name = "log_compression_cpus",
3351 .lname = "Log Compression CPUs",
3352 .type = FIO_OPT_STR,
3353 .cb = str_log_cpus_allowed_cb,
3354 .off1 = td_var_offset(log_gz_cpumask),
3355 .parent = "log_compression",
3356 .help = "Limit log compression to these CPUs",
3357 .category = FIO_OPT_C_LOG,
3358 .group = FIO_OPT_G_INVALID,
3359 },
3360#endif
b26317c9
JA
3361 {
3362 .name = "log_store_compressed",
3363 .lname = "Log store compressed",
3364 .type = FIO_OPT_BOOL,
3365 .off1 = td_var_offset(log_gz_store),
3366 .help = "Store logs in a compressed format",
3367 .category = FIO_OPT_C_LOG,
3368 .group = FIO_OPT_G_INVALID,
3369 },
aee2ab67 3370#endif
66347cfa
DE
3371 {
3372 .name = "block_error_percentiles",
3373 .lname = "Block error percentiles",
3374 .type = FIO_OPT_BOOL,
3375 .off1 = td_var_offset(block_error_hist),
3376 .help = "Record trim block errors and make a histogram",
3377 .def = "0",
3378 .category = FIO_OPT_C_LOG,
3379 .group = FIO_OPT_G_INVALID,
3380 },
c504ee55
JA
3381 {
3382 .name = "bwavgtime",
3383 .lname = "Bandwidth average time",
3384 .type = FIO_OPT_INT,
3385 .off1 = td_var_offset(bw_avg_time),
3386 .help = "Time window over which to calculate bandwidth"
3387 " (msec)",
3388 .def = "500",
3389 .parent = "write_bw_log",
3390 .hide = 1,
3391 .interval = 100,
3392 .category = FIO_OPT_C_LOG,
3393 .group = FIO_OPT_G_INVALID,
3394 },
3395 {
3396 .name = "iopsavgtime",
3397 .lname = "IOPS average time",
3398 .type = FIO_OPT_INT,
3399 .off1 = td_var_offset(iops_avg_time),
3400 .help = "Time window over which to calculate IOPS (msec)",
3401 .def = "500",
3402 .parent = "write_iops_log",
3403 .hide = 1,
3404 .interval = 100,
3405 .category = FIO_OPT_C_LOG,
3406 .group = FIO_OPT_G_INVALID,
3407 },
214e1eca
JA
3408 {
3409 .name = "group_reporting",
e8b0e958 3410 .lname = "Group reporting",
d2507043 3411 .type = FIO_OPT_STR_SET,
214e1eca
JA
3412 .off1 = td_var_offset(group_reporting),
3413 .help = "Do reporting on a per-group basis",
10860056 3414 .category = FIO_OPT_C_STAT,
e8b0e958 3415 .group = FIO_OPT_G_INVALID,
214e1eca 3416 },
e9459e5a
JA
3417 {
3418 .name = "zero_buffers",
e8b0e958 3419 .lname = "Zero I/O buffers",
e9459e5a
JA
3420 .type = FIO_OPT_STR_SET,
3421 .off1 = td_var_offset(zero_buffers),
3422 .help = "Init IO buffers to all zeroes",
e8b0e958 3423 .category = FIO_OPT_C_IO,
3ceb458f 3424 .group = FIO_OPT_G_IO_BUF,
e9459e5a 3425 },
5973cafb
JA
3426 {
3427 .name = "refill_buffers",
e8b0e958 3428 .lname = "Refill I/O buffers",
5973cafb
JA
3429 .type = FIO_OPT_STR_SET,
3430 .off1 = td_var_offset(refill_buffers),
3431 .help = "Refill IO buffers on every IO submit",
e8b0e958 3432 .category = FIO_OPT_C_IO,
3ceb458f 3433 .group = FIO_OPT_G_IO_BUF,
5973cafb 3434 },
fd68418e
JA
3435 {
3436 .name = "scramble_buffers",
e8b0e958 3437 .lname = "Scramble I/O buffers",
fd68418e
JA
3438 .type = FIO_OPT_BOOL,
3439 .off1 = td_var_offset(scramble_buffers),
3440 .help = "Slightly scramble buffers on every IO submit",
3441 .def = "1",
e8b0e958 3442 .category = FIO_OPT_C_IO,
3ceb458f 3443 .group = FIO_OPT_G_IO_BUF,
fd68418e 3444 },
ce35b1ec
JA
3445 {
3446 .name = "buffer_pattern",
3447 .lname = "Buffer pattern",
3448 .type = FIO_OPT_STR,
3449 .cb = str_buffer_pattern_cb,
a8523a6a 3450 .off1 = td_var_offset(buffer_pattern),
ce35b1ec
JA
3451 .help = "Fill pattern for IO buffers",
3452 .category = FIO_OPT_C_IO,
3453 .group = FIO_OPT_G_IO_BUF,
3454 },
9c42684e
JA
3455 {
3456 .name = "buffer_compress_percentage",
e8b0e958 3457 .lname = "Buffer compression percentage",
9c42684e 3458 .type = FIO_OPT_INT,
bedc9dc2 3459 .cb = str_buffer_compress_cb,
a8523a6a 3460 .off1 = td_var_offset(compress_percentage),
9c42684e 3461 .maxval = 100,
e7f5de90 3462 .minval = 0,
9c42684e 3463 .help = "How compressible the buffer is (approximately)",
20eb06bd 3464 .interval = 5,
e8b0e958 3465 .category = FIO_OPT_C_IO,
3ceb458f 3466 .group = FIO_OPT_G_IO_BUF,
9c42684e 3467 },
f97a43a1
JA
3468 {
3469 .name = "buffer_compress_chunk",
e8b0e958 3470 .lname = "Buffer compression chunk size",
f97a43a1
JA
3471 .type = FIO_OPT_INT,
3472 .off1 = td_var_offset(compress_chunk),
207b18e4 3473 .parent = "buffer_compress_percentage",
d71c154c 3474 .hide = 1,
f97a43a1 3475 .help = "Size of compressible region in buffer",
20eb06bd 3476 .interval = 256,
e8b0e958 3477 .category = FIO_OPT_C_IO,
3ceb458f 3478 .group = FIO_OPT_G_IO_BUF,
f97a43a1 3479 },
5c94b008
JA
3480 {
3481 .name = "dedupe_percentage",
3482 .lname = "Dedupe percentage",
3483 .type = FIO_OPT_INT,
3484 .cb = str_dedupe_cb,
a8523a6a 3485 .off1 = td_var_offset(dedupe_percentage),
5c94b008
JA
3486 .maxval = 100,
3487 .minval = 0,
3488 .help = "Percentage of buffers that are dedupable",
3489 .interval = 1,
3490 .category = FIO_OPT_C_IO,
3491 .group = FIO_OPT_G_IO_BUF,
3492 },
83349190
YH
3493 {
3494 .name = "clat_percentiles",
e8b0e958 3495 .lname = "Completion latency percentiles",
83349190
YH
3496 .type = FIO_OPT_BOOL,
3497 .off1 = td_var_offset(clat_percentiles),
3498 .help = "Enable the reporting of completion latency percentiles",
467b35ed 3499 .def = "1",
e8b0e958
JA
3500 .category = FIO_OPT_C_STAT,
3501 .group = FIO_OPT_G_INVALID,
83349190
YH
3502 },
3503 {
3504 .name = "percentile_list",
66347cfa 3505 .lname = "Percentile list",
83349190
YH
3506 .type = FIO_OPT_FLOAT_LIST,
3507 .off1 = td_var_offset(percentile_list),
435d195a 3508 .off2 = td_var_offset(percentile_precision),
66347cfa
DE
3509 .help = "Specify a custom list of percentiles to report for "
3510 "completion latency and block errors",
fd112d34 3511 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
3512 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3513 .minfp = 0.0,
3514 .maxfp = 100.0,
e8b0e958
JA
3515 .category = FIO_OPT_C_STAT,
3516 .group = FIO_OPT_G_INVALID,
83349190
YH
3517 },
3518
0a839f30
JA
3519#ifdef FIO_HAVE_DISK_UTIL
3520 {
3521 .name = "disk_util",
e8b0e958 3522 .lname = "Disk utilization",
0a839f30
JA
3523 .type = FIO_OPT_BOOL,
3524 .off1 = td_var_offset(do_disk_util),
f66ab3c8 3525 .help = "Log disk utilization statistics",
0a839f30 3526 .def = "1",
e8b0e958
JA
3527 .category = FIO_OPT_C_STAT,
3528 .group = FIO_OPT_G_INVALID,
0a839f30
JA
3529 },
3530#endif
993bf48b
JA
3531 {
3532 .name = "gtod_reduce",
e8b0e958 3533 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
3534 .type = FIO_OPT_BOOL,
3535 .help = "Greatly reduce number of gettimeofday() calls",
3536 .cb = str_gtod_reduce_cb,
3537 .def = "0",
a4ed77fe 3538 .hide_on_set = 1,
e8b0e958
JA
3539 .category = FIO_OPT_C_STAT,
3540 .group = FIO_OPT_G_INVALID,
993bf48b 3541 },
02af0988
JA
3542 {
3543 .name = "disable_lat",
e8b0e958 3544 .lname = "Disable all latency stats",
02af0988
JA
3545 .type = FIO_OPT_BOOL,
3546 .off1 = td_var_offset(disable_lat),
3547 .help = "Disable latency numbers",
3548 .parent = "gtod_reduce",
d71c154c 3549 .hide = 1,
02af0988 3550 .def = "0",
e8b0e958
JA
3551 .category = FIO_OPT_C_STAT,
3552 .group = FIO_OPT_G_INVALID,
02af0988 3553 },
9520ebb9
JA
3554 {
3555 .name = "disable_clat",
e8b0e958 3556 .lname = "Disable completion latency stats",
9520ebb9
JA
3557 .type = FIO_OPT_BOOL,
3558 .off1 = td_var_offset(disable_clat),
3559 .help = "Disable completion latency numbers",
993bf48b 3560 .parent = "gtod_reduce",
d71c154c 3561 .hide = 1,
9520ebb9 3562 .def = "0",
e8b0e958
JA
3563 .category = FIO_OPT_C_STAT,
3564 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3565 },
3566 {
3567 .name = "disable_slat",
e8b0e958 3568 .lname = "Disable submission latency stats",
9520ebb9
JA
3569 .type = FIO_OPT_BOOL,
3570 .off1 = td_var_offset(disable_slat),
03e20d68 3571 .help = "Disable submission latency numbers",
993bf48b 3572 .parent = "gtod_reduce",
d71c154c 3573 .hide = 1,
9520ebb9 3574 .def = "0",
e8b0e958
JA
3575 .category = FIO_OPT_C_STAT,
3576 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3577 },
3578 {
3579 .name = "disable_bw_measurement",
e8b0e958 3580 .lname = "Disable bandwidth stats",
9520ebb9
JA
3581 .type = FIO_OPT_BOOL,
3582 .off1 = td_var_offset(disable_bw),
3583 .help = "Disable bandwidth logging",
993bf48b 3584 .parent = "gtod_reduce",
d71c154c 3585 .hide = 1,
9520ebb9 3586 .def = "0",
e8b0e958
JA
3587 .category = FIO_OPT_C_STAT,
3588 .group = FIO_OPT_G_INVALID,
9520ebb9 3589 },
be4ecfdf
JA
3590 {
3591 .name = "gtod_cpu",
e8b0e958 3592 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 3593 .type = FIO_OPT_INT,
79c896a1 3594 .off1 = td_var_offset(gtod_cpu),
03e20d68 3595 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 3596 .verify = gtod_cpu_verify,
e8b0e958 3597 .category = FIO_OPT_C_GENERAL,
10860056 3598 .group = FIO_OPT_G_CLOCK,
be4ecfdf 3599 },
771e58be
JA
3600 {
3601 .name = "unified_rw_reporting",
3602 .type = FIO_OPT_BOOL,
3603 .off1 = td_var_offset(unified_rw_rep),
3604 .help = "Unify reporting across data direction",
3605 .def = "0",
90b7a96d
JA
3606 .category = FIO_OPT_C_GENERAL,
3607 .group = FIO_OPT_G_INVALID,
771e58be 3608 },
f2bba182
RR
3609 {
3610 .name = "continue_on_error",
e8b0e958 3611 .lname = "Continue on error",
06842027 3612 .type = FIO_OPT_STR,
f2bba182 3613 .off1 = td_var_offset(continue_on_error),
03e20d68 3614 .help = "Continue on non-fatal errors during IO",
06842027 3615 .def = "none",
e8b0e958 3616 .category = FIO_OPT_C_GENERAL,
bc3f552f 3617 .group = FIO_OPT_G_ERR,
06842027
SL
3618 .posval = {
3619 { .ival = "none",
3620 .oval = ERROR_TYPE_NONE,
3621 .help = "Exit when an error is encountered",
3622 },
3623 { .ival = "read",
3624 .oval = ERROR_TYPE_READ,
3625 .help = "Continue on read errors only",
3626 },
3627 { .ival = "write",
3628 .oval = ERROR_TYPE_WRITE,
3629 .help = "Continue on write errors only",
3630 },
3631 { .ival = "io",
3632 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
3633 .help = "Continue on any IO errors",
3634 },
3635 { .ival = "verify",
3636 .oval = ERROR_TYPE_VERIFY,
3637 .help = "Continue on verify errors only",
3638 },
3639 { .ival = "all",
3640 .oval = ERROR_TYPE_ANY,
3641 .help = "Continue on all io and verify errors",
3642 },
3643 { .ival = "0",
3644 .oval = ERROR_TYPE_NONE,
3645 .help = "Alias for 'none'",
3646 },
3647 { .ival = "1",
3648 .oval = ERROR_TYPE_ANY,
3649 .help = "Alias for 'all'",
3650 },
3651 },
f2bba182 3652 },
8b28bd41
DM
3653 {
3654 .name = "ignore_error",
3655 .type = FIO_OPT_STR,
3656 .cb = str_ignore_error_cb,
a8523a6a 3657 .off1 = td_var_offset(ignore_error_nr),
8b28bd41
DM
3658 .help = "Set a specific list of errors to ignore",
3659 .parent = "rw",
a94eb99a 3660 .category = FIO_OPT_C_GENERAL,
bc3f552f 3661 .group = FIO_OPT_G_ERR,
8b28bd41
DM
3662 },
3663 {
3664 .name = "error_dump",
3665 .type = FIO_OPT_BOOL,
3666 .off1 = td_var_offset(error_dump),
3667 .def = "0",
3668 .help = "Dump info on each error",
a94eb99a 3669 .category = FIO_OPT_C_GENERAL,
bc3f552f 3670 .group = FIO_OPT_G_ERR,
8b28bd41 3671 },
9ac8a797
JA
3672 {
3673 .name = "profile",
e8b0e958 3674 .lname = "Profile",
79d16311 3675 .type = FIO_OPT_STR_STORE,
9ac8a797 3676 .off1 = td_var_offset(profile),
9ac8a797 3677 .help = "Select a specific builtin performance test",
13fca827 3678 .category = FIO_OPT_C_PROFILE,
e8b0e958 3679 .group = FIO_OPT_G_INVALID,
9ac8a797 3680 },
a696fa2a
JA
3681 {
3682 .name = "cgroup",
e8b0e958 3683 .lname = "Cgroup",
a696fa2a
JA
3684 .type = FIO_OPT_STR_STORE,
3685 .off1 = td_var_offset(cgroup),
3686 .help = "Add job to cgroup of this name",
e8b0e958 3687 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
3688 .group = FIO_OPT_G_CGROUP,
3689 },
3690 {
3691 .name = "cgroup_nodelete",
3692 .lname = "Cgroup no-delete",
3693 .type = FIO_OPT_BOOL,
3694 .off1 = td_var_offset(cgroup_nodelete),
3695 .help = "Do not delete cgroups after job completion",
3696 .def = "0",
3697 .parent = "cgroup",
3698 .category = FIO_OPT_C_GENERAL,
3699 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
3700 },
3701 {
3702 .name = "cgroup_weight",
e8b0e958 3703 .lname = "Cgroup weight",
a696fa2a
JA
3704 .type = FIO_OPT_INT,
3705 .off1 = td_var_offset(cgroup_weight),
3706 .help = "Use given weight for cgroup",
3707 .minval = 100,
3708 .maxval = 1000,
a1f6afec 3709 .parent = "cgroup",
e8b0e958 3710 .category = FIO_OPT_C_GENERAL,
a1f6afec 3711 .group = FIO_OPT_G_CGROUP,
7de87099 3712 },
e0b0d892
JA
3713 {
3714 .name = "uid",
e8b0e958 3715 .lname = "User ID",
e0b0d892
JA
3716 .type = FIO_OPT_INT,
3717 .off1 = td_var_offset(uid),
3718 .help = "Run job with this user ID",
e8b0e958 3719 .category = FIO_OPT_C_GENERAL,
10860056 3720 .group = FIO_OPT_G_CRED,
e0b0d892
JA
3721 },
3722 {
3723 .name = "gid",
e8b0e958 3724 .lname = "Group ID",
e0b0d892
JA
3725 .type = FIO_OPT_INT,
3726 .off1 = td_var_offset(gid),
3727 .help = "Run job with this group ID",
e8b0e958 3728 .category = FIO_OPT_C_GENERAL,
10860056 3729 .group = FIO_OPT_G_CRED,
e0b0d892 3730 },
a1f6afec
JA
3731 {
3732 .name = "kb_base",
3733 .lname = "KB Base",
3734 .type = FIO_OPT_INT,
3735 .off1 = td_var_offset(kb_base),
a1f6afec
JA
3736 .prio = 1,
3737 .def = "1024",
ba9c7219
JA
3738 .posval = {
3739 { .ival = "1024",
3740 .oval = 1024,
3741 .help = "Use 1024 as the K base",
3742 },
3743 { .ival = "1000",
3744 .oval = 1000,
3745 .help = "Use 1000 as the K base",
3746 },
3747 },
a1f6afec
JA
3748 .help = "How many bytes per KB for reporting (1000 or 1024)",
3749 .category = FIO_OPT_C_GENERAL,
3750 .group = FIO_OPT_G_INVALID,
3751 },
cf3a0518
JA
3752 {
3753 .name = "unit_base",
ba9c7219 3754 .lname = "Base unit for reporting (Bits or Bytes)",
cf3a0518
JA
3755 .type = FIO_OPT_INT,
3756 .off1 = td_var_offset(unit_base),
cf3a0518 3757 .prio = 1,
71a08258
JA
3758 .posval = {
3759 { .ival = "0",
3760 .oval = 0,
3761 .help = "Auto-detect",
3762 },
3763 { .ival = "8",
3764 .oval = 8,
3765 .help = "Normal (byte based)",
3766 },
3767 { .ival = "1",
3768 .oval = 1,
3769 .help = "Bit based",
3770 },
3771 },
cf3a0518
JA
3772 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
3773 .category = FIO_OPT_C_GENERAL,
3774 .group = FIO_OPT_G_INVALID,
3775 },
3ceb458f
JA
3776 {
3777 .name = "hugepage-size",
3778 .lname = "Hugepage size",
3779 .type = FIO_OPT_INT,
3780 .off1 = td_var_offset(hugepage_size),
3781 .help = "When using hugepages, specify size of each page",
3782 .def = __fio_stringify(FIO_HUGE_PAGE),
3783 .interval = 1024 * 1024,
3784 .category = FIO_OPT_C_GENERAL,
3785 .group = FIO_OPT_G_INVALID,
3786 },
9e684a49
DE
3787 {
3788 .name = "flow_id",
e8b0e958 3789 .lname = "I/O flow ID",
9e684a49
DE
3790 .type = FIO_OPT_INT,
3791 .off1 = td_var_offset(flow_id),
3792 .help = "The flow index ID to use",
3793 .def = "0",
e8b0e958
JA
3794 .category = FIO_OPT_C_IO,
3795 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3796 },
3797 {
3798 .name = "flow",
e8b0e958 3799 .lname = "I/O flow weight",
9e684a49
DE
3800 .type = FIO_OPT_INT,
3801 .off1 = td_var_offset(flow),
3802 .help = "Weight for flow control of this job",
3803 .parent = "flow_id",
d71c154c 3804 .hide = 1,
9e684a49 3805 .def = "0",
e8b0e958
JA
3806 .category = FIO_OPT_C_IO,
3807 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3808 },
3809 {
3810 .name = "flow_watermark",
e8b0e958 3811 .lname = "I/O flow watermark",
9e684a49
DE
3812 .type = FIO_OPT_INT,
3813 .off1 = td_var_offset(flow_watermark),
3814 .help = "High watermark for flow control. This option"
3815 " should be set to the same value for all threads"
3816 " with non-zero flow.",
3817 .parent = "flow_id",
d71c154c 3818 .hide = 1,
9e684a49 3819 .def = "1024",
e8b0e958
JA
3820 .category = FIO_OPT_C_IO,
3821 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3822 },
3823 {
3824 .name = "flow_sleep",
e8b0e958 3825 .lname = "I/O flow sleep",
9e684a49
DE
3826 .type = FIO_OPT_INT,
3827 .off1 = td_var_offset(flow_sleep),
3828 .help = "How many microseconds to sleep after being held"
3829 " back by the flow control mechanism",
3830 .parent = "flow_id",
d71c154c 3831 .hide = 1,
9e684a49 3832 .def = "0",
e8b0e958
JA
3833 .category = FIO_OPT_C_IO,
3834 .group = FIO_OPT_G_IO_FLOW,
9e684a49 3835 },
65fa28ca
DE
3836 {
3837 .name = "skip_bad",
3838 .lname = "Skip operations against bad blocks",
3839 .type = FIO_OPT_BOOL,
3840 .off1 = td_var_offset(skip_bad),
3841 .help = "Skip operations against known bad blocks.",
3842 .hide = 1,
3843 .def = "0",
3844 .category = FIO_OPT_C_IO,
3845 .group = FIO_OPT_G_MTD,
3846 },
214e1eca
JA
3847 {
3848 .name = NULL,
3849 },
3850};
3851
17af15d4 3852static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 3853 const char *name, int val)
9f81736c 3854{
17af15d4 3855 lopt->name = (char *) name;
de890a1e 3856 lopt->val = val;
9f81736c 3857 if (o->type == FIO_OPT_STR_SET)
ff52be3d 3858 lopt->has_arg = optional_argument;
9f81736c
JA
3859 else
3860 lopt->has_arg = required_argument;
3861}
3862
de890a1e
SL
3863static void options_to_lopts(struct fio_option *opts,
3864 struct option *long_options,
3865 int i, int option_type)
214e1eca 3866{
de890a1e 3867 struct fio_option *o = &opts[0];
214e1eca 3868 while (o->name) {
de890a1e 3869 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
3870 if (o->alias) {
3871 i++;
de890a1e 3872 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 3873 }
214e1eca
JA
3874
3875 i++;
3876 o++;
3877 assert(i < FIO_NR_OPTIONS);
3878 }
3879}
3880
de890a1e
SL
3881void fio_options_set_ioengine_opts(struct option *long_options,
3882 struct thread_data *td)
3883{
3884 unsigned int i;
3885
3886 i = 0;
3887 while (long_options[i].name) {
3888 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
3889 memset(&long_options[i], 0, sizeof(*long_options));
3890 break;
3891 }
3892 i++;
3893 }
3894
3895 /*
3896 * Just clear out the prior ioengine options.
3897 */
3898 if (!td || !td->eo)
3899 return;
3900
3901 options_to_lopts(td->io_ops->options, long_options, i,
3902 FIO_GETOPT_IOENGINE);
3903}
3904
3905void fio_options_dup_and_init(struct option *long_options)
3906{
3907 unsigned int i;
3908
9af4a244 3909 options_init(fio_options);
de890a1e
SL
3910
3911 i = 0;
3912 while (long_options[i].name)
3913 i++;
3914
9af4a244 3915 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
3916}
3917
74929ac2
JA
3918struct fio_keyword {
3919 const char *word;
3920 const char *desc;
3921 char *replace;
3922};
3923
3924static struct fio_keyword fio_keywords[] = {
3925 {
3926 .word = "$pagesize",
3927 .desc = "Page size in the system",
3928 },
3929 {
3930 .word = "$mb_memory",
3931 .desc = "Megabytes of memory online",
3932 },
3933 {
3934 .word = "$ncpus",
3935 .desc = "Number of CPUs online in the system",
3936 },
3937 {
3938 .word = NULL,
3939 },
3940};
3941
af1dc266
JA
3942void fio_keywords_exit(void)
3943{
3944 struct fio_keyword *kw;
3945
3946 kw = &fio_keywords[0];
3947 while (kw->word) {
3948 free(kw->replace);
3949 kw->replace = NULL;
3950 kw++;
3951 }
3952}
3953
74929ac2
JA
3954void fio_keywords_init(void)
3955{
3b2e1464 3956 unsigned long long mb_memory;
74929ac2
JA
3957 char buf[128];
3958 long l;
3959
a4cfc477 3960 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
3961 fio_keywords[0].replace = strdup(buf);
3962
8eb016d3 3963 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 3964 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
3965 fio_keywords[1].replace = strdup(buf);
3966
c00a2289 3967 l = cpus_online();
74929ac2
JA
3968 sprintf(buf, "%lu", l);
3969 fio_keywords[2].replace = strdup(buf);
3970}
3971
892a6ffc
JA
3972#define BC_APP "bc"
3973
3974static char *bc_calc(char *str)
3975{
d0c814ec 3976 char buf[128], *tmp;
892a6ffc
JA
3977 FILE *f;
3978 int ret;
3979
3980 /*
3981 * No math, just return string
3982 */
d0c814ec
SL
3983 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
3984 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
3985 return str;
3986
3987 /*
3988 * Split option from value, we only need to calculate the value
3989 */
3990 tmp = strchr(str, '=');
3991 if (!tmp)
3992 return str;
3993
3994 tmp++;
892a6ffc 3995
d0c814ec
SL
3996 /*
3997 * Prevent buffer overflows; such a case isn't reasonable anyway
3998 */
3999 if (strlen(str) >= 128 || strlen(tmp) > 100)
4000 return str;
892a6ffc
JA
4001
4002 sprintf(buf, "which %s > /dev/null", BC_APP);
4003 if (system(buf)) {
4004 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
4005 return NULL;
4006 }
4007
d0c814ec 4008 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 4009 f = popen(buf, "r");
3c3ed070 4010 if (!f)
892a6ffc 4011 return NULL;
892a6ffc 4012
d0c814ec 4013 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
4014 if (ret <= 0) {
4015 pclose(f);
892a6ffc 4016 return NULL;
1d824f37 4017 }
892a6ffc 4018
892a6ffc 4019 pclose(f);
d0c814ec
SL
4020 buf[(tmp - str) + ret - 1] = '\0';
4021 memcpy(buf, str, tmp - str);
892a6ffc 4022 free(str);
d0c814ec
SL
4023 return strdup(buf);
4024}
4025
4026/*
4027 * Return a copy of the input string with substrings of the form ${VARNAME}
4028 * substituted with the value of the environment variable VARNAME. The
4029 * substitution always occurs, even if VARNAME is empty or the corresponding
4030 * environment variable undefined.
4031 */
4032static char *option_dup_subs(const char *opt)
4033{
4034 char out[OPT_LEN_MAX+1];
4035 char in[OPT_LEN_MAX+1];
4036 char *outptr = out;
4037 char *inptr = in;
4038 char *ch1, *ch2, *env;
4039 ssize_t nchr = OPT_LEN_MAX;
4040 size_t envlen;
4041
4042 if (strlen(opt) + 1 > OPT_LEN_MAX) {
4043 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
4044 return NULL;
4045 }
4046
4047 in[OPT_LEN_MAX] = '\0';
4048 strncpy(in, opt, OPT_LEN_MAX);
4049
4050 while (*inptr && nchr > 0) {
4051 if (inptr[0] == '$' && inptr[1] == '{') {
4052 ch2 = strchr(inptr, '}');
4053 if (ch2 && inptr+1 < ch2) {
4054 ch1 = inptr+2;
4055 inptr = ch2+1;
4056 *ch2 = '\0';
4057
4058 env = getenv(ch1);
4059 if (env) {
4060 envlen = strlen(env);
4061 if (envlen <= nchr) {
4062 memcpy(outptr, env, envlen);
4063 outptr += envlen;
4064 nchr -= envlen;
4065 }
4066 }
4067
4068 continue;
4069 }
4070 }
4071
4072 *outptr++ = *inptr++;
4073 --nchr;
4074 }
4075
4076 *outptr = '\0';
4077 return strdup(out);
892a6ffc
JA
4078}
4079
74929ac2
JA
4080/*
4081 * Look for reserved variable names and replace them with real values
4082 */
4083static char *fio_keyword_replace(char *opt)
4084{
4085 char *s;
4086 int i;
d0c814ec 4087 int docalc = 0;
74929ac2
JA
4088
4089 for (i = 0; fio_keywords[i].word != NULL; i++) {
4090 struct fio_keyword *kw = &fio_keywords[i];
4091
4092 while ((s = strstr(opt, kw->word)) != NULL) {
4093 char *new = malloc(strlen(opt) + 1);
4094 char *o_org = opt;
4095 int olen = s - opt;
4096 int len;
4097
4098 /*
4099 * Copy part of the string before the keyword and
4100 * sprintf() the replacement after it.
4101 */
4102 memcpy(new, opt, olen);
4103 len = sprintf(new + olen, "%s", kw->replace);
4104
4105 /*
4106 * If there's more in the original string, copy that
4107 * in too
4108 */
4109 opt += strlen(kw->word) + olen;
4110 if (strlen(opt))
4111 memcpy(new + olen + len, opt, opt - o_org - 1);
4112
4113 /*
4114 * replace opt and free the old opt
4115 */
4116 opt = new;
d0c814ec 4117 free(o_org);
7a958bd5 4118
d0c814ec 4119 docalc = 1;
74929ac2
JA
4120 }
4121 }
4122
d0c814ec
SL
4123 /*
4124 * Check for potential math and invoke bc, if possible
4125 */
4126 if (docalc)
4127 opt = bc_calc(opt);
4128
7a958bd5 4129 return opt;
74929ac2
JA
4130}
4131
d0c814ec
SL
4132static char **dup_and_sub_options(char **opts, int num_opts)
4133{
4134 int i;
4135 char **opts_copy = malloc(num_opts * sizeof(*opts));
4136 for (i = 0; i < num_opts; i++) {
4137 opts_copy[i] = option_dup_subs(opts[i]);
4138 if (!opts_copy[i])
4139 continue;
4140 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
4141 }
4142 return opts_copy;
4143}
4144
e15b023b 4145static void show_closest_option(const char *opt)
a2d027b9
JA
4146{
4147 int best_option, best_distance;
4148 int i, distance;
e15b023b
JA
4149 char *name;
4150
4151 if (!strlen(opt))
4152 return;
4153
4154 name = strdup(opt);
4155 i = 0;
4156 while (name[i] != '\0' && name[i] != '=')
4157 i++;
4158 name[i] = '\0';
a2d027b9
JA
4159
4160 best_option = -1;
4161 best_distance = INT_MAX;
4162 i = 0;
4163 while (fio_options[i].name) {
4164 distance = string_distance(name, fio_options[i].name);
4165 if (distance < best_distance) {
4166 best_distance = distance;
4167 best_option = i;
4168 }
4169 i++;
4170 }
4171
3701636d 4172 if (best_option != -1 && string_distance_ok(name, best_distance))
a2d027b9 4173 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
4174
4175 free(name);
a2d027b9
JA
4176}
4177
c2292325 4178int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 4179{
de890a1e 4180 int i, ret, unknown;
d0c814ec 4181 char **opts_copy;
3b8b7135 4182
9af4a244 4183 sort_options(opts, fio_options, num_opts);
d0c814ec 4184 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 4185
de890a1e
SL
4186 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
4187 struct fio_option *o;
9af4a244 4188 int newret = parse_option(opts_copy[i], opts[i], fio_options,
66e19a38 4189 &o, td, &td->opt_list);
d0c814ec 4190
a8523a6a
JA
4191 if (!newret && o)
4192 fio_option_mark_set(&td->o, o);
4193
de890a1e
SL
4194 if (opts_copy[i]) {
4195 if (newret && !o) {
4196 unknown++;
4197 continue;
4198 }
d0c814ec 4199 free(opts_copy[i]);
de890a1e
SL
4200 opts_copy[i] = NULL;
4201 }
4202
4203 ret |= newret;
4204 }
4205
4206 if (unknown) {
4207 ret |= ioengine_load(td);
4208 if (td->eo) {
4209 sort_options(opts_copy, td->io_ops->options, num_opts);
4210 opts = opts_copy;
4211 }
4212 for (i = 0; i < num_opts; i++) {
4213 struct fio_option *o = NULL;
4214 int newret = 1;
a2d027b9 4215
de890a1e
SL
4216 if (!opts_copy[i])
4217 continue;
4218
4219 if (td->eo)
4220 newret = parse_option(opts_copy[i], opts[i],
4221 td->io_ops->options, &o,
66e19a38 4222 td->eo, &td->opt_list);
de890a1e
SL
4223
4224 ret |= newret;
a2d027b9 4225 if (!o) {
de890a1e 4226 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
4227 show_closest_option(opts[i]);
4228 }
de890a1e
SL
4229 free(opts_copy[i]);
4230 opts_copy[i] = NULL;
4231 }
74929ac2 4232 }
3b8b7135 4233
d0c814ec 4234 free(opts_copy);
3b8b7135 4235 return ret;
214e1eca
JA
4236}
4237
4238int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
4239{
a8523a6a
JA
4240 int ret;
4241
d8b4f395 4242 ret = parse_cmd_option(opt, val, fio_options, td, &td->opt_list);
a8523a6a
JA
4243 if (!ret) {
4244 struct fio_option *o;
4245
4246 o = find_option(fio_options, opt);
4247 if (o)
4248 fio_option_mark_set(&td->o, o);
4249 }
4250
4251 return ret;
214e1eca
JA
4252}
4253
de890a1e
SL
4254int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
4255 char *val)
4256{
d8b4f395
JA
4257 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
4258 &td->opt_list);
de890a1e
SL
4259}
4260
214e1eca
JA
4261void fio_fill_default_options(struct thread_data *td)
4262{
cb1402d6 4263 td->o.magic = OPT_MAGIC;
9af4a244 4264 fill_default_options(td, fio_options);
214e1eca
JA
4265}
4266
4267int fio_show_option_help(const char *opt)
4268{
9af4a244 4269 return show_cmd_help(fio_options, opt);
214e1eca 4270}
d23bb327 4271
de890a1e 4272void options_mem_dupe(void *data, struct fio_option *options)
d23bb327 4273{
de890a1e 4274 struct fio_option *o;
d23bb327 4275 char **ptr;
d23bb327 4276
de890a1e
SL
4277 for (o = &options[0]; o->name; o++) {
4278 if (o->type != FIO_OPT_STR_STORE)
d23bb327
JA
4279 continue;
4280
f0fdbcaf 4281 ptr = td_var(data, o, o->off1);
7e356b2d
JA
4282 if (*ptr)
4283 *ptr = strdup(*ptr);
d23bb327
JA
4284 }
4285}
4286
de890a1e
SL
4287/*
4288 * dupe FIO_OPT_STR_STORE options
4289 */
4290void fio_options_mem_dupe(struct thread_data *td)
4291{
9af4a244 4292 options_mem_dupe(&td->o, fio_options);
1647f592
JA
4293
4294 if (td->eo && td->io_ops) {
de890a1e 4295 void *oldeo = td->eo;
1647f592 4296
de890a1e
SL
4297 td->eo = malloc(td->io_ops->option_struct_size);
4298 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
4299 options_mem_dupe(td->eo, td->io_ops->options);
4300 }
4301}
4302
d6978a32
JA
4303unsigned int fio_get_kb_base(void *data)
4304{
83ea422a 4305 struct thread_options *o = data;
d6978a32
JA
4306 unsigned int kb_base = 0;
4307
cb1402d6
JA
4308 /*
4309 * This is a hack... For private options, *data is not holding
4310 * a pointer to the thread_options, but to private data. This means
4311 * we can't safely dereference it, but magic is first so mem wise
4312 * it is valid. But this also means that if the job first sets
4313 * kb_base and expects that to be honored by private options,
4314 * it will be disappointed. We will return the global default
4315 * for this.
4316 */
4317 if (o && o->magic == OPT_MAGIC)
83ea422a 4318 kb_base = o->kb_base;
d6978a32
JA
4319 if (!kb_base)
4320 kb_base = 1024;
4321
4322 return kb_base;
4323}
9f988e2e 4324
07b3232d 4325int add_option(struct fio_option *o)
9f988e2e 4326{
07b3232d
JA
4327 struct fio_option *__o;
4328 int opt_index = 0;
4329
9af4a244 4330 __o = fio_options;
07b3232d
JA
4331 while (__o->name) {
4332 opt_index++;
4333 __o++;
4334 }
4335
7b504edd
JA
4336 if (opt_index + 1 == FIO_MAX_OPTS) {
4337 log_err("fio: FIO_MAX_OPTS is too small\n");
4338 return 1;
4339 }
4340
9af4a244 4341 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 4342 fio_options[opt_index + 1].name = NULL;
07b3232d 4343 return 0;
9f988e2e 4344}
e2de69da 4345
07b3232d 4346void invalidate_profile_options(const char *prof_name)
e2de69da 4347{
07b3232d 4348 struct fio_option *o;
e2de69da 4349
9af4a244 4350 o = fio_options;
07b3232d
JA
4351 while (o->name) {
4352 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
4353 o->type = FIO_OPT_INVALID;
4354 o->prof_name = NULL;
4355 }
4356 o++;
e2de69da
JA
4357 }
4358}
f5b6bb85
JA
4359
4360void add_opt_posval(const char *optname, const char *ival, const char *help)
4361{
4362 struct fio_option *o;
4363 unsigned int i;
4364
9af4a244 4365 o = find_option(fio_options, optname);
f5b6bb85
JA
4366 if (!o)
4367 return;
4368
4369 for (i = 0; i < PARSE_MAX_VP; i++) {
4370 if (o->posval[i].ival)
4371 continue;
4372
4373 o->posval[i].ival = ival;
4374 o->posval[i].help = help;
4375 break;
4376 }
4377}
4378
4379void del_opt_posval(const char *optname, const char *ival)
4380{
4381 struct fio_option *o;
4382 unsigned int i;
4383
9af4a244 4384 o = find_option(fio_options, optname);
f5b6bb85
JA
4385 if (!o)
4386 return;
4387
4388 for (i = 0; i < PARSE_MAX_VP; i++) {
4389 if (!o->posval[i].ival)
4390 continue;
4391 if (strcmp(o->posval[i].ival, ival))
4392 continue;
4393
4394 o->posval[i].ival = NULL;
4395 o->posval[i].help = NULL;
4396 }
4397}
7e356b2d
JA
4398
4399void fio_options_free(struct thread_data *td)
4400{
9af4a244 4401 options_free(fio_options, td);
de890a1e
SL
4402 if (td->eo && td->io_ops && td->io_ops->options) {
4403 options_free(td->io_ops->options, td->eo);
4404 free(td->eo);
4405 td->eo = NULL;
4406 }
7e356b2d 4407}
c504ee55
JA
4408
4409struct fio_option *fio_option_find(const char *name)
4410{
4411 return find_option(fio_options, name);
4412}
4413
f0e7f45a
JA
4414static struct fio_option *find_next_opt(struct thread_options *o,
4415 struct fio_option *from,
4416 unsigned int off1)
a8523a6a 4417{
f0e7f45a 4418 struct fio_option *opt;
a8523a6a 4419
f0e7f45a
JA
4420 if (!from)
4421 from = &fio_options[0];
4422 else
4423 from++;
4424
4425 opt = NULL;
4426 do {
4427 if (off1 == from->off1) {
4428 opt = from;
a8523a6a
JA
4429 break;
4430 }
f0e7f45a
JA
4431 from++;
4432 } while (from->name);
a8523a6a 4433
f0e7f45a
JA
4434 return opt;
4435}
4436
4437static int opt_is_set(struct thread_options *o, struct fio_option *opt)
4438{
4439 unsigned int opt_off, index, offset;
a8523a6a
JA
4440
4441 opt_off = opt - &fio_options[0];
4442 index = opt_off / (8 * sizeof(uint64_t));
4443 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 4444 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
4445}
4446
72f39748 4447bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
4448{
4449 struct fio_option *opt, *next;
4450
4451 next = NULL;
4452 while ((opt = find_next_opt(o, next, off1)) != NULL) {
4453 if (opt_is_set(o, opt))
72f39748 4454 return true;
f0e7f45a
JA
4455
4456 next = opt;
4457 }
4458
72f39748 4459 return false;
f0e7f45a
JA
4460}
4461
a8523a6a
JA
4462void fio_option_mark_set(struct thread_options *o, struct fio_option *opt)
4463{
4464 unsigned int opt_off, index, offset;
4465
4466 opt_off = opt - &fio_options[0];
4467 index = opt_off / (8 * sizeof(uint64_t));
4468 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 4469 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 4470}