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