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