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