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