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