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