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