allow --client to work with shared filesystem
[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 },
214e1eca
JA
2671 {
2672 .name = "exec_prerun",
e8b0e958 2673 .lname = "Pre-execute runnable",
214e1eca
JA
2674 .type = FIO_OPT_STR_STORE,
2675 .off1 = td_var_offset(exec_prerun),
2676 .help = "Execute this file prior to running job",
e8b0e958
JA
2677 .category = FIO_OPT_C_GENERAL,
2678 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2679 },
2680 {
2681 .name = "exec_postrun",
e8b0e958 2682 .lname = "Post-execute runnable",
214e1eca
JA
2683 .type = FIO_OPT_STR_STORE,
2684 .off1 = td_var_offset(exec_postrun),
2685 .help = "Execute this file after running job",
e8b0e958
JA
2686 .category = FIO_OPT_C_GENERAL,
2687 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2688 },
2689#ifdef FIO_HAVE_IOSCHED_SWITCH
2690 {
2691 .name = "ioscheduler",
e8b0e958 2692 .lname = "I/O scheduler",
214e1eca
JA
2693 .type = FIO_OPT_STR_STORE,
2694 .off1 = td_var_offset(ioscheduler),
2695 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
2696 .category = FIO_OPT_C_FILE,
2697 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2698 },
2699#endif
2700 {
2701 .name = "zonesize",
e8b0e958 2702 .lname = "Zone size",
214e1eca
JA
2703 .type = FIO_OPT_STR_VAL,
2704 .off1 = td_var_offset(zone_size),
ed335855
SN
2705 .help = "Amount of data to read per zone",
2706 .def = "0",
20eb06bd 2707 .interval = 1024 * 1024,
e8b0e958
JA
2708 .category = FIO_OPT_C_IO,
2709 .group = FIO_OPT_G_ZONE,
ed335855
SN
2710 },
2711 {
2712 .name = "zonerange",
e8b0e958 2713 .lname = "Zone range",
ed335855
SN
2714 .type = FIO_OPT_STR_VAL,
2715 .off1 = td_var_offset(zone_range),
214e1eca
JA
2716 .help = "Give size of an IO zone",
2717 .def = "0",
20eb06bd 2718 .interval = 1024 * 1024,
e8b0e958
JA
2719 .category = FIO_OPT_C_IO,
2720 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2721 },
2722 {
2723 .name = "zoneskip",
e8b0e958 2724 .lname = "Zone skip",
214e1eca
JA
2725 .type = FIO_OPT_STR_VAL,
2726 .off1 = td_var_offset(zone_skip),
2727 .help = "Space between IO zones",
2728 .def = "0",
20eb06bd 2729 .interval = 1024 * 1024,
e8b0e958
JA
2730 .category = FIO_OPT_C_IO,
2731 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2732 },
2733 {
2734 .name = "lockmem",
e8b0e958 2735 .lname = "Lock memory",
214e1eca 2736 .type = FIO_OPT_STR_VAL,
1b79a070 2737 .off1 = td_var_offset(lockmem),
81c6b6cd 2738 .help = "Lock down this amount of memory (per worker)",
214e1eca 2739 .def = "0",
20eb06bd 2740 .interval = 1024 * 1024,
e8b0e958
JA
2741 .category = FIO_OPT_C_GENERAL,
2742 .group = FIO_OPT_G_INVALID,
214e1eca 2743 },
214e1eca
JA
2744 {
2745 .name = "rwmixread",
e8b0e958 2746 .lname = "Read/write mix read",
214e1eca 2747 .type = FIO_OPT_INT,
cb499fc4 2748 .cb = str_rwmix_read_cb,
a8523a6a 2749 .off1 = td_var_offset(rwmix[DDIR_READ]),
214e1eca
JA
2750 .maxval = 100,
2751 .help = "Percentage of mixed workload that is reads",
2752 .def = "50",
20eb06bd 2753 .interval = 5,
90265353 2754 .inverse = "rwmixwrite",
e8b0e958
JA
2755 .category = FIO_OPT_C_IO,
2756 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
2757 },
2758 {
2759 .name = "rwmixwrite",
e8b0e958 2760 .lname = "Read/write mix write",
214e1eca 2761 .type = FIO_OPT_INT,
cb499fc4 2762 .cb = str_rwmix_write_cb,
a8523a6a 2763 .off1 = td_var_offset(rwmix[DDIR_WRITE]),
214e1eca
JA
2764 .maxval = 100,
2765 .help = "Percentage of mixed workload that is writes",
2766 .def = "50",
20eb06bd 2767 .interval = 5,
90265353 2768 .inverse = "rwmixread",
e8b0e958
JA
2769 .category = FIO_OPT_C_IO,
2770 .group = FIO_OPT_G_RWMIX,
214e1eca 2771 },
afdf9352
JA
2772 {
2773 .name = "rwmixcycle",
e8b0e958 2774 .lname = "Read/write mix cycle",
15ca150e 2775 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
2776 .category = FIO_OPT_C_IO,
2777 .group = FIO_OPT_G_RWMIX,
afdf9352 2778 },
214e1eca
JA
2779 {
2780 .name = "nice",
e8b0e958 2781 .lname = "Nice",
214e1eca
JA
2782 .type = FIO_OPT_INT,
2783 .off1 = td_var_offset(nice),
2784 .help = "Set job CPU nice value",
2785 .minval = -19,
2786 .maxval = 20,
2787 .def = "0",
20eb06bd 2788 .interval = 1,
e8b0e958 2789 .category = FIO_OPT_C_GENERAL,
10860056 2790 .group = FIO_OPT_G_CRED,
214e1eca
JA
2791 },
2792#ifdef FIO_HAVE_IOPRIO
2793 {
2794 .name = "prio",
e8b0e958 2795 .lname = "I/O nice priority",
214e1eca 2796 .type = FIO_OPT_INT,
28727df7 2797 .off1 = td_var_offset(ioprio),
214e1eca
JA
2798 .help = "Set job IO priority value",
2799 .minval = 0,
2800 .maxval = 7,
20eb06bd 2801 .interval = 1,
e8b0e958 2802 .category = FIO_OPT_C_GENERAL,
10860056 2803 .group = FIO_OPT_G_CRED,
214e1eca
JA
2804 },
2805 {
2806 .name = "prioclass",
e8b0e958 2807 .lname = "I/O nice priority class",
214e1eca 2808 .type = FIO_OPT_INT,
28727df7 2809 .off1 = td_var_offset(ioprio_class),
214e1eca
JA
2810 .help = "Set job IO priority class",
2811 .minval = 0,
2812 .maxval = 3,
20eb06bd 2813 .interval = 1,
e8b0e958 2814 .category = FIO_OPT_C_GENERAL,
10860056 2815 .group = FIO_OPT_G_CRED,
214e1eca
JA
2816 },
2817#endif
2818 {
2819 .name = "thinktime",
e8b0e958 2820 .lname = "Thinktime",
214e1eca
JA
2821 .type = FIO_OPT_INT,
2822 .off1 = td_var_offset(thinktime),
2823 .help = "Idle time between IO buffers (usec)",
2824 .def = "0",
88038bc7 2825 .is_time = 1,
e8b0e958 2826 .category = FIO_OPT_C_IO,
3ceb458f 2827 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2828 },
2829 {
2830 .name = "thinktime_spin",
e8b0e958 2831 .lname = "Thinktime spin",
214e1eca
JA
2832 .type = FIO_OPT_INT,
2833 .off1 = td_var_offset(thinktime_spin),
2834 .help = "Start think time by spinning this amount (usec)",
2835 .def = "0",
88038bc7 2836 .is_time = 1,
afdf9352 2837 .parent = "thinktime",
d71c154c 2838 .hide = 1,
e8b0e958 2839 .category = FIO_OPT_C_IO,
3ceb458f 2840 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2841 },
2842 {
2843 .name = "thinktime_blocks",
e8b0e958 2844 .lname = "Thinktime blocks",
214e1eca
JA
2845 .type = FIO_OPT_INT,
2846 .off1 = td_var_offset(thinktime_blocks),
2847 .help = "IO buffer period between 'thinktime'",
2848 .def = "1",
afdf9352 2849 .parent = "thinktime",
d71c154c 2850 .hide = 1,
e8b0e958 2851 .category = FIO_OPT_C_IO,
3ceb458f 2852 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2853 },
2854 {
2855 .name = "rate",
e8b0e958 2856 .lname = "I/O rate",
e01b22b8 2857 .type = FIO_OPT_INT,
6eaf09d6
SL
2858 .off1 = td_var_offset(rate[DDIR_READ]),
2859 .off2 = td_var_offset(rate[DDIR_WRITE]),
2860 .off3 = td_var_offset(rate[DDIR_TRIM]),
214e1eca 2861 .help = "Set bandwidth rate",
e8b0e958
JA
2862 .category = FIO_OPT_C_IO,
2863 .group = FIO_OPT_G_RATE,
214e1eca
JA
2864 },
2865 {
2866 .name = "ratemin",
e8b0e958 2867 .lname = "I/O min rate",
e01b22b8 2868 .type = FIO_OPT_INT,
6eaf09d6
SL
2869 .off1 = td_var_offset(ratemin[DDIR_READ]),
2870 .off2 = td_var_offset(ratemin[DDIR_WRITE]),
2871 .off3 = td_var_offset(ratemin[DDIR_TRIM]),
4e991c23 2872 .help = "Job must meet this rate or it will be shutdown",
afdf9352 2873 .parent = "rate",
d71c154c 2874 .hide = 1,
e8b0e958
JA
2875 .category = FIO_OPT_C_IO,
2876 .group = FIO_OPT_G_RATE,
4e991c23
JA
2877 },
2878 {
2879 .name = "rate_iops",
e8b0e958 2880 .lname = "I/O rate IOPS",
e01b22b8 2881 .type = FIO_OPT_INT,
6eaf09d6
SL
2882 .off1 = td_var_offset(rate_iops[DDIR_READ]),
2883 .off2 = td_var_offset(rate_iops[DDIR_WRITE]),
2884 .off3 = td_var_offset(rate_iops[DDIR_TRIM]),
4e991c23 2885 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 2886 .hide = 1,
e8b0e958
JA
2887 .category = FIO_OPT_C_IO,
2888 .group = FIO_OPT_G_RATE,
4e991c23
JA
2889 },
2890 {
2891 .name = "rate_iops_min",
e8b0e958 2892 .lname = "I/O min rate IOPS",
e01b22b8 2893 .type = FIO_OPT_INT,
6eaf09d6
SL
2894 .off1 = td_var_offset(rate_iops_min[DDIR_READ]),
2895 .off2 = td_var_offset(rate_iops_min[DDIR_WRITE]),
2896 .off3 = td_var_offset(rate_iops_min[DDIR_TRIM]),
03e20d68 2897 .help = "Job must meet this rate or it will be shut down",
afdf9352 2898 .parent = "rate_iops",
d71c154c 2899 .hide = 1,
e8b0e958
JA
2900 .category = FIO_OPT_C_IO,
2901 .group = FIO_OPT_G_RATE,
214e1eca
JA
2902 },
2903 {
2904 .name = "ratecycle",
e8b0e958 2905 .lname = "I/O rate cycle",
214e1eca
JA
2906 .type = FIO_OPT_INT,
2907 .off1 = td_var_offset(ratecycle),
2908 .help = "Window average for rate limits (msec)",
2909 .def = "1000",
afdf9352 2910 .parent = "rate",
d71c154c 2911 .hide = 1,
e8b0e958
JA
2912 .category = FIO_OPT_C_IO,
2913 .group = FIO_OPT_G_RATE,
214e1eca 2914 },
15501535
JA
2915 {
2916 .name = "max_latency",
2917 .type = FIO_OPT_INT,
2918 .off1 = td_var_offset(max_latency),
2919 .help = "Maximum tolerated IO latency (usec)",
88038bc7 2920 .is_time = 1,
1e5324e7 2921 .category = FIO_OPT_C_IO,
3e260a46
JA
2922 .group = FIO_OPT_G_LATPROF,
2923 },
2924 {
2925 .name = "latency_target",
2926 .lname = "Latency Target (usec)",
2927 .type = FIO_OPT_STR_VAL_TIME,
2928 .off1 = td_var_offset(latency_target),
2929 .help = "Ramp to max queue depth supporting this latency",
88038bc7 2930 .is_time = 1,
3e260a46
JA
2931 .category = FIO_OPT_C_IO,
2932 .group = FIO_OPT_G_LATPROF,
2933 },
2934 {
2935 .name = "latency_window",
2936 .lname = "Latency Window (usec)",
2937 .type = FIO_OPT_STR_VAL_TIME,
2938 .off1 = td_var_offset(latency_window),
2939 .help = "Time to sustain latency_target",
88038bc7 2940 .is_time = 1,
3e260a46
JA
2941 .category = FIO_OPT_C_IO,
2942 .group = FIO_OPT_G_LATPROF,
2943 },
2944 {
2945 .name = "latency_percentile",
2946 .lname = "Latency Percentile",
2947 .type = FIO_OPT_FLOAT_LIST,
2948 .off1 = td_var_offset(latency_percentile),
2949 .help = "Percentile of IOs must be below latency_target",
2950 .def = "100",
2951 .maxlen = 1,
2952 .minfp = 0.0,
2953 .maxfp = 100.0,
2954 .category = FIO_OPT_C_IO,
2955 .group = FIO_OPT_G_LATPROF,
15501535 2956 },
214e1eca
JA
2957 {
2958 .name = "invalidate",
e8b0e958 2959 .lname = "Cache invalidate",
214e1eca
JA
2960 .type = FIO_OPT_BOOL,
2961 .off1 = td_var_offset(invalidate_cache),
2962 .help = "Invalidate buffer/page cache prior to running job",
2963 .def = "1",
e8b0e958 2964 .category = FIO_OPT_C_IO,
3ceb458f 2965 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2966 },
2967 {
2968 .name = "sync",
e8b0e958 2969 .lname = "Synchronous I/O",
214e1eca
JA
2970 .type = FIO_OPT_BOOL,
2971 .off1 = td_var_offset(sync_io),
2972 .help = "Use O_SYNC for buffered writes",
2973 .def = "0",
67a1000f 2974 .parent = "buffered",
d71c154c 2975 .hide = 1,
e8b0e958 2976 .category = FIO_OPT_C_IO,
3ceb458f 2977 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2978 },
214e1eca
JA
2979 {
2980 .name = "create_serialize",
e8b0e958 2981 .lname = "Create serialize",
214e1eca
JA
2982 .type = FIO_OPT_BOOL,
2983 .off1 = td_var_offset(create_serialize),
2984 .help = "Serialize creating of job files",
2985 .def = "1",
e8b0e958
JA
2986 .category = FIO_OPT_C_FILE,
2987 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2988 },
2989 {
2990 .name = "create_fsync",
e8b0e958 2991 .lname = "Create fsync",
214e1eca
JA
2992 .type = FIO_OPT_BOOL,
2993 .off1 = td_var_offset(create_fsync),
03e20d68 2994 .help = "fsync file after creation",
214e1eca 2995 .def = "1",
e8b0e958
JA
2996 .category = FIO_OPT_C_FILE,
2997 .group = FIO_OPT_G_INVALID,
214e1eca 2998 },
814452bd
JA
2999 {
3000 .name = "create_on_open",
e8b0e958 3001 .lname = "Create on open",
814452bd
JA
3002 .type = FIO_OPT_BOOL,
3003 .off1 = td_var_offset(create_on_open),
3004 .help = "Create files when they are opened for IO",
3005 .def = "0",
e8b0e958
JA
3006 .category = FIO_OPT_C_FILE,
3007 .group = FIO_OPT_G_INVALID,
814452bd 3008 },
25460cf6
JA
3009 {
3010 .name = "create_only",
3011 .type = FIO_OPT_BOOL,
3012 .off1 = td_var_offset(create_only),
3013 .help = "Only perform file creation phase",
d17fda71 3014 .category = FIO_OPT_C_FILE,
25460cf6
JA
3015 .def = "0",
3016 },
0b9d69ec 3017 {
afad68f7 3018 .name = "pre_read",
e8b0e958 3019 .lname = "Pre-read files",
afad68f7
ZY
3020 .type = FIO_OPT_BOOL,
3021 .off1 = td_var_offset(pre_read),
03e20d68 3022 .help = "Pre-read files before starting official testing",
afad68f7 3023 .def = "0",
e8b0e958
JA
3024 .category = FIO_OPT_C_FILE,
3025 .group = FIO_OPT_G_INVALID,
afad68f7 3026 },
214e1eca
JA
3027#ifdef FIO_HAVE_CPU_AFFINITY
3028 {
3029 .name = "cpumask",
e8b0e958 3030 .lname = "CPU mask",
214e1eca
JA
3031 .type = FIO_OPT_INT,
3032 .cb = str_cpumask_cb,
a8523a6a 3033 .off1 = td_var_offset(cpumask),
214e1eca 3034 .help = "CPU affinity mask",
e8b0e958 3035 .category = FIO_OPT_C_GENERAL,
10860056 3036 .group = FIO_OPT_G_CRED,
214e1eca 3037 },
d2e268b0
JA
3038 {
3039 .name = "cpus_allowed",
e8b0e958 3040 .lname = "CPUs allowed",
d2e268b0
JA
3041 .type = FIO_OPT_STR,
3042 .cb = str_cpus_allowed_cb,
a8523a6a 3043 .off1 = td_var_offset(cpumask),
d2e268b0 3044 .help = "Set CPUs allowed",
e8b0e958 3045 .category = FIO_OPT_C_GENERAL,
10860056 3046 .group = FIO_OPT_G_CRED,
d2e268b0 3047 },
c2acfbac
JA
3048 {
3049 .name = "cpus_allowed_policy",
3050 .lname = "CPUs allowed distribution policy",
3051 .type = FIO_OPT_STR,
3052 .off1 = td_var_offset(cpus_allowed_policy),
3053 .help = "Distribution policy for cpus_allowed",
3054 .parent = "cpus_allowed",
3055 .prio = 1,
3056 .posval = {
3057 { .ival = "shared",
3058 .oval = FIO_CPUS_SHARED,
3059 .help = "Mask shared between threads",
3060 },
3061 { .ival = "split",
3062 .oval = FIO_CPUS_SPLIT,
3063 .help = "Mask split between threads",
3064 },
3065 },
3066 .category = FIO_OPT_C_GENERAL,
3067 .group = FIO_OPT_G_CRED,
3068 },
d0b937ed 3069#endif
67bf9823 3070#ifdef CONFIG_LIBNUMA
d0b937ed
YR
3071 {
3072 .name = "numa_cpu_nodes",
3073 .type = FIO_OPT_STR,
3074 .cb = str_numa_cpunodes_cb,
b2a9e649 3075 .off1 = td_var_offset(numa_cpunodes),
d0b937ed 3076 .help = "NUMA CPU nodes bind",
6be54b2d
JA
3077 .category = FIO_OPT_C_GENERAL,
3078 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
3079 },
3080 {
3081 .name = "numa_mem_policy",
3082 .type = FIO_OPT_STR,
3083 .cb = str_numa_mpol_cb,
b2a9e649 3084 .off1 = td_var_offset(numa_memnodes),
d0b937ed 3085 .help = "NUMA memory policy setup",
6be54b2d
JA
3086 .category = FIO_OPT_C_GENERAL,
3087 .group = FIO_OPT_G_INVALID,
d0b937ed 3088 },
214e1eca
JA
3089#endif
3090 {
3091 .name = "end_fsync",
e8b0e958 3092 .lname = "End fsync",
214e1eca
JA
3093 .type = FIO_OPT_BOOL,
3094 .off1 = td_var_offset(end_fsync),
3095 .help = "Include fsync at the end of job",
3096 .def = "0",
e8b0e958
JA
3097 .category = FIO_OPT_C_FILE,
3098 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3099 },
3100 {
3101 .name = "fsync_on_close",
e8b0e958 3102 .lname = "Fsync on close",
214e1eca
JA
3103 .type = FIO_OPT_BOOL,
3104 .off1 = td_var_offset(fsync_on_close),
3105 .help = "fsync files on close",
3106 .def = "0",
e8b0e958
JA
3107 .category = FIO_OPT_C_FILE,
3108 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3109 },
3110 {
3111 .name = "unlink",
e8b0e958 3112 .lname = "Unlink file",
214e1eca
JA
3113 .type = FIO_OPT_BOOL,
3114 .off1 = td_var_offset(unlink),
3115 .help = "Unlink created files after job has completed",
3116 .def = "0",
e8b0e958
JA
3117 .category = FIO_OPT_C_FILE,
3118 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3119 },
3120 {
3121 .name = "exitall",
e8b0e958 3122 .lname = "Exit-all on terminate",
214e1eca
JA
3123 .type = FIO_OPT_STR_SET,
3124 .cb = str_exitall_cb,
3125 .help = "Terminate all jobs when one exits",
e8b0e958 3126 .category = FIO_OPT_C_GENERAL,
a1f6afec 3127 .group = FIO_OPT_G_PROCESS,
214e1eca
JA
3128 },
3129 {
3130 .name = "stonewall",
e8b0e958 3131 .lname = "Wait for previous",
d392365e 3132 .alias = "wait_for_previous",
214e1eca
JA
3133 .type = FIO_OPT_STR_SET,
3134 .off1 = td_var_offset(stonewall),
3135 .help = "Insert a hard barrier between this job and previous",
e8b0e958 3136 .category = FIO_OPT_C_GENERAL,
a1f6afec 3137 .group = FIO_OPT_G_PROCESS,
214e1eca 3138 },
b3d62a75
JA
3139 {
3140 .name = "new_group",
e8b0e958 3141 .lname = "New group",
b3d62a75
JA
3142 .type = FIO_OPT_STR_SET,
3143 .off1 = td_var_offset(new_group),
3144 .help = "Mark the start of a new group (for reporting)",
e8b0e958 3145 .category = FIO_OPT_C_GENERAL,
a1f6afec 3146 .group = FIO_OPT_G_PROCESS,
b3d62a75 3147 },
214e1eca
JA
3148 {
3149 .name = "thread",
e8b0e958 3150 .lname = "Thread",
214e1eca
JA
3151 .type = FIO_OPT_STR_SET,
3152 .off1 = td_var_offset(use_thread),
20eb06bd 3153 .help = "Use threads instead of processes",
c8931876
JA
3154#ifdef CONFIG_NO_SHM
3155 .def = "1",
3156 .no_warn_def = 1,
3157#endif
e8b0e958 3158 .category = FIO_OPT_C_GENERAL,
a1f6afec 3159 .group = FIO_OPT_G_PROCESS,
214e1eca
JA
3160 },
3161 {
3162 .name = "write_bw_log",
e8b0e958 3163 .lname = "Write bandwidth log",
203160d5
JA
3164 .type = FIO_OPT_STR_STORE,
3165 .off1 = td_var_offset(bw_log_file),
214e1eca 3166 .help = "Write log of bandwidth during run",
e8b0e958
JA
3167 .category = FIO_OPT_C_LOG,
3168 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3169 },
3170 {
3171 .name = "write_lat_log",
e8b0e958 3172 .lname = "Write latency log",
203160d5
JA
3173 .type = FIO_OPT_STR_STORE,
3174 .off1 = td_var_offset(lat_log_file),
214e1eca 3175 .help = "Write log of latency during run",
e8b0e958
JA
3176 .category = FIO_OPT_C_LOG,
3177 .group = FIO_OPT_G_INVALID,
214e1eca 3178 },
c8eeb9df
JA
3179 {
3180 .name = "write_iops_log",
e8b0e958 3181 .lname = "Write IOPS log",
577c83bd 3182 .type = FIO_OPT_STR_STORE,
203160d5 3183 .off1 = td_var_offset(iops_log_file),
c8eeb9df 3184 .help = "Write log of IOPS during run",
e8b0e958
JA
3185 .category = FIO_OPT_C_LOG,
3186 .group = FIO_OPT_G_INVALID,
c8eeb9df 3187 },
b8bc8cba
JA
3188 {
3189 .name = "log_avg_msec",
e8b0e958 3190 .lname = "Log averaging (msec)",
b8bc8cba
JA
3191 .type = FIO_OPT_INT,
3192 .off1 = td_var_offset(log_avg_msec),
3193 .help = "Average bw/iops/lat logs over this period of time",
3194 .def = "0",
e8b0e958
JA
3195 .category = FIO_OPT_C_LOG,
3196 .group = FIO_OPT_G_INVALID,
b8bc8cba 3197 },
ae588852
JA
3198 {
3199 .name = "log_offset",
3200 .lname = "Log offset of IO",
3201 .type = FIO_OPT_BOOL,
3202 .off1 = td_var_offset(log_offset),
3203 .help = "Include offset of IO for each log entry",
3204 .def = "0",
3205 .category = FIO_OPT_C_LOG,
3206 .group = FIO_OPT_G_INVALID,
3207 },
aee2ab67
JA
3208#ifdef CONFIG_ZLIB
3209 {
3210 .name = "log_compression",
3211 .lname = "Log compression",
3212 .type = FIO_OPT_INT,
3213 .off1 = td_var_offset(log_gz),
3214 .help = "Log in compressed chunks of this size",
3215 .minval = 32 * 1024 * 1024ULL,
3216 .maxval = 512 * 1024 * 1024ULL,
3217 .category = FIO_OPT_C_LOG,
3218 .group = FIO_OPT_G_INVALID,
3219 },
b26317c9
JA
3220 {
3221 .name = "log_store_compressed",
3222 .lname = "Log store compressed",
3223 .type = FIO_OPT_BOOL,
3224 .off1 = td_var_offset(log_gz_store),
3225 .help = "Store logs in a compressed format",
3226 .category = FIO_OPT_C_LOG,
3227 .group = FIO_OPT_G_INVALID,
3228 },
aee2ab67 3229#endif
66347cfa
DE
3230 {
3231 .name = "block_error_percentiles",
3232 .lname = "Block error percentiles",
3233 .type = FIO_OPT_BOOL,
3234 .off1 = td_var_offset(block_error_hist),
3235 .help = "Record trim block errors and make a histogram",
3236 .def = "0",
3237 .category = FIO_OPT_C_LOG,
3238 .group = FIO_OPT_G_INVALID,
3239 },
c504ee55
JA
3240 {
3241 .name = "bwavgtime",
3242 .lname = "Bandwidth average time",
3243 .type = FIO_OPT_INT,
3244 .off1 = td_var_offset(bw_avg_time),
3245 .help = "Time window over which to calculate bandwidth"
3246 " (msec)",
3247 .def = "500",
3248 .parent = "write_bw_log",
3249 .hide = 1,
3250 .interval = 100,
3251 .category = FIO_OPT_C_LOG,
3252 .group = FIO_OPT_G_INVALID,
3253 },
3254 {
3255 .name = "iopsavgtime",
3256 .lname = "IOPS average time",
3257 .type = FIO_OPT_INT,
3258 .off1 = td_var_offset(iops_avg_time),
3259 .help = "Time window over which to calculate IOPS (msec)",
3260 .def = "500",
3261 .parent = "write_iops_log",
3262 .hide = 1,
3263 .interval = 100,
3264 .category = FIO_OPT_C_LOG,
3265 .group = FIO_OPT_G_INVALID,
3266 },
214e1eca
JA
3267 {
3268 .name = "group_reporting",
e8b0e958 3269 .lname = "Group reporting",
d2507043 3270 .type = FIO_OPT_STR_SET,
214e1eca
JA
3271 .off1 = td_var_offset(group_reporting),
3272 .help = "Do reporting on a per-group basis",
10860056 3273 .category = FIO_OPT_C_STAT,
e8b0e958 3274 .group = FIO_OPT_G_INVALID,
214e1eca 3275 },
e9459e5a
JA
3276 {
3277 .name = "zero_buffers",
e8b0e958 3278 .lname = "Zero I/O buffers",
e9459e5a
JA
3279 .type = FIO_OPT_STR_SET,
3280 .off1 = td_var_offset(zero_buffers),
3281 .help = "Init IO buffers to all zeroes",
e8b0e958 3282 .category = FIO_OPT_C_IO,
3ceb458f 3283 .group = FIO_OPT_G_IO_BUF,
e9459e5a 3284 },
5973cafb
JA
3285 {
3286 .name = "refill_buffers",
e8b0e958 3287 .lname = "Refill I/O buffers",
5973cafb
JA
3288 .type = FIO_OPT_STR_SET,
3289 .off1 = td_var_offset(refill_buffers),
3290 .help = "Refill IO buffers on every IO submit",
e8b0e958 3291 .category = FIO_OPT_C_IO,
3ceb458f 3292 .group = FIO_OPT_G_IO_BUF,
5973cafb 3293 },
fd68418e
JA
3294 {
3295 .name = "scramble_buffers",
e8b0e958 3296 .lname = "Scramble I/O buffers",
fd68418e
JA
3297 .type = FIO_OPT_BOOL,
3298 .off1 = td_var_offset(scramble_buffers),
3299 .help = "Slightly scramble buffers on every IO submit",
3300 .def = "1",
e8b0e958 3301 .category = FIO_OPT_C_IO,
3ceb458f 3302 .group = FIO_OPT_G_IO_BUF,
fd68418e 3303 },
ce35b1ec
JA
3304 {
3305 .name = "buffer_pattern",
3306 .lname = "Buffer pattern",
3307 .type = FIO_OPT_STR,
3308 .cb = str_buffer_pattern_cb,
a8523a6a 3309 .off1 = td_var_offset(buffer_pattern),
ce35b1ec
JA
3310 .help = "Fill pattern for IO buffers",
3311 .category = FIO_OPT_C_IO,
3312 .group = FIO_OPT_G_IO_BUF,
3313 },
9c42684e
JA
3314 {
3315 .name = "buffer_compress_percentage",
e8b0e958 3316 .lname = "Buffer compression percentage",
9c42684e 3317 .type = FIO_OPT_INT,
bedc9dc2 3318 .cb = str_buffer_compress_cb,
a8523a6a 3319 .off1 = td_var_offset(compress_percentage),
9c42684e 3320 .maxval = 100,
e7f5de90 3321 .minval = 0,
9c42684e 3322 .help = "How compressible the buffer is (approximately)",
20eb06bd 3323 .interval = 5,
e8b0e958 3324 .category = FIO_OPT_C_IO,
3ceb458f 3325 .group = FIO_OPT_G_IO_BUF,
9c42684e 3326 },
f97a43a1
JA
3327 {
3328 .name = "buffer_compress_chunk",
e8b0e958 3329 .lname = "Buffer compression chunk size",
f97a43a1
JA
3330 .type = FIO_OPT_INT,
3331 .off1 = td_var_offset(compress_chunk),
207b18e4 3332 .parent = "buffer_compress_percentage",
d71c154c 3333 .hide = 1,
f97a43a1 3334 .help = "Size of compressible region in buffer",
20eb06bd 3335 .interval = 256,
e8b0e958 3336 .category = FIO_OPT_C_IO,
3ceb458f 3337 .group = FIO_OPT_G_IO_BUF,
f97a43a1 3338 },
5c94b008
JA
3339 {
3340 .name = "dedupe_percentage",
3341 .lname = "Dedupe percentage",
3342 .type = FIO_OPT_INT,
3343 .cb = str_dedupe_cb,
a8523a6a 3344 .off1 = td_var_offset(dedupe_percentage),
5c94b008
JA
3345 .maxval = 100,
3346 .minval = 0,
3347 .help = "Percentage of buffers that are dedupable",
3348 .interval = 1,
3349 .category = FIO_OPT_C_IO,
3350 .group = FIO_OPT_G_IO_BUF,
3351 },
83349190
YH
3352 {
3353 .name = "clat_percentiles",
e8b0e958 3354 .lname = "Completion latency percentiles",
83349190
YH
3355 .type = FIO_OPT_BOOL,
3356 .off1 = td_var_offset(clat_percentiles),
3357 .help = "Enable the reporting of completion latency percentiles",
467b35ed 3358 .def = "1",
e8b0e958
JA
3359 .category = FIO_OPT_C_STAT,
3360 .group = FIO_OPT_G_INVALID,
83349190
YH
3361 },
3362 {
3363 .name = "percentile_list",
66347cfa 3364 .lname = "Percentile list",
83349190
YH
3365 .type = FIO_OPT_FLOAT_LIST,
3366 .off1 = td_var_offset(percentile_list),
435d195a 3367 .off2 = td_var_offset(percentile_precision),
66347cfa
DE
3368 .help = "Specify a custom list of percentiles to report for "
3369 "completion latency and block errors",
fd112d34 3370 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
3371 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3372 .minfp = 0.0,
3373 .maxfp = 100.0,
e8b0e958
JA
3374 .category = FIO_OPT_C_STAT,
3375 .group = FIO_OPT_G_INVALID,
83349190
YH
3376 },
3377
0a839f30
JA
3378#ifdef FIO_HAVE_DISK_UTIL
3379 {
3380 .name = "disk_util",
e8b0e958 3381 .lname = "Disk utilization",
0a839f30
JA
3382 .type = FIO_OPT_BOOL,
3383 .off1 = td_var_offset(do_disk_util),
f66ab3c8 3384 .help = "Log disk utilization statistics",
0a839f30 3385 .def = "1",
e8b0e958
JA
3386 .category = FIO_OPT_C_STAT,
3387 .group = FIO_OPT_G_INVALID,
0a839f30
JA
3388 },
3389#endif
993bf48b
JA
3390 {
3391 .name = "gtod_reduce",
e8b0e958 3392 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
3393 .type = FIO_OPT_BOOL,
3394 .help = "Greatly reduce number of gettimeofday() calls",
3395 .cb = str_gtod_reduce_cb,
3396 .def = "0",
a4ed77fe 3397 .hide_on_set = 1,
e8b0e958
JA
3398 .category = FIO_OPT_C_STAT,
3399 .group = FIO_OPT_G_INVALID,
993bf48b 3400 },
02af0988
JA
3401 {
3402 .name = "disable_lat",
e8b0e958 3403 .lname = "Disable all latency stats",
02af0988
JA
3404 .type = FIO_OPT_BOOL,
3405 .off1 = td_var_offset(disable_lat),
3406 .help = "Disable latency numbers",
3407 .parent = "gtod_reduce",
d71c154c 3408 .hide = 1,
02af0988 3409 .def = "0",
e8b0e958
JA
3410 .category = FIO_OPT_C_STAT,
3411 .group = FIO_OPT_G_INVALID,
02af0988 3412 },
9520ebb9
JA
3413 {
3414 .name = "disable_clat",
e8b0e958 3415 .lname = "Disable completion latency stats",
9520ebb9
JA
3416 .type = FIO_OPT_BOOL,
3417 .off1 = td_var_offset(disable_clat),
3418 .help = "Disable completion latency numbers",
993bf48b 3419 .parent = "gtod_reduce",
d71c154c 3420 .hide = 1,
9520ebb9 3421 .def = "0",
e8b0e958
JA
3422 .category = FIO_OPT_C_STAT,
3423 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3424 },
3425 {
3426 .name = "disable_slat",
e8b0e958 3427 .lname = "Disable submission latency stats",
9520ebb9
JA
3428 .type = FIO_OPT_BOOL,
3429 .off1 = td_var_offset(disable_slat),
03e20d68 3430 .help = "Disable submission latency numbers",
993bf48b 3431 .parent = "gtod_reduce",
d71c154c 3432 .hide = 1,
9520ebb9 3433 .def = "0",
e8b0e958
JA
3434 .category = FIO_OPT_C_STAT,
3435 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3436 },
3437 {
3438 .name = "disable_bw_measurement",
e8b0e958 3439 .lname = "Disable bandwidth stats",
9520ebb9
JA
3440 .type = FIO_OPT_BOOL,
3441 .off1 = td_var_offset(disable_bw),
3442 .help = "Disable bandwidth logging",
993bf48b 3443 .parent = "gtod_reduce",
d71c154c 3444 .hide = 1,
9520ebb9 3445 .def = "0",
e8b0e958
JA
3446 .category = FIO_OPT_C_STAT,
3447 .group = FIO_OPT_G_INVALID,
9520ebb9 3448 },
be4ecfdf
JA
3449 {
3450 .name = "gtod_cpu",
e8b0e958 3451 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 3452 .type = FIO_OPT_INT,
79c896a1 3453 .off1 = td_var_offset(gtod_cpu),
03e20d68 3454 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 3455 .verify = gtod_cpu_verify,
e8b0e958 3456 .category = FIO_OPT_C_GENERAL,
10860056 3457 .group = FIO_OPT_G_CLOCK,
be4ecfdf 3458 },
771e58be
JA
3459 {
3460 .name = "unified_rw_reporting",
3461 .type = FIO_OPT_BOOL,
3462 .off1 = td_var_offset(unified_rw_rep),
3463 .help = "Unify reporting across data direction",
3464 .def = "0",
90b7a96d
JA
3465 .category = FIO_OPT_C_GENERAL,
3466 .group = FIO_OPT_G_INVALID,
771e58be 3467 },
f2bba182
RR
3468 {
3469 .name = "continue_on_error",
e8b0e958 3470 .lname = "Continue on error",
06842027 3471 .type = FIO_OPT_STR,
f2bba182 3472 .off1 = td_var_offset(continue_on_error),
03e20d68 3473 .help = "Continue on non-fatal errors during IO",
06842027 3474 .def = "none",
e8b0e958 3475 .category = FIO_OPT_C_GENERAL,
bc3f552f 3476 .group = FIO_OPT_G_ERR,
06842027
SL
3477 .posval = {
3478 { .ival = "none",
3479 .oval = ERROR_TYPE_NONE,
3480 .help = "Exit when an error is encountered",
3481 },
3482 { .ival = "read",
3483 .oval = ERROR_TYPE_READ,
3484 .help = "Continue on read errors only",
3485 },
3486 { .ival = "write",
3487 .oval = ERROR_TYPE_WRITE,
3488 .help = "Continue on write errors only",
3489 },
3490 { .ival = "io",
3491 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
3492 .help = "Continue on any IO errors",
3493 },
3494 { .ival = "verify",
3495 .oval = ERROR_TYPE_VERIFY,
3496 .help = "Continue on verify errors only",
3497 },
3498 { .ival = "all",
3499 .oval = ERROR_TYPE_ANY,
3500 .help = "Continue on all io and verify errors",
3501 },
3502 { .ival = "0",
3503 .oval = ERROR_TYPE_NONE,
3504 .help = "Alias for 'none'",
3505 },
3506 { .ival = "1",
3507 .oval = ERROR_TYPE_ANY,
3508 .help = "Alias for 'all'",
3509 },
3510 },
f2bba182 3511 },
8b28bd41
DM
3512 {
3513 .name = "ignore_error",
3514 .type = FIO_OPT_STR,
3515 .cb = str_ignore_error_cb,
a8523a6a 3516 .off1 = td_var_offset(ignore_error_nr),
8b28bd41
DM
3517 .help = "Set a specific list of errors to ignore",
3518 .parent = "rw",
a94eb99a 3519 .category = FIO_OPT_C_GENERAL,
bc3f552f 3520 .group = FIO_OPT_G_ERR,
8b28bd41
DM
3521 },
3522 {
3523 .name = "error_dump",
3524 .type = FIO_OPT_BOOL,
3525 .off1 = td_var_offset(error_dump),
3526 .def = "0",
3527 .help = "Dump info on each error",
a94eb99a 3528 .category = FIO_OPT_C_GENERAL,
bc3f552f 3529 .group = FIO_OPT_G_ERR,
8b28bd41 3530 },
9ac8a797
JA
3531 {
3532 .name = "profile",
e8b0e958 3533 .lname = "Profile",
79d16311 3534 .type = FIO_OPT_STR_STORE,
9ac8a797 3535 .off1 = td_var_offset(profile),
9ac8a797 3536 .help = "Select a specific builtin performance test",
13fca827 3537 .category = FIO_OPT_C_PROFILE,
e8b0e958 3538 .group = FIO_OPT_G_INVALID,
9ac8a797 3539 },
a696fa2a
JA
3540 {
3541 .name = "cgroup",
e8b0e958 3542 .lname = "Cgroup",
a696fa2a
JA
3543 .type = FIO_OPT_STR_STORE,
3544 .off1 = td_var_offset(cgroup),
3545 .help = "Add job to cgroup of this name",
e8b0e958 3546 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
3547 .group = FIO_OPT_G_CGROUP,
3548 },
3549 {
3550 .name = "cgroup_nodelete",
3551 .lname = "Cgroup no-delete",
3552 .type = FIO_OPT_BOOL,
3553 .off1 = td_var_offset(cgroup_nodelete),
3554 .help = "Do not delete cgroups after job completion",
3555 .def = "0",
3556 .parent = "cgroup",
3557 .category = FIO_OPT_C_GENERAL,
3558 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
3559 },
3560 {
3561 .name = "cgroup_weight",
e8b0e958 3562 .lname = "Cgroup weight",
a696fa2a
JA
3563 .type = FIO_OPT_INT,
3564 .off1 = td_var_offset(cgroup_weight),
3565 .help = "Use given weight for cgroup",
3566 .minval = 100,
3567 .maxval = 1000,
a1f6afec 3568 .parent = "cgroup",
e8b0e958 3569 .category = FIO_OPT_C_GENERAL,
a1f6afec 3570 .group = FIO_OPT_G_CGROUP,
7de87099 3571 },
e0b0d892
JA
3572 {
3573 .name = "uid",
e8b0e958 3574 .lname = "User ID",
e0b0d892
JA
3575 .type = FIO_OPT_INT,
3576 .off1 = td_var_offset(uid),
3577 .help = "Run job with this user ID",
e8b0e958 3578 .category = FIO_OPT_C_GENERAL,
10860056 3579 .group = FIO_OPT_G_CRED,
e0b0d892
JA
3580 },
3581 {
3582 .name = "gid",
e8b0e958 3583 .lname = "Group ID",
e0b0d892
JA
3584 .type = FIO_OPT_INT,
3585 .off1 = td_var_offset(gid),
3586 .help = "Run job with this group ID",
e8b0e958 3587 .category = FIO_OPT_C_GENERAL,
10860056 3588 .group = FIO_OPT_G_CRED,
e0b0d892 3589 },
a1f6afec
JA
3590 {
3591 .name = "kb_base",
3592 .lname = "KB Base",
3593 .type = FIO_OPT_INT,
3594 .off1 = td_var_offset(kb_base),
a1f6afec
JA
3595 .prio = 1,
3596 .def = "1024",
ba9c7219
JA
3597 .posval = {
3598 { .ival = "1024",
3599 .oval = 1024,
3600 .help = "Use 1024 as the K base",
3601 },
3602 { .ival = "1000",
3603 .oval = 1000,
3604 .help = "Use 1000 as the K base",
3605 },
3606 },
a1f6afec
JA
3607 .help = "How many bytes per KB for reporting (1000 or 1024)",
3608 .category = FIO_OPT_C_GENERAL,
3609 .group = FIO_OPT_G_INVALID,
3610 },
cf3a0518
JA
3611 {
3612 .name = "unit_base",
ba9c7219 3613 .lname = "Base unit for reporting (Bits or Bytes)",
cf3a0518
JA
3614 .type = FIO_OPT_INT,
3615 .off1 = td_var_offset(unit_base),
cf3a0518 3616 .prio = 1,
71a08258
JA
3617 .posval = {
3618 { .ival = "0",
3619 .oval = 0,
3620 .help = "Auto-detect",
3621 },
3622 { .ival = "8",
3623 .oval = 8,
3624 .help = "Normal (byte based)",
3625 },
3626 { .ival = "1",
3627 .oval = 1,
3628 .help = "Bit based",
3629 },
3630 },
cf3a0518
JA
3631 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
3632 .category = FIO_OPT_C_GENERAL,
3633 .group = FIO_OPT_G_INVALID,
3634 },
3ceb458f
JA
3635 {
3636 .name = "hugepage-size",
3637 .lname = "Hugepage size",
3638 .type = FIO_OPT_INT,
3639 .off1 = td_var_offset(hugepage_size),
3640 .help = "When using hugepages, specify size of each page",
3641 .def = __fio_stringify(FIO_HUGE_PAGE),
3642 .interval = 1024 * 1024,
3643 .category = FIO_OPT_C_GENERAL,
3644 .group = FIO_OPT_G_INVALID,
3645 },
9e684a49
DE
3646 {
3647 .name = "flow_id",
e8b0e958 3648 .lname = "I/O flow ID",
9e684a49
DE
3649 .type = FIO_OPT_INT,
3650 .off1 = td_var_offset(flow_id),
3651 .help = "The flow index ID to use",
3652 .def = "0",
e8b0e958
JA
3653 .category = FIO_OPT_C_IO,
3654 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3655 },
3656 {
3657 .name = "flow",
e8b0e958 3658 .lname = "I/O flow weight",
9e684a49
DE
3659 .type = FIO_OPT_INT,
3660 .off1 = td_var_offset(flow),
3661 .help = "Weight for flow control of this job",
3662 .parent = "flow_id",
d71c154c 3663 .hide = 1,
9e684a49 3664 .def = "0",
e8b0e958
JA
3665 .category = FIO_OPT_C_IO,
3666 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3667 },
3668 {
3669 .name = "flow_watermark",
e8b0e958 3670 .lname = "I/O flow watermark",
9e684a49
DE
3671 .type = FIO_OPT_INT,
3672 .off1 = td_var_offset(flow_watermark),
3673 .help = "High watermark for flow control. This option"
3674 " should be set to the same value for all threads"
3675 " with non-zero flow.",
3676 .parent = "flow_id",
d71c154c 3677 .hide = 1,
9e684a49 3678 .def = "1024",
e8b0e958
JA
3679 .category = FIO_OPT_C_IO,
3680 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3681 },
3682 {
3683 .name = "flow_sleep",
e8b0e958 3684 .lname = "I/O flow sleep",
9e684a49
DE
3685 .type = FIO_OPT_INT,
3686 .off1 = td_var_offset(flow_sleep),
3687 .help = "How many microseconds to sleep after being held"
3688 " back by the flow control mechanism",
3689 .parent = "flow_id",
d71c154c 3690 .hide = 1,
9e684a49 3691 .def = "0",
e8b0e958
JA
3692 .category = FIO_OPT_C_IO,
3693 .group = FIO_OPT_G_IO_FLOW,
9e684a49 3694 },
65fa28ca
DE
3695 {
3696 .name = "skip_bad",
3697 .lname = "Skip operations against bad blocks",
3698 .type = FIO_OPT_BOOL,
3699 .off1 = td_var_offset(skip_bad),
3700 .help = "Skip operations against known bad blocks.",
3701 .hide = 1,
3702 .def = "0",
3703 .category = FIO_OPT_C_IO,
3704 .group = FIO_OPT_G_MTD,
3705 },
214e1eca
JA
3706 {
3707 .name = NULL,
3708 },
3709};
3710
17af15d4 3711static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 3712 const char *name, int val)
9f81736c 3713{
17af15d4 3714 lopt->name = (char *) name;
de890a1e 3715 lopt->val = val;
9f81736c 3716 if (o->type == FIO_OPT_STR_SET)
ff52be3d 3717 lopt->has_arg = optional_argument;
9f81736c
JA
3718 else
3719 lopt->has_arg = required_argument;
3720}
3721
de890a1e
SL
3722static void options_to_lopts(struct fio_option *opts,
3723 struct option *long_options,
3724 int i, int option_type)
214e1eca 3725{
de890a1e 3726 struct fio_option *o = &opts[0];
214e1eca 3727 while (o->name) {
de890a1e 3728 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
3729 if (o->alias) {
3730 i++;
de890a1e 3731 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 3732 }
214e1eca
JA
3733
3734 i++;
3735 o++;
3736 assert(i < FIO_NR_OPTIONS);
3737 }
3738}
3739
de890a1e
SL
3740void fio_options_set_ioengine_opts(struct option *long_options,
3741 struct thread_data *td)
3742{
3743 unsigned int i;
3744
3745 i = 0;
3746 while (long_options[i].name) {
3747 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
3748 memset(&long_options[i], 0, sizeof(*long_options));
3749 break;
3750 }
3751 i++;
3752 }
3753
3754 /*
3755 * Just clear out the prior ioengine options.
3756 */
3757 if (!td || !td->eo)
3758 return;
3759
3760 options_to_lopts(td->io_ops->options, long_options, i,
3761 FIO_GETOPT_IOENGINE);
3762}
3763
3764void fio_options_dup_and_init(struct option *long_options)
3765{
3766 unsigned int i;
3767
9af4a244 3768 options_init(fio_options);
de890a1e
SL
3769
3770 i = 0;
3771 while (long_options[i].name)
3772 i++;
3773
9af4a244 3774 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
3775}
3776
74929ac2
JA
3777struct fio_keyword {
3778 const char *word;
3779 const char *desc;
3780 char *replace;
3781};
3782
3783static struct fio_keyword fio_keywords[] = {
3784 {
3785 .word = "$pagesize",
3786 .desc = "Page size in the system",
3787 },
3788 {
3789 .word = "$mb_memory",
3790 .desc = "Megabytes of memory online",
3791 },
3792 {
3793 .word = "$ncpus",
3794 .desc = "Number of CPUs online in the system",
3795 },
3796 {
3797 .word = NULL,
3798 },
3799};
3800
3801void fio_keywords_init(void)
3802{
3b2e1464 3803 unsigned long long mb_memory;
74929ac2
JA
3804 char buf[128];
3805 long l;
3806
a4cfc477 3807 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
3808 fio_keywords[0].replace = strdup(buf);
3809
8eb016d3 3810 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 3811 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
3812 fio_keywords[1].replace = strdup(buf);
3813
c00a2289 3814 l = cpus_online();
74929ac2
JA
3815 sprintf(buf, "%lu", l);
3816 fio_keywords[2].replace = strdup(buf);
3817}
3818
892a6ffc
JA
3819#define BC_APP "bc"
3820
3821static char *bc_calc(char *str)
3822{
d0c814ec 3823 char buf[128], *tmp;
892a6ffc
JA
3824 FILE *f;
3825 int ret;
3826
3827 /*
3828 * No math, just return string
3829 */
d0c814ec
SL
3830 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
3831 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
3832 return str;
3833
3834 /*
3835 * Split option from value, we only need to calculate the value
3836 */
3837 tmp = strchr(str, '=');
3838 if (!tmp)
3839 return str;
3840
3841 tmp++;
892a6ffc 3842
d0c814ec
SL
3843 /*
3844 * Prevent buffer overflows; such a case isn't reasonable anyway
3845 */
3846 if (strlen(str) >= 128 || strlen(tmp) > 100)
3847 return str;
892a6ffc
JA
3848
3849 sprintf(buf, "which %s > /dev/null", BC_APP);
3850 if (system(buf)) {
3851 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
3852 return NULL;
3853 }
3854
d0c814ec 3855 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 3856 f = popen(buf, "r");
3c3ed070 3857 if (!f)
892a6ffc 3858 return NULL;
892a6ffc 3859
d0c814ec 3860 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
3861 if (ret <= 0) {
3862 pclose(f);
892a6ffc 3863 return NULL;
1d824f37 3864 }
892a6ffc 3865
892a6ffc 3866 pclose(f);
d0c814ec
SL
3867 buf[(tmp - str) + ret - 1] = '\0';
3868 memcpy(buf, str, tmp - str);
892a6ffc 3869 free(str);
d0c814ec
SL
3870 return strdup(buf);
3871}
3872
3873/*
3874 * Return a copy of the input string with substrings of the form ${VARNAME}
3875 * substituted with the value of the environment variable VARNAME. The
3876 * substitution always occurs, even if VARNAME is empty or the corresponding
3877 * environment variable undefined.
3878 */
3879static char *option_dup_subs(const char *opt)
3880{
3881 char out[OPT_LEN_MAX+1];
3882 char in[OPT_LEN_MAX+1];
3883 char *outptr = out;
3884 char *inptr = in;
3885 char *ch1, *ch2, *env;
3886 ssize_t nchr = OPT_LEN_MAX;
3887 size_t envlen;
3888
3889 if (strlen(opt) + 1 > OPT_LEN_MAX) {
3890 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
3891 return NULL;
3892 }
3893
3894 in[OPT_LEN_MAX] = '\0';
3895 strncpy(in, opt, OPT_LEN_MAX);
3896
3897 while (*inptr && nchr > 0) {
3898 if (inptr[0] == '$' && inptr[1] == '{') {
3899 ch2 = strchr(inptr, '}');
3900 if (ch2 && inptr+1 < ch2) {
3901 ch1 = inptr+2;
3902 inptr = ch2+1;
3903 *ch2 = '\0';
3904
3905 env = getenv(ch1);
3906 if (env) {
3907 envlen = strlen(env);
3908 if (envlen <= nchr) {
3909 memcpy(outptr, env, envlen);
3910 outptr += envlen;
3911 nchr -= envlen;
3912 }
3913 }
3914
3915 continue;
3916 }
3917 }
3918
3919 *outptr++ = *inptr++;
3920 --nchr;
3921 }
3922
3923 *outptr = '\0';
3924 return strdup(out);
892a6ffc
JA
3925}
3926
74929ac2
JA
3927/*
3928 * Look for reserved variable names and replace them with real values
3929 */
3930static char *fio_keyword_replace(char *opt)
3931{
3932 char *s;
3933 int i;
d0c814ec 3934 int docalc = 0;
74929ac2
JA
3935
3936 for (i = 0; fio_keywords[i].word != NULL; i++) {
3937 struct fio_keyword *kw = &fio_keywords[i];
3938
3939 while ((s = strstr(opt, kw->word)) != NULL) {
3940 char *new = malloc(strlen(opt) + 1);
3941 char *o_org = opt;
3942 int olen = s - opt;
3943 int len;
3944
3945 /*
3946 * Copy part of the string before the keyword and
3947 * sprintf() the replacement after it.
3948 */
3949 memcpy(new, opt, olen);
3950 len = sprintf(new + olen, "%s", kw->replace);
3951
3952 /*
3953 * If there's more in the original string, copy that
3954 * in too
3955 */
3956 opt += strlen(kw->word) + olen;
3957 if (strlen(opt))
3958 memcpy(new + olen + len, opt, opt - o_org - 1);
3959
3960 /*
3961 * replace opt and free the old opt
3962 */
3963 opt = new;
d0c814ec 3964 free(o_org);
7a958bd5 3965
d0c814ec 3966 docalc = 1;
74929ac2
JA
3967 }
3968 }
3969
d0c814ec
SL
3970 /*
3971 * Check for potential math and invoke bc, if possible
3972 */
3973 if (docalc)
3974 opt = bc_calc(opt);
3975
7a958bd5 3976 return opt;
74929ac2
JA
3977}
3978
d0c814ec
SL
3979static char **dup_and_sub_options(char **opts, int num_opts)
3980{
3981 int i;
3982 char **opts_copy = malloc(num_opts * sizeof(*opts));
3983 for (i = 0; i < num_opts; i++) {
3984 opts_copy[i] = option_dup_subs(opts[i]);
3985 if (!opts_copy[i])
3986 continue;
3987 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
3988 }
3989 return opts_copy;
3990}
3991
e15b023b 3992static void show_closest_option(const char *opt)
a2d027b9
JA
3993{
3994 int best_option, best_distance;
3995 int i, distance;
e15b023b
JA
3996 char *name;
3997
3998 if (!strlen(opt))
3999 return;
4000
4001 name = strdup(opt);
4002 i = 0;
4003 while (name[i] != '\0' && name[i] != '=')
4004 i++;
4005 name[i] = '\0';
a2d027b9
JA
4006
4007 best_option = -1;
4008 best_distance = INT_MAX;
4009 i = 0;
4010 while (fio_options[i].name) {
4011 distance = string_distance(name, fio_options[i].name);
4012 if (distance < best_distance) {
4013 best_distance = distance;
4014 best_option = i;
4015 }
4016 i++;
4017 }
4018
4019 if (best_option != -1)
4020 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
4021
4022 free(name);
a2d027b9
JA
4023}
4024
292cc475
JA
4025int fio_options_parse(struct thread_data *td, char **opts, int num_opts,
4026 int dump_cmdline)
214e1eca 4027{
de890a1e 4028 int i, ret, unknown;
d0c814ec 4029 char **opts_copy;
3b8b7135 4030
9af4a244 4031 sort_options(opts, fio_options, num_opts);
d0c814ec 4032 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 4033
de890a1e
SL
4034 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
4035 struct fio_option *o;
9af4a244 4036 int newret = parse_option(opts_copy[i], opts[i], fio_options,
292cc475 4037 &o, td, dump_cmdline);
d0c814ec 4038
a8523a6a
JA
4039 if (!newret && o)
4040 fio_option_mark_set(&td->o, o);
4041
de890a1e
SL
4042 if (opts_copy[i]) {
4043 if (newret && !o) {
4044 unknown++;
4045 continue;
4046 }
d0c814ec 4047 free(opts_copy[i]);
de890a1e
SL
4048 opts_copy[i] = NULL;
4049 }
4050
4051 ret |= newret;
4052 }
4053
4054 if (unknown) {
4055 ret |= ioengine_load(td);
4056 if (td->eo) {
4057 sort_options(opts_copy, td->io_ops->options, num_opts);
4058 opts = opts_copy;
4059 }
4060 for (i = 0; i < num_opts; i++) {
4061 struct fio_option *o = NULL;
4062 int newret = 1;
a2d027b9 4063
de890a1e
SL
4064 if (!opts_copy[i])
4065 continue;
4066
4067 if (td->eo)
4068 newret = parse_option(opts_copy[i], opts[i],
4069 td->io_ops->options, &o,
292cc475 4070 td->eo, dump_cmdline);
de890a1e
SL
4071
4072 ret |= newret;
a2d027b9 4073 if (!o) {
de890a1e 4074 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
4075 show_closest_option(opts[i]);
4076 }
de890a1e
SL
4077 free(opts_copy[i]);
4078 opts_copy[i] = NULL;
4079 }
74929ac2 4080 }
3b8b7135 4081
d0c814ec 4082 free(opts_copy);
3b8b7135 4083 return ret;
214e1eca
JA
4084}
4085
4086int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
4087{
a8523a6a
JA
4088 int ret;
4089
4090 ret = parse_cmd_option(opt, val, fio_options, td);
4091 if (!ret) {
4092 struct fio_option *o;
4093
4094 o = find_option(fio_options, opt);
4095 if (o)
4096 fio_option_mark_set(&td->o, o);
4097 }
4098
4099 return ret;
214e1eca
JA
4100}
4101
de890a1e
SL
4102int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
4103 char *val)
4104{
8a96c80e 4105 return parse_cmd_option(opt, val, td->io_ops->options, td->eo);
de890a1e
SL
4106}
4107
214e1eca
JA
4108void fio_fill_default_options(struct thread_data *td)
4109{
cb1402d6 4110 td->o.magic = OPT_MAGIC;
9af4a244 4111 fill_default_options(td, fio_options);
214e1eca
JA
4112}
4113
4114int fio_show_option_help(const char *opt)
4115{
9af4a244 4116 return show_cmd_help(fio_options, opt);
214e1eca 4117}
d23bb327 4118
de890a1e 4119void options_mem_dupe(void *data, struct fio_option *options)
d23bb327 4120{
de890a1e 4121 struct fio_option *o;
d23bb327 4122 char **ptr;
d23bb327 4123
de890a1e
SL
4124 for (o = &options[0]; o->name; o++) {
4125 if (o->type != FIO_OPT_STR_STORE)
d23bb327
JA
4126 continue;
4127
f0fdbcaf 4128 ptr = td_var(data, o, o->off1);
7e356b2d
JA
4129 if (*ptr)
4130 *ptr = strdup(*ptr);
d23bb327
JA
4131 }
4132}
4133
de890a1e
SL
4134/*
4135 * dupe FIO_OPT_STR_STORE options
4136 */
4137void fio_options_mem_dupe(struct thread_data *td)
4138{
9af4a244 4139 options_mem_dupe(&td->o, fio_options);
1647f592
JA
4140
4141 if (td->eo && td->io_ops) {
de890a1e 4142 void *oldeo = td->eo;
1647f592 4143
de890a1e
SL
4144 td->eo = malloc(td->io_ops->option_struct_size);
4145 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
4146 options_mem_dupe(td->eo, td->io_ops->options);
4147 }
4148}
4149
d6978a32
JA
4150unsigned int fio_get_kb_base(void *data)
4151{
83ea422a 4152 struct thread_options *o = data;
d6978a32
JA
4153 unsigned int kb_base = 0;
4154
cb1402d6
JA
4155 /*
4156 * This is a hack... For private options, *data is not holding
4157 * a pointer to the thread_options, but to private data. This means
4158 * we can't safely dereference it, but magic is first so mem wise
4159 * it is valid. But this also means that if the job first sets
4160 * kb_base and expects that to be honored by private options,
4161 * it will be disappointed. We will return the global default
4162 * for this.
4163 */
4164 if (o && o->magic == OPT_MAGIC)
83ea422a 4165 kb_base = o->kb_base;
d6978a32
JA
4166 if (!kb_base)
4167 kb_base = 1024;
4168
4169 return kb_base;
4170}
9f988e2e 4171
07b3232d 4172int add_option(struct fio_option *o)
9f988e2e 4173{
07b3232d
JA
4174 struct fio_option *__o;
4175 int opt_index = 0;
4176
9af4a244 4177 __o = fio_options;
07b3232d
JA
4178 while (__o->name) {
4179 opt_index++;
4180 __o++;
4181 }
4182
7b504edd
JA
4183 if (opt_index + 1 == FIO_MAX_OPTS) {
4184 log_err("fio: FIO_MAX_OPTS is too small\n");
4185 return 1;
4186 }
4187
9af4a244 4188 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 4189 fio_options[opt_index + 1].name = NULL;
07b3232d 4190 return 0;
9f988e2e 4191}
e2de69da 4192
07b3232d 4193void invalidate_profile_options(const char *prof_name)
e2de69da 4194{
07b3232d 4195 struct fio_option *o;
e2de69da 4196
9af4a244 4197 o = fio_options;
07b3232d
JA
4198 while (o->name) {
4199 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
4200 o->type = FIO_OPT_INVALID;
4201 o->prof_name = NULL;
4202 }
4203 o++;
e2de69da
JA
4204 }
4205}
f5b6bb85
JA
4206
4207void add_opt_posval(const char *optname, const char *ival, const char *help)
4208{
4209 struct fio_option *o;
4210 unsigned int i;
4211
9af4a244 4212 o = find_option(fio_options, optname);
f5b6bb85
JA
4213 if (!o)
4214 return;
4215
4216 for (i = 0; i < PARSE_MAX_VP; i++) {
4217 if (o->posval[i].ival)
4218 continue;
4219
4220 o->posval[i].ival = ival;
4221 o->posval[i].help = help;
4222 break;
4223 }
4224}
4225
4226void del_opt_posval(const char *optname, const char *ival)
4227{
4228 struct fio_option *o;
4229 unsigned int i;
4230
9af4a244 4231 o = find_option(fio_options, optname);
f5b6bb85
JA
4232 if (!o)
4233 return;
4234
4235 for (i = 0; i < PARSE_MAX_VP; i++) {
4236 if (!o->posval[i].ival)
4237 continue;
4238 if (strcmp(o->posval[i].ival, ival))
4239 continue;
4240
4241 o->posval[i].ival = NULL;
4242 o->posval[i].help = NULL;
4243 }
4244}
7e356b2d
JA
4245
4246void fio_options_free(struct thread_data *td)
4247{
9af4a244 4248 options_free(fio_options, td);
de890a1e
SL
4249 if (td->eo && td->io_ops && td->io_ops->options) {
4250 options_free(td->io_ops->options, td->eo);
4251 free(td->eo);
4252 td->eo = NULL;
4253 }
7e356b2d 4254}
c504ee55
JA
4255
4256struct fio_option *fio_option_find(const char *name)
4257{
4258 return find_option(fio_options, name);
4259}
4260
f0e7f45a
JA
4261static struct fio_option *find_next_opt(struct thread_options *o,
4262 struct fio_option *from,
4263 unsigned int off1)
a8523a6a 4264{
f0e7f45a 4265 struct fio_option *opt;
a8523a6a 4266
f0e7f45a
JA
4267 if (!from)
4268 from = &fio_options[0];
4269 else
4270 from++;
4271
4272 opt = NULL;
4273 do {
4274 if (off1 == from->off1) {
4275 opt = from;
a8523a6a
JA
4276 break;
4277 }
f0e7f45a
JA
4278 from++;
4279 } while (from->name);
a8523a6a 4280
f0e7f45a
JA
4281 return opt;
4282}
4283
4284static int opt_is_set(struct thread_options *o, struct fio_option *opt)
4285{
4286 unsigned int opt_off, index, offset;
a8523a6a
JA
4287
4288 opt_off = opt - &fio_options[0];
4289 index = opt_off / (8 * sizeof(uint64_t));
4290 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
4291 return (o->set_options[index] & (1UL << offset)) != 0;
4292}
4293
f0e7f45a
JA
4294int __fio_option_is_set(struct thread_options *o, unsigned int off1)
4295{
4296 struct fio_option *opt, *next;
4297
4298 next = NULL;
4299 while ((opt = find_next_opt(o, next, off1)) != NULL) {
4300 if (opt_is_set(o, opt))
4301 return 1;
4302
4303 next = opt;
4304 }
4305
4306 return 0;
4307}
4308
a8523a6a
JA
4309void fio_option_mark_set(struct thread_options *o, struct fio_option *opt)
4310{
4311 unsigned int opt_off, index, offset;
4312
4313 opt_off = opt - &fio_options[0];
4314 index = opt_off / (8 * sizeof(uint64_t));
4315 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
4316 o->set_options[index] |= 1UL << offset;
4317}