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