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