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