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