Enable request flow under Poisson process
[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 {
2821 .name = "ratemin",
e8b0e958 2822 .lname = "I/O min rate",
e01b22b8 2823 .type = FIO_OPT_INT,
6eaf09d6
SL
2824 .off1 = td_var_offset(ratemin[DDIR_READ]),
2825 .off2 = td_var_offset(ratemin[DDIR_WRITE]),
2826 .off3 = td_var_offset(ratemin[DDIR_TRIM]),
4e991c23 2827 .help = "Job must meet this rate or it will be shutdown",
afdf9352 2828 .parent = "rate",
d71c154c 2829 .hide = 1,
e8b0e958
JA
2830 .category = FIO_OPT_C_IO,
2831 .group = FIO_OPT_G_RATE,
4e991c23
JA
2832 },
2833 {
2834 .name = "rate_iops",
e8b0e958 2835 .lname = "I/O rate IOPS",
e01b22b8 2836 .type = FIO_OPT_INT,
6eaf09d6
SL
2837 .off1 = td_var_offset(rate_iops[DDIR_READ]),
2838 .off2 = td_var_offset(rate_iops[DDIR_WRITE]),
2839 .off3 = td_var_offset(rate_iops[DDIR_TRIM]),
4e991c23 2840 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 2841 .hide = 1,
e8b0e958
JA
2842 .category = FIO_OPT_C_IO,
2843 .group = FIO_OPT_G_RATE,
4e991c23
JA
2844 },
2845 {
2846 .name = "rate_iops_min",
e8b0e958 2847 .lname = "I/O min rate IOPS",
e01b22b8 2848 .type = FIO_OPT_INT,
6eaf09d6
SL
2849 .off1 = td_var_offset(rate_iops_min[DDIR_READ]),
2850 .off2 = td_var_offset(rate_iops_min[DDIR_WRITE]),
2851 .off3 = td_var_offset(rate_iops_min[DDIR_TRIM]),
03e20d68 2852 .help = "Job must meet this rate or it will be shut down",
afdf9352 2853 .parent = "rate_iops",
d71c154c 2854 .hide = 1,
e8b0e958
JA
2855 .category = FIO_OPT_C_IO,
2856 .group = FIO_OPT_G_RATE,
214e1eca 2857 },
ff6bb260
SL
2858 {
2859 .name = "poisson",
2860 .lname = "simulate requests under Poisson process",
2861 .type = FIO_OPT_BOOL,
2862 .off1 = td_var_offset(poisson_request),
2863 .help = "with rate limit, try simulate requests that follow Poisson process",
2864 .def = "0",
2865 .hide = 1,
2866 .category = FIO_OPT_C_IO,
2867 .group = FIO_OPT_G_RATE,
2868 },
214e1eca
JA
2869 {
2870 .name = "ratecycle",
e8b0e958 2871 .lname = "I/O rate cycle",
214e1eca
JA
2872 .type = FIO_OPT_INT,
2873 .off1 = td_var_offset(ratecycle),
2874 .help = "Window average for rate limits (msec)",
2875 .def = "1000",
afdf9352 2876 .parent = "rate",
d71c154c 2877 .hide = 1,
e8b0e958
JA
2878 .category = FIO_OPT_C_IO,
2879 .group = FIO_OPT_G_RATE,
214e1eca 2880 },
15501535
JA
2881 {
2882 .name = "max_latency",
2883 .type = FIO_OPT_INT,
2884 .off1 = td_var_offset(max_latency),
2885 .help = "Maximum tolerated IO latency (usec)",
88038bc7 2886 .is_time = 1,
1e5324e7 2887 .category = FIO_OPT_C_IO,
3e260a46
JA
2888 .group = FIO_OPT_G_LATPROF,
2889 },
2890 {
2891 .name = "latency_target",
2892 .lname = "Latency Target (usec)",
2893 .type = FIO_OPT_STR_VAL_TIME,
2894 .off1 = td_var_offset(latency_target),
2895 .help = "Ramp to max queue depth supporting this latency",
88038bc7 2896 .is_time = 1,
3e260a46
JA
2897 .category = FIO_OPT_C_IO,
2898 .group = FIO_OPT_G_LATPROF,
2899 },
2900 {
2901 .name = "latency_window",
2902 .lname = "Latency Window (usec)",
2903 .type = FIO_OPT_STR_VAL_TIME,
2904 .off1 = td_var_offset(latency_window),
2905 .help = "Time to sustain latency_target",
88038bc7 2906 .is_time = 1,
3e260a46
JA
2907 .category = FIO_OPT_C_IO,
2908 .group = FIO_OPT_G_LATPROF,
2909 },
2910 {
2911 .name = "latency_percentile",
2912 .lname = "Latency Percentile",
2913 .type = FIO_OPT_FLOAT_LIST,
2914 .off1 = td_var_offset(latency_percentile),
2915 .help = "Percentile of IOs must be below latency_target",
2916 .def = "100",
2917 .maxlen = 1,
2918 .minfp = 0.0,
2919 .maxfp = 100.0,
2920 .category = FIO_OPT_C_IO,
2921 .group = FIO_OPT_G_LATPROF,
15501535 2922 },
214e1eca
JA
2923 {
2924 .name = "invalidate",
e8b0e958 2925 .lname = "Cache invalidate",
214e1eca
JA
2926 .type = FIO_OPT_BOOL,
2927 .off1 = td_var_offset(invalidate_cache),
2928 .help = "Invalidate buffer/page cache prior to running job",
2929 .def = "1",
e8b0e958 2930 .category = FIO_OPT_C_IO,
3ceb458f 2931 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2932 },
2933 {
2934 .name = "sync",
e8b0e958 2935 .lname = "Synchronous I/O",
214e1eca
JA
2936 .type = FIO_OPT_BOOL,
2937 .off1 = td_var_offset(sync_io),
2938 .help = "Use O_SYNC for buffered writes",
2939 .def = "0",
67a1000f 2940 .parent = "buffered",
d71c154c 2941 .hide = 1,
e8b0e958 2942 .category = FIO_OPT_C_IO,
3ceb458f 2943 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2944 },
214e1eca
JA
2945 {
2946 .name = "create_serialize",
e8b0e958 2947 .lname = "Create serialize",
214e1eca
JA
2948 .type = FIO_OPT_BOOL,
2949 .off1 = td_var_offset(create_serialize),
2950 .help = "Serialize creating of job files",
2951 .def = "1",
e8b0e958
JA
2952 .category = FIO_OPT_C_FILE,
2953 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2954 },
2955 {
2956 .name = "create_fsync",
e8b0e958 2957 .lname = "Create fsync",
214e1eca
JA
2958 .type = FIO_OPT_BOOL,
2959 .off1 = td_var_offset(create_fsync),
03e20d68 2960 .help = "fsync file after creation",
214e1eca 2961 .def = "1",
e8b0e958
JA
2962 .category = FIO_OPT_C_FILE,
2963 .group = FIO_OPT_G_INVALID,
214e1eca 2964 },
814452bd
JA
2965 {
2966 .name = "create_on_open",
e8b0e958 2967 .lname = "Create on open",
814452bd
JA
2968 .type = FIO_OPT_BOOL,
2969 .off1 = td_var_offset(create_on_open),
2970 .help = "Create files when they are opened for IO",
2971 .def = "0",
e8b0e958
JA
2972 .category = FIO_OPT_C_FILE,
2973 .group = FIO_OPT_G_INVALID,
814452bd 2974 },
25460cf6
JA
2975 {
2976 .name = "create_only",
2977 .type = FIO_OPT_BOOL,
2978 .off1 = td_var_offset(create_only),
2979 .help = "Only perform file creation phase",
d17fda71 2980 .category = FIO_OPT_C_FILE,
25460cf6
JA
2981 .def = "0",
2982 },
2378826d
JA
2983 {
2984 .name = "allow_file_create",
e81ecca3 2985 .lname = "Allow file create",
2378826d
JA
2986 .type = FIO_OPT_BOOL,
2987 .off1 = td_var_offset(allow_create),
2988 .help = "Permit fio to create files, if they don't exist",
2989 .def = "1",
2990 .category = FIO_OPT_C_FILE,
2991 .group = FIO_OPT_G_FILENAME,
2992 },
e81ecca3
JA
2993 {
2994 .name = "allow_mounted_write",
2995 .lname = "Allow mounted write",
2996 .type = FIO_OPT_BOOL,
2997 .off1 = td_var_offset(allow_mounted_write),
2998 .help = "Allow writes to a mounted partition",
2999 .def = "0",
3000 .category = FIO_OPT_C_FILE,
3001 .group = FIO_OPT_G_FILENAME,
3002 },
0b9d69ec 3003 {
afad68f7 3004 .name = "pre_read",
e8b0e958 3005 .lname = "Pre-read files",
afad68f7
ZY
3006 .type = FIO_OPT_BOOL,
3007 .off1 = td_var_offset(pre_read),
03e20d68 3008 .help = "Pre-read files before starting official testing",
afad68f7 3009 .def = "0",
e8b0e958
JA
3010 .category = FIO_OPT_C_FILE,
3011 .group = FIO_OPT_G_INVALID,
afad68f7 3012 },
214e1eca
JA
3013#ifdef FIO_HAVE_CPU_AFFINITY
3014 {
3015 .name = "cpumask",
e8b0e958 3016 .lname = "CPU mask",
214e1eca
JA
3017 .type = FIO_OPT_INT,
3018 .cb = str_cpumask_cb,
a8523a6a 3019 .off1 = td_var_offset(cpumask),
214e1eca 3020 .help = "CPU affinity mask",
e8b0e958 3021 .category = FIO_OPT_C_GENERAL,
10860056 3022 .group = FIO_OPT_G_CRED,
214e1eca 3023 },
d2e268b0
JA
3024 {
3025 .name = "cpus_allowed",
e8b0e958 3026 .lname = "CPUs allowed",
d2e268b0
JA
3027 .type = FIO_OPT_STR,
3028 .cb = str_cpus_allowed_cb,
a8523a6a 3029 .off1 = td_var_offset(cpumask),
d2e268b0 3030 .help = "Set CPUs allowed",
e8b0e958 3031 .category = FIO_OPT_C_GENERAL,
10860056 3032 .group = FIO_OPT_G_CRED,
d2e268b0 3033 },
c2acfbac
JA
3034 {
3035 .name = "cpus_allowed_policy",
3036 .lname = "CPUs allowed distribution policy",
3037 .type = FIO_OPT_STR,
3038 .off1 = td_var_offset(cpus_allowed_policy),
3039 .help = "Distribution policy for cpus_allowed",
3040 .parent = "cpus_allowed",
3041 .prio = 1,
3042 .posval = {
3043 { .ival = "shared",
3044 .oval = FIO_CPUS_SHARED,
3045 .help = "Mask shared between threads",
3046 },
3047 { .ival = "split",
3048 .oval = FIO_CPUS_SPLIT,
3049 .help = "Mask split between threads",
3050 },
3051 },
3052 .category = FIO_OPT_C_GENERAL,
3053 .group = FIO_OPT_G_CRED,
3054 },
d0b937ed 3055#endif
67bf9823 3056#ifdef CONFIG_LIBNUMA
d0b937ed
YR
3057 {
3058 .name = "numa_cpu_nodes",
3059 .type = FIO_OPT_STR,
3060 .cb = str_numa_cpunodes_cb,
b2a9e649 3061 .off1 = td_var_offset(numa_cpunodes),
d0b937ed 3062 .help = "NUMA CPU nodes bind",
6be54b2d
JA
3063 .category = FIO_OPT_C_GENERAL,
3064 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
3065 },
3066 {
3067 .name = "numa_mem_policy",
3068 .type = FIO_OPT_STR,
3069 .cb = str_numa_mpol_cb,
b2a9e649 3070 .off1 = td_var_offset(numa_memnodes),
d0b937ed 3071 .help = "NUMA memory policy setup",
6be54b2d
JA
3072 .category = FIO_OPT_C_GENERAL,
3073 .group = FIO_OPT_G_INVALID,
d0b937ed 3074 },
214e1eca
JA
3075#endif
3076 {
3077 .name = "end_fsync",
e8b0e958 3078 .lname = "End fsync",
214e1eca
JA
3079 .type = FIO_OPT_BOOL,
3080 .off1 = td_var_offset(end_fsync),
3081 .help = "Include fsync at the end of job",
3082 .def = "0",
e8b0e958
JA
3083 .category = FIO_OPT_C_FILE,
3084 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3085 },
3086 {
3087 .name = "fsync_on_close",
e8b0e958 3088 .lname = "Fsync on close",
214e1eca
JA
3089 .type = FIO_OPT_BOOL,
3090 .off1 = td_var_offset(fsync_on_close),
3091 .help = "fsync files on close",
3092 .def = "0",
e8b0e958
JA
3093 .category = FIO_OPT_C_FILE,
3094 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3095 },
3096 {
3097 .name = "unlink",
e8b0e958 3098 .lname = "Unlink file",
214e1eca
JA
3099 .type = FIO_OPT_BOOL,
3100 .off1 = td_var_offset(unlink),
3101 .help = "Unlink created files after job has completed",
3102 .def = "0",
e8b0e958
JA
3103 .category = FIO_OPT_C_FILE,
3104 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3105 },
3106 {
3107 .name = "exitall",
e8b0e958 3108 .lname = "Exit-all on terminate",
214e1eca
JA
3109 .type = FIO_OPT_STR_SET,
3110 .cb = str_exitall_cb,
3111 .help = "Terminate all jobs when one exits",
e8b0e958 3112 .category = FIO_OPT_C_GENERAL,
a1f6afec 3113 .group = FIO_OPT_G_PROCESS,
214e1eca
JA
3114 },
3115 {
3116 .name = "stonewall",
e8b0e958 3117 .lname = "Wait for previous",
d392365e 3118 .alias = "wait_for_previous",
214e1eca
JA
3119 .type = FIO_OPT_STR_SET,
3120 .off1 = td_var_offset(stonewall),
3121 .help = "Insert a hard barrier between this job and previous",
e8b0e958 3122 .category = FIO_OPT_C_GENERAL,
a1f6afec 3123 .group = FIO_OPT_G_PROCESS,
214e1eca 3124 },
b3d62a75
JA
3125 {
3126 .name = "new_group",
e8b0e958 3127 .lname = "New group",
b3d62a75
JA
3128 .type = FIO_OPT_STR_SET,
3129 .off1 = td_var_offset(new_group),
3130 .help = "Mark the start of a new group (for reporting)",
e8b0e958 3131 .category = FIO_OPT_C_GENERAL,
a1f6afec 3132 .group = FIO_OPT_G_PROCESS,
b3d62a75 3133 },
214e1eca
JA
3134 {
3135 .name = "thread",
e8b0e958 3136 .lname = "Thread",
214e1eca
JA
3137 .type = FIO_OPT_STR_SET,
3138 .off1 = td_var_offset(use_thread),
20eb06bd 3139 .help = "Use threads instead of processes",
c8931876
JA
3140#ifdef CONFIG_NO_SHM
3141 .def = "1",
3142 .no_warn_def = 1,
3143#endif
e8b0e958 3144 .category = FIO_OPT_C_GENERAL,
a1f6afec 3145 .group = FIO_OPT_G_PROCESS,
214e1eca 3146 },
3a5db920
JA
3147 {
3148 .name = "per_job_logs",
3149 .type = FIO_OPT_BOOL,
3150 .off1 = td_var_offset(per_job_logs),
3151 .help = "Include job number in generated log files or not",
3152 .def = "1",
3153 .category = FIO_OPT_C_LOG,
3154 .group = FIO_OPT_G_INVALID,
3155 },
214e1eca
JA
3156 {
3157 .name = "write_bw_log",
e8b0e958 3158 .lname = "Write bandwidth log",
203160d5
JA
3159 .type = FIO_OPT_STR_STORE,
3160 .off1 = td_var_offset(bw_log_file),
214e1eca 3161 .help = "Write log of bandwidth during run",
e8b0e958
JA
3162 .category = FIO_OPT_C_LOG,
3163 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3164 },
3165 {
3166 .name = "write_lat_log",
e8b0e958 3167 .lname = "Write latency log",
203160d5
JA
3168 .type = FIO_OPT_STR_STORE,
3169 .off1 = td_var_offset(lat_log_file),
214e1eca 3170 .help = "Write log of latency during run",
e8b0e958
JA
3171 .category = FIO_OPT_C_LOG,
3172 .group = FIO_OPT_G_INVALID,
214e1eca 3173 },
c8eeb9df
JA
3174 {
3175 .name = "write_iops_log",
e8b0e958 3176 .lname = "Write IOPS log",
577c83bd 3177 .type = FIO_OPT_STR_STORE,
203160d5 3178 .off1 = td_var_offset(iops_log_file),
c8eeb9df 3179 .help = "Write log of IOPS during run",
e8b0e958
JA
3180 .category = FIO_OPT_C_LOG,
3181 .group = FIO_OPT_G_INVALID,
c8eeb9df 3182 },
b8bc8cba
JA
3183 {
3184 .name = "log_avg_msec",
e8b0e958 3185 .lname = "Log averaging (msec)",
b8bc8cba
JA
3186 .type = FIO_OPT_INT,
3187 .off1 = td_var_offset(log_avg_msec),
3188 .help = "Average bw/iops/lat logs over this period of time",
3189 .def = "0",
e8b0e958
JA
3190 .category = FIO_OPT_C_LOG,
3191 .group = FIO_OPT_G_INVALID,
b8bc8cba 3192 },
ae588852
JA
3193 {
3194 .name = "log_offset",
3195 .lname = "Log offset of IO",
3196 .type = FIO_OPT_BOOL,
3197 .off1 = td_var_offset(log_offset),
3198 .help = "Include offset of IO for each log entry",
3199 .def = "0",
3200 .category = FIO_OPT_C_LOG,
3201 .group = FIO_OPT_G_INVALID,
3202 },
aee2ab67
JA
3203#ifdef CONFIG_ZLIB
3204 {
3205 .name = "log_compression",
3206 .lname = "Log compression",
3207 .type = FIO_OPT_INT,
3208 .off1 = td_var_offset(log_gz),
3209 .help = "Log in compressed chunks of this size",
9919b27b 3210 .minval = 1024ULL,
aee2ab67
JA
3211 .maxval = 512 * 1024 * 1024ULL,
3212 .category = FIO_OPT_C_LOG,
3213 .group = FIO_OPT_G_INVALID,
3214 },
b26317c9
JA
3215 {
3216 .name = "log_store_compressed",
3217 .lname = "Log store compressed",
3218 .type = FIO_OPT_BOOL,
3219 .off1 = td_var_offset(log_gz_store),
3220 .help = "Store logs in a compressed format",
3221 .category = FIO_OPT_C_LOG,
3222 .group = FIO_OPT_G_INVALID,
3223 },
aee2ab67 3224#endif
66347cfa
DE
3225 {
3226 .name = "block_error_percentiles",
3227 .lname = "Block error percentiles",
3228 .type = FIO_OPT_BOOL,
3229 .off1 = td_var_offset(block_error_hist),
3230 .help = "Record trim block errors and make a histogram",
3231 .def = "0",
3232 .category = FIO_OPT_C_LOG,
3233 .group = FIO_OPT_G_INVALID,
3234 },
c504ee55
JA
3235 {
3236 .name = "bwavgtime",
3237 .lname = "Bandwidth average time",
3238 .type = FIO_OPT_INT,
3239 .off1 = td_var_offset(bw_avg_time),
3240 .help = "Time window over which to calculate bandwidth"
3241 " (msec)",
3242 .def = "500",
3243 .parent = "write_bw_log",
3244 .hide = 1,
3245 .interval = 100,
3246 .category = FIO_OPT_C_LOG,
3247 .group = FIO_OPT_G_INVALID,
3248 },
3249 {
3250 .name = "iopsavgtime",
3251 .lname = "IOPS average time",
3252 .type = FIO_OPT_INT,
3253 .off1 = td_var_offset(iops_avg_time),
3254 .help = "Time window over which to calculate IOPS (msec)",
3255 .def = "500",
3256 .parent = "write_iops_log",
3257 .hide = 1,
3258 .interval = 100,
3259 .category = FIO_OPT_C_LOG,
3260 .group = FIO_OPT_G_INVALID,
3261 },
214e1eca
JA
3262 {
3263 .name = "group_reporting",
e8b0e958 3264 .lname = "Group reporting",
d2507043 3265 .type = FIO_OPT_STR_SET,
214e1eca
JA
3266 .off1 = td_var_offset(group_reporting),
3267 .help = "Do reporting on a per-group basis",
10860056 3268 .category = FIO_OPT_C_STAT,
e8b0e958 3269 .group = FIO_OPT_G_INVALID,
214e1eca 3270 },
e9459e5a
JA
3271 {
3272 .name = "zero_buffers",
e8b0e958 3273 .lname = "Zero I/O buffers",
e9459e5a
JA
3274 .type = FIO_OPT_STR_SET,
3275 .off1 = td_var_offset(zero_buffers),
3276 .help = "Init IO buffers to all zeroes",
e8b0e958 3277 .category = FIO_OPT_C_IO,
3ceb458f 3278 .group = FIO_OPT_G_IO_BUF,
e9459e5a 3279 },
5973cafb
JA
3280 {
3281 .name = "refill_buffers",
e8b0e958 3282 .lname = "Refill I/O buffers",
5973cafb
JA
3283 .type = FIO_OPT_STR_SET,
3284 .off1 = td_var_offset(refill_buffers),
3285 .help = "Refill IO buffers on every IO submit",
e8b0e958 3286 .category = FIO_OPT_C_IO,
3ceb458f 3287 .group = FIO_OPT_G_IO_BUF,
5973cafb 3288 },
fd68418e
JA
3289 {
3290 .name = "scramble_buffers",
e8b0e958 3291 .lname = "Scramble I/O buffers",
fd68418e
JA
3292 .type = FIO_OPT_BOOL,
3293 .off1 = td_var_offset(scramble_buffers),
3294 .help = "Slightly scramble buffers on every IO submit",
3295 .def = "1",
e8b0e958 3296 .category = FIO_OPT_C_IO,
3ceb458f 3297 .group = FIO_OPT_G_IO_BUF,
fd68418e 3298 },
ce35b1ec
JA
3299 {
3300 .name = "buffer_pattern",
3301 .lname = "Buffer pattern",
3302 .type = FIO_OPT_STR,
3303 .cb = str_buffer_pattern_cb,
a8523a6a 3304 .off1 = td_var_offset(buffer_pattern),
ce35b1ec
JA
3305 .help = "Fill pattern for IO buffers",
3306 .category = FIO_OPT_C_IO,
3307 .group = FIO_OPT_G_IO_BUF,
3308 },
9c42684e
JA
3309 {
3310 .name = "buffer_compress_percentage",
e8b0e958 3311 .lname = "Buffer compression percentage",
9c42684e 3312 .type = FIO_OPT_INT,
bedc9dc2 3313 .cb = str_buffer_compress_cb,
a8523a6a 3314 .off1 = td_var_offset(compress_percentage),
9c42684e 3315 .maxval = 100,
e7f5de90 3316 .minval = 0,
9c42684e 3317 .help = "How compressible the buffer is (approximately)",
20eb06bd 3318 .interval = 5,
e8b0e958 3319 .category = FIO_OPT_C_IO,
3ceb458f 3320 .group = FIO_OPT_G_IO_BUF,
9c42684e 3321 },
f97a43a1
JA
3322 {
3323 .name = "buffer_compress_chunk",
e8b0e958 3324 .lname = "Buffer compression chunk size",
f97a43a1
JA
3325 .type = FIO_OPT_INT,
3326 .off1 = td_var_offset(compress_chunk),
207b18e4 3327 .parent = "buffer_compress_percentage",
d71c154c 3328 .hide = 1,
f97a43a1 3329 .help = "Size of compressible region in buffer",
20eb06bd 3330 .interval = 256,
e8b0e958 3331 .category = FIO_OPT_C_IO,
3ceb458f 3332 .group = FIO_OPT_G_IO_BUF,
f97a43a1 3333 },
5c94b008
JA
3334 {
3335 .name = "dedupe_percentage",
3336 .lname = "Dedupe percentage",
3337 .type = FIO_OPT_INT,
3338 .cb = str_dedupe_cb,
a8523a6a 3339 .off1 = td_var_offset(dedupe_percentage),
5c94b008
JA
3340 .maxval = 100,
3341 .minval = 0,
3342 .help = "Percentage of buffers that are dedupable",
3343 .interval = 1,
3344 .category = FIO_OPT_C_IO,
3345 .group = FIO_OPT_G_IO_BUF,
3346 },
83349190
YH
3347 {
3348 .name = "clat_percentiles",
e8b0e958 3349 .lname = "Completion latency percentiles",
83349190
YH
3350 .type = FIO_OPT_BOOL,
3351 .off1 = td_var_offset(clat_percentiles),
3352 .help = "Enable the reporting of completion latency percentiles",
467b35ed 3353 .def = "1",
e8b0e958
JA
3354 .category = FIO_OPT_C_STAT,
3355 .group = FIO_OPT_G_INVALID,
83349190
YH
3356 },
3357 {
3358 .name = "percentile_list",
66347cfa 3359 .lname = "Percentile list",
83349190
YH
3360 .type = FIO_OPT_FLOAT_LIST,
3361 .off1 = td_var_offset(percentile_list),
435d195a 3362 .off2 = td_var_offset(percentile_precision),
66347cfa
DE
3363 .help = "Specify a custom list of percentiles to report for "
3364 "completion latency and block errors",
fd112d34 3365 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
3366 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3367 .minfp = 0.0,
3368 .maxfp = 100.0,
e8b0e958
JA
3369 .category = FIO_OPT_C_STAT,
3370 .group = FIO_OPT_G_INVALID,
83349190
YH
3371 },
3372
0a839f30
JA
3373#ifdef FIO_HAVE_DISK_UTIL
3374 {
3375 .name = "disk_util",
e8b0e958 3376 .lname = "Disk utilization",
0a839f30
JA
3377 .type = FIO_OPT_BOOL,
3378 .off1 = td_var_offset(do_disk_util),
f66ab3c8 3379 .help = "Log disk utilization statistics",
0a839f30 3380 .def = "1",
e8b0e958
JA
3381 .category = FIO_OPT_C_STAT,
3382 .group = FIO_OPT_G_INVALID,
0a839f30
JA
3383 },
3384#endif
993bf48b
JA
3385 {
3386 .name = "gtod_reduce",
e8b0e958 3387 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
3388 .type = FIO_OPT_BOOL,
3389 .help = "Greatly reduce number of gettimeofday() calls",
3390 .cb = str_gtod_reduce_cb,
3391 .def = "0",
a4ed77fe 3392 .hide_on_set = 1,
e8b0e958
JA
3393 .category = FIO_OPT_C_STAT,
3394 .group = FIO_OPT_G_INVALID,
993bf48b 3395 },
02af0988
JA
3396 {
3397 .name = "disable_lat",
e8b0e958 3398 .lname = "Disable all latency stats",
02af0988
JA
3399 .type = FIO_OPT_BOOL,
3400 .off1 = td_var_offset(disable_lat),
3401 .help = "Disable latency numbers",
3402 .parent = "gtod_reduce",
d71c154c 3403 .hide = 1,
02af0988 3404 .def = "0",
e8b0e958
JA
3405 .category = FIO_OPT_C_STAT,
3406 .group = FIO_OPT_G_INVALID,
02af0988 3407 },
9520ebb9
JA
3408 {
3409 .name = "disable_clat",
e8b0e958 3410 .lname = "Disable completion latency stats",
9520ebb9
JA
3411 .type = FIO_OPT_BOOL,
3412 .off1 = td_var_offset(disable_clat),
3413 .help = "Disable completion latency numbers",
993bf48b 3414 .parent = "gtod_reduce",
d71c154c 3415 .hide = 1,
9520ebb9 3416 .def = "0",
e8b0e958
JA
3417 .category = FIO_OPT_C_STAT,
3418 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3419 },
3420 {
3421 .name = "disable_slat",
e8b0e958 3422 .lname = "Disable submission latency stats",
9520ebb9
JA
3423 .type = FIO_OPT_BOOL,
3424 .off1 = td_var_offset(disable_slat),
03e20d68 3425 .help = "Disable submission latency numbers",
993bf48b 3426 .parent = "gtod_reduce",
d71c154c 3427 .hide = 1,
9520ebb9 3428 .def = "0",
e8b0e958
JA
3429 .category = FIO_OPT_C_STAT,
3430 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3431 },
3432 {
3433 .name = "disable_bw_measurement",
e8b0e958 3434 .lname = "Disable bandwidth stats",
9520ebb9
JA
3435 .type = FIO_OPT_BOOL,
3436 .off1 = td_var_offset(disable_bw),
3437 .help = "Disable bandwidth logging",
993bf48b 3438 .parent = "gtod_reduce",
d71c154c 3439 .hide = 1,
9520ebb9 3440 .def = "0",
e8b0e958
JA
3441 .category = FIO_OPT_C_STAT,
3442 .group = FIO_OPT_G_INVALID,
9520ebb9 3443 },
be4ecfdf
JA
3444 {
3445 .name = "gtod_cpu",
e8b0e958 3446 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 3447 .type = FIO_OPT_INT,
79c896a1 3448 .off1 = td_var_offset(gtod_cpu),
03e20d68 3449 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 3450 .verify = gtod_cpu_verify,
e8b0e958 3451 .category = FIO_OPT_C_GENERAL,
10860056 3452 .group = FIO_OPT_G_CLOCK,
be4ecfdf 3453 },
771e58be
JA
3454 {
3455 .name = "unified_rw_reporting",
3456 .type = FIO_OPT_BOOL,
3457 .off1 = td_var_offset(unified_rw_rep),
3458 .help = "Unify reporting across data direction",
3459 .def = "0",
90b7a96d
JA
3460 .category = FIO_OPT_C_GENERAL,
3461 .group = FIO_OPT_G_INVALID,
771e58be 3462 },
f2bba182
RR
3463 {
3464 .name = "continue_on_error",
e8b0e958 3465 .lname = "Continue on error",
06842027 3466 .type = FIO_OPT_STR,
f2bba182 3467 .off1 = td_var_offset(continue_on_error),
03e20d68 3468 .help = "Continue on non-fatal errors during IO",
06842027 3469 .def = "none",
e8b0e958 3470 .category = FIO_OPT_C_GENERAL,
bc3f552f 3471 .group = FIO_OPT_G_ERR,
06842027
SL
3472 .posval = {
3473 { .ival = "none",
3474 .oval = ERROR_TYPE_NONE,
3475 .help = "Exit when an error is encountered",
3476 },
3477 { .ival = "read",
3478 .oval = ERROR_TYPE_READ,
3479 .help = "Continue on read errors only",
3480 },
3481 { .ival = "write",
3482 .oval = ERROR_TYPE_WRITE,
3483 .help = "Continue on write errors only",
3484 },
3485 { .ival = "io",
3486 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
3487 .help = "Continue on any IO errors",
3488 },
3489 { .ival = "verify",
3490 .oval = ERROR_TYPE_VERIFY,
3491 .help = "Continue on verify errors only",
3492 },
3493 { .ival = "all",
3494 .oval = ERROR_TYPE_ANY,
3495 .help = "Continue on all io and verify errors",
3496 },
3497 { .ival = "0",
3498 .oval = ERROR_TYPE_NONE,
3499 .help = "Alias for 'none'",
3500 },
3501 { .ival = "1",
3502 .oval = ERROR_TYPE_ANY,
3503 .help = "Alias for 'all'",
3504 },
3505 },
f2bba182 3506 },
8b28bd41
DM
3507 {
3508 .name = "ignore_error",
3509 .type = FIO_OPT_STR,
3510 .cb = str_ignore_error_cb,
a8523a6a 3511 .off1 = td_var_offset(ignore_error_nr),
8b28bd41
DM
3512 .help = "Set a specific list of errors to ignore",
3513 .parent = "rw",
a94eb99a 3514 .category = FIO_OPT_C_GENERAL,
bc3f552f 3515 .group = FIO_OPT_G_ERR,
8b28bd41
DM
3516 },
3517 {
3518 .name = "error_dump",
3519 .type = FIO_OPT_BOOL,
3520 .off1 = td_var_offset(error_dump),
3521 .def = "0",
3522 .help = "Dump info on each error",
a94eb99a 3523 .category = FIO_OPT_C_GENERAL,
bc3f552f 3524 .group = FIO_OPT_G_ERR,
8b28bd41 3525 },
9ac8a797
JA
3526 {
3527 .name = "profile",
e8b0e958 3528 .lname = "Profile",
79d16311 3529 .type = FIO_OPT_STR_STORE,
9ac8a797 3530 .off1 = td_var_offset(profile),
9ac8a797 3531 .help = "Select a specific builtin performance test",
13fca827 3532 .category = FIO_OPT_C_PROFILE,
e8b0e958 3533 .group = FIO_OPT_G_INVALID,
9ac8a797 3534 },
a696fa2a
JA
3535 {
3536 .name = "cgroup",
e8b0e958 3537 .lname = "Cgroup",
a696fa2a
JA
3538 .type = FIO_OPT_STR_STORE,
3539 .off1 = td_var_offset(cgroup),
3540 .help = "Add job to cgroup of this name",
e8b0e958 3541 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
3542 .group = FIO_OPT_G_CGROUP,
3543 },
3544 {
3545 .name = "cgroup_nodelete",
3546 .lname = "Cgroup no-delete",
3547 .type = FIO_OPT_BOOL,
3548 .off1 = td_var_offset(cgroup_nodelete),
3549 .help = "Do not delete cgroups after job completion",
3550 .def = "0",
3551 .parent = "cgroup",
3552 .category = FIO_OPT_C_GENERAL,
3553 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
3554 },
3555 {
3556 .name = "cgroup_weight",
e8b0e958 3557 .lname = "Cgroup weight",
a696fa2a
JA
3558 .type = FIO_OPT_INT,
3559 .off1 = td_var_offset(cgroup_weight),
3560 .help = "Use given weight for cgroup",
3561 .minval = 100,
3562 .maxval = 1000,
a1f6afec 3563 .parent = "cgroup",
e8b0e958 3564 .category = FIO_OPT_C_GENERAL,
a1f6afec 3565 .group = FIO_OPT_G_CGROUP,
7de87099 3566 },
e0b0d892
JA
3567 {
3568 .name = "uid",
e8b0e958 3569 .lname = "User ID",
e0b0d892
JA
3570 .type = FIO_OPT_INT,
3571 .off1 = td_var_offset(uid),
3572 .help = "Run job with this user ID",
e8b0e958 3573 .category = FIO_OPT_C_GENERAL,
10860056 3574 .group = FIO_OPT_G_CRED,
e0b0d892
JA
3575 },
3576 {
3577 .name = "gid",
e8b0e958 3578 .lname = "Group ID",
e0b0d892
JA
3579 .type = FIO_OPT_INT,
3580 .off1 = td_var_offset(gid),
3581 .help = "Run job with this group ID",
e8b0e958 3582 .category = FIO_OPT_C_GENERAL,
10860056 3583 .group = FIO_OPT_G_CRED,
e0b0d892 3584 },
a1f6afec
JA
3585 {
3586 .name = "kb_base",
3587 .lname = "KB Base",
3588 .type = FIO_OPT_INT,
3589 .off1 = td_var_offset(kb_base),
a1f6afec
JA
3590 .prio = 1,
3591 .def = "1024",
ba9c7219
JA
3592 .posval = {
3593 { .ival = "1024",
3594 .oval = 1024,
3595 .help = "Use 1024 as the K base",
3596 },
3597 { .ival = "1000",
3598 .oval = 1000,
3599 .help = "Use 1000 as the K base",
3600 },
3601 },
a1f6afec
JA
3602 .help = "How many bytes per KB for reporting (1000 or 1024)",
3603 .category = FIO_OPT_C_GENERAL,
3604 .group = FIO_OPT_G_INVALID,
3605 },
cf3a0518
JA
3606 {
3607 .name = "unit_base",
ba9c7219 3608 .lname = "Base unit for reporting (Bits or Bytes)",
cf3a0518
JA
3609 .type = FIO_OPT_INT,
3610 .off1 = td_var_offset(unit_base),
cf3a0518 3611 .prio = 1,
71a08258
JA
3612 .posval = {
3613 { .ival = "0",
3614 .oval = 0,
3615 .help = "Auto-detect",
3616 },
3617 { .ival = "8",
3618 .oval = 8,
3619 .help = "Normal (byte based)",
3620 },
3621 { .ival = "1",
3622 .oval = 1,
3623 .help = "Bit based",
3624 },
3625 },
cf3a0518
JA
3626 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
3627 .category = FIO_OPT_C_GENERAL,
3628 .group = FIO_OPT_G_INVALID,
3629 },
3ceb458f
JA
3630 {
3631 .name = "hugepage-size",
3632 .lname = "Hugepage size",
3633 .type = FIO_OPT_INT,
3634 .off1 = td_var_offset(hugepage_size),
3635 .help = "When using hugepages, specify size of each page",
3636 .def = __fio_stringify(FIO_HUGE_PAGE),
3637 .interval = 1024 * 1024,
3638 .category = FIO_OPT_C_GENERAL,
3639 .group = FIO_OPT_G_INVALID,
3640 },
9e684a49
DE
3641 {
3642 .name = "flow_id",
e8b0e958 3643 .lname = "I/O flow ID",
9e684a49
DE
3644 .type = FIO_OPT_INT,
3645 .off1 = td_var_offset(flow_id),
3646 .help = "The flow index ID to use",
3647 .def = "0",
e8b0e958
JA
3648 .category = FIO_OPT_C_IO,
3649 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3650 },
3651 {
3652 .name = "flow",
e8b0e958 3653 .lname = "I/O flow weight",
9e684a49
DE
3654 .type = FIO_OPT_INT,
3655 .off1 = td_var_offset(flow),
3656 .help = "Weight for flow control of this job",
3657 .parent = "flow_id",
d71c154c 3658 .hide = 1,
9e684a49 3659 .def = "0",
e8b0e958
JA
3660 .category = FIO_OPT_C_IO,
3661 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3662 },
3663 {
3664 .name = "flow_watermark",
e8b0e958 3665 .lname = "I/O flow watermark",
9e684a49
DE
3666 .type = FIO_OPT_INT,
3667 .off1 = td_var_offset(flow_watermark),
3668 .help = "High watermark for flow control. This option"
3669 " should be set to the same value for all threads"
3670 " with non-zero flow.",
3671 .parent = "flow_id",
d71c154c 3672 .hide = 1,
9e684a49 3673 .def = "1024",
e8b0e958
JA
3674 .category = FIO_OPT_C_IO,
3675 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3676 },
3677 {
3678 .name = "flow_sleep",
e8b0e958 3679 .lname = "I/O flow sleep",
9e684a49
DE
3680 .type = FIO_OPT_INT,
3681 .off1 = td_var_offset(flow_sleep),
3682 .help = "How many microseconds to sleep after being held"
3683 " back by the flow control mechanism",
3684 .parent = "flow_id",
d71c154c 3685 .hide = 1,
9e684a49 3686 .def = "0",
e8b0e958
JA
3687 .category = FIO_OPT_C_IO,
3688 .group = FIO_OPT_G_IO_FLOW,
9e684a49 3689 },
65fa28ca
DE
3690 {
3691 .name = "skip_bad",
3692 .lname = "Skip operations against bad blocks",
3693 .type = FIO_OPT_BOOL,
3694 .off1 = td_var_offset(skip_bad),
3695 .help = "Skip operations against known bad blocks.",
3696 .hide = 1,
3697 .def = "0",
3698 .category = FIO_OPT_C_IO,
3699 .group = FIO_OPT_G_MTD,
3700 },
214e1eca
JA
3701 {
3702 .name = NULL,
3703 },
3704};
3705
17af15d4 3706static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 3707 const char *name, int val)
9f81736c 3708{
17af15d4 3709 lopt->name = (char *) name;
de890a1e 3710 lopt->val = val;
9f81736c 3711 if (o->type == FIO_OPT_STR_SET)
ff52be3d 3712 lopt->has_arg = optional_argument;
9f81736c
JA
3713 else
3714 lopt->has_arg = required_argument;
3715}
3716
de890a1e
SL
3717static void options_to_lopts(struct fio_option *opts,
3718 struct option *long_options,
3719 int i, int option_type)
214e1eca 3720{
de890a1e 3721 struct fio_option *o = &opts[0];
214e1eca 3722 while (o->name) {
de890a1e 3723 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
3724 if (o->alias) {
3725 i++;
de890a1e 3726 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 3727 }
214e1eca
JA
3728
3729 i++;
3730 o++;
3731 assert(i < FIO_NR_OPTIONS);
3732 }
3733}
3734
de890a1e
SL
3735void fio_options_set_ioengine_opts(struct option *long_options,
3736 struct thread_data *td)
3737{
3738 unsigned int i;
3739
3740 i = 0;
3741 while (long_options[i].name) {
3742 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
3743 memset(&long_options[i], 0, sizeof(*long_options));
3744 break;
3745 }
3746 i++;
3747 }
3748
3749 /*
3750 * Just clear out the prior ioengine options.
3751 */
3752 if (!td || !td->eo)
3753 return;
3754
3755 options_to_lopts(td->io_ops->options, long_options, i,
3756 FIO_GETOPT_IOENGINE);
3757}
3758
3759void fio_options_dup_and_init(struct option *long_options)
3760{
3761 unsigned int i;
3762
9af4a244 3763 options_init(fio_options);
de890a1e
SL
3764
3765 i = 0;
3766 while (long_options[i].name)
3767 i++;
3768
9af4a244 3769 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
3770}
3771
74929ac2
JA
3772struct fio_keyword {
3773 const char *word;
3774 const char *desc;
3775 char *replace;
3776};
3777
3778static struct fio_keyword fio_keywords[] = {
3779 {
3780 .word = "$pagesize",
3781 .desc = "Page size in the system",
3782 },
3783 {
3784 .word = "$mb_memory",
3785 .desc = "Megabytes of memory online",
3786 },
3787 {
3788 .word = "$ncpus",
3789 .desc = "Number of CPUs online in the system",
3790 },
3791 {
3792 .word = NULL,
3793 },
3794};
3795
af1dc266
JA
3796void fio_keywords_exit(void)
3797{
3798 struct fio_keyword *kw;
3799
3800 kw = &fio_keywords[0];
3801 while (kw->word) {
3802 free(kw->replace);
3803 kw->replace = NULL;
3804 kw++;
3805 }
3806}
3807
74929ac2
JA
3808void fio_keywords_init(void)
3809{
3b2e1464 3810 unsigned long long mb_memory;
74929ac2
JA
3811 char buf[128];
3812 long l;
3813
a4cfc477 3814 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
3815 fio_keywords[0].replace = strdup(buf);
3816
8eb016d3 3817 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 3818 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
3819 fio_keywords[1].replace = strdup(buf);
3820
c00a2289 3821 l = cpus_online();
74929ac2
JA
3822 sprintf(buf, "%lu", l);
3823 fio_keywords[2].replace = strdup(buf);
3824}
3825
892a6ffc
JA
3826#define BC_APP "bc"
3827
3828static char *bc_calc(char *str)
3829{
d0c814ec 3830 char buf[128], *tmp;
892a6ffc
JA
3831 FILE *f;
3832 int ret;
3833
3834 /*
3835 * No math, just return string
3836 */
d0c814ec
SL
3837 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
3838 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
3839 return str;
3840
3841 /*
3842 * Split option from value, we only need to calculate the value
3843 */
3844 tmp = strchr(str, '=');
3845 if (!tmp)
3846 return str;
3847
3848 tmp++;
892a6ffc 3849
d0c814ec
SL
3850 /*
3851 * Prevent buffer overflows; such a case isn't reasonable anyway
3852 */
3853 if (strlen(str) >= 128 || strlen(tmp) > 100)
3854 return str;
892a6ffc
JA
3855
3856 sprintf(buf, "which %s > /dev/null", BC_APP);
3857 if (system(buf)) {
3858 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
3859 return NULL;
3860 }
3861
d0c814ec 3862 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 3863 f = popen(buf, "r");
3c3ed070 3864 if (!f)
892a6ffc 3865 return NULL;
892a6ffc 3866
d0c814ec 3867 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
3868 if (ret <= 0) {
3869 pclose(f);
892a6ffc 3870 return NULL;
1d824f37 3871 }
892a6ffc 3872
892a6ffc 3873 pclose(f);
d0c814ec
SL
3874 buf[(tmp - str) + ret - 1] = '\0';
3875 memcpy(buf, str, tmp - str);
892a6ffc 3876 free(str);
d0c814ec
SL
3877 return strdup(buf);
3878}
3879
3880/*
3881 * Return a copy of the input string with substrings of the form ${VARNAME}
3882 * substituted with the value of the environment variable VARNAME. The
3883 * substitution always occurs, even if VARNAME is empty or the corresponding
3884 * environment variable undefined.
3885 */
3886static char *option_dup_subs(const char *opt)
3887{
3888 char out[OPT_LEN_MAX+1];
3889 char in[OPT_LEN_MAX+1];
3890 char *outptr = out;
3891 char *inptr = in;
3892 char *ch1, *ch2, *env;
3893 ssize_t nchr = OPT_LEN_MAX;
3894 size_t envlen;
3895
3896 if (strlen(opt) + 1 > OPT_LEN_MAX) {
3897 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
3898 return NULL;
3899 }
3900
3901 in[OPT_LEN_MAX] = '\0';
3902 strncpy(in, opt, OPT_LEN_MAX);
3903
3904 while (*inptr && nchr > 0) {
3905 if (inptr[0] == '$' && inptr[1] == '{') {
3906 ch2 = strchr(inptr, '}');
3907 if (ch2 && inptr+1 < ch2) {
3908 ch1 = inptr+2;
3909 inptr = ch2+1;
3910 *ch2 = '\0';
3911
3912 env = getenv(ch1);
3913 if (env) {
3914 envlen = strlen(env);
3915 if (envlen <= nchr) {
3916 memcpy(outptr, env, envlen);
3917 outptr += envlen;
3918 nchr -= envlen;
3919 }
3920 }
3921
3922 continue;
3923 }
3924 }
3925
3926 *outptr++ = *inptr++;
3927 --nchr;
3928 }
3929
3930 *outptr = '\0';
3931 return strdup(out);
892a6ffc
JA
3932}
3933
74929ac2
JA
3934/*
3935 * Look for reserved variable names and replace them with real values
3936 */
3937static char *fio_keyword_replace(char *opt)
3938{
3939 char *s;
3940 int i;
d0c814ec 3941 int docalc = 0;
74929ac2
JA
3942
3943 for (i = 0; fio_keywords[i].word != NULL; i++) {
3944 struct fio_keyword *kw = &fio_keywords[i];
3945
3946 while ((s = strstr(opt, kw->word)) != NULL) {
3947 char *new = malloc(strlen(opt) + 1);
3948 char *o_org = opt;
3949 int olen = s - opt;
3950 int len;
3951
3952 /*
3953 * Copy part of the string before the keyword and
3954 * sprintf() the replacement after it.
3955 */
3956 memcpy(new, opt, olen);
3957 len = sprintf(new + olen, "%s", kw->replace);
3958
3959 /*
3960 * If there's more in the original string, copy that
3961 * in too
3962 */
3963 opt += strlen(kw->word) + olen;
3964 if (strlen(opt))
3965 memcpy(new + olen + len, opt, opt - o_org - 1);
3966
3967 /*
3968 * replace opt and free the old opt
3969 */
3970 opt = new;
d0c814ec 3971 free(o_org);
7a958bd5 3972
d0c814ec 3973 docalc = 1;
74929ac2
JA
3974 }
3975 }
3976
d0c814ec
SL
3977 /*
3978 * Check for potential math and invoke bc, if possible
3979 */
3980 if (docalc)
3981 opt = bc_calc(opt);
3982
7a958bd5 3983 return opt;
74929ac2
JA
3984}
3985
d0c814ec
SL
3986static char **dup_and_sub_options(char **opts, int num_opts)
3987{
3988 int i;
3989 char **opts_copy = malloc(num_opts * sizeof(*opts));
3990 for (i = 0; i < num_opts; i++) {
3991 opts_copy[i] = option_dup_subs(opts[i]);
3992 if (!opts_copy[i])
3993 continue;
3994 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
3995 }
3996 return opts_copy;
3997}
3998
e15b023b 3999static void show_closest_option(const char *opt)
a2d027b9
JA
4000{
4001 int best_option, best_distance;
4002 int i, distance;
e15b023b
JA
4003 char *name;
4004
4005 if (!strlen(opt))
4006 return;
4007
4008 name = strdup(opt);
4009 i = 0;
4010 while (name[i] != '\0' && name[i] != '=')
4011 i++;
4012 name[i] = '\0';
a2d027b9
JA
4013
4014 best_option = -1;
4015 best_distance = INT_MAX;
4016 i = 0;
4017 while (fio_options[i].name) {
4018 distance = string_distance(name, fio_options[i].name);
4019 if (distance < best_distance) {
4020 best_distance = distance;
4021 best_option = i;
4022 }
4023 i++;
4024 }
4025
3701636d 4026 if (best_option != -1 && string_distance_ok(name, best_distance))
a2d027b9 4027 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
4028
4029 free(name);
a2d027b9
JA
4030}
4031
292cc475
JA
4032int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
4033 int dump_cmdline)
214e1eca 4034{
de890a1e 4035 int i, ret, unknown;
d0c814ec 4036 char **opts_copy;
3b8b7135 4037
9af4a244 4038 sort_options(opts, fio_options, num_opts);
d0c814ec 4039 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 4040
de890a1e
SL
4041 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
4042 struct fio_option *o;
9af4a244 4043 int newret = parse_option(opts_copy[i], opts[i], fio_options,
292cc475 4044 &o, td, dump_cmdline);
d0c814ec 4045
a8523a6a
JA
4046 if (!newret && o)
4047 fio_option_mark_set(&td->o, o);
4048
de890a1e
SL
4049 if (opts_copy[i]) {
4050 if (newret && !o) {
4051 unknown++;
4052 continue;
4053 }
d0c814ec 4054 free(opts_copy[i]);
de890a1e
SL
4055 opts_copy[i] = NULL;
4056 }
4057
4058 ret |= newret;
4059 }
4060
4061 if (unknown) {
4062 ret |= ioengine_load(td);
4063 if (td->eo) {
4064 sort_options(opts_copy, td->io_ops->options, num_opts);
4065 opts = opts_copy;
4066 }
4067 for (i = 0; i < num_opts; i++) {
4068 struct fio_option *o = NULL;
4069 int newret = 1;
a2d027b9 4070
de890a1e
SL
4071 if (!opts_copy[i])
4072 continue;
4073
4074 if (td->eo)
4075 newret = parse_option(opts_copy[i], opts[i],
4076 td->io_ops->options, &o,
292cc475 4077 td->eo, dump_cmdline);
de890a1e
SL
4078
4079 ret |= newret;
a2d027b9 4080 if (!o) {
de890a1e 4081 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
4082 show_closest_option(opts[i]);
4083 }
de890a1e
SL
4084 free(opts_copy[i]);
4085 opts_copy[i] = NULL;
4086 }
74929ac2 4087 }
3b8b7135 4088
d0c814ec 4089 free(opts_copy);
3b8b7135 4090 return ret;
214e1eca
JA
4091}
4092
4093int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
4094{
a8523a6a
JA
4095 int ret;
4096
4097 ret = parse_cmd_option(opt, val, fio_options, td);
4098 if (!ret) {
4099 struct fio_option *o;
4100
4101 o = find_option(fio_options, opt);
4102 if (o)
4103 fio_option_mark_set(&td->o, o);
4104 }
4105
4106 return ret;
214e1eca
JA
4107}
4108
de890a1e
SL
4109int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
4110 char *val)
4111{
8a96c80e 4112 return parse_cmd_option(opt, val, td->io_ops->options, td->eo);
de890a1e
SL
4113}
4114
214e1eca
JA
4115void fio_fill_default_options(struct thread_data *td)
4116{
cb1402d6 4117 td->o.magic = OPT_MAGIC;
9af4a244 4118 fill_default_options(td, fio_options);
214e1eca
JA
4119}
4120
4121int fio_show_option_help(const char *opt)
4122{
9af4a244 4123 return show_cmd_help(fio_options, opt);
214e1eca 4124}
d23bb327 4125
de890a1e 4126void options_mem_dupe(void *data, struct fio_option *options)
d23bb327 4127{
de890a1e 4128 struct fio_option *o;
d23bb327 4129 char **ptr;
d23bb327 4130
de890a1e
SL
4131 for (o = &options[0]; o->name; o++) {
4132 if (o->type != FIO_OPT_STR_STORE)
d23bb327
JA
4133 continue;
4134
f0fdbcaf 4135 ptr = td_var(data, o, o->off1);
7e356b2d
JA
4136 if (*ptr)
4137 *ptr = strdup(*ptr);
d23bb327
JA
4138 }
4139}
4140
de890a1e
SL
4141/*
4142 * dupe FIO_OPT_STR_STORE options
4143 */
4144void fio_options_mem_dupe(struct thread_data *td)
4145{
9af4a244 4146 options_mem_dupe(&td->o, fio_options);
1647f592
JA
4147
4148 if (td->eo && td->io_ops) {
de890a1e 4149 void *oldeo = td->eo;
1647f592 4150
de890a1e
SL
4151 td->eo = malloc(td->io_ops->option_struct_size);
4152 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
4153 options_mem_dupe(td->eo, td->io_ops->options);
4154 }
4155}
4156
d6978a32
JA
4157unsigned int fio_get_kb_base(void *data)
4158{
83ea422a 4159 struct thread_options *o = data;
d6978a32
JA
4160 unsigned int kb_base = 0;
4161
cb1402d6
JA
4162 /*
4163 * This is a hack... For private options, *data is not holding
4164 * a pointer to the thread_options, but to private data. This means
4165 * we can't safely dereference it, but magic is first so mem wise
4166 * it is valid. But this also means that if the job first sets
4167 * kb_base and expects that to be honored by private options,
4168 * it will be disappointed. We will return the global default
4169 * for this.
4170 */
4171 if (o && o->magic == OPT_MAGIC)
83ea422a 4172 kb_base = o->kb_base;
d6978a32
JA
4173 if (!kb_base)
4174 kb_base = 1024;
4175
4176 return kb_base;
4177}
9f988e2e 4178
07b3232d 4179int add_option(struct fio_option *o)
9f988e2e 4180{
07b3232d
JA
4181 struct fio_option *__o;
4182 int opt_index = 0;
4183
9af4a244 4184 __o = fio_options;
07b3232d
JA
4185 while (__o->name) {
4186 opt_index++;
4187 __o++;
4188 }
4189
7b504edd
JA
4190 if (opt_index + 1 == FIO_MAX_OPTS) {
4191 log_err("fio: FIO_MAX_OPTS is too small\n");
4192 return 1;
4193 }
4194
9af4a244 4195 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 4196 fio_options[opt_index + 1].name = NULL;
07b3232d 4197 return 0;
9f988e2e 4198}
e2de69da 4199
07b3232d 4200void invalidate_profile_options(const char *prof_name)
e2de69da 4201{
07b3232d 4202 struct fio_option *o;
e2de69da 4203
9af4a244 4204 o = fio_options;
07b3232d
JA
4205 while (o->name) {
4206 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
4207 o->type = FIO_OPT_INVALID;
4208 o->prof_name = NULL;
4209 }
4210 o++;
e2de69da
JA
4211 }
4212}
f5b6bb85
JA
4213
4214void add_opt_posval(const char *optname, const char *ival, const char *help)
4215{
4216 struct fio_option *o;
4217 unsigned int i;
4218
9af4a244 4219 o = find_option(fio_options, optname);
f5b6bb85
JA
4220 if (!o)
4221 return;
4222
4223 for (i = 0; i < PARSE_MAX_VP; i++) {
4224 if (o->posval[i].ival)
4225 continue;
4226
4227 o->posval[i].ival = ival;
4228 o->posval[i].help = help;
4229 break;
4230 }
4231}
4232
4233void del_opt_posval(const char *optname, const char *ival)
4234{
4235 struct fio_option *o;
4236 unsigned int i;
4237
9af4a244 4238 o = find_option(fio_options, optname);
f5b6bb85
JA
4239 if (!o)
4240 return;
4241
4242 for (i = 0; i < PARSE_MAX_VP; i++) {
4243 if (!o->posval[i].ival)
4244 continue;
4245 if (strcmp(o->posval[i].ival, ival))
4246 continue;
4247
4248 o->posval[i].ival = NULL;
4249 o->posval[i].help = NULL;
4250 }
4251}
7e356b2d
JA
4252
4253void fio_options_free(struct thread_data *td)
4254{
9af4a244 4255 options_free(fio_options, td);
de890a1e
SL
4256 if (td->eo && td->io_ops && td->io_ops->options) {
4257 options_free(td->io_ops->options, td->eo);
4258 free(td->eo);
4259 td->eo = NULL;
4260 }
7e356b2d 4261}
c504ee55
JA
4262
4263struct fio_option *fio_option_find(const char *name)
4264{
4265 return find_option(fio_options, name);
4266}
4267
f0e7f45a
JA
4268static struct fio_option *find_next_opt(struct thread_options *o,
4269 struct fio_option *from,
4270 unsigned int off1)
a8523a6a 4271{
f0e7f45a 4272 struct fio_option *opt;
a8523a6a 4273
f0e7f45a
JA
4274 if (!from)
4275 from = &fio_options[0];
4276 else
4277 from++;
4278
4279 opt = NULL;
4280 do {
4281 if (off1 == from->off1) {
4282 opt = from;
a8523a6a
JA
4283 break;
4284 }
f0e7f45a
JA
4285 from++;
4286 } while (from->name);
a8523a6a 4287
f0e7f45a
JA
4288 return opt;
4289}
4290
4291static int opt_is_set(struct thread_options *o, struct fio_option *opt)
4292{
4293 unsigned int opt_off, index, offset;
a8523a6a
JA
4294
4295 opt_off = opt - &fio_options[0];
4296 index = opt_off / (8 * sizeof(uint64_t));
4297 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 4298 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
4299}
4300
f0e7f45a
JA
4301int __fio_option_is_set(struct thread_options *o, unsigned int off1)
4302{
4303 struct fio_option *opt, *next;
4304
4305 next = NULL;
4306 while ((opt = find_next_opt(o, next, off1)) != NULL) {
4307 if (opt_is_set(o, opt))
4308 return 1;
4309
4310 next = opt;
4311 }
4312
4313 return 0;
4314}
4315
a8523a6a
JA
4316void fio_option_mark_set(struct thread_options *o, struct fio_option *opt)
4317{
4318 unsigned int opt_off, index, offset;
4319
4320 opt_off = opt - &fio_options[0];
4321 index = opt_off / (8 * sizeof(uint64_t));
4322 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 4323 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 4324}