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