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