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