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