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