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