Get rid of td->o.perc_seq
[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 },
67bf9823 1305#ifdef CONFIG_LIBAIO
214e1eca
JA
1306 { .ival = "libaio",
1307 .help = "Linux native asynchronous IO",
1308 },
1309#endif
67bf9823 1310#ifdef CONFIG_POSIXAIO
214e1eca
JA
1311 { .ival = "posixaio",
1312 .help = "POSIX asynchronous IO",
1313 },
417f0068 1314#endif
997843cb 1315#ifdef CONFIG_SOLARISAIO
417f0068
JA
1316 { .ival = "solarisaio",
1317 .help = "Solaris native asynchronous IO",
1318 },
214e1eca 1319#endif
4700b234 1320#ifdef CONFIG_WINDOWSAIO
03e20d68 1321 { .ival = "windowsaio",
3be80071 1322 .help = "Windows native asynchronous IO"
de890a1e 1323 },
3be80071 1324#endif
214e1eca 1325 { .ival = "mmap",
03e20d68 1326 .help = "Memory mapped IO"
214e1eca 1327 },
67bf9823 1328#ifdef CONFIG_LINUX_SPLICE
214e1eca
JA
1329 { .ival = "splice",
1330 .help = "splice/vmsplice based IO",
1331 },
9cce02e8
JA
1332 { .ival = "netsplice",
1333 .help = "splice/vmsplice to/from the network",
1334 },
214e1eca
JA
1335#endif
1336#ifdef FIO_HAVE_SGIO
1337 { .ival = "sg",
1338 .help = "SCSI generic v3 IO",
1339 },
1340#endif
1341 { .ival = "null",
1342 .help = "Testing engine (no data transfer)",
1343 },
1344 { .ival = "net",
1345 .help = "Network IO",
1346 },
214e1eca 1347 { .ival = "cpuio",
03e20d68 1348 .help = "CPU cycle burner engine",
214e1eca 1349 },
67bf9823 1350#ifdef CONFIG_GUASI
b8c82a46
JA
1351 { .ival = "guasi",
1352 .help = "GUASI IO engine",
1353 },
79a43187
JA
1354#endif
1355#ifdef FIO_HAVE_BINJECT
1356 { .ival = "binject",
1357 .help = "binject direct inject block engine",
1358 },
21b8aee8 1359#endif
67bf9823 1360#ifdef CONFIG_RDMA
21b8aee8 1361 { .ival = "rdma",
1362 .help = "RDMA IO engine",
1363 },
8200b8c7 1364#endif
67bf9823 1365#ifdef CONFIG_FUSION_AW
8200b8c7
JA
1366 { .ival = "fusion-aw-sync",
1367 .help = "Fusion-io atomic write engine",
1368 },
1ecc95ca 1369#endif
997843cb 1370#ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
1ecc95ca
JA
1371 { .ival = "e4defrag",
1372 .help = "ext4 defrag engine",
1373 },
1374#endif
997843cb 1375#ifdef CONFIG_LINUX_FALLOCATE
1ecc95ca
JA
1376 { .ival = "falloc",
1377 .help = "fallocate() file based engine",
1378 },
b8c82a46 1379#endif
214e1eca
JA
1380 { .ival = "external",
1381 .help = "Load external engine (append name)",
1382 },
1383 },
1384 },
1385 {
1386 .name = "iodepth",
e8b0e958 1387 .lname = "IO Depth",
214e1eca
JA
1388 .type = FIO_OPT_INT,
1389 .off1 = td_var_offset(iodepth),
03e20d68 1390 .help = "Number of IO buffers to keep in flight",
757aff4f 1391 .minval = 1,
20eb06bd 1392 .interval = 1,
214e1eca 1393 .def = "1",
e8b0e958 1394 .category = FIO_OPT_C_IO,
0626037e 1395 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1396 },
1397 {
1398 .name = "iodepth_batch",
e8b0e958 1399 .lname = "IO Depth batch",
4950421a 1400 .alias = "iodepth_batch_submit",
214e1eca
JA
1401 .type = FIO_OPT_INT,
1402 .off1 = td_var_offset(iodepth_batch),
d65db441 1403 .help = "Number of IO buffers to submit in one go",
afdf9352 1404 .parent = "iodepth",
d71c154c 1405 .hide = 1,
a2e6f8ac 1406 .minval = 1,
20eb06bd 1407 .interval = 1,
a2e6f8ac 1408 .def = "1",
e8b0e958 1409 .category = FIO_OPT_C_IO,
0626037e 1410 .group = FIO_OPT_G_IO_BASIC,
4950421a
JA
1411 },
1412 {
1413 .name = "iodepth_batch_complete",
e8b0e958 1414 .lname = "IO Depth batch complete",
4950421a
JA
1415 .type = FIO_OPT_INT,
1416 .off1 = td_var_offset(iodepth_batch_complete),
d65db441 1417 .help = "Number of IO buffers to retrieve in one go",
4950421a 1418 .parent = "iodepth",
d71c154c 1419 .hide = 1,
4950421a 1420 .minval = 0,
20eb06bd 1421 .interval = 1,
4950421a 1422 .def = "1",
e8b0e958 1423 .category = FIO_OPT_C_IO,
0626037e 1424 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1425 },
1426 {
1427 .name = "iodepth_low",
e8b0e958 1428 .lname = "IO Depth batch low",
214e1eca
JA
1429 .type = FIO_OPT_INT,
1430 .off1 = td_var_offset(iodepth_low),
1431 .help = "Low water mark for queuing depth",
afdf9352 1432 .parent = "iodepth",
d71c154c 1433 .hide = 1,
20eb06bd 1434 .interval = 1,
e8b0e958 1435 .category = FIO_OPT_C_IO,
0626037e 1436 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1437 },
1438 {
1439 .name = "size",
e8b0e958 1440 .lname = "Size",
214e1eca 1441 .type = FIO_OPT_STR_VAL,
7bb59102 1442 .cb = str_size_cb,
214e1eca 1443 .help = "Total size of device or files",
20eb06bd 1444 .interval = 1024 * 1024,
e8b0e958
JA
1445 .category = FIO_OPT_C_IO,
1446 .group = FIO_OPT_G_INVALID,
214e1eca 1447 },
aa31f1f1
SL
1448 {
1449 .name = "fill_device",
e8b0e958 1450 .lname = "Fill device",
74586c1e 1451 .alias = "fill_fs",
aa31f1f1
SL
1452 .type = FIO_OPT_BOOL,
1453 .off1 = td_var_offset(fill_device),
1454 .help = "Write until an ENOSPC error occurs",
1455 .def = "0",
e8b0e958
JA
1456 .category = FIO_OPT_C_FILE,
1457 .group = FIO_OPT_G_INVALID,
aa31f1f1 1458 },
214e1eca
JA
1459 {
1460 .name = "filesize",
e8b0e958 1461 .lname = "File size",
214e1eca
JA
1462 .type = FIO_OPT_STR_VAL,
1463 .off1 = td_var_offset(file_size_low),
1464 .off2 = td_var_offset(file_size_high),
c3edbdba 1465 .minval = 1,
214e1eca 1466 .help = "Size of individual files",
20eb06bd 1467 .interval = 1024 * 1024,
e8b0e958
JA
1468 .category = FIO_OPT_C_FILE,
1469 .group = FIO_OPT_G_INVALID,
214e1eca 1470 },
67a1000f
JA
1471 {
1472 .name = "offset",
e8b0e958 1473 .lname = "IO offset",
67a1000f
JA
1474 .alias = "fileoffset",
1475 .type = FIO_OPT_STR_VAL,
1476 .off1 = td_var_offset(start_offset),
1477 .help = "Start IO from this offset",
1478 .def = "0",
20eb06bd 1479 .interval = 1024 * 1024,
e8b0e958
JA
1480 .category = FIO_OPT_C_IO,
1481 .group = FIO_OPT_G_INVALID,
67a1000f 1482 },
2d7cd868
JA
1483 {
1484 .name = "offset_increment",
e8b0e958 1485 .lname = "IO offset increment",
2d7cd868
JA
1486 .type = FIO_OPT_STR_VAL,
1487 .off1 = td_var_offset(offset_increment),
1488 .help = "What is the increment from one offset to the next",
1489 .parent = "offset",
d71c154c 1490 .hide = 1,
2d7cd868 1491 .def = "0",
20eb06bd 1492 .interval = 1024 * 1024,
e8b0e958
JA
1493 .category = FIO_OPT_C_IO,
1494 .group = FIO_OPT_G_INVALID,
2d7cd868 1495 },
214e1eca
JA
1496 {
1497 .name = "bs",
e8b0e958 1498 .lname = "Block size",
d3aad8f2 1499 .alias = "blocksize",
e01b22b8 1500 .type = FIO_OPT_INT,
214e1eca
JA
1501 .off1 = td_var_offset(bs[DDIR_READ]),
1502 .off2 = td_var_offset(bs[DDIR_WRITE]),
6eaf09d6 1503 .off3 = td_var_offset(bs[DDIR_TRIM]),
c3edbdba 1504 .minval = 1,
214e1eca
JA
1505 .help = "Block size unit",
1506 .def = "4k",
67a1000f 1507 .parent = "rw",
d71c154c 1508 .hide = 1,
20eb06bd 1509 .interval = 512,
e8b0e958
JA
1510 .category = FIO_OPT_C_IO,
1511 .group = FIO_OPT_G_INVALID,
214e1eca 1512 },
2b7a01d0
JA
1513 {
1514 .name = "ba",
e8b0e958 1515 .lname = "Block size align",
2b7a01d0 1516 .alias = "blockalign",
e01b22b8 1517 .type = FIO_OPT_INT,
2b7a01d0
JA
1518 .off1 = td_var_offset(ba[DDIR_READ]),
1519 .off2 = td_var_offset(ba[DDIR_WRITE]),
6eaf09d6 1520 .off3 = td_var_offset(ba[DDIR_TRIM]),
2b7a01d0
JA
1521 .minval = 1,
1522 .help = "IO block offset alignment",
1523 .parent = "rw",
d71c154c 1524 .hide = 1,
20eb06bd 1525 .interval = 512,
e8b0e958
JA
1526 .category = FIO_OPT_C_IO,
1527 .group = FIO_OPT_G_INVALID,
2b7a01d0 1528 },
214e1eca
JA
1529 {
1530 .name = "bsrange",
e8b0e958 1531 .lname = "Block size range",
d3aad8f2 1532 .alias = "blocksize_range",
214e1eca
JA
1533 .type = FIO_OPT_RANGE,
1534 .off1 = td_var_offset(min_bs[DDIR_READ]),
1535 .off2 = td_var_offset(max_bs[DDIR_READ]),
1536 .off3 = td_var_offset(min_bs[DDIR_WRITE]),
1537 .off4 = td_var_offset(max_bs[DDIR_WRITE]),
6eaf09d6
SL
1538 .off5 = td_var_offset(min_bs[DDIR_TRIM]),
1539 .off6 = td_var_offset(max_bs[DDIR_TRIM]),
c3edbdba 1540 .minval = 1,
214e1eca 1541 .help = "Set block size range (in more detail than bs)",
67a1000f 1542 .parent = "rw",
d71c154c 1543 .hide = 1,
20eb06bd 1544 .interval = 4096,
e8b0e958
JA
1545 .category = FIO_OPT_C_IO,
1546 .group = FIO_OPT_G_INVALID,
214e1eca 1547 },
564ca972
JA
1548 {
1549 .name = "bssplit",
e8b0e958 1550 .lname = "Block size split",
564ca972
JA
1551 .type = FIO_OPT_STR,
1552 .cb = str_bssplit_cb,
1553 .help = "Set a specific mix of block sizes",
1554 .parent = "rw",
d71c154c 1555 .hide = 1,
e8b0e958
JA
1556 .category = FIO_OPT_C_IO,
1557 .group = FIO_OPT_G_INVALID,
564ca972 1558 },
214e1eca
JA
1559 {
1560 .name = "bs_unaligned",
e8b0e958 1561 .lname = "Block size unaligned",
d3aad8f2 1562 .alias = "blocksize_unaligned",
214e1eca
JA
1563 .type = FIO_OPT_STR_SET,
1564 .off1 = td_var_offset(bs_unaligned),
1565 .help = "Don't sector align IO buffer sizes",
67a1000f 1566 .parent = "rw",
d71c154c 1567 .hide = 1,
e8b0e958
JA
1568 .category = FIO_OPT_C_IO,
1569 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1570 },
1571 {
1572 .name = "randrepeat",
e8b0e958 1573 .lname = "Random repeatable",
214e1eca
JA
1574 .type = FIO_OPT_BOOL,
1575 .off1 = td_var_offset(rand_repeatable),
1576 .help = "Use repeatable random IO pattern",
1577 .def = "1",
67a1000f 1578 .parent = "rw",
d71c154c 1579 .hide = 1,
e8b0e958 1580 .category = FIO_OPT_C_IO,
3ceb458f 1581 .group = FIO_OPT_G_RANDOM,
214e1eca 1582 },
2615cc4b
JA
1583 {
1584 .name = "use_os_rand",
e8b0e958 1585 .lname = "Use OS random",
2615cc4b
JA
1586 .type = FIO_OPT_BOOL,
1587 .off1 = td_var_offset(use_os_rand),
1588 .help = "Set to use OS random generator",
1589 .def = "0",
1590 .parent = "rw",
d71c154c 1591 .hide = 1,
e8b0e958 1592 .category = FIO_OPT_C_IO,
3ceb458f 1593 .group = FIO_OPT_G_RANDOM,
2615cc4b 1594 },
214e1eca
JA
1595 {
1596 .name = "norandommap",
e8b0e958 1597 .lname = "No randommap",
214e1eca
JA
1598 .type = FIO_OPT_STR_SET,
1599 .off1 = td_var_offset(norandommap),
1600 .help = "Accept potential duplicate random blocks",
67a1000f 1601 .parent = "rw",
d71c154c 1602 .hide = 1,
b2452a43 1603 .hide_on_set = 1,
e8b0e958 1604 .category = FIO_OPT_C_IO,
3ceb458f 1605 .group = FIO_OPT_G_RANDOM,
214e1eca 1606 },
2b386d25
JA
1607 {
1608 .name = "softrandommap",
e8b0e958 1609 .lname = "Soft randommap",
2b386d25
JA
1610 .type = FIO_OPT_BOOL,
1611 .off1 = td_var_offset(softrandommap),
f66ab3c8 1612 .help = "Set norandommap if randommap allocation fails",
2b386d25 1613 .parent = "norandommap",
d71c154c 1614 .hide = 1,
2b386d25 1615 .def = "0",
e8b0e958 1616 .category = FIO_OPT_C_IO,
3ceb458f 1617 .group = FIO_OPT_G_RANDOM,
2b386d25 1618 },
8055e41d
JA
1619 {
1620 .name = "random_generator",
1621 .type = FIO_OPT_STR,
1622 .off1 = td_var_offset(random_generator),
1623 .help = "Type of random number generator to use",
1624 .def = "tausworthe",
1625 .posval = {
1626 { .ival = "tausworthe",
1627 .oval = FIO_RAND_GEN_TAUSWORTHE,
1628 .help = "Strong Tausworthe generator",
1629 },
1630 { .ival = "lfsr",
1631 .oval = FIO_RAND_GEN_LFSR,
1632 .help = "Variable length LFSR",
1633 },
1634 },
48107598
JA
1635 .category = FIO_OPT_C_IO,
1636 .group = FIO_OPT_G_RANDOM,
8055e41d 1637 },
e25839d4
JA
1638 {
1639 .name = "random_distribution",
1640 .type = FIO_OPT_STR,
1641 .off1 = td_var_offset(random_distribution),
1642 .cb = str_random_distribution_cb,
1643 .help = "Random offset distribution generator",
1644 .def = "random",
1645 .posval = {
1646 { .ival = "random",
1647 .oval = FIO_RAND_DIST_RANDOM,
1648 .help = "Completely random",
1649 },
1650 { .ival = "zipf",
1651 .oval = FIO_RAND_DIST_ZIPF,
1652 .help = "Zipf distribution",
1653 },
925fee33
JA
1654 { .ival = "pareto",
1655 .oval = FIO_RAND_DIST_PARETO,
1656 .help = "Pareto distribution",
1657 },
e25839d4 1658 },
48107598
JA
1659 .category = FIO_OPT_C_IO,
1660 .group = FIO_OPT_G_RANDOM,
e25839d4 1661 },
211c9b89
JA
1662 {
1663 .name = "percentage_random",
1664 .lname = "Percentage Random",
1665 .type = FIO_OPT_INT,
1666 .cb = str_perc_rand_cb,
1667 .maxval = 100,
1668 .help = "Percentage of seq/random mix that should be random",
1669 .def = "100",
1670 .interval = 5,
1671 .inverse = "percentage_sequential",
1672 .category = FIO_OPT_C_IO,
1673 .group = FIO_OPT_G_RANDOM,
1674 },
1675 {
1676 .name = "percentage_sequential",
1677 .lname = "Percentage Sequential",
1678 .type = FIO_OPT_INT,
1679 .cb = str_perc_seq_cb,
1680 .maxval = 100,
1681 .help = "Percentage of seq/random mix that should be sequential",
1682 .def = "0",
1683 .interval = 5,
1684 .inverse = "percentage_random",
1685 .category = FIO_OPT_C_IO,
1686 .group = FIO_OPT_G_RANDOM,
1687 },
214e1eca
JA
1688 {
1689 .name = "nrfiles",
e8b0e958 1690 .lname = "Number of files",
d7c8be03 1691 .alias = "nr_files",
214e1eca
JA
1692 .type = FIO_OPT_INT,
1693 .off1 = td_var_offset(nr_files),
1694 .help = "Split job workload between this number of files",
1695 .def = "1",
20eb06bd 1696 .interval = 1,
e8b0e958
JA
1697 .category = FIO_OPT_C_FILE,
1698 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1699 },
1700 {
1701 .name = "openfiles",
e8b0e958 1702 .lname = "Number of open files",
214e1eca
JA
1703 .type = FIO_OPT_INT,
1704 .off1 = td_var_offset(open_files),
1705 .help = "Number of files to keep open at the same time",
e8b0e958
JA
1706 .category = FIO_OPT_C_FILE,
1707 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1708 },
1709 {
1710 .name = "file_service_type",
e8b0e958 1711 .lname = "File service type",
214e1eca
JA
1712 .type = FIO_OPT_STR,
1713 .cb = str_fst_cb,
1714 .off1 = td_var_offset(file_service_type),
1715 .help = "How to select which file to service next",
1716 .def = "roundrobin",
e8b0e958
JA
1717 .category = FIO_OPT_C_FILE,
1718 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1719 .posval = {
1720 { .ival = "random",
1721 .oval = FIO_FSERVICE_RANDOM,
1722 .help = "Choose a file at random",
1723 },
1724 { .ival = "roundrobin",
1725 .oval = FIO_FSERVICE_RR,
1726 .help = "Round robin select files",
1727 },
a086c257
JA
1728 { .ival = "sequential",
1729 .oval = FIO_FSERVICE_SEQ,
1730 .help = "Finish one file before moving to the next",
1731 },
214e1eca 1732 },
67a1000f 1733 .parent = "nrfiles",
d71c154c 1734 .hide = 1,
67a1000f 1735 },
97ac992c 1736#ifdef CONFIG_POSIX_FALLOCATE
7bc8c2cf
JA
1737 {
1738 .name = "fallocate",
e8b0e958 1739 .lname = "Fallocate",
a596f047
EG
1740 .type = FIO_OPT_STR,
1741 .off1 = td_var_offset(fallocate_mode),
1742 .help = "Whether pre-allocation is performed when laying out files",
1743 .def = "posix",
e8b0e958
JA
1744 .category = FIO_OPT_C_FILE,
1745 .group = FIO_OPT_G_INVALID,
a596f047
EG
1746 .posval = {
1747 { .ival = "none",
1748 .oval = FIO_FALLOCATE_NONE,
1749 .help = "Do not pre-allocate space",
1750 },
1751 { .ival = "posix",
1752 .oval = FIO_FALLOCATE_POSIX,
1753 .help = "Use posix_fallocate()",
1754 },
97ac992c 1755#ifdef CONFIG_LINUX_FALLOCATE
a596f047
EG
1756 { .ival = "keep",
1757 .oval = FIO_FALLOCATE_KEEP_SIZE,
1758 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
1759 },
7bc8c2cf 1760#endif
a596f047
EG
1761 /* Compatibility with former boolean values */
1762 { .ival = "0",
1763 .oval = FIO_FALLOCATE_NONE,
1764 .help = "Alias for 'none'",
1765 },
1766 { .ival = "1",
1767 .oval = FIO_FALLOCATE_POSIX,
1768 .help = "Alias for 'posix'",
1769 },
1770 },
1771 },
97ac992c 1772#endif /* CONFIG_POSIX_FALLOCATE */
67a1000f
JA
1773 {
1774 .name = "fadvise_hint",
e8b0e958 1775 .lname = "Fadvise hint",
67a1000f
JA
1776 .type = FIO_OPT_BOOL,
1777 .off1 = td_var_offset(fadvise_hint),
1778 .help = "Use fadvise() to advise the kernel on IO pattern",
1779 .def = "1",
e8b0e958
JA
1780 .category = FIO_OPT_C_FILE,
1781 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1782 },
1783 {
1784 .name = "fsync",
e8b0e958 1785 .lname = "Fsync",
214e1eca
JA
1786 .type = FIO_OPT_INT,
1787 .off1 = td_var_offset(fsync_blocks),
1788 .help = "Issue fsync for writes every given number of blocks",
1789 .def = "0",
20eb06bd 1790 .interval = 1,
e8b0e958
JA
1791 .category = FIO_OPT_C_FILE,
1792 .group = FIO_OPT_G_INVALID,
214e1eca 1793 },
5f9099ea
JA
1794 {
1795 .name = "fdatasync",
e8b0e958 1796 .lname = "Fdatasync",
5f9099ea
JA
1797 .type = FIO_OPT_INT,
1798 .off1 = td_var_offset(fdatasync_blocks),
1799 .help = "Issue fdatasync for writes every given number of blocks",
1800 .def = "0",
20eb06bd 1801 .interval = 1,
e8b0e958
JA
1802 .category = FIO_OPT_C_FILE,
1803 .group = FIO_OPT_G_INVALID,
5f9099ea 1804 },
1ef2b6be
JA
1805 {
1806 .name = "write_barrier",
e8b0e958 1807 .lname = "Write barrier",
1ef2b6be
JA
1808 .type = FIO_OPT_INT,
1809 .off1 = td_var_offset(barrier_blocks),
1810 .help = "Make every Nth write a barrier write",
1811 .def = "0",
20eb06bd 1812 .interval = 1,
e8b0e958
JA
1813 .category = FIO_OPT_C_IO,
1814 .group = FIO_OPT_G_INVALID,
1ef2b6be 1815 },
67bf9823 1816#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
1817 {
1818 .name = "sync_file_range",
e8b0e958 1819 .lname = "Sync file range",
44f29692
JA
1820 .posval = {
1821 { .ival = "wait_before",
1822 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
1823 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
3843deb3 1824 .or = 1,
44f29692
JA
1825 },
1826 { .ival = "write",
1827 .oval = SYNC_FILE_RANGE_WRITE,
1828 .help = "SYNC_FILE_RANGE_WRITE",
3843deb3 1829 .or = 1,
44f29692
JA
1830 },
1831 {
1832 .ival = "wait_after",
1833 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
1834 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
3843deb3 1835 .or = 1,
44f29692
JA
1836 },
1837 },
3843deb3 1838 .type = FIO_OPT_STR_MULTI,
44f29692
JA
1839 .cb = str_sfr_cb,
1840 .off1 = td_var_offset(sync_file_range),
1841 .help = "Use sync_file_range()",
e8b0e958
JA
1842 .category = FIO_OPT_C_FILE,
1843 .group = FIO_OPT_G_INVALID,
44f29692
JA
1844 },
1845#endif
214e1eca
JA
1846 {
1847 .name = "direct",
e8b0e958 1848 .lname = "Direct I/O",
214e1eca
JA
1849 .type = FIO_OPT_BOOL,
1850 .off1 = td_var_offset(odirect),
1851 .help = "Use O_DIRECT IO (negates buffered)",
1852 .def = "0",
a01a1bc5 1853 .inverse = "buffered",
e8b0e958 1854 .category = FIO_OPT_C_IO,
3ceb458f 1855 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
1856 },
1857 {
1858 .name = "buffered",
e8b0e958 1859 .lname = "Buffered I/O",
214e1eca
JA
1860 .type = FIO_OPT_BOOL,
1861 .off1 = td_var_offset(odirect),
1862 .neg = 1,
1863 .help = "Use buffered IO (negates direct)",
1864 .def = "1",
a01a1bc5 1865 .inverse = "direct",
e8b0e958 1866 .category = FIO_OPT_C_IO,
3ceb458f 1867 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
1868 },
1869 {
1870 .name = "overwrite",
e8b0e958 1871 .lname = "Overwrite",
214e1eca
JA
1872 .type = FIO_OPT_BOOL,
1873 .off1 = td_var_offset(overwrite),
1874 .help = "When writing, set whether to overwrite current data",
1875 .def = "0",
e8b0e958
JA
1876 .category = FIO_OPT_C_FILE,
1877 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1878 },
1879 {
1880 .name = "loops",
e8b0e958 1881 .lname = "Loops",
214e1eca
JA
1882 .type = FIO_OPT_INT,
1883 .off1 = td_var_offset(loops),
1884 .help = "Number of times to run the job",
1885 .def = "1",
20eb06bd 1886 .interval = 1,
e8b0e958 1887 .category = FIO_OPT_C_GENERAL,
a1f6afec 1888 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
1889 },
1890 {
1891 .name = "numjobs",
e8b0e958 1892 .lname = "Number of jobs",
214e1eca
JA
1893 .type = FIO_OPT_INT,
1894 .off1 = td_var_offset(numjobs),
1895 .help = "Duplicate this job this many times",
1896 .def = "1",
20eb06bd 1897 .interval = 1,
e8b0e958 1898 .category = FIO_OPT_C_GENERAL,
a1f6afec 1899 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
1900 },
1901 {
1902 .name = "startdelay",
e8b0e958 1903 .lname = "Start delay",
a5737c93 1904 .type = FIO_OPT_STR_VAL_TIME,
214e1eca
JA
1905 .off1 = td_var_offset(start_delay),
1906 .help = "Only start job when this period has passed",
1907 .def = "0",
e8b0e958 1908 .category = FIO_OPT_C_GENERAL,
a1f6afec 1909 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
1910 },
1911 {
1912 .name = "runtime",
e8b0e958 1913 .lname = "Runtime",
214e1eca
JA
1914 .alias = "timeout",
1915 .type = FIO_OPT_STR_VAL_TIME,
1916 .off1 = td_var_offset(timeout),
1917 .help = "Stop workload when this amount of time has passed",
1918 .def = "0",
e8b0e958 1919 .category = FIO_OPT_C_GENERAL,
a1f6afec 1920 .group = FIO_OPT_G_RUNTIME,
214e1eca 1921 },
cf4464ca
JA
1922 {
1923 .name = "time_based",
e8b0e958 1924 .lname = "Time based",
cf4464ca
JA
1925 .type = FIO_OPT_STR_SET,
1926 .off1 = td_var_offset(time_based),
1927 .help = "Keep running until runtime/timeout is met",
e8b0e958 1928 .category = FIO_OPT_C_GENERAL,
a1f6afec 1929 .group = FIO_OPT_G_RUNTIME,
cf4464ca 1930 },
721938ae
JA
1931 {
1932 .name = "ramp_time",
e8b0e958 1933 .lname = "Ramp time",
721938ae
JA
1934 .type = FIO_OPT_STR_VAL_TIME,
1935 .off1 = td_var_offset(ramp_time),
1936 .help = "Ramp up time before measuring performance",
e8b0e958 1937 .category = FIO_OPT_C_GENERAL,
a1f6afec 1938 .group = FIO_OPT_G_RUNTIME,
721938ae 1939 },
c223da83
JA
1940 {
1941 .name = "clocksource",
e8b0e958 1942 .lname = "Clock source",
c223da83
JA
1943 .type = FIO_OPT_STR,
1944 .cb = fio_clock_source_cb,
1945 .off1 = td_var_offset(clocksource),
1946 .help = "What type of timing source to use",
e8b0e958 1947 .category = FIO_OPT_C_GENERAL,
10860056 1948 .group = FIO_OPT_G_CLOCK,
c223da83 1949 .posval = {
67bf9823 1950#ifdef CONFIG_GETTIMEOFDAY
c223da83
JA
1951 { .ival = "gettimeofday",
1952 .oval = CS_GTOD,
1953 .help = "Use gettimeofday(2) for timing",
1954 },
67bf9823
JA
1955#endif
1956#ifdef CONFIG_CLOCK_GETTIME
c223da83
JA
1957 { .ival = "clock_gettime",
1958 .oval = CS_CGETTIME,
1959 .help = "Use clock_gettime(2) for timing",
1960 },
67bf9823 1961#endif
c223da83
JA
1962#ifdef ARCH_HAVE_CPU_CLOCK
1963 { .ival = "cpu",
1964 .oval = CS_CPUCLOCK,
1965 .help = "Use CPU private clock",
1966 },
1967#endif
1968 },
1969 },
214e1eca
JA
1970 {
1971 .name = "mem",
d3aad8f2 1972 .alias = "iomem",
e8b0e958 1973 .lname = "I/O Memory",
214e1eca
JA
1974 .type = FIO_OPT_STR,
1975 .cb = str_mem_cb,
1976 .off1 = td_var_offset(mem_type),
1977 .help = "Backing type for IO buffers",
1978 .def = "malloc",
e8b0e958
JA
1979 .category = FIO_OPT_C_IO,
1980 .group = FIO_OPT_G_INVALID,
214e1eca
JA
1981 .posval = {
1982 { .ival = "malloc",
1983 .oval = MEM_MALLOC,
1984 .help = "Use malloc(3) for IO buffers",
1985 },
37c8cdfe
JA
1986 { .ival = "shm",
1987 .oval = MEM_SHM,
1988 .help = "Use shared memory segments for IO buffers",
1989 },
214e1eca
JA
1990#ifdef FIO_HAVE_HUGETLB
1991 { .ival = "shmhuge",
1992 .oval = MEM_SHMHUGE,
1993 .help = "Like shm, but use huge pages",
1994 },
b370e46a 1995#endif
37c8cdfe
JA
1996 { .ival = "mmap",
1997 .oval = MEM_MMAP,
1998 .help = "Use mmap(2) (file or anon) for IO buffers",
1999 },
214e1eca
JA
2000#ifdef FIO_HAVE_HUGETLB
2001 { .ival = "mmaphuge",
2002 .oval = MEM_MMAPHUGE,
2003 .help = "Like mmap, but use huge pages",
2004 },
2005#endif
2006 },
2007 },
d529ee19
JA
2008 {
2009 .name = "iomem_align",
2010 .alias = "mem_align",
e8b0e958 2011 .lname = "I/O memory alignment",
d529ee19
JA
2012 .type = FIO_OPT_INT,
2013 .off1 = td_var_offset(mem_align),
2014 .minval = 0,
2015 .help = "IO memory buffer offset alignment",
2016 .def = "0",
2017 .parent = "iomem",
d71c154c 2018 .hide = 1,
e8b0e958
JA
2019 .category = FIO_OPT_C_IO,
2020 .group = FIO_OPT_G_INVALID,
d529ee19 2021 },
214e1eca
JA
2022 {
2023 .name = "verify",
e8b0e958 2024 .lname = "Verify",
214e1eca
JA
2025 .type = FIO_OPT_STR,
2026 .off1 = td_var_offset(verify),
2027 .help = "Verify data written",
2028 .def = "0",
e8b0e958 2029 .category = FIO_OPT_C_IO,
3ceb458f 2030 .group = FIO_OPT_G_VERIFY,
214e1eca
JA
2031 .posval = {
2032 { .ival = "0",
2033 .oval = VERIFY_NONE,
2034 .help = "Don't do IO verification",
2035 },
fcca4b58
JA
2036 { .ival = "md5",
2037 .oval = VERIFY_MD5,
2038 .help = "Use md5 checksums for verification",
2039 },
d77a7af3
JA
2040 { .ival = "crc64",
2041 .oval = VERIFY_CRC64,
2042 .help = "Use crc64 checksums for verification",
2043 },
214e1eca
JA
2044 { .ival = "crc32",
2045 .oval = VERIFY_CRC32,
2046 .help = "Use crc32 checksums for verification",
2047 },
af497e6a 2048 { .ival = "crc32c-intel",
e3aaafc4
JA
2049 .oval = VERIFY_CRC32C,
2050 .help = "Use crc32c checksums for verification (hw assisted, if available)",
af497e6a 2051 },
bac39e0e
JA
2052 { .ival = "crc32c",
2053 .oval = VERIFY_CRC32C,
e3aaafc4 2054 .help = "Use crc32c checksums for verification (hw assisted, if available)",
bac39e0e 2055 },
969f7ed3
JA
2056 { .ival = "crc16",
2057 .oval = VERIFY_CRC16,
2058 .help = "Use crc16 checksums for verification",
2059 },
1e154bdb
JA
2060 { .ival = "crc7",
2061 .oval = VERIFY_CRC7,
2062 .help = "Use crc7 checksums for verification",
2063 },
7c353ceb
JA
2064 { .ival = "sha1",
2065 .oval = VERIFY_SHA1,
2066 .help = "Use sha1 checksums for verification",
2067 },
cd14cc10
JA
2068 { .ival = "sha256",
2069 .oval = VERIFY_SHA256,
2070 .help = "Use sha256 checksums for verification",
2071 },
2072 { .ival = "sha512",
2073 .oval = VERIFY_SHA512,
2074 .help = "Use sha512 checksums for verification",
2075 },
7437ee87
SL
2076 { .ival = "meta",
2077 .oval = VERIFY_META,
2078 .help = "Use io information",
2079 },
36690c9b
JA
2080 {
2081 .ival = "null",
2082 .oval = VERIFY_NULL,
2083 .help = "Pretend to verify",
2084 },
214e1eca
JA
2085 },
2086 },
005c565a
JA
2087 {
2088 .name = "do_verify",
e8b0e958 2089 .lname = "Perform verify step",
68e1f29a 2090 .type = FIO_OPT_BOOL,
005c565a
JA
2091 .off1 = td_var_offset(do_verify),
2092 .help = "Run verification stage after write",
2093 .def = "1",
2094 .parent = "verify",
d71c154c 2095 .hide = 1,
e8b0e958
JA
2096 .category = FIO_OPT_C_IO,
2097 .group = FIO_OPT_G_VERIFY,
005c565a 2098 },
160b966d
JA
2099 {
2100 .name = "verifysort",
e8b0e958 2101 .lname = "Verify sort",
160b966d
JA
2102 .type = FIO_OPT_BOOL,
2103 .off1 = td_var_offset(verifysort),
2104 .help = "Sort written verify blocks for read back",
2105 .def = "1",
c83f2df1 2106 .parent = "verify",
d71c154c 2107 .hide = 1,
e8b0e958
JA
2108 .category = FIO_OPT_C_IO,
2109 .group = FIO_OPT_G_VERIFY,
160b966d 2110 },
1ae83d45
JA
2111 {
2112 .name = "verifysort_nr",
2113 .type = FIO_OPT_INT,
2114 .off1 = td_var_offset(verifysort_nr),
2115 .help = "Pre-load and sort verify blocks for a read workload",
2116 .minval = 0,
2117 .maxval = 131072,
2118 .def = "1024",
2119 .parent = "verify",
836fcc0f
JA
2120 .category = FIO_OPT_C_IO,
2121 .group = FIO_OPT_G_VERIFY,
1ae83d45 2122 },
3f9f4e26 2123 {
a59e170d 2124 .name = "verify_interval",
e8b0e958 2125 .lname = "Verify interval",
e01b22b8 2126 .type = FIO_OPT_INT,
a59e170d 2127 .off1 = td_var_offset(verify_interval),
819a9680 2128 .minval = 2 * sizeof(struct verify_header),
a59e170d 2129 .help = "Store verify buffer header every N bytes",
afdf9352 2130 .parent = "verify",
d71c154c 2131 .hide = 1,
20eb06bd 2132 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
2133 .category = FIO_OPT_C_IO,
2134 .group = FIO_OPT_G_VERIFY,
3f9f4e26 2135 },
546a9142 2136 {
a59e170d 2137 .name = "verify_offset",
e8b0e958 2138 .lname = "Verify offset",
e01b22b8 2139 .type = FIO_OPT_INT,
a59e170d 2140 .help = "Offset verify header location by N bytes",
203160d5
JA
2141 .off1 = td_var_offset(verify_offset),
2142 .minval = sizeof(struct verify_header),
afdf9352 2143 .parent = "verify",
d71c154c 2144 .hide = 1,
e8b0e958
JA
2145 .category = FIO_OPT_C_IO,
2146 .group = FIO_OPT_G_VERIFY,
546a9142 2147 },
e28218f3
SL
2148 {
2149 .name = "verify_pattern",
e8b0e958 2150 .lname = "Verify pattern",
0e92f873 2151 .type = FIO_OPT_STR,
e28218f3
SL
2152 .cb = str_verify_pattern_cb,
2153 .help = "Fill pattern for IO buffers",
2154 .parent = "verify",
d71c154c 2155 .hide = 1,
e8b0e958
JA
2156 .category = FIO_OPT_C_IO,
2157 .group = FIO_OPT_G_VERIFY,
e28218f3 2158 },
a12a3b4d
JA
2159 {
2160 .name = "verify_fatal",
e8b0e958 2161 .lname = "Verify fatal",
68e1f29a 2162 .type = FIO_OPT_BOOL,
a12a3b4d
JA
2163 .off1 = td_var_offset(verify_fatal),
2164 .def = "0",
2165 .help = "Exit on a single verify failure, don't continue",
2166 .parent = "verify",
d71c154c 2167 .hide = 1,
e8b0e958
JA
2168 .category = FIO_OPT_C_IO,
2169 .group = FIO_OPT_G_VERIFY,
a12a3b4d 2170 },
b463e936
JA
2171 {
2172 .name = "verify_dump",
e8b0e958 2173 .lname = "Verify dump",
b463e936
JA
2174 .type = FIO_OPT_BOOL,
2175 .off1 = td_var_offset(verify_dump),
ef71e317 2176 .def = "0",
b463e936
JA
2177 .help = "Dump contents of good and bad blocks on failure",
2178 .parent = "verify",
d71c154c 2179 .hide = 1,
e8b0e958
JA
2180 .category = FIO_OPT_C_IO,
2181 .group = FIO_OPT_G_VERIFY,
b463e936 2182 },
e8462bd8
JA
2183 {
2184 .name = "verify_async",
e8b0e958 2185 .lname = "Verify asynchronously",
e8462bd8
JA
2186 .type = FIO_OPT_INT,
2187 .off1 = td_var_offset(verify_async),
2188 .def = "0",
2189 .help = "Number of async verifier threads to use",
2190 .parent = "verify",
d71c154c 2191 .hide = 1,
e8b0e958
JA
2192 .category = FIO_OPT_C_IO,
2193 .group = FIO_OPT_G_VERIFY,
e8462bd8 2194 },
9e144189
JA
2195 {
2196 .name = "verify_backlog",
e8b0e958 2197 .lname = "Verify backlog",
9e144189
JA
2198 .type = FIO_OPT_STR_VAL,
2199 .off1 = td_var_offset(verify_backlog),
2200 .help = "Verify after this number of blocks are written",
2201 .parent = "verify",
d71c154c 2202 .hide = 1,
e8b0e958
JA
2203 .category = FIO_OPT_C_IO,
2204 .group = FIO_OPT_G_VERIFY,
9e144189
JA
2205 },
2206 {
2207 .name = "verify_backlog_batch",
e8b0e958 2208 .lname = "Verify backlog batch",
9e144189
JA
2209 .type = FIO_OPT_INT,
2210 .off1 = td_var_offset(verify_batch),
2211 .help = "Verify this number of IO blocks",
0d29de83 2212 .parent = "verify",
d71c154c 2213 .hide = 1,
e8b0e958
JA
2214 .category = FIO_OPT_C_IO,
2215 .group = FIO_OPT_G_VERIFY,
9e144189 2216 },
e8462bd8
JA
2217#ifdef FIO_HAVE_CPU_AFFINITY
2218 {
2219 .name = "verify_async_cpus",
e8b0e958 2220 .lname = "Async verify CPUs",
e8462bd8
JA
2221 .type = FIO_OPT_STR,
2222 .cb = str_verify_cpus_allowed_cb,
2223 .help = "Set CPUs allowed for async verify threads",
2224 .parent = "verify_async",
d71c154c 2225 .hide = 1,
e8b0e958
JA
2226 .category = FIO_OPT_C_IO,
2227 .group = FIO_OPT_G_VERIFY,
e8462bd8 2228 },
0d29de83 2229#endif
51aa2da8
JA
2230 {
2231 .name = "experimental_verify",
2232 .off1 = td_var_offset(experimental_verify),
2233 .type = FIO_OPT_BOOL,
b31eaac9 2234 .help = "Enable experimental verification",
836fcc0f
JA
2235 .category = FIO_OPT_C_IO,
2236 .group = FIO_OPT_G_VERIFY,
51aa2da8 2237 },
0d29de83
JA
2238#ifdef FIO_HAVE_TRIM
2239 {
2240 .name = "trim_percentage",
e8b0e958 2241 .lname = "Trim percentage",
0d29de83 2242 .type = FIO_OPT_INT,
203160d5 2243 .off1 = td_var_offset(trim_percentage),
20eb06bd 2244 .minval = 0,
0d29de83
JA
2245 .maxval = 100,
2246 .help = "Number of verify blocks to discard/trim",
2247 .parent = "verify",
2248 .def = "0",
20eb06bd 2249 .interval = 1,
d71c154c 2250 .hide = 1,
e8b0e958
JA
2251 .category = FIO_OPT_C_IO,
2252 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2253 },
2254 {
2255 .name = "trim_verify_zero",
e8b0e958 2256 .lname = "Verify trim zero",
20eb06bd 2257 .type = FIO_OPT_BOOL,
0d29de83
JA
2258 .help = "Verify that trim/discarded blocks are returned as zeroes",
2259 .off1 = td_var_offset(trim_zero),
2260 .parent = "trim_percentage",
d71c154c 2261 .hide = 1,
0d29de83 2262 .def = "1",
e8b0e958
JA
2263 .category = FIO_OPT_C_IO,
2264 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2265 },
2266 {
2267 .name = "trim_backlog",
e8b0e958 2268 .lname = "Trim backlog",
0d29de83
JA
2269 .type = FIO_OPT_STR_VAL,
2270 .off1 = td_var_offset(trim_backlog),
2271 .help = "Trim after this number of blocks are written",
2272 .parent = "trim_percentage",
d71c154c 2273 .hide = 1,
20eb06bd 2274 .interval = 1,
e8b0e958
JA
2275 .category = FIO_OPT_C_IO,
2276 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2277 },
2278 {
2279 .name = "trim_backlog_batch",
e8b0e958 2280 .lname = "Trim backlog batch",
0d29de83
JA
2281 .type = FIO_OPT_INT,
2282 .off1 = td_var_offset(trim_batch),
2283 .help = "Trim this number of IO blocks",
2284 .parent = "trim_percentage",
d71c154c 2285 .hide = 1,
20eb06bd 2286 .interval = 1,
e8b0e958
JA
2287 .category = FIO_OPT_C_IO,
2288 .group = FIO_OPT_G_TRIM,
0d29de83 2289 },
e8462bd8 2290#endif
214e1eca
JA
2291 {
2292 .name = "write_iolog",
e8b0e958 2293 .lname = "Write I/O log",
214e1eca
JA
2294 .type = FIO_OPT_STR_STORE,
2295 .off1 = td_var_offset(write_iolog_file),
2296 .help = "Store IO pattern to file",
e8b0e958
JA
2297 .category = FIO_OPT_C_IO,
2298 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
2299 },
2300 {
2301 .name = "read_iolog",
e8b0e958 2302 .lname = "Read I/O log",
214e1eca
JA
2303 .type = FIO_OPT_STR_STORE,
2304 .off1 = td_var_offset(read_iolog_file),
2305 .help = "Playback IO pattern from file",
e8b0e958
JA
2306 .category = FIO_OPT_C_IO,
2307 .group = FIO_OPT_G_IOLOG,
214e1eca 2308 },
64bbb865
DN
2309 {
2310 .name = "replay_no_stall",
e8b0e958 2311 .lname = "Don't stall on replay",
20eb06bd 2312 .type = FIO_OPT_BOOL,
64bbb865
DN
2313 .off1 = td_var_offset(no_stall),
2314 .def = "0",
87e7a972 2315 .parent = "read_iolog",
d71c154c 2316 .hide = 1,
64bbb865 2317 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
2318 .category = FIO_OPT_C_IO,
2319 .group = FIO_OPT_G_IOLOG,
64bbb865 2320 },
d1c46c04
DN
2321 {
2322 .name = "replay_redirect",
e8b0e958 2323 .lname = "Redirect device for replay",
d1c46c04
DN
2324 .type = FIO_OPT_STR_STORE,
2325 .off1 = td_var_offset(replay_redirect),
2326 .parent = "read_iolog",
d71c154c 2327 .hide = 1,
d1c46c04 2328 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
2329 .category = FIO_OPT_C_IO,
2330 .group = FIO_OPT_G_IOLOG,
d1c46c04 2331 },
214e1eca
JA
2332 {
2333 .name = "exec_prerun",
e8b0e958 2334 .lname = "Pre-execute runnable",
214e1eca
JA
2335 .type = FIO_OPT_STR_STORE,
2336 .off1 = td_var_offset(exec_prerun),
2337 .help = "Execute this file prior to running job",
e8b0e958
JA
2338 .category = FIO_OPT_C_GENERAL,
2339 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2340 },
2341 {
2342 .name = "exec_postrun",
e8b0e958 2343 .lname = "Post-execute runnable",
214e1eca
JA
2344 .type = FIO_OPT_STR_STORE,
2345 .off1 = td_var_offset(exec_postrun),
2346 .help = "Execute this file after running job",
e8b0e958
JA
2347 .category = FIO_OPT_C_GENERAL,
2348 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2349 },
2350#ifdef FIO_HAVE_IOSCHED_SWITCH
2351 {
2352 .name = "ioscheduler",
e8b0e958 2353 .lname = "I/O scheduler",
214e1eca
JA
2354 .type = FIO_OPT_STR_STORE,
2355 .off1 = td_var_offset(ioscheduler),
2356 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
2357 .category = FIO_OPT_C_FILE,
2358 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2359 },
2360#endif
2361 {
2362 .name = "zonesize",
e8b0e958 2363 .lname = "Zone size",
214e1eca
JA
2364 .type = FIO_OPT_STR_VAL,
2365 .off1 = td_var_offset(zone_size),
ed335855
SN
2366 .help = "Amount of data to read per zone",
2367 .def = "0",
20eb06bd 2368 .interval = 1024 * 1024,
e8b0e958
JA
2369 .category = FIO_OPT_C_IO,
2370 .group = FIO_OPT_G_ZONE,
ed335855
SN
2371 },
2372 {
2373 .name = "zonerange",
e8b0e958 2374 .lname = "Zone range",
ed335855
SN
2375 .type = FIO_OPT_STR_VAL,
2376 .off1 = td_var_offset(zone_range),
214e1eca
JA
2377 .help = "Give size of an IO zone",
2378 .def = "0",
20eb06bd 2379 .interval = 1024 * 1024,
e8b0e958
JA
2380 .category = FIO_OPT_C_IO,
2381 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2382 },
2383 {
2384 .name = "zoneskip",
e8b0e958 2385 .lname = "Zone skip",
214e1eca
JA
2386 .type = FIO_OPT_STR_VAL,
2387 .off1 = td_var_offset(zone_skip),
2388 .help = "Space between IO zones",
2389 .def = "0",
20eb06bd 2390 .interval = 1024 * 1024,
e8b0e958
JA
2391 .category = FIO_OPT_C_IO,
2392 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2393 },
2394 {
2395 .name = "lockmem",
e8b0e958 2396 .lname = "Lock memory",
214e1eca 2397 .type = FIO_OPT_STR_VAL,
1b79a070 2398 .off1 = td_var_offset(lockmem),
81c6b6cd 2399 .help = "Lock down this amount of memory (per worker)",
214e1eca 2400 .def = "0",
20eb06bd 2401 .interval = 1024 * 1024,
e8b0e958
JA
2402 .category = FIO_OPT_C_GENERAL,
2403 .group = FIO_OPT_G_INVALID,
214e1eca 2404 },
214e1eca
JA
2405 {
2406 .name = "rwmixread",
e8b0e958 2407 .lname = "Read/write mix read",
214e1eca 2408 .type = FIO_OPT_INT,
cb499fc4 2409 .cb = str_rwmix_read_cb,
214e1eca
JA
2410 .maxval = 100,
2411 .help = "Percentage of mixed workload that is reads",
2412 .def = "50",
20eb06bd 2413 .interval = 5,
90265353 2414 .inverse = "rwmixwrite",
e8b0e958
JA
2415 .category = FIO_OPT_C_IO,
2416 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
2417 },
2418 {
2419 .name = "rwmixwrite",
e8b0e958 2420 .lname = "Read/write mix write",
214e1eca 2421 .type = FIO_OPT_INT,
cb499fc4 2422 .cb = str_rwmix_write_cb,
214e1eca
JA
2423 .maxval = 100,
2424 .help = "Percentage of mixed workload that is writes",
2425 .def = "50",
20eb06bd 2426 .interval = 5,
90265353 2427 .inverse = "rwmixread",
e8b0e958
JA
2428 .category = FIO_OPT_C_IO,
2429 .group = FIO_OPT_G_RWMIX,
214e1eca 2430 },
afdf9352
JA
2431 {
2432 .name = "rwmixcycle",
e8b0e958 2433 .lname = "Read/write mix cycle",
15ca150e 2434 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
2435 .category = FIO_OPT_C_IO,
2436 .group = FIO_OPT_G_RWMIX,
afdf9352 2437 },
214e1eca
JA
2438 {
2439 .name = "nice",
e8b0e958 2440 .lname = "Nice",
214e1eca
JA
2441 .type = FIO_OPT_INT,
2442 .off1 = td_var_offset(nice),
2443 .help = "Set job CPU nice value",
2444 .minval = -19,
2445 .maxval = 20,
2446 .def = "0",
20eb06bd 2447 .interval = 1,
e8b0e958 2448 .category = FIO_OPT_C_GENERAL,
10860056 2449 .group = FIO_OPT_G_CRED,
214e1eca
JA
2450 },
2451#ifdef FIO_HAVE_IOPRIO
2452 {
2453 .name = "prio",
e8b0e958 2454 .lname = "I/O nice priority",
214e1eca 2455 .type = FIO_OPT_INT,
28727df7 2456 .off1 = td_var_offset(ioprio),
214e1eca
JA
2457 .help = "Set job IO priority value",
2458 .minval = 0,
2459 .maxval = 7,
20eb06bd 2460 .interval = 1,
e8b0e958 2461 .category = FIO_OPT_C_GENERAL,
10860056 2462 .group = FIO_OPT_G_CRED,
214e1eca
JA
2463 },
2464 {
2465 .name = "prioclass",
e8b0e958 2466 .lname = "I/O nice priority class",
214e1eca 2467 .type = FIO_OPT_INT,
28727df7 2468 .off1 = td_var_offset(ioprio_class),
214e1eca
JA
2469 .help = "Set job IO priority class",
2470 .minval = 0,
2471 .maxval = 3,
20eb06bd 2472 .interval = 1,
e8b0e958 2473 .category = FIO_OPT_C_GENERAL,
10860056 2474 .group = FIO_OPT_G_CRED,
214e1eca
JA
2475 },
2476#endif
2477 {
2478 .name = "thinktime",
e8b0e958 2479 .lname = "Thinktime",
214e1eca
JA
2480 .type = FIO_OPT_INT,
2481 .off1 = td_var_offset(thinktime),
2482 .help = "Idle time between IO buffers (usec)",
2483 .def = "0",
e8b0e958 2484 .category = FIO_OPT_C_IO,
3ceb458f 2485 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2486 },
2487 {
2488 .name = "thinktime_spin",
e8b0e958 2489 .lname = "Thinktime spin",
214e1eca
JA
2490 .type = FIO_OPT_INT,
2491 .off1 = td_var_offset(thinktime_spin),
2492 .help = "Start think time by spinning this amount (usec)",
2493 .def = "0",
afdf9352 2494 .parent = "thinktime",
d71c154c 2495 .hide = 1,
e8b0e958 2496 .category = FIO_OPT_C_IO,
3ceb458f 2497 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2498 },
2499 {
2500 .name = "thinktime_blocks",
e8b0e958 2501 .lname = "Thinktime blocks",
214e1eca
JA
2502 .type = FIO_OPT_INT,
2503 .off1 = td_var_offset(thinktime_blocks),
2504 .help = "IO buffer period between 'thinktime'",
2505 .def = "1",
afdf9352 2506 .parent = "thinktime",
d71c154c 2507 .hide = 1,
e8b0e958 2508 .category = FIO_OPT_C_IO,
3ceb458f 2509 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2510 },
2511 {
2512 .name = "rate",
e8b0e958 2513 .lname = "I/O rate",
e01b22b8 2514 .type = FIO_OPT_INT,
6eaf09d6
SL
2515 .off1 = td_var_offset(rate[DDIR_READ]),
2516 .off2 = td_var_offset(rate[DDIR_WRITE]),
2517 .off3 = td_var_offset(rate[DDIR_TRIM]),
214e1eca 2518 .help = "Set bandwidth rate",
e8b0e958
JA
2519 .category = FIO_OPT_C_IO,
2520 .group = FIO_OPT_G_RATE,
214e1eca
JA
2521 },
2522 {
2523 .name = "ratemin",
e8b0e958 2524 .lname = "I/O min rate",
e01b22b8 2525 .type = FIO_OPT_INT,
6eaf09d6
SL
2526 .off1 = td_var_offset(ratemin[DDIR_READ]),
2527 .off2 = td_var_offset(ratemin[DDIR_WRITE]),
2528 .off3 = td_var_offset(ratemin[DDIR_TRIM]),
4e991c23 2529 .help = "Job must meet this rate or it will be shutdown",
afdf9352 2530 .parent = "rate",
d71c154c 2531 .hide = 1,
e8b0e958
JA
2532 .category = FIO_OPT_C_IO,
2533 .group = FIO_OPT_G_RATE,
4e991c23
JA
2534 },
2535 {
2536 .name = "rate_iops",
e8b0e958 2537 .lname = "I/O rate IOPS",
e01b22b8 2538 .type = FIO_OPT_INT,
6eaf09d6
SL
2539 .off1 = td_var_offset(rate_iops[DDIR_READ]),
2540 .off2 = td_var_offset(rate_iops[DDIR_WRITE]),
2541 .off3 = td_var_offset(rate_iops[DDIR_TRIM]),
4e991c23 2542 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 2543 .hide = 1,
e8b0e958
JA
2544 .category = FIO_OPT_C_IO,
2545 .group = FIO_OPT_G_RATE,
4e991c23
JA
2546 },
2547 {
2548 .name = "rate_iops_min",
e8b0e958 2549 .lname = "I/O min rate IOPS",
e01b22b8 2550 .type = FIO_OPT_INT,
6eaf09d6
SL
2551 .off1 = td_var_offset(rate_iops_min[DDIR_READ]),
2552 .off2 = td_var_offset(rate_iops_min[DDIR_WRITE]),
2553 .off3 = td_var_offset(rate_iops_min[DDIR_TRIM]),
03e20d68 2554 .help = "Job must meet this rate or it will be shut down",
afdf9352 2555 .parent = "rate_iops",
d71c154c 2556 .hide = 1,
e8b0e958
JA
2557 .category = FIO_OPT_C_IO,
2558 .group = FIO_OPT_G_RATE,
214e1eca
JA
2559 },
2560 {
2561 .name = "ratecycle",
e8b0e958 2562 .lname = "I/O rate cycle",
214e1eca
JA
2563 .type = FIO_OPT_INT,
2564 .off1 = td_var_offset(ratecycle),
2565 .help = "Window average for rate limits (msec)",
2566 .def = "1000",
afdf9352 2567 .parent = "rate",
d71c154c 2568 .hide = 1,
e8b0e958
JA
2569 .category = FIO_OPT_C_IO,
2570 .group = FIO_OPT_G_RATE,
214e1eca 2571 },
15501535
JA
2572 {
2573 .name = "max_latency",
2574 .type = FIO_OPT_INT,
2575 .off1 = td_var_offset(max_latency),
2576 .help = "Maximum tolerated IO latency (usec)",
1e5324e7
JA
2577 .category = FIO_OPT_C_IO,
2578 .group = FIO_OPT_G_RATE,
15501535 2579 },
214e1eca
JA
2580 {
2581 .name = "invalidate",
e8b0e958 2582 .lname = "Cache invalidate",
214e1eca
JA
2583 .type = FIO_OPT_BOOL,
2584 .off1 = td_var_offset(invalidate_cache),
2585 .help = "Invalidate buffer/page cache prior to running job",
2586 .def = "1",
e8b0e958 2587 .category = FIO_OPT_C_IO,
3ceb458f 2588 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2589 },
2590 {
2591 .name = "sync",
e8b0e958 2592 .lname = "Synchronous I/O",
214e1eca
JA
2593 .type = FIO_OPT_BOOL,
2594 .off1 = td_var_offset(sync_io),
2595 .help = "Use O_SYNC for buffered writes",
2596 .def = "0",
67a1000f 2597 .parent = "buffered",
d71c154c 2598 .hide = 1,
e8b0e958 2599 .category = FIO_OPT_C_IO,
3ceb458f 2600 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2601 },
214e1eca
JA
2602 {
2603 .name = "create_serialize",
e8b0e958 2604 .lname = "Create serialize",
214e1eca
JA
2605 .type = FIO_OPT_BOOL,
2606 .off1 = td_var_offset(create_serialize),
2607 .help = "Serialize creating of job files",
2608 .def = "1",
e8b0e958
JA
2609 .category = FIO_OPT_C_FILE,
2610 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2611 },
2612 {
2613 .name = "create_fsync",
e8b0e958 2614 .lname = "Create fsync",
214e1eca
JA
2615 .type = FIO_OPT_BOOL,
2616 .off1 = td_var_offset(create_fsync),
03e20d68 2617 .help = "fsync file after creation",
214e1eca 2618 .def = "1",
e8b0e958
JA
2619 .category = FIO_OPT_C_FILE,
2620 .group = FIO_OPT_G_INVALID,
214e1eca 2621 },
814452bd
JA
2622 {
2623 .name = "create_on_open",
e8b0e958 2624 .lname = "Create on open",
814452bd
JA
2625 .type = FIO_OPT_BOOL,
2626 .off1 = td_var_offset(create_on_open),
2627 .help = "Create files when they are opened for IO",
2628 .def = "0",
e8b0e958
JA
2629 .category = FIO_OPT_C_FILE,
2630 .group = FIO_OPT_G_INVALID,
814452bd 2631 },
25460cf6
JA
2632 {
2633 .name = "create_only",
2634 .type = FIO_OPT_BOOL,
2635 .off1 = td_var_offset(create_only),
2636 .help = "Only perform file creation phase",
d17fda71 2637 .category = FIO_OPT_C_FILE,
25460cf6
JA
2638 .def = "0",
2639 },
0b9d69ec 2640 {
afad68f7 2641 .name = "pre_read",
e8b0e958 2642 .lname = "Pre-read files",
afad68f7
ZY
2643 .type = FIO_OPT_BOOL,
2644 .off1 = td_var_offset(pre_read),
03e20d68 2645 .help = "Pre-read files before starting official testing",
afad68f7 2646 .def = "0",
e8b0e958
JA
2647 .category = FIO_OPT_C_FILE,
2648 .group = FIO_OPT_G_INVALID,
afad68f7 2649 },
214e1eca
JA
2650#ifdef FIO_HAVE_CPU_AFFINITY
2651 {
2652 .name = "cpumask",
e8b0e958 2653 .lname = "CPU mask",
214e1eca
JA
2654 .type = FIO_OPT_INT,
2655 .cb = str_cpumask_cb,
2656 .help = "CPU affinity mask",
e8b0e958 2657 .category = FIO_OPT_C_GENERAL,
10860056 2658 .group = FIO_OPT_G_CRED,
214e1eca 2659 },
d2e268b0
JA
2660 {
2661 .name = "cpus_allowed",
e8b0e958 2662 .lname = "CPUs allowed",
d2e268b0
JA
2663 .type = FIO_OPT_STR,
2664 .cb = str_cpus_allowed_cb,
2665 .help = "Set CPUs allowed",
e8b0e958 2666 .category = FIO_OPT_C_GENERAL,
10860056 2667 .group = FIO_OPT_G_CRED,
d2e268b0 2668 },
d0b937ed 2669#endif
67bf9823 2670#ifdef CONFIG_LIBNUMA
d0b937ed
YR
2671 {
2672 .name = "numa_cpu_nodes",
2673 .type = FIO_OPT_STR,
2674 .cb = str_numa_cpunodes_cb,
2675 .help = "NUMA CPU nodes bind",
6be54b2d
JA
2676 .category = FIO_OPT_C_GENERAL,
2677 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
2678 },
2679 {
2680 .name = "numa_mem_policy",
2681 .type = FIO_OPT_STR,
2682 .cb = str_numa_mpol_cb,
2683 .help = "NUMA memory policy setup",
6be54b2d
JA
2684 .category = FIO_OPT_C_GENERAL,
2685 .group = FIO_OPT_G_INVALID,
d0b937ed 2686 },
214e1eca
JA
2687#endif
2688 {
2689 .name = "end_fsync",
e8b0e958 2690 .lname = "End fsync",
214e1eca
JA
2691 .type = FIO_OPT_BOOL,
2692 .off1 = td_var_offset(end_fsync),
2693 .help = "Include fsync at the end of job",
2694 .def = "0",
e8b0e958
JA
2695 .category = FIO_OPT_C_FILE,
2696 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2697 },
2698 {
2699 .name = "fsync_on_close",
e8b0e958 2700 .lname = "Fsync on close",
214e1eca
JA
2701 .type = FIO_OPT_BOOL,
2702 .off1 = td_var_offset(fsync_on_close),
2703 .help = "fsync files on close",
2704 .def = "0",
e8b0e958
JA
2705 .category = FIO_OPT_C_FILE,
2706 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2707 },
2708 {
2709 .name = "unlink",
e8b0e958 2710 .lname = "Unlink file",
214e1eca
JA
2711 .type = FIO_OPT_BOOL,
2712 .off1 = td_var_offset(unlink),
2713 .help = "Unlink created files after job has completed",
2714 .def = "0",
e8b0e958
JA
2715 .category = FIO_OPT_C_FILE,
2716 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2717 },
2718 {
2719 .name = "exitall",
e8b0e958 2720 .lname = "Exit-all on terminate",
214e1eca
JA
2721 .type = FIO_OPT_STR_SET,
2722 .cb = str_exitall_cb,
2723 .help = "Terminate all jobs when one exits",
e8b0e958 2724 .category = FIO_OPT_C_GENERAL,
a1f6afec 2725 .group = FIO_OPT_G_PROCESS,
214e1eca
JA
2726 },
2727 {
2728 .name = "stonewall",
e8b0e958 2729 .lname = "Wait for previous",
d392365e 2730 .alias = "wait_for_previous",
214e1eca
JA
2731 .type = FIO_OPT_STR_SET,
2732 .off1 = td_var_offset(stonewall),
2733 .help = "Insert a hard barrier between this job and previous",
e8b0e958 2734 .category = FIO_OPT_C_GENERAL,
a1f6afec 2735 .group = FIO_OPT_G_PROCESS,
214e1eca 2736 },
b3d62a75
JA
2737 {
2738 .name = "new_group",
e8b0e958 2739 .lname = "New group",
b3d62a75
JA
2740 .type = FIO_OPT_STR_SET,
2741 .off1 = td_var_offset(new_group),
2742 .help = "Mark the start of a new group (for reporting)",
e8b0e958 2743 .category = FIO_OPT_C_GENERAL,
a1f6afec 2744 .group = FIO_OPT_G_PROCESS,
b3d62a75 2745 },
214e1eca
JA
2746 {
2747 .name = "thread",
e8b0e958 2748 .lname = "Thread",
214e1eca
JA
2749 .type = FIO_OPT_STR_SET,
2750 .off1 = td_var_offset(use_thread),
20eb06bd 2751 .help = "Use threads instead of processes",
e8b0e958 2752 .category = FIO_OPT_C_GENERAL,
a1f6afec 2753 .group = FIO_OPT_G_PROCESS,
214e1eca
JA
2754 },
2755 {
2756 .name = "write_bw_log",
e8b0e958 2757 .lname = "Write bandwidth log",
203160d5
JA
2758 .type = FIO_OPT_STR_STORE,
2759 .off1 = td_var_offset(bw_log_file),
214e1eca 2760 .help = "Write log of bandwidth during run",
e8b0e958
JA
2761 .category = FIO_OPT_C_LOG,
2762 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2763 },
2764 {
2765 .name = "write_lat_log",
e8b0e958 2766 .lname = "Write latency log",
203160d5
JA
2767 .type = FIO_OPT_STR_STORE,
2768 .off1 = td_var_offset(lat_log_file),
214e1eca 2769 .help = "Write log of latency during run",
e8b0e958
JA
2770 .category = FIO_OPT_C_LOG,
2771 .group = FIO_OPT_G_INVALID,
214e1eca 2772 },
c8eeb9df
JA
2773 {
2774 .name = "write_iops_log",
e8b0e958 2775 .lname = "Write IOPS log",
c8eeb9df 2776 .type = FIO_OPT_STR,
203160d5 2777 .off1 = td_var_offset(iops_log_file),
c8eeb9df 2778 .help = "Write log of IOPS during run",
e8b0e958
JA
2779 .category = FIO_OPT_C_LOG,
2780 .group = FIO_OPT_G_INVALID,
c8eeb9df 2781 },
b8bc8cba
JA
2782 {
2783 .name = "log_avg_msec",
e8b0e958 2784 .lname = "Log averaging (msec)",
b8bc8cba
JA
2785 .type = FIO_OPT_INT,
2786 .off1 = td_var_offset(log_avg_msec),
2787 .help = "Average bw/iops/lat logs over this period of time",
2788 .def = "0",
e8b0e958
JA
2789 .category = FIO_OPT_C_LOG,
2790 .group = FIO_OPT_G_INVALID,
b8bc8cba 2791 },
c504ee55
JA
2792 {
2793 .name = "bwavgtime",
2794 .lname = "Bandwidth average time",
2795 .type = FIO_OPT_INT,
2796 .off1 = td_var_offset(bw_avg_time),
2797 .help = "Time window over which to calculate bandwidth"
2798 " (msec)",
2799 .def = "500",
2800 .parent = "write_bw_log",
2801 .hide = 1,
2802 .interval = 100,
2803 .category = FIO_OPT_C_LOG,
2804 .group = FIO_OPT_G_INVALID,
2805 },
2806 {
2807 .name = "iopsavgtime",
2808 .lname = "IOPS average time",
2809 .type = FIO_OPT_INT,
2810 .off1 = td_var_offset(iops_avg_time),
2811 .help = "Time window over which to calculate IOPS (msec)",
2812 .def = "500",
2813 .parent = "write_iops_log",
2814 .hide = 1,
2815 .interval = 100,
2816 .category = FIO_OPT_C_LOG,
2817 .group = FIO_OPT_G_INVALID,
2818 },
214e1eca
JA
2819 {
2820 .name = "group_reporting",
e8b0e958
JA
2821 .lname = "Group reporting",
2822 .type = FIO_OPT_BOOL,
214e1eca
JA
2823 .off1 = td_var_offset(group_reporting),
2824 .help = "Do reporting on a per-group basis",
10860056 2825 .category = FIO_OPT_C_STAT,
e8b0e958 2826 .group = FIO_OPT_G_INVALID,
214e1eca 2827 },
e9459e5a
JA
2828 {
2829 .name = "zero_buffers",
e8b0e958 2830 .lname = "Zero I/O buffers",
e9459e5a
JA
2831 .type = FIO_OPT_STR_SET,
2832 .off1 = td_var_offset(zero_buffers),
2833 .help = "Init IO buffers to all zeroes",
e8b0e958 2834 .category = FIO_OPT_C_IO,
3ceb458f 2835 .group = FIO_OPT_G_IO_BUF,
e9459e5a 2836 },
5973cafb
JA
2837 {
2838 .name = "refill_buffers",
e8b0e958 2839 .lname = "Refill I/O buffers",
5973cafb
JA
2840 .type = FIO_OPT_STR_SET,
2841 .off1 = td_var_offset(refill_buffers),
2842 .help = "Refill IO buffers on every IO submit",
e8b0e958 2843 .category = FIO_OPT_C_IO,
3ceb458f 2844 .group = FIO_OPT_G_IO_BUF,
5973cafb 2845 },
fd68418e
JA
2846 {
2847 .name = "scramble_buffers",
e8b0e958 2848 .lname = "Scramble I/O buffers",
fd68418e
JA
2849 .type = FIO_OPT_BOOL,
2850 .off1 = td_var_offset(scramble_buffers),
2851 .help = "Slightly scramble buffers on every IO submit",
2852 .def = "1",
e8b0e958 2853 .category = FIO_OPT_C_IO,
3ceb458f 2854 .group = FIO_OPT_G_IO_BUF,
fd68418e 2855 },
9c42684e
JA
2856 {
2857 .name = "buffer_compress_percentage",
e8b0e958 2858 .lname = "Buffer compression percentage",
9c42684e
JA
2859 .type = FIO_OPT_INT,
2860 .off1 = td_var_offset(compress_percentage),
2861 .maxval = 100,
2862 .minval = 1,
2863 .help = "How compressible the buffer is (approximately)",
20eb06bd 2864 .interval = 5,
e8b0e958 2865 .category = FIO_OPT_C_IO,
3ceb458f 2866 .group = FIO_OPT_G_IO_BUF,
9c42684e 2867 },
f97a43a1
JA
2868 {
2869 .name = "buffer_compress_chunk",
e8b0e958 2870 .lname = "Buffer compression chunk size",
f97a43a1
JA
2871 .type = FIO_OPT_INT,
2872 .off1 = td_var_offset(compress_chunk),
207b18e4 2873 .parent = "buffer_compress_percentage",
d71c154c 2874 .hide = 1,
f97a43a1 2875 .help = "Size of compressible region in buffer",
20eb06bd 2876 .interval = 256,
e8b0e958 2877 .category = FIO_OPT_C_IO,
3ceb458f 2878 .group = FIO_OPT_G_IO_BUF,
f97a43a1 2879 },
83349190
YH
2880 {
2881 .name = "clat_percentiles",
e8b0e958 2882 .lname = "Completion latency percentiles",
83349190
YH
2883 .type = FIO_OPT_BOOL,
2884 .off1 = td_var_offset(clat_percentiles),
2885 .help = "Enable the reporting of completion latency percentiles",
467b35ed 2886 .def = "1",
e8b0e958
JA
2887 .category = FIO_OPT_C_STAT,
2888 .group = FIO_OPT_G_INVALID,
83349190
YH
2889 },
2890 {
2891 .name = "percentile_list",
e8b0e958 2892 .lname = "Completion latency percentile list",
83349190
YH
2893 .type = FIO_OPT_FLOAT_LIST,
2894 .off1 = td_var_offset(percentile_list),
435d195a 2895 .off2 = td_var_offset(percentile_precision),
83349190 2896 .help = "Specify a custom list of percentiles to report",
fd112d34 2897 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
2898 .maxlen = FIO_IO_U_LIST_MAX_LEN,
2899 .minfp = 0.0,
2900 .maxfp = 100.0,
e8b0e958
JA
2901 .category = FIO_OPT_C_STAT,
2902 .group = FIO_OPT_G_INVALID,
83349190
YH
2903 },
2904
0a839f30
JA
2905#ifdef FIO_HAVE_DISK_UTIL
2906 {
2907 .name = "disk_util",
e8b0e958 2908 .lname = "Disk utilization",
0a839f30
JA
2909 .type = FIO_OPT_BOOL,
2910 .off1 = td_var_offset(do_disk_util),
f66ab3c8 2911 .help = "Log disk utilization statistics",
0a839f30 2912 .def = "1",
e8b0e958
JA
2913 .category = FIO_OPT_C_STAT,
2914 .group = FIO_OPT_G_INVALID,
0a839f30
JA
2915 },
2916#endif
993bf48b
JA
2917 {
2918 .name = "gtod_reduce",
e8b0e958 2919 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
2920 .type = FIO_OPT_BOOL,
2921 .help = "Greatly reduce number of gettimeofday() calls",
2922 .cb = str_gtod_reduce_cb,
2923 .def = "0",
a4ed77fe 2924 .hide_on_set = 1,
e8b0e958
JA
2925 .category = FIO_OPT_C_STAT,
2926 .group = FIO_OPT_G_INVALID,
993bf48b 2927 },
02af0988
JA
2928 {
2929 .name = "disable_lat",
e8b0e958 2930 .lname = "Disable all latency stats",
02af0988
JA
2931 .type = FIO_OPT_BOOL,
2932 .off1 = td_var_offset(disable_lat),
2933 .help = "Disable latency numbers",
2934 .parent = "gtod_reduce",
d71c154c 2935 .hide = 1,
02af0988 2936 .def = "0",
e8b0e958
JA
2937 .category = FIO_OPT_C_STAT,
2938 .group = FIO_OPT_G_INVALID,
02af0988 2939 },
9520ebb9
JA
2940 {
2941 .name = "disable_clat",
e8b0e958 2942 .lname = "Disable completion latency stats",
9520ebb9
JA
2943 .type = FIO_OPT_BOOL,
2944 .off1 = td_var_offset(disable_clat),
2945 .help = "Disable completion latency numbers",
993bf48b 2946 .parent = "gtod_reduce",
d71c154c 2947 .hide = 1,
9520ebb9 2948 .def = "0",
e8b0e958
JA
2949 .category = FIO_OPT_C_STAT,
2950 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
2951 },
2952 {
2953 .name = "disable_slat",
e8b0e958 2954 .lname = "Disable submission latency stats",
9520ebb9
JA
2955 .type = FIO_OPT_BOOL,
2956 .off1 = td_var_offset(disable_slat),
03e20d68 2957 .help = "Disable submission latency numbers",
993bf48b 2958 .parent = "gtod_reduce",
d71c154c 2959 .hide = 1,
9520ebb9 2960 .def = "0",
e8b0e958
JA
2961 .category = FIO_OPT_C_STAT,
2962 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
2963 },
2964 {
2965 .name = "disable_bw_measurement",
e8b0e958 2966 .lname = "Disable bandwidth stats",
9520ebb9
JA
2967 .type = FIO_OPT_BOOL,
2968 .off1 = td_var_offset(disable_bw),
2969 .help = "Disable bandwidth logging",
993bf48b 2970 .parent = "gtod_reduce",
d71c154c 2971 .hide = 1,
9520ebb9 2972 .def = "0",
e8b0e958
JA
2973 .category = FIO_OPT_C_STAT,
2974 .group = FIO_OPT_G_INVALID,
9520ebb9 2975 },
be4ecfdf
JA
2976 {
2977 .name = "gtod_cpu",
e8b0e958 2978 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf
JA
2979 .type = FIO_OPT_INT,
2980 .cb = str_gtod_cpu_cb,
03e20d68 2981 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 2982 .verify = gtod_cpu_verify,
e8b0e958 2983 .category = FIO_OPT_C_GENERAL,
10860056 2984 .group = FIO_OPT_G_CLOCK,
be4ecfdf 2985 },
771e58be
JA
2986 {
2987 .name = "unified_rw_reporting",
2988 .type = FIO_OPT_BOOL,
2989 .off1 = td_var_offset(unified_rw_rep),
2990 .help = "Unify reporting across data direction",
2991 .def = "0",
90b7a96d
JA
2992 .category = FIO_OPT_C_GENERAL,
2993 .group = FIO_OPT_G_INVALID,
771e58be 2994 },
f2bba182
RR
2995 {
2996 .name = "continue_on_error",
e8b0e958 2997 .lname = "Continue on error",
06842027 2998 .type = FIO_OPT_STR,
f2bba182 2999 .off1 = td_var_offset(continue_on_error),
03e20d68 3000 .help = "Continue on non-fatal errors during IO",
06842027 3001 .def = "none",
e8b0e958 3002 .category = FIO_OPT_C_GENERAL,
bc3f552f 3003 .group = FIO_OPT_G_ERR,
06842027
SL
3004 .posval = {
3005 { .ival = "none",
3006 .oval = ERROR_TYPE_NONE,
3007 .help = "Exit when an error is encountered",
3008 },
3009 { .ival = "read",
3010 .oval = ERROR_TYPE_READ,
3011 .help = "Continue on read errors only",
3012 },
3013 { .ival = "write",
3014 .oval = ERROR_TYPE_WRITE,
3015 .help = "Continue on write errors only",
3016 },
3017 { .ival = "io",
3018 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
3019 .help = "Continue on any IO errors",
3020 },
3021 { .ival = "verify",
3022 .oval = ERROR_TYPE_VERIFY,
3023 .help = "Continue on verify errors only",
3024 },
3025 { .ival = "all",
3026 .oval = ERROR_TYPE_ANY,
3027 .help = "Continue on all io and verify errors",
3028 },
3029 { .ival = "0",
3030 .oval = ERROR_TYPE_NONE,
3031 .help = "Alias for 'none'",
3032 },
3033 { .ival = "1",
3034 .oval = ERROR_TYPE_ANY,
3035 .help = "Alias for 'all'",
3036 },
3037 },
f2bba182 3038 },
8b28bd41
DM
3039 {
3040 .name = "ignore_error",
3041 .type = FIO_OPT_STR,
3042 .cb = str_ignore_error_cb,
3043 .help = "Set a specific list of errors to ignore",
3044 .parent = "rw",
a94eb99a 3045 .category = FIO_OPT_C_GENERAL,
bc3f552f 3046 .group = FIO_OPT_G_ERR,
8b28bd41
DM
3047 },
3048 {
3049 .name = "error_dump",
3050 .type = FIO_OPT_BOOL,
3051 .off1 = td_var_offset(error_dump),
3052 .def = "0",
3053 .help = "Dump info on each error",
a94eb99a 3054 .category = FIO_OPT_C_GENERAL,
bc3f552f 3055 .group = FIO_OPT_G_ERR,
8b28bd41 3056 },
9ac8a797
JA
3057 {
3058 .name = "profile",
e8b0e958 3059 .lname = "Profile",
79d16311 3060 .type = FIO_OPT_STR_STORE,
9ac8a797 3061 .off1 = td_var_offset(profile),
9ac8a797 3062 .help = "Select a specific builtin performance test",
13fca827 3063 .category = FIO_OPT_C_PROFILE,
e8b0e958 3064 .group = FIO_OPT_G_INVALID,
9ac8a797 3065 },
a696fa2a
JA
3066 {
3067 .name = "cgroup",
e8b0e958 3068 .lname = "Cgroup",
a696fa2a
JA
3069 .type = FIO_OPT_STR_STORE,
3070 .off1 = td_var_offset(cgroup),
3071 .help = "Add job to cgroup of this name",
e8b0e958 3072 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
3073 .group = FIO_OPT_G_CGROUP,
3074 },
3075 {
3076 .name = "cgroup_nodelete",
3077 .lname = "Cgroup no-delete",
3078 .type = FIO_OPT_BOOL,
3079 .off1 = td_var_offset(cgroup_nodelete),
3080 .help = "Do not delete cgroups after job completion",
3081 .def = "0",
3082 .parent = "cgroup",
3083 .category = FIO_OPT_C_GENERAL,
3084 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
3085 },
3086 {
3087 .name = "cgroup_weight",
e8b0e958 3088 .lname = "Cgroup weight",
a696fa2a
JA
3089 .type = FIO_OPT_INT,
3090 .off1 = td_var_offset(cgroup_weight),
3091 .help = "Use given weight for cgroup",
3092 .minval = 100,
3093 .maxval = 1000,
a1f6afec 3094 .parent = "cgroup",
e8b0e958 3095 .category = FIO_OPT_C_GENERAL,
a1f6afec 3096 .group = FIO_OPT_G_CGROUP,
7de87099 3097 },
e0b0d892
JA
3098 {
3099 .name = "uid",
e8b0e958 3100 .lname = "User ID",
e0b0d892
JA
3101 .type = FIO_OPT_INT,
3102 .off1 = td_var_offset(uid),
3103 .help = "Run job with this user ID",
e8b0e958 3104 .category = FIO_OPT_C_GENERAL,
10860056 3105 .group = FIO_OPT_G_CRED,
e0b0d892
JA
3106 },
3107 {
3108 .name = "gid",
e8b0e958 3109 .lname = "Group ID",
e0b0d892
JA
3110 .type = FIO_OPT_INT,
3111 .off1 = td_var_offset(gid),
3112 .help = "Run job with this group ID",
e8b0e958 3113 .category = FIO_OPT_C_GENERAL,
10860056 3114 .group = FIO_OPT_G_CRED,
e0b0d892 3115 },
a1f6afec
JA
3116 {
3117 .name = "kb_base",
3118 .lname = "KB Base",
3119 .type = FIO_OPT_INT,
3120 .off1 = td_var_offset(kb_base),
a1f6afec
JA
3121 .prio = 1,
3122 .def = "1024",
ba9c7219
JA
3123 .posval = {
3124 { .ival = "1024",
3125 .oval = 1024,
3126 .help = "Use 1024 as the K base",
3127 },
3128 { .ival = "1000",
3129 .oval = 1000,
3130 .help = "Use 1000 as the K base",
3131 },
3132 },
a1f6afec
JA
3133 .help = "How many bytes per KB for reporting (1000 or 1024)",
3134 .category = FIO_OPT_C_GENERAL,
3135 .group = FIO_OPT_G_INVALID,
3136 },
cf3a0518
JA
3137 {
3138 .name = "unit_base",
ba9c7219 3139 .lname = "Base unit for reporting (Bits or Bytes)",
cf3a0518
JA
3140 .type = FIO_OPT_INT,
3141 .off1 = td_var_offset(unit_base),
cf3a0518 3142 .prio = 1,
71a08258
JA
3143 .posval = {
3144 { .ival = "0",
3145 .oval = 0,
3146 .help = "Auto-detect",
3147 },
3148 { .ival = "8",
3149 .oval = 8,
3150 .help = "Normal (byte based)",
3151 },
3152 { .ival = "1",
3153 .oval = 1,
3154 .help = "Bit based",
3155 },
3156 },
cf3a0518
JA
3157 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
3158 .category = FIO_OPT_C_GENERAL,
3159 .group = FIO_OPT_G_INVALID,
3160 },
3ceb458f
JA
3161 {
3162 .name = "hugepage-size",
3163 .lname = "Hugepage size",
3164 .type = FIO_OPT_INT,
3165 .off1 = td_var_offset(hugepage_size),
3166 .help = "When using hugepages, specify size of each page",
3167 .def = __fio_stringify(FIO_HUGE_PAGE),
3168 .interval = 1024 * 1024,
3169 .category = FIO_OPT_C_GENERAL,
3170 .group = FIO_OPT_G_INVALID,
3171 },
9e684a49
DE
3172 {
3173 .name = "flow_id",
e8b0e958 3174 .lname = "I/O flow ID",
9e684a49
DE
3175 .type = FIO_OPT_INT,
3176 .off1 = td_var_offset(flow_id),
3177 .help = "The flow index ID to use",
3178 .def = "0",
e8b0e958
JA
3179 .category = FIO_OPT_C_IO,
3180 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3181 },
3182 {
3183 .name = "flow",
e8b0e958 3184 .lname = "I/O flow weight",
9e684a49
DE
3185 .type = FIO_OPT_INT,
3186 .off1 = td_var_offset(flow),
3187 .help = "Weight for flow control of this job",
3188 .parent = "flow_id",
d71c154c 3189 .hide = 1,
9e684a49 3190 .def = "0",
e8b0e958
JA
3191 .category = FIO_OPT_C_IO,
3192 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3193 },
3194 {
3195 .name = "flow_watermark",
e8b0e958 3196 .lname = "I/O flow watermark",
9e684a49
DE
3197 .type = FIO_OPT_INT,
3198 .off1 = td_var_offset(flow_watermark),
3199 .help = "High watermark for flow control. This option"
3200 " should be set to the same value for all threads"
3201 " with non-zero flow.",
3202 .parent = "flow_id",
d71c154c 3203 .hide = 1,
9e684a49 3204 .def = "1024",
e8b0e958
JA
3205 .category = FIO_OPT_C_IO,
3206 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3207 },
3208 {
3209 .name = "flow_sleep",
e8b0e958 3210 .lname = "I/O flow sleep",
9e684a49
DE
3211 .type = FIO_OPT_INT,
3212 .off1 = td_var_offset(flow_sleep),
3213 .help = "How many microseconds to sleep after being held"
3214 " back by the flow control mechanism",
3215 .parent = "flow_id",
d71c154c 3216 .hide = 1,
9e684a49 3217 .def = "0",
e8b0e958
JA
3218 .category = FIO_OPT_C_IO,
3219 .group = FIO_OPT_G_IO_FLOW,
9e684a49 3220 },
214e1eca
JA
3221 {
3222 .name = NULL,
3223 },
3224};
3225
17af15d4 3226static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 3227 const char *name, int val)
9f81736c 3228{
17af15d4 3229 lopt->name = (char *) name;
de890a1e 3230 lopt->val = val;
9f81736c
JA
3231 if (o->type == FIO_OPT_STR_SET)
3232 lopt->has_arg = no_argument;
3233 else
3234 lopt->has_arg = required_argument;
3235}
3236
de890a1e
SL
3237static void options_to_lopts(struct fio_option *opts,
3238 struct option *long_options,
3239 int i, int option_type)
214e1eca 3240{
de890a1e 3241 struct fio_option *o = &opts[0];
214e1eca 3242 while (o->name) {
de890a1e 3243 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
3244 if (o->alias) {
3245 i++;
de890a1e 3246 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 3247 }
214e1eca
JA
3248
3249 i++;
3250 o++;
3251 assert(i < FIO_NR_OPTIONS);
3252 }
3253}
3254
de890a1e
SL
3255void fio_options_set_ioengine_opts(struct option *long_options,
3256 struct thread_data *td)
3257{
3258 unsigned int i;
3259
3260 i = 0;
3261 while (long_options[i].name) {
3262 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
3263 memset(&long_options[i], 0, sizeof(*long_options));
3264 break;
3265 }
3266 i++;
3267 }
3268
3269 /*
3270 * Just clear out the prior ioengine options.
3271 */
3272 if (!td || !td->eo)
3273 return;
3274
3275 options_to_lopts(td->io_ops->options, long_options, i,
3276 FIO_GETOPT_IOENGINE);
3277}
3278
3279void fio_options_dup_and_init(struct option *long_options)
3280{
3281 unsigned int i;
3282
9af4a244 3283 options_init(fio_options);
de890a1e
SL
3284
3285 i = 0;
3286 while (long_options[i].name)
3287 i++;
3288
9af4a244 3289 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
3290}
3291
74929ac2
JA
3292struct fio_keyword {
3293 const char *word;
3294 const char *desc;
3295 char *replace;
3296};
3297
3298static struct fio_keyword fio_keywords[] = {
3299 {
3300 .word = "$pagesize",
3301 .desc = "Page size in the system",
3302 },
3303 {
3304 .word = "$mb_memory",
3305 .desc = "Megabytes of memory online",
3306 },
3307 {
3308 .word = "$ncpus",
3309 .desc = "Number of CPUs online in the system",
3310 },
3311 {
3312 .word = NULL,
3313 },
3314};
3315
3316void fio_keywords_init(void)
3317{
3b2e1464 3318 unsigned long long mb_memory;
74929ac2
JA
3319 char buf[128];
3320 long l;
3321
a4cfc477 3322 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
3323 fio_keywords[0].replace = strdup(buf);
3324
8eb016d3 3325 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 3326 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
3327 fio_keywords[1].replace = strdup(buf);
3328
c00a2289 3329 l = cpus_online();
74929ac2
JA
3330 sprintf(buf, "%lu", l);
3331 fio_keywords[2].replace = strdup(buf);
3332}
3333
892a6ffc
JA
3334#define BC_APP "bc"
3335
3336static char *bc_calc(char *str)
3337{
d0c814ec 3338 char buf[128], *tmp;
892a6ffc
JA
3339 FILE *f;
3340 int ret;
3341
3342 /*
3343 * No math, just return string
3344 */
d0c814ec
SL
3345 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
3346 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
3347 return str;
3348
3349 /*
3350 * Split option from value, we only need to calculate the value
3351 */
3352 tmp = strchr(str, '=');
3353 if (!tmp)
3354 return str;
3355
3356 tmp++;
892a6ffc 3357
d0c814ec
SL
3358 /*
3359 * Prevent buffer overflows; such a case isn't reasonable anyway
3360 */
3361 if (strlen(str) >= 128 || strlen(tmp) > 100)
3362 return str;
892a6ffc
JA
3363
3364 sprintf(buf, "which %s > /dev/null", BC_APP);
3365 if (system(buf)) {
3366 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
3367 return NULL;
3368 }
3369
d0c814ec 3370 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 3371 f = popen(buf, "r");
3c3ed070 3372 if (!f)
892a6ffc 3373 return NULL;
892a6ffc 3374
d0c814ec 3375 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
3c3ed070 3376 if (ret <= 0)
892a6ffc 3377 return NULL;
892a6ffc 3378
892a6ffc 3379 pclose(f);
d0c814ec
SL
3380 buf[(tmp - str) + ret - 1] = '\0';
3381 memcpy(buf, str, tmp - str);
892a6ffc 3382 free(str);
d0c814ec
SL
3383 return strdup(buf);
3384}
3385
3386/*
3387 * Return a copy of the input string with substrings of the form ${VARNAME}
3388 * substituted with the value of the environment variable VARNAME. The
3389 * substitution always occurs, even if VARNAME is empty or the corresponding
3390 * environment variable undefined.
3391 */
3392static char *option_dup_subs(const char *opt)
3393{
3394 char out[OPT_LEN_MAX+1];
3395 char in[OPT_LEN_MAX+1];
3396 char *outptr = out;
3397 char *inptr = in;
3398 char *ch1, *ch2, *env;
3399 ssize_t nchr = OPT_LEN_MAX;
3400 size_t envlen;
3401
3402 if (strlen(opt) + 1 > OPT_LEN_MAX) {
3403 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
3404 return NULL;
3405 }
3406
3407 in[OPT_LEN_MAX] = '\0';
3408 strncpy(in, opt, OPT_LEN_MAX);
3409
3410 while (*inptr && nchr > 0) {
3411 if (inptr[0] == '$' && inptr[1] == '{') {
3412 ch2 = strchr(inptr, '}');
3413 if (ch2 && inptr+1 < ch2) {
3414 ch1 = inptr+2;
3415 inptr = ch2+1;
3416 *ch2 = '\0';
3417
3418 env = getenv(ch1);
3419 if (env) {
3420 envlen = strlen(env);
3421 if (envlen <= nchr) {
3422 memcpy(outptr, env, envlen);
3423 outptr += envlen;
3424 nchr -= envlen;
3425 }
3426 }
3427
3428 continue;
3429 }
3430 }
3431
3432 *outptr++ = *inptr++;
3433 --nchr;
3434 }
3435
3436 *outptr = '\0';
3437 return strdup(out);
892a6ffc
JA
3438}
3439
74929ac2
JA
3440/*
3441 * Look for reserved variable names and replace them with real values
3442 */
3443static char *fio_keyword_replace(char *opt)
3444{
3445 char *s;
3446 int i;
d0c814ec 3447 int docalc = 0;
74929ac2
JA
3448
3449 for (i = 0; fio_keywords[i].word != NULL; i++) {
3450 struct fio_keyword *kw = &fio_keywords[i];
3451
3452 while ((s = strstr(opt, kw->word)) != NULL) {
3453 char *new = malloc(strlen(opt) + 1);
3454 char *o_org = opt;
3455 int olen = s - opt;
3456 int len;
3457
3458 /*
3459 * Copy part of the string before the keyword and
3460 * sprintf() the replacement after it.
3461 */
3462 memcpy(new, opt, olen);
3463 len = sprintf(new + olen, "%s", kw->replace);
3464
3465 /*
3466 * If there's more in the original string, copy that
3467 * in too
3468 */
3469 opt += strlen(kw->word) + olen;
3470 if (strlen(opt))
3471 memcpy(new + olen + len, opt, opt - o_org - 1);
3472
3473 /*
3474 * replace opt and free the old opt
3475 */
3476 opt = new;
d0c814ec 3477 free(o_org);
7a958bd5 3478
d0c814ec 3479 docalc = 1;
74929ac2
JA
3480 }
3481 }
3482
d0c814ec
SL
3483 /*
3484 * Check for potential math and invoke bc, if possible
3485 */
3486 if (docalc)
3487 opt = bc_calc(opt);
3488
7a958bd5 3489 return opt;
74929ac2
JA
3490}
3491
d0c814ec
SL
3492static char **dup_and_sub_options(char **opts, int num_opts)
3493{
3494 int i;
3495 char **opts_copy = malloc(num_opts * sizeof(*opts));
3496 for (i = 0; i < num_opts; i++) {
3497 opts_copy[i] = option_dup_subs(opts[i]);
3498 if (!opts_copy[i])
3499 continue;
3500 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
3501 }
3502 return opts_copy;
3503}
3504
3b8b7135 3505int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 3506{
de890a1e 3507 int i, ret, unknown;
d0c814ec 3508 char **opts_copy;
3b8b7135 3509
9af4a244 3510 sort_options(opts, fio_options, num_opts);
d0c814ec 3511 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 3512
de890a1e
SL
3513 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
3514 struct fio_option *o;
9af4a244
JA
3515 int newret = parse_option(opts_copy[i], opts[i], fio_options,
3516 &o, td);
d0c814ec 3517
de890a1e
SL
3518 if (opts_copy[i]) {
3519 if (newret && !o) {
3520 unknown++;
3521 continue;
3522 }
d0c814ec 3523 free(opts_copy[i]);
de890a1e
SL
3524 opts_copy[i] = NULL;
3525 }
3526
3527 ret |= newret;
3528 }
3529
3530 if (unknown) {
3531 ret |= ioengine_load(td);
3532 if (td->eo) {
3533 sort_options(opts_copy, td->io_ops->options, num_opts);
3534 opts = opts_copy;
3535 }
3536 for (i = 0; i < num_opts; i++) {
3537 struct fio_option *o = NULL;
3538 int newret = 1;
3539 if (!opts_copy[i])
3540 continue;
3541
3542 if (td->eo)
3543 newret = parse_option(opts_copy[i], opts[i],
3544 td->io_ops->options, &o,
3545 td->eo);
3546
3547 ret |= newret;
3548 if (!o)
3549 log_err("Bad option <%s>\n", opts[i]);
3550
3551 free(opts_copy[i]);
3552 opts_copy[i] = NULL;
3553 }
74929ac2 3554 }
3b8b7135 3555
d0c814ec 3556 free(opts_copy);
3b8b7135 3557 return ret;
214e1eca
JA
3558}
3559
3560int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
3561{
9af4a244 3562 return parse_cmd_option(opt, val, fio_options, td);
214e1eca
JA
3563}
3564
de890a1e
SL
3565int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
3566 char *val)
3567{
3568 return parse_cmd_option(opt, val, td->io_ops->options, td);
3569}
3570
214e1eca
JA
3571void fio_fill_default_options(struct thread_data *td)
3572{
9af4a244 3573 fill_default_options(td, fio_options);
214e1eca
JA
3574}
3575
3576int fio_show_option_help(const char *opt)
3577{
9af4a244 3578 return show_cmd_help(fio_options, opt);
214e1eca 3579}
d23bb327 3580
de890a1e 3581void options_mem_dupe(void *data, struct fio_option *options)
d23bb327 3582{
de890a1e 3583 struct fio_option *o;
d23bb327 3584 char **ptr;
d23bb327 3585
de890a1e
SL
3586 for (o = &options[0]; o->name; o++) {
3587 if (o->type != FIO_OPT_STR_STORE)
d23bb327
JA
3588 continue;
3589
de890a1e 3590 ptr = td_var(data, o->off1);
7e356b2d
JA
3591 if (*ptr)
3592 *ptr = strdup(*ptr);
d23bb327
JA
3593 }
3594}
3595
de890a1e
SL
3596/*
3597 * dupe FIO_OPT_STR_STORE options
3598 */
3599void fio_options_mem_dupe(struct thread_data *td)
3600{
9af4a244 3601 options_mem_dupe(&td->o, fio_options);
1647f592
JA
3602
3603 if (td->eo && td->io_ops) {
de890a1e 3604 void *oldeo = td->eo;
1647f592 3605
de890a1e
SL
3606 td->eo = malloc(td->io_ops->option_struct_size);
3607 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
3608 options_mem_dupe(td->eo, td->io_ops->options);
3609 }
3610}
3611
d6978a32
JA
3612unsigned int fio_get_kb_base(void *data)
3613{
83ea422a 3614 struct thread_options *o = data;
d6978a32
JA
3615 unsigned int kb_base = 0;
3616
83ea422a
JA
3617 if (o)
3618 kb_base = o->kb_base;
d6978a32
JA
3619 if (!kb_base)
3620 kb_base = 1024;
3621
3622 return kb_base;
3623}
9f988e2e 3624
07b3232d 3625int add_option(struct fio_option *o)
9f988e2e 3626{
07b3232d
JA
3627 struct fio_option *__o;
3628 int opt_index = 0;
3629
9af4a244 3630 __o = fio_options;
07b3232d
JA
3631 while (__o->name) {
3632 opt_index++;
3633 __o++;
3634 }
3635
9af4a244 3636 memcpy(&fio_options[opt_index], o, sizeof(*o));
07b3232d 3637 return 0;
9f988e2e 3638}
e2de69da 3639
07b3232d 3640void invalidate_profile_options(const char *prof_name)
e2de69da 3641{
07b3232d 3642 struct fio_option *o;
e2de69da 3643
9af4a244 3644 o = fio_options;
07b3232d
JA
3645 while (o->name) {
3646 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
3647 o->type = FIO_OPT_INVALID;
3648 o->prof_name = NULL;
3649 }
3650 o++;
e2de69da
JA
3651 }
3652}
f5b6bb85
JA
3653
3654void add_opt_posval(const char *optname, const char *ival, const char *help)
3655{
3656 struct fio_option *o;
3657 unsigned int i;
3658
9af4a244 3659 o = find_option(fio_options, optname);
f5b6bb85
JA
3660 if (!o)
3661 return;
3662
3663 for (i = 0; i < PARSE_MAX_VP; i++) {
3664 if (o->posval[i].ival)
3665 continue;
3666
3667 o->posval[i].ival = ival;
3668 o->posval[i].help = help;
3669 break;
3670 }
3671}
3672
3673void del_opt_posval(const char *optname, const char *ival)
3674{
3675 struct fio_option *o;
3676 unsigned int i;
3677
9af4a244 3678 o = find_option(fio_options, optname);
f5b6bb85
JA
3679 if (!o)
3680 return;
3681
3682 for (i = 0; i < PARSE_MAX_VP; i++) {
3683 if (!o->posval[i].ival)
3684 continue;
3685 if (strcmp(o->posval[i].ival, ival))
3686 continue;
3687
3688 o->posval[i].ival = NULL;
3689 o->posval[i].help = NULL;
3690 }
3691}
7e356b2d
JA
3692
3693void fio_options_free(struct thread_data *td)
3694{
9af4a244 3695 options_free(fio_options, td);
de890a1e
SL
3696 if (td->eo && td->io_ops && td->io_ops->options) {
3697 options_free(td->io_ops->options, td->eo);
3698 free(td->eo);
3699 td->eo = NULL;
3700 }
7e356b2d 3701}
c504ee55
JA
3702
3703struct fio_option *fio_option_find(const char *name)
3704{
3705 return find_option(fio_options, name);
3706}
3707