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