verify: increase state file name and log error on failure
[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 },
5c4ef02e
JA
1571#endif
1572#ifdef CONFIG_PMEMBLK
1573 { .ival = "pmemblk",
1574 .help = "NVML libpmemblk based IO engine",
1575 },
1576
1b10477b 1577#endif
214e1eca
JA
1578 { .ival = "external",
1579 .help = "Load external engine (append name)",
1580 },
1581 },
1582 },
1583 {
1584 .name = "iodepth",
e8b0e958 1585 .lname = "IO Depth",
214e1eca
JA
1586 .type = FIO_OPT_INT,
1587 .off1 = td_var_offset(iodepth),
03e20d68 1588 .help = "Number of IO buffers to keep in flight",
757aff4f 1589 .minval = 1,
20eb06bd 1590 .interval = 1,
214e1eca 1591 .def = "1",
e8b0e958 1592 .category = FIO_OPT_C_IO,
0626037e 1593 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1594 },
1595 {
1596 .name = "iodepth_batch",
e8b0e958 1597 .lname = "IO Depth batch",
4950421a 1598 .alias = "iodepth_batch_submit",
214e1eca
JA
1599 .type = FIO_OPT_INT,
1600 .off1 = td_var_offset(iodepth_batch),
d65db441 1601 .help = "Number of IO buffers to submit in one go",
afdf9352 1602 .parent = "iodepth",
d71c154c 1603 .hide = 1,
a2e6f8ac 1604 .minval = 1,
20eb06bd 1605 .interval = 1,
a2e6f8ac 1606 .def = "1",
e8b0e958 1607 .category = FIO_OPT_C_IO,
0626037e 1608 .group = FIO_OPT_G_IO_BASIC,
4950421a
JA
1609 },
1610 {
82407585
RP
1611 .name = "iodepth_batch_complete_min",
1612 .lname = "Min IO depth batch complete",
1613 .alias = "iodepth_batch_complete",
4950421a 1614 .type = FIO_OPT_INT,
82407585
RP
1615 .off1 = td_var_offset(iodepth_batch_complete_min),
1616 .help = "Min number of IO buffers to retrieve in one go",
4950421a 1617 .parent = "iodepth",
d71c154c 1618 .hide = 1,
4950421a 1619 .minval = 0,
20eb06bd 1620 .interval = 1,
4950421a 1621 .def = "1",
e8b0e958 1622 .category = FIO_OPT_C_IO,
0626037e 1623 .group = FIO_OPT_G_IO_BASIC,
214e1eca 1624 },
82407585
RP
1625 {
1626 .name = "iodepth_batch_complete_max",
1627 .lname = "Max IO depth batch complete",
1628 .type = FIO_OPT_INT,
1629 .off1 = td_var_offset(iodepth_batch_complete_max),
1630 .help = "Max number of IO buffers to retrieve in one go",
1631 .parent = "iodepth",
1632 .hide = 1,
1633 .minval = 0,
1634 .interval = 1,
1635 .category = FIO_OPT_C_IO,
1636 .group = FIO_OPT_G_IO_BASIC,
1637 },
214e1eca
JA
1638 {
1639 .name = "iodepth_low",
e8b0e958 1640 .lname = "IO Depth batch low",
214e1eca
JA
1641 .type = FIO_OPT_INT,
1642 .off1 = td_var_offset(iodepth_low),
1643 .help = "Low water mark for queuing depth",
afdf9352 1644 .parent = "iodepth",
d71c154c 1645 .hide = 1,
20eb06bd 1646 .interval = 1,
e8b0e958 1647 .category = FIO_OPT_C_IO,
0626037e 1648 .group = FIO_OPT_G_IO_BASIC,
214e1eca 1649 },
a9da8ab2
JA
1650 {
1651 .name = "io_submit_mode",
1652 .lname = "IO submit mode",
1653 .type = FIO_OPT_STR,
1654 .off1 = td_var_offset(io_submit_mode),
1655 .help = "How IO submissions and completions are done",
1656 .def = "inline",
1657 .category = FIO_OPT_C_IO,
1658 .group = FIO_OPT_G_IO_BASIC,
1659 .posval = {
1660 { .ival = "inline",
1661 .oval = IO_MODE_INLINE,
1662 .help = "Submit and complete IO inline",
1663 },
1664 { .ival = "offload",
1665 .oval = IO_MODE_OFFLOAD,
1666 .help = "Offload submit and complete to threads",
1667 },
1668 },
1669 },
214e1eca
JA
1670 {
1671 .name = "size",
e8b0e958 1672 .lname = "Size",
214e1eca 1673 .type = FIO_OPT_STR_VAL,
7bb59102 1674 .cb = str_size_cb,
a8523a6a 1675 .off1 = td_var_offset(size),
214e1eca 1676 .help = "Total size of device or files",
20eb06bd 1677 .interval = 1024 * 1024,
e8b0e958
JA
1678 .category = FIO_OPT_C_IO,
1679 .group = FIO_OPT_G_INVALID,
214e1eca 1680 },
77731b29 1681 {
a4d3b4db
JA
1682 .name = "io_size",
1683 .alias = "io_limit",
1684 .lname = "IO Size",
77731b29
JA
1685 .type = FIO_OPT_STR_VAL,
1686 .off1 = td_var_offset(io_limit),
1687 .interval = 1024 * 1024,
1688 .category = FIO_OPT_C_IO,
1689 .group = FIO_OPT_G_INVALID,
1690 },
aa31f1f1
SL
1691 {
1692 .name = "fill_device",
e8b0e958 1693 .lname = "Fill device",
74586c1e 1694 .alias = "fill_fs",
aa31f1f1
SL
1695 .type = FIO_OPT_BOOL,
1696 .off1 = td_var_offset(fill_device),
1697 .help = "Write until an ENOSPC error occurs",
1698 .def = "0",
e8b0e958
JA
1699 .category = FIO_OPT_C_FILE,
1700 .group = FIO_OPT_G_INVALID,
aa31f1f1 1701 },
214e1eca
JA
1702 {
1703 .name = "filesize",
e8b0e958 1704 .lname = "File size",
214e1eca
JA
1705 .type = FIO_OPT_STR_VAL,
1706 .off1 = td_var_offset(file_size_low),
1707 .off2 = td_var_offset(file_size_high),
c3edbdba 1708 .minval = 1,
214e1eca 1709 .help = "Size of individual files",
20eb06bd 1710 .interval = 1024 * 1024,
e8b0e958
JA
1711 .category = FIO_OPT_C_FILE,
1712 .group = FIO_OPT_G_INVALID,
214e1eca 1713 },
bedc9dc2
JA
1714 {
1715 .name = "file_append",
1716 .lname = "File append",
1717 .type = FIO_OPT_BOOL,
1718 .off1 = td_var_offset(file_append),
1719 .help = "IO will start at the end of the file(s)",
1720 .def = "0",
1721 .category = FIO_OPT_C_FILE,
1722 .group = FIO_OPT_G_INVALID,
1723 },
67a1000f
JA
1724 {
1725 .name = "offset",
e8b0e958 1726 .lname = "IO offset",
67a1000f
JA
1727 .alias = "fileoffset",
1728 .type = FIO_OPT_STR_VAL,
1729 .off1 = td_var_offset(start_offset),
1730 .help = "Start IO from this offset",
1731 .def = "0",
20eb06bd 1732 .interval = 1024 * 1024,
e8b0e958
JA
1733 .category = FIO_OPT_C_IO,
1734 .group = FIO_OPT_G_INVALID,
67a1000f 1735 },
2d7cd868
JA
1736 {
1737 .name = "offset_increment",
e8b0e958 1738 .lname = "IO offset increment",
2d7cd868
JA
1739 .type = FIO_OPT_STR_VAL,
1740 .off1 = td_var_offset(offset_increment),
1741 .help = "What is the increment from one offset to the next",
1742 .parent = "offset",
d71c154c 1743 .hide = 1,
2d7cd868 1744 .def = "0",
20eb06bd 1745 .interval = 1024 * 1024,
e8b0e958
JA
1746 .category = FIO_OPT_C_IO,
1747 .group = FIO_OPT_G_INVALID,
2d7cd868 1748 },
ddf24e42
JA
1749 {
1750 .name = "number_ios",
1751 .lname = "Number of IOs to perform",
1752 .type = FIO_OPT_STR_VAL,
1753 .off1 = td_var_offset(number_ios),
be3fec7d 1754 .help = "Force job completion after this number of IOs",
ddf24e42
JA
1755 .def = "0",
1756 .category = FIO_OPT_C_IO,
1757 .group = FIO_OPT_G_INVALID,
1758 },
214e1eca
JA
1759 {
1760 .name = "bs",
e8b0e958 1761 .lname = "Block size",
d3aad8f2 1762 .alias = "blocksize",
e01b22b8 1763 .type = FIO_OPT_INT,
214e1eca
JA
1764 .off1 = td_var_offset(bs[DDIR_READ]),
1765 .off2 = td_var_offset(bs[DDIR_WRITE]),
6eaf09d6 1766 .off3 = td_var_offset(bs[DDIR_TRIM]),
c3edbdba 1767 .minval = 1,
214e1eca
JA
1768 .help = "Block size unit",
1769 .def = "4k",
67a1000f 1770 .parent = "rw",
d71c154c 1771 .hide = 1,
20eb06bd 1772 .interval = 512,
e8b0e958
JA
1773 .category = FIO_OPT_C_IO,
1774 .group = FIO_OPT_G_INVALID,
214e1eca 1775 },
2b7a01d0
JA
1776 {
1777 .name = "ba",
e8b0e958 1778 .lname = "Block size align",
2b7a01d0 1779 .alias = "blockalign",
e01b22b8 1780 .type = FIO_OPT_INT,
2b7a01d0
JA
1781 .off1 = td_var_offset(ba[DDIR_READ]),
1782 .off2 = td_var_offset(ba[DDIR_WRITE]),
6eaf09d6 1783 .off3 = td_var_offset(ba[DDIR_TRIM]),
2b7a01d0
JA
1784 .minval = 1,
1785 .help = "IO block offset alignment",
1786 .parent = "rw",
d71c154c 1787 .hide = 1,
20eb06bd 1788 .interval = 512,
e8b0e958
JA
1789 .category = FIO_OPT_C_IO,
1790 .group = FIO_OPT_G_INVALID,
2b7a01d0 1791 },
214e1eca
JA
1792 {
1793 .name = "bsrange",
e8b0e958 1794 .lname = "Block size range",
d3aad8f2 1795 .alias = "blocksize_range",
214e1eca
JA
1796 .type = FIO_OPT_RANGE,
1797 .off1 = td_var_offset(min_bs[DDIR_READ]),
1798 .off2 = td_var_offset(max_bs[DDIR_READ]),
1799 .off3 = td_var_offset(min_bs[DDIR_WRITE]),
1800 .off4 = td_var_offset(max_bs[DDIR_WRITE]),
6eaf09d6
SL
1801 .off5 = td_var_offset(min_bs[DDIR_TRIM]),
1802 .off6 = td_var_offset(max_bs[DDIR_TRIM]),
c3edbdba 1803 .minval = 1,
214e1eca 1804 .help = "Set block size range (in more detail than bs)",
67a1000f 1805 .parent = "rw",
d71c154c 1806 .hide = 1,
20eb06bd 1807 .interval = 4096,
e8b0e958
JA
1808 .category = FIO_OPT_C_IO,
1809 .group = FIO_OPT_G_INVALID,
214e1eca 1810 },
564ca972
JA
1811 {
1812 .name = "bssplit",
e8b0e958 1813 .lname = "Block size split",
564ca972
JA
1814 .type = FIO_OPT_STR,
1815 .cb = str_bssplit_cb,
a8523a6a 1816 .off1 = td_var_offset(bssplit),
564ca972
JA
1817 .help = "Set a specific mix of block sizes",
1818 .parent = "rw",
d71c154c 1819 .hide = 1,
e8b0e958
JA
1820 .category = FIO_OPT_C_IO,
1821 .group = FIO_OPT_G_INVALID,
564ca972 1822 },
214e1eca
JA
1823 {
1824 .name = "bs_unaligned",
e8b0e958 1825 .lname = "Block size unaligned",
d3aad8f2 1826 .alias = "blocksize_unaligned",
214e1eca
JA
1827 .type = FIO_OPT_STR_SET,
1828 .off1 = td_var_offset(bs_unaligned),
1829 .help = "Don't sector align IO buffer sizes",
67a1000f 1830 .parent = "rw",
d71c154c 1831 .hide = 1,
e8b0e958
JA
1832 .category = FIO_OPT_C_IO,
1833 .group = FIO_OPT_G_INVALID,
214e1eca 1834 },
6aca9b3d
JA
1835 {
1836 .name = "bs_is_seq_rand",
1837 .lname = "Block size division is seq/random (not read/write)",
1838 .type = FIO_OPT_BOOL,
1839 .off1 = td_var_offset(bs_is_seq_rand),
86d59660 1840 .help = "Consider any blocksize setting to be sequential,random",
6aca9b3d
JA
1841 .def = "0",
1842 .parent = "blocksize",
1843 .category = FIO_OPT_C_IO,
1844 .group = FIO_OPT_G_INVALID,
1845 },
214e1eca
JA
1846 {
1847 .name = "randrepeat",
e8b0e958 1848 .lname = "Random repeatable",
214e1eca
JA
1849 .type = FIO_OPT_BOOL,
1850 .off1 = td_var_offset(rand_repeatable),
1851 .help = "Use repeatable random IO pattern",
1852 .def = "1",
67a1000f 1853 .parent = "rw",
d71c154c 1854 .hide = 1,
e8b0e958 1855 .category = FIO_OPT_C_IO,
3ceb458f 1856 .group = FIO_OPT_G_RANDOM,
214e1eca 1857 },
04778baf
JA
1858 {
1859 .name = "randseed",
1860 .lname = "The random generator seed",
363cffa7 1861 .type = FIO_OPT_STR_VAL,
04778baf
JA
1862 .off1 = td_var_offset(rand_seed),
1863 .help = "Set the random generator seed value",
40fe5e7b 1864 .def = "0x89",
04778baf
JA
1865 .parent = "rw",
1866 .category = FIO_OPT_C_IO,
1867 .group = FIO_OPT_G_RANDOM,
1868 },
2615cc4b
JA
1869 {
1870 .name = "use_os_rand",
e8b0e958 1871 .lname = "Use OS random",
54a21917
JA
1872 .type = FIO_OPT_DEPRECATED,
1873 .off1 = td_var_offset(dep_use_os_rand),
e8b0e958 1874 .category = FIO_OPT_C_IO,
3ceb458f 1875 .group = FIO_OPT_G_RANDOM,
2615cc4b 1876 },
214e1eca
JA
1877 {
1878 .name = "norandommap",
e8b0e958 1879 .lname = "No randommap",
214e1eca
JA
1880 .type = FIO_OPT_STR_SET,
1881 .off1 = td_var_offset(norandommap),
1882 .help = "Accept potential duplicate random blocks",
67a1000f 1883 .parent = "rw",
d71c154c 1884 .hide = 1,
b2452a43 1885 .hide_on_set = 1,
e8b0e958 1886 .category = FIO_OPT_C_IO,
3ceb458f 1887 .group = FIO_OPT_G_RANDOM,
214e1eca 1888 },
2b386d25
JA
1889 {
1890 .name = "softrandommap",
e8b0e958 1891 .lname = "Soft randommap",
2b386d25
JA
1892 .type = FIO_OPT_BOOL,
1893 .off1 = td_var_offset(softrandommap),
f66ab3c8 1894 .help = "Set norandommap if randommap allocation fails",
2b386d25 1895 .parent = "norandommap",
d71c154c 1896 .hide = 1,
2b386d25 1897 .def = "0",
e8b0e958 1898 .category = FIO_OPT_C_IO,
3ceb458f 1899 .group = FIO_OPT_G_RANDOM,
2b386d25 1900 },
8055e41d
JA
1901 {
1902 .name = "random_generator",
1903 .type = FIO_OPT_STR,
1904 .off1 = td_var_offset(random_generator),
1905 .help = "Type of random number generator to use",
1906 .def = "tausworthe",
1907 .posval = {
1908 { .ival = "tausworthe",
1909 .oval = FIO_RAND_GEN_TAUSWORTHE,
1910 .help = "Strong Tausworthe generator",
1911 },
1912 { .ival = "lfsr",
1913 .oval = FIO_RAND_GEN_LFSR,
1914 .help = "Variable length LFSR",
1915 },
c3546b53
JA
1916 {
1917 .ival = "tausworthe64",
1918 .oval = FIO_RAND_GEN_TAUSWORTHE64,
1919 .help = "64-bit Tausworthe variant",
1920 },
8055e41d 1921 },
48107598
JA
1922 .category = FIO_OPT_C_IO,
1923 .group = FIO_OPT_G_RANDOM,
8055e41d 1924 },
e25839d4
JA
1925 {
1926 .name = "random_distribution",
1927 .type = FIO_OPT_STR,
1928 .off1 = td_var_offset(random_distribution),
1929 .cb = str_random_distribution_cb,
1930 .help = "Random offset distribution generator",
1931 .def = "random",
1932 .posval = {
1933 { .ival = "random",
1934 .oval = FIO_RAND_DIST_RANDOM,
1935 .help = "Completely random",
1936 },
1937 { .ival = "zipf",
1938 .oval = FIO_RAND_DIST_ZIPF,
1939 .help = "Zipf distribution",
1940 },
925fee33
JA
1941 { .ival = "pareto",
1942 .oval = FIO_RAND_DIST_PARETO,
1943 .help = "Pareto distribution",
1944 },
56d9fa4b
JA
1945 { .ival = "normal",
1946 .oval = FIO_RAND_DIST_GAUSS,
1947 .help = "Normal (gaussian) distribution",
1948 },
e0a04ac1
JA
1949 { .ival = "zoned",
1950 .oval = FIO_RAND_DIST_ZONED,
1951 .help = "Zoned random distribution",
1952 },
1953
e25839d4 1954 },
48107598
JA
1955 .category = FIO_OPT_C_IO,
1956 .group = FIO_OPT_G_RANDOM,
e25839d4 1957 },
211c9b89
JA
1958 {
1959 .name = "percentage_random",
1960 .lname = "Percentage Random",
1961 .type = FIO_OPT_INT,
d9472271
JA
1962 .off1 = td_var_offset(perc_rand[DDIR_READ]),
1963 .off2 = td_var_offset(perc_rand[DDIR_WRITE]),
1964 .off3 = td_var_offset(perc_rand[DDIR_TRIM]),
211c9b89
JA
1965 .maxval = 100,
1966 .help = "Percentage of seq/random mix that should be random",
d9472271 1967 .def = "100,100,100",
211c9b89
JA
1968 .interval = 5,
1969 .inverse = "percentage_sequential",
1970 .category = FIO_OPT_C_IO,
1971 .group = FIO_OPT_G_RANDOM,
1972 },
1973 {
1974 .name = "percentage_sequential",
1975 .lname = "Percentage Sequential",
d9472271 1976 .type = FIO_OPT_DEPRECATED,
211c9b89
JA
1977 .category = FIO_OPT_C_IO,
1978 .group = FIO_OPT_G_RANDOM,
1979 },
56e2a5fc
CE
1980 {
1981 .name = "allrandrepeat",
1982 .type = FIO_OPT_BOOL,
1983 .off1 = td_var_offset(allrand_repeatable),
1984 .help = "Use repeatable random numbers for everything",
1985 .def = "0",
a869d9c6
JA
1986 .category = FIO_OPT_C_IO,
1987 .group = FIO_OPT_G_RANDOM,
56e2a5fc 1988 },
214e1eca
JA
1989 {
1990 .name = "nrfiles",
e8b0e958 1991 .lname = "Number of files",
d7c8be03 1992 .alias = "nr_files",
214e1eca
JA
1993 .type = FIO_OPT_INT,
1994 .off1 = td_var_offset(nr_files),
1995 .help = "Split job workload between this number of files",
1996 .def = "1",
20eb06bd 1997 .interval = 1,
e8b0e958
JA
1998 .category = FIO_OPT_C_FILE,
1999 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2000 },
2001 {
2002 .name = "openfiles",
e8b0e958 2003 .lname = "Number of open files",
214e1eca
JA
2004 .type = FIO_OPT_INT,
2005 .off1 = td_var_offset(open_files),
2006 .help = "Number of files to keep open at the same time",
e8b0e958
JA
2007 .category = FIO_OPT_C_FILE,
2008 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2009 },
2010 {
2011 .name = "file_service_type",
e8b0e958 2012 .lname = "File service type",
214e1eca
JA
2013 .type = FIO_OPT_STR,
2014 .cb = str_fst_cb,
2015 .off1 = td_var_offset(file_service_type),
2016 .help = "How to select which file to service next",
2017 .def = "roundrobin",
e8b0e958
JA
2018 .category = FIO_OPT_C_FILE,
2019 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2020 .posval = {
2021 { .ival = "random",
2022 .oval = FIO_FSERVICE_RANDOM,
2023 .help = "Choose a file at random",
2024 },
2025 { .ival = "roundrobin",
2026 .oval = FIO_FSERVICE_RR,
2027 .help = "Round robin select files",
2028 },
a086c257
JA
2029 { .ival = "sequential",
2030 .oval = FIO_FSERVICE_SEQ,
2031 .help = "Finish one file before moving to the next",
2032 },
214e1eca 2033 },
67a1000f 2034 .parent = "nrfiles",
d71c154c 2035 .hide = 1,
67a1000f 2036 },
97ac992c 2037#ifdef CONFIG_POSIX_FALLOCATE
7bc8c2cf
JA
2038 {
2039 .name = "fallocate",
e8b0e958 2040 .lname = "Fallocate",
a596f047
EG
2041 .type = FIO_OPT_STR,
2042 .off1 = td_var_offset(fallocate_mode),
2043 .help = "Whether pre-allocation is performed when laying out files",
2044 .def = "posix",
e8b0e958
JA
2045 .category = FIO_OPT_C_FILE,
2046 .group = FIO_OPT_G_INVALID,
a596f047
EG
2047 .posval = {
2048 { .ival = "none",
2049 .oval = FIO_FALLOCATE_NONE,
2050 .help = "Do not pre-allocate space",
2051 },
2052 { .ival = "posix",
2053 .oval = FIO_FALLOCATE_POSIX,
2054 .help = "Use posix_fallocate()",
2055 },
97ac992c 2056#ifdef CONFIG_LINUX_FALLOCATE
a596f047
EG
2057 { .ival = "keep",
2058 .oval = FIO_FALLOCATE_KEEP_SIZE,
2059 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
2060 },
7bc8c2cf 2061#endif
a596f047
EG
2062 /* Compatibility with former boolean values */
2063 { .ival = "0",
2064 .oval = FIO_FALLOCATE_NONE,
2065 .help = "Alias for 'none'",
2066 },
2067 { .ival = "1",
2068 .oval = FIO_FALLOCATE_POSIX,
2069 .help = "Alias for 'posix'",
2070 },
2071 },
2072 },
97ac992c 2073#endif /* CONFIG_POSIX_FALLOCATE */
67a1000f
JA
2074 {
2075 .name = "fadvise_hint",
e8b0e958 2076 .lname = "Fadvise hint",
67a1000f
JA
2077 .type = FIO_OPT_BOOL,
2078 .off1 = td_var_offset(fadvise_hint),
2079 .help = "Use fadvise() to advise the kernel on IO pattern",
2080 .def = "1",
e8b0e958
JA
2081 .category = FIO_OPT_C_FILE,
2082 .group = FIO_OPT_G_INVALID,
214e1eca 2083 },
37659335
JA
2084#ifdef FIO_HAVE_STREAMID
2085 {
2086 .name = "fadvise_stream",
2087 .lname = "Fadvise stream",
2088 .type = FIO_OPT_INT,
2089 .off1 = td_var_offset(fadvise_stream),
2090 .help = "Use fadvise() to set stream ID",
2091 .category = FIO_OPT_C_FILE,
2092 .group = FIO_OPT_G_INVALID,
2093 },
2094#endif
214e1eca
JA
2095 {
2096 .name = "fsync",
e8b0e958 2097 .lname = "Fsync",
214e1eca
JA
2098 .type = FIO_OPT_INT,
2099 .off1 = td_var_offset(fsync_blocks),
2100 .help = "Issue fsync for writes every given number of blocks",
2101 .def = "0",
20eb06bd 2102 .interval = 1,
e8b0e958
JA
2103 .category = FIO_OPT_C_FILE,
2104 .group = FIO_OPT_G_INVALID,
214e1eca 2105 },
5f9099ea
JA
2106 {
2107 .name = "fdatasync",
e8b0e958 2108 .lname = "Fdatasync",
5f9099ea
JA
2109 .type = FIO_OPT_INT,
2110 .off1 = td_var_offset(fdatasync_blocks),
2111 .help = "Issue fdatasync for writes every given number of blocks",
2112 .def = "0",
20eb06bd 2113 .interval = 1,
e8b0e958
JA
2114 .category = FIO_OPT_C_FILE,
2115 .group = FIO_OPT_G_INVALID,
5f9099ea 2116 },
1ef2b6be
JA
2117 {
2118 .name = "write_barrier",
e8b0e958 2119 .lname = "Write barrier",
1ef2b6be
JA
2120 .type = FIO_OPT_INT,
2121 .off1 = td_var_offset(barrier_blocks),
2122 .help = "Make every Nth write a barrier write",
2123 .def = "0",
20eb06bd 2124 .interval = 1,
e8b0e958
JA
2125 .category = FIO_OPT_C_IO,
2126 .group = FIO_OPT_G_INVALID,
1ef2b6be 2127 },
67bf9823 2128#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
2129 {
2130 .name = "sync_file_range",
e8b0e958 2131 .lname = "Sync file range",
44f29692
JA
2132 .posval = {
2133 { .ival = "wait_before",
2134 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
2135 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
ebadc0ce 2136 .orval = 1,
44f29692
JA
2137 },
2138 { .ival = "write",
2139 .oval = SYNC_FILE_RANGE_WRITE,
2140 .help = "SYNC_FILE_RANGE_WRITE",
ebadc0ce 2141 .orval = 1,
44f29692
JA
2142 },
2143 {
2144 .ival = "wait_after",
2145 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
2146 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
ebadc0ce 2147 .orval = 1,
44f29692
JA
2148 },
2149 },
3843deb3 2150 .type = FIO_OPT_STR_MULTI,
44f29692
JA
2151 .cb = str_sfr_cb,
2152 .off1 = td_var_offset(sync_file_range),
2153 .help = "Use sync_file_range()",
e8b0e958
JA
2154 .category = FIO_OPT_C_FILE,
2155 .group = FIO_OPT_G_INVALID,
44f29692
JA
2156 },
2157#endif
214e1eca
JA
2158 {
2159 .name = "direct",
e8b0e958 2160 .lname = "Direct I/O",
214e1eca
JA
2161 .type = FIO_OPT_BOOL,
2162 .off1 = td_var_offset(odirect),
2163 .help = "Use O_DIRECT IO (negates buffered)",
2164 .def = "0",
a01a1bc5 2165 .inverse = "buffered",
e8b0e958 2166 .category = FIO_OPT_C_IO,
3ceb458f 2167 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2168 },
d01612f3
CM
2169 {
2170 .name = "atomic",
2171 .lname = "Atomic I/O",
2172 .type = FIO_OPT_BOOL,
2173 .off1 = td_var_offset(oatomic),
2174 .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
2175 .def = "0",
2176 .category = FIO_OPT_C_IO,
2177 .group = FIO_OPT_G_IO_TYPE,
2178 },
214e1eca
JA
2179 {
2180 .name = "buffered",
e8b0e958 2181 .lname = "Buffered I/O",
214e1eca
JA
2182 .type = FIO_OPT_BOOL,
2183 .off1 = td_var_offset(odirect),
2184 .neg = 1,
2185 .help = "Use buffered IO (negates direct)",
2186 .def = "1",
a01a1bc5 2187 .inverse = "direct",
e8b0e958 2188 .category = FIO_OPT_C_IO,
3ceb458f 2189 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2190 },
2191 {
2192 .name = "overwrite",
e8b0e958 2193 .lname = "Overwrite",
214e1eca
JA
2194 .type = FIO_OPT_BOOL,
2195 .off1 = td_var_offset(overwrite),
2196 .help = "When writing, set whether to overwrite current data",
2197 .def = "0",
e8b0e958
JA
2198 .category = FIO_OPT_C_FILE,
2199 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2200 },
2201 {
2202 .name = "loops",
e8b0e958 2203 .lname = "Loops",
214e1eca
JA
2204 .type = FIO_OPT_INT,
2205 .off1 = td_var_offset(loops),
2206 .help = "Number of times to run the job",
2207 .def = "1",
20eb06bd 2208 .interval = 1,
e8b0e958 2209 .category = FIO_OPT_C_GENERAL,
a1f6afec 2210 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2211 },
2212 {
2213 .name = "numjobs",
e8b0e958 2214 .lname = "Number of jobs",
214e1eca
JA
2215 .type = FIO_OPT_INT,
2216 .off1 = td_var_offset(numjobs),
2217 .help = "Duplicate this job this many times",
2218 .def = "1",
20eb06bd 2219 .interval = 1,
e8b0e958 2220 .category = FIO_OPT_C_GENERAL,
a1f6afec 2221 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2222 },
2223 {
2224 .name = "startdelay",
e8b0e958 2225 .lname = "Start delay",
a5737c93 2226 .type = FIO_OPT_STR_VAL_TIME,
214e1eca 2227 .off1 = td_var_offset(start_delay),
23ed19b0 2228 .off2 = td_var_offset(start_delay_high),
214e1eca
JA
2229 .help = "Only start job when this period has passed",
2230 .def = "0",
0de5b26f 2231 .is_seconds = 1,
88038bc7 2232 .is_time = 1,
e8b0e958 2233 .category = FIO_OPT_C_GENERAL,
a1f6afec 2234 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2235 },
2236 {
2237 .name = "runtime",
e8b0e958 2238 .lname = "Runtime",
214e1eca
JA
2239 .alias = "timeout",
2240 .type = FIO_OPT_STR_VAL_TIME,
2241 .off1 = td_var_offset(timeout),
2242 .help = "Stop workload when this amount of time has passed",
2243 .def = "0",
0de5b26f 2244 .is_seconds = 1,
88038bc7 2245 .is_time = 1,
e8b0e958 2246 .category = FIO_OPT_C_GENERAL,
a1f6afec 2247 .group = FIO_OPT_G_RUNTIME,
214e1eca 2248 },
cf4464ca
JA
2249 {
2250 .name = "time_based",
e8b0e958 2251 .lname = "Time based",
cf4464ca
JA
2252 .type = FIO_OPT_STR_SET,
2253 .off1 = td_var_offset(time_based),
2254 .help = "Keep running until runtime/timeout is met",
e8b0e958 2255 .category = FIO_OPT_C_GENERAL,
a1f6afec 2256 .group = FIO_OPT_G_RUNTIME,
cf4464ca 2257 },
62167762
JC
2258 {
2259 .name = "verify_only",
2260 .lname = "Verify only",
2261 .type = FIO_OPT_STR_SET,
2262 .off1 = td_var_offset(verify_only),
2263 .help = "Verifies previously written data is still valid",
2264 .category = FIO_OPT_C_GENERAL,
2265 .group = FIO_OPT_G_RUNTIME,
2266 },
721938ae
JA
2267 {
2268 .name = "ramp_time",
e8b0e958 2269 .lname = "Ramp time",
721938ae
JA
2270 .type = FIO_OPT_STR_VAL_TIME,
2271 .off1 = td_var_offset(ramp_time),
2272 .help = "Ramp up time before measuring performance",
0de5b26f 2273 .is_seconds = 1,
88038bc7 2274 .is_time = 1,
e8b0e958 2275 .category = FIO_OPT_C_GENERAL,
a1f6afec 2276 .group = FIO_OPT_G_RUNTIME,
721938ae 2277 },
c223da83
JA
2278 {
2279 .name = "clocksource",
e8b0e958 2280 .lname = "Clock source",
c223da83
JA
2281 .type = FIO_OPT_STR,
2282 .cb = fio_clock_source_cb,
2283 .off1 = td_var_offset(clocksource),
2284 .help = "What type of timing source to use",
e8b0e958 2285 .category = FIO_OPT_C_GENERAL,
10860056 2286 .group = FIO_OPT_G_CLOCK,
c223da83 2287 .posval = {
67bf9823 2288#ifdef CONFIG_GETTIMEOFDAY
c223da83
JA
2289 { .ival = "gettimeofday",
2290 .oval = CS_GTOD,
2291 .help = "Use gettimeofday(2) for timing",
2292 },
67bf9823
JA
2293#endif
2294#ifdef CONFIG_CLOCK_GETTIME
c223da83
JA
2295 { .ival = "clock_gettime",
2296 .oval = CS_CGETTIME,
2297 .help = "Use clock_gettime(2) for timing",
2298 },
67bf9823 2299#endif
c223da83
JA
2300#ifdef ARCH_HAVE_CPU_CLOCK
2301 { .ival = "cpu",
2302 .oval = CS_CPUCLOCK,
2303 .help = "Use CPU private clock",
2304 },
2305#endif
2306 },
2307 },
214e1eca
JA
2308 {
2309 .name = "mem",
d3aad8f2 2310 .alias = "iomem",
e8b0e958 2311 .lname = "I/O Memory",
214e1eca
JA
2312 .type = FIO_OPT_STR,
2313 .cb = str_mem_cb,
2314 .off1 = td_var_offset(mem_type),
2315 .help = "Backing type for IO buffers",
2316 .def = "malloc",
e8b0e958
JA
2317 .category = FIO_OPT_C_IO,
2318 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2319 .posval = {
2320 { .ival = "malloc",
2321 .oval = MEM_MALLOC,
2322 .help = "Use malloc(3) for IO buffers",
2323 },
c8931876 2324#ifndef CONFIG_NO_SHM
37c8cdfe
JA
2325 { .ival = "shm",
2326 .oval = MEM_SHM,
2327 .help = "Use shared memory segments for IO buffers",
2328 },
214e1eca
JA
2329#ifdef FIO_HAVE_HUGETLB
2330 { .ival = "shmhuge",
2331 .oval = MEM_SHMHUGE,
2332 .help = "Like shm, but use huge pages",
2333 },
c8931876 2334#endif
b370e46a 2335#endif
37c8cdfe
JA
2336 { .ival = "mmap",
2337 .oval = MEM_MMAP,
2338 .help = "Use mmap(2) (file or anon) for IO buffers",
2339 },
217b0f1d
LG
2340 { .ival = "mmapshared",
2341 .oval = MEM_MMAPSHARED,
2342 .help = "Like mmap, but use the shared flag",
2343 },
214e1eca
JA
2344#ifdef FIO_HAVE_HUGETLB
2345 { .ival = "mmaphuge",
2346 .oval = MEM_MMAPHUGE,
2347 .help = "Like mmap, but use huge pages",
2348 },
2349#endif
2350 },
2351 },
d529ee19
JA
2352 {
2353 .name = "iomem_align",
2354 .alias = "mem_align",
e8b0e958 2355 .lname = "I/O memory alignment",
d529ee19
JA
2356 .type = FIO_OPT_INT,
2357 .off1 = td_var_offset(mem_align),
2358 .minval = 0,
2359 .help = "IO memory buffer offset alignment",
2360 .def = "0",
2361 .parent = "iomem",
d71c154c 2362 .hide = 1,
e8b0e958
JA
2363 .category = FIO_OPT_C_IO,
2364 .group = FIO_OPT_G_INVALID,
d529ee19 2365 },
214e1eca
JA
2366 {
2367 .name = "verify",
e8b0e958 2368 .lname = "Verify",
214e1eca
JA
2369 .type = FIO_OPT_STR,
2370 .off1 = td_var_offset(verify),
2371 .help = "Verify data written",
2372 .def = "0",
e8b0e958 2373 .category = FIO_OPT_C_IO,
3ceb458f 2374 .group = FIO_OPT_G_VERIFY,
214e1eca
JA
2375 .posval = {
2376 { .ival = "0",
2377 .oval = VERIFY_NONE,
2378 .help = "Don't do IO verification",
2379 },
fcca4b58
JA
2380 { .ival = "md5",
2381 .oval = VERIFY_MD5,
2382 .help = "Use md5 checksums for verification",
2383 },
d77a7af3
JA
2384 { .ival = "crc64",
2385 .oval = VERIFY_CRC64,
2386 .help = "Use crc64 checksums for verification",
2387 },
214e1eca
JA
2388 { .ival = "crc32",
2389 .oval = VERIFY_CRC32,
2390 .help = "Use crc32 checksums for verification",
2391 },
af497e6a 2392 { .ival = "crc32c-intel",
e3aaafc4
JA
2393 .oval = VERIFY_CRC32C,
2394 .help = "Use crc32c checksums for verification (hw assisted, if available)",
af497e6a 2395 },
bac39e0e
JA
2396 { .ival = "crc32c",
2397 .oval = VERIFY_CRC32C,
e3aaafc4 2398 .help = "Use crc32c checksums for verification (hw assisted, if available)",
bac39e0e 2399 },
969f7ed3
JA
2400 { .ival = "crc16",
2401 .oval = VERIFY_CRC16,
2402 .help = "Use crc16 checksums for verification",
2403 },
1e154bdb
JA
2404 { .ival = "crc7",
2405 .oval = VERIFY_CRC7,
2406 .help = "Use crc7 checksums for verification",
2407 },
7c353ceb
JA
2408 { .ival = "sha1",
2409 .oval = VERIFY_SHA1,
2410 .help = "Use sha1 checksums for verification",
2411 },
cd14cc10
JA
2412 { .ival = "sha256",
2413 .oval = VERIFY_SHA256,
2414 .help = "Use sha256 checksums for verification",
2415 },
2416 { .ival = "sha512",
2417 .oval = VERIFY_SHA512,
2418 .help = "Use sha512 checksums for verification",
2419 },
844ea602
JA
2420 { .ival = "xxhash",
2421 .oval = VERIFY_XXHASH,
2422 .help = "Use xxhash checksums for verification",
2423 },
b638d82f
RP
2424 /* Meta information was included into verify_header,
2425 * 'meta' verification is implied by default. */
7437ee87 2426 { .ival = "meta",
b638d82f
RP
2427 .oval = VERIFY_HDR_ONLY,
2428 .help = "Use io information for verification. "
2429 "Now is implied by default, thus option is obsolete, "
2430 "don't use it",
7437ee87 2431 },
59245381
JA
2432 { .ival = "pattern",
2433 .oval = VERIFY_PATTERN_NO_HDR,
2434 .help = "Verify strict pattern",
2435 },
36690c9b
JA
2436 {
2437 .ival = "null",
2438 .oval = VERIFY_NULL,
2439 .help = "Pretend to verify",
2440 },
214e1eca
JA
2441 },
2442 },
005c565a
JA
2443 {
2444 .name = "do_verify",
e8b0e958 2445 .lname = "Perform verify step",
68e1f29a 2446 .type = FIO_OPT_BOOL,
005c565a
JA
2447 .off1 = td_var_offset(do_verify),
2448 .help = "Run verification stage after write",
2449 .def = "1",
2450 .parent = "verify",
d71c154c 2451 .hide = 1,
e8b0e958
JA
2452 .category = FIO_OPT_C_IO,
2453 .group = FIO_OPT_G_VERIFY,
005c565a 2454 },
160b966d
JA
2455 {
2456 .name = "verifysort",
e8b0e958 2457 .lname = "Verify sort",
160b966d
JA
2458 .type = FIO_OPT_BOOL,
2459 .off1 = td_var_offset(verifysort),
2460 .help = "Sort written verify blocks for read back",
2461 .def = "1",
c83f2df1 2462 .parent = "verify",
d71c154c 2463 .hide = 1,
e8b0e958
JA
2464 .category = FIO_OPT_C_IO,
2465 .group = FIO_OPT_G_VERIFY,
160b966d 2466 },
1ae83d45
JA
2467 {
2468 .name = "verifysort_nr",
2469 .type = FIO_OPT_INT,
2470 .off1 = td_var_offset(verifysort_nr),
2471 .help = "Pre-load and sort verify blocks for a read workload",
2472 .minval = 0,
2473 .maxval = 131072,
2474 .def = "1024",
2475 .parent = "verify",
836fcc0f
JA
2476 .category = FIO_OPT_C_IO,
2477 .group = FIO_OPT_G_VERIFY,
1ae83d45 2478 },
3f9f4e26 2479 {
a59e170d 2480 .name = "verify_interval",
e8b0e958 2481 .lname = "Verify interval",
e01b22b8 2482 .type = FIO_OPT_INT,
a59e170d 2483 .off1 = td_var_offset(verify_interval),
819a9680 2484 .minval = 2 * sizeof(struct verify_header),
a59e170d 2485 .help = "Store verify buffer header every N bytes",
afdf9352 2486 .parent = "verify",
d71c154c 2487 .hide = 1,
20eb06bd 2488 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
2489 .category = FIO_OPT_C_IO,
2490 .group = FIO_OPT_G_VERIFY,
3f9f4e26 2491 },
546a9142 2492 {
a59e170d 2493 .name = "verify_offset",
e8b0e958 2494 .lname = "Verify offset",
e01b22b8 2495 .type = FIO_OPT_INT,
a59e170d 2496 .help = "Offset verify header location by N bytes",
203160d5
JA
2497 .off1 = td_var_offset(verify_offset),
2498 .minval = sizeof(struct verify_header),
afdf9352 2499 .parent = "verify",
d71c154c 2500 .hide = 1,
e8b0e958
JA
2501 .category = FIO_OPT_C_IO,
2502 .group = FIO_OPT_G_VERIFY,
546a9142 2503 },
e28218f3
SL
2504 {
2505 .name = "verify_pattern",
e8b0e958 2506 .lname = "Verify pattern",
0e92f873 2507 .type = FIO_OPT_STR,
e28218f3 2508 .cb = str_verify_pattern_cb,
a8523a6a 2509 .off1 = td_var_offset(verify_pattern),
e28218f3
SL
2510 .help = "Fill pattern for IO buffers",
2511 .parent = "verify",
d71c154c 2512 .hide = 1,
e8b0e958
JA
2513 .category = FIO_OPT_C_IO,
2514 .group = FIO_OPT_G_VERIFY,
e28218f3 2515 },
a12a3b4d
JA
2516 {
2517 .name = "verify_fatal",
e8b0e958 2518 .lname = "Verify fatal",
68e1f29a 2519 .type = FIO_OPT_BOOL,
a12a3b4d
JA
2520 .off1 = td_var_offset(verify_fatal),
2521 .def = "0",
2522 .help = "Exit on a single verify failure, don't continue",
2523 .parent = "verify",
d71c154c 2524 .hide = 1,
e8b0e958
JA
2525 .category = FIO_OPT_C_IO,
2526 .group = FIO_OPT_G_VERIFY,
a12a3b4d 2527 },
b463e936
JA
2528 {
2529 .name = "verify_dump",
e8b0e958 2530 .lname = "Verify dump",
b463e936
JA
2531 .type = FIO_OPT_BOOL,
2532 .off1 = td_var_offset(verify_dump),
ef71e317 2533 .def = "0",
b463e936
JA
2534 .help = "Dump contents of good and bad blocks on failure",
2535 .parent = "verify",
d71c154c 2536 .hide = 1,
e8b0e958
JA
2537 .category = FIO_OPT_C_IO,
2538 .group = FIO_OPT_G_VERIFY,
b463e936 2539 },
e8462bd8
JA
2540 {
2541 .name = "verify_async",
e8b0e958 2542 .lname = "Verify asynchronously",
e8462bd8
JA
2543 .type = FIO_OPT_INT,
2544 .off1 = td_var_offset(verify_async),
2545 .def = "0",
2546 .help = "Number of async verifier threads to use",
2547 .parent = "verify",
d71c154c 2548 .hide = 1,
e8b0e958
JA
2549 .category = FIO_OPT_C_IO,
2550 .group = FIO_OPT_G_VERIFY,
e8462bd8 2551 },
9e144189
JA
2552 {
2553 .name = "verify_backlog",
e8b0e958 2554 .lname = "Verify backlog",
9e144189
JA
2555 .type = FIO_OPT_STR_VAL,
2556 .off1 = td_var_offset(verify_backlog),
2557 .help = "Verify after this number of blocks are written",
2558 .parent = "verify",
d71c154c 2559 .hide = 1,
e8b0e958
JA
2560 .category = FIO_OPT_C_IO,
2561 .group = FIO_OPT_G_VERIFY,
9e144189
JA
2562 },
2563 {
2564 .name = "verify_backlog_batch",
e8b0e958 2565 .lname = "Verify backlog batch",
9e144189
JA
2566 .type = FIO_OPT_INT,
2567 .off1 = td_var_offset(verify_batch),
2568 .help = "Verify this number of IO blocks",
0d29de83 2569 .parent = "verify",
d71c154c 2570 .hide = 1,
e8b0e958
JA
2571 .category = FIO_OPT_C_IO,
2572 .group = FIO_OPT_G_VERIFY,
9e144189 2573 },
e8462bd8
JA
2574#ifdef FIO_HAVE_CPU_AFFINITY
2575 {
2576 .name = "verify_async_cpus",
e8b0e958 2577 .lname = "Async verify CPUs",
e8462bd8
JA
2578 .type = FIO_OPT_STR,
2579 .cb = str_verify_cpus_allowed_cb,
a8523a6a 2580 .off1 = td_var_offset(verify_cpumask),
e8462bd8
JA
2581 .help = "Set CPUs allowed for async verify threads",
2582 .parent = "verify_async",
d71c154c 2583 .hide = 1,
e8b0e958
JA
2584 .category = FIO_OPT_C_IO,
2585 .group = FIO_OPT_G_VERIFY,
e8462bd8 2586 },
0d29de83 2587#endif
51aa2da8
JA
2588 {
2589 .name = "experimental_verify",
2590 .off1 = td_var_offset(experimental_verify),
2591 .type = FIO_OPT_BOOL,
b31eaac9 2592 .help = "Enable experimental verification",
ca09be4b
JA
2593 .parent = "verify",
2594 .category = FIO_OPT_C_IO,
2595 .group = FIO_OPT_G_VERIFY,
2596 },
2597 {
2598 .name = "verify_state_load",
2599 .lname = "Load verify state",
2600 .off1 = td_var_offset(verify_state),
2601 .type = FIO_OPT_BOOL,
2602 .help = "Load verify termination state",
2603 .parent = "verify",
2604 .category = FIO_OPT_C_IO,
2605 .group = FIO_OPT_G_VERIFY,
2606 },
2607 {
2608 .name = "verify_state_save",
2609 .lname = "Save verify state",
2610 .off1 = td_var_offset(verify_state_save),
2611 .type = FIO_OPT_BOOL,
2612 .def = "1",
2613 .help = "Save verify state on termination",
2614 .parent = "verify",
836fcc0f
JA
2615 .category = FIO_OPT_C_IO,
2616 .group = FIO_OPT_G_VERIFY,
51aa2da8 2617 },
0d29de83
JA
2618#ifdef FIO_HAVE_TRIM
2619 {
2620 .name = "trim_percentage",
e8b0e958 2621 .lname = "Trim percentage",
0d29de83 2622 .type = FIO_OPT_INT,
203160d5 2623 .off1 = td_var_offset(trim_percentage),
20eb06bd 2624 .minval = 0,
0d29de83
JA
2625 .maxval = 100,
2626 .help = "Number of verify blocks to discard/trim",
2627 .parent = "verify",
2628 .def = "0",
20eb06bd 2629 .interval = 1,
d71c154c 2630 .hide = 1,
e8b0e958
JA
2631 .category = FIO_OPT_C_IO,
2632 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2633 },
2634 {
2635 .name = "trim_verify_zero",
e8b0e958 2636 .lname = "Verify trim zero",
20eb06bd 2637 .type = FIO_OPT_BOOL,
0d29de83
JA
2638 .help = "Verify that trim/discarded blocks are returned as zeroes",
2639 .off1 = td_var_offset(trim_zero),
2640 .parent = "trim_percentage",
d71c154c 2641 .hide = 1,
0d29de83 2642 .def = "1",
e8b0e958
JA
2643 .category = FIO_OPT_C_IO,
2644 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2645 },
2646 {
2647 .name = "trim_backlog",
e8b0e958 2648 .lname = "Trim backlog",
0d29de83
JA
2649 .type = FIO_OPT_STR_VAL,
2650 .off1 = td_var_offset(trim_backlog),
2651 .help = "Trim after this number of blocks are written",
2652 .parent = "trim_percentage",
d71c154c 2653 .hide = 1,
20eb06bd 2654 .interval = 1,
e8b0e958
JA
2655 .category = FIO_OPT_C_IO,
2656 .group = FIO_OPT_G_TRIM,
0d29de83
JA
2657 },
2658 {
2659 .name = "trim_backlog_batch",
e8b0e958 2660 .lname = "Trim backlog batch",
0d29de83
JA
2661 .type = FIO_OPT_INT,
2662 .off1 = td_var_offset(trim_batch),
2663 .help = "Trim this number of IO blocks",
2664 .parent = "trim_percentage",
d71c154c 2665 .hide = 1,
20eb06bd 2666 .interval = 1,
e8b0e958
JA
2667 .category = FIO_OPT_C_IO,
2668 .group = FIO_OPT_G_TRIM,
0d29de83 2669 },
e8462bd8 2670#endif
214e1eca
JA
2671 {
2672 .name = "write_iolog",
e8b0e958 2673 .lname = "Write I/O log",
214e1eca
JA
2674 .type = FIO_OPT_STR_STORE,
2675 .off1 = td_var_offset(write_iolog_file),
2676 .help = "Store IO pattern to file",
e8b0e958
JA
2677 .category = FIO_OPT_C_IO,
2678 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
2679 },
2680 {
2681 .name = "read_iolog",
e8b0e958 2682 .lname = "Read I/O log",
214e1eca
JA
2683 .type = FIO_OPT_STR_STORE,
2684 .off1 = td_var_offset(read_iolog_file),
2685 .help = "Playback IO pattern from file",
e8b0e958
JA
2686 .category = FIO_OPT_C_IO,
2687 .group = FIO_OPT_G_IOLOG,
214e1eca 2688 },
64bbb865
DN
2689 {
2690 .name = "replay_no_stall",
e8b0e958 2691 .lname = "Don't stall on replay",
20eb06bd 2692 .type = FIO_OPT_BOOL,
64bbb865
DN
2693 .off1 = td_var_offset(no_stall),
2694 .def = "0",
87e7a972 2695 .parent = "read_iolog",
d71c154c 2696 .hide = 1,
64bbb865 2697 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
2698 .category = FIO_OPT_C_IO,
2699 .group = FIO_OPT_G_IOLOG,
64bbb865 2700 },
d1c46c04
DN
2701 {
2702 .name = "replay_redirect",
e8b0e958 2703 .lname = "Redirect device for replay",
d1c46c04
DN
2704 .type = FIO_OPT_STR_STORE,
2705 .off1 = td_var_offset(replay_redirect),
2706 .parent = "read_iolog",
d71c154c 2707 .hide = 1,
d1c46c04 2708 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
2709 .category = FIO_OPT_C_IO,
2710 .group = FIO_OPT_G_IOLOG,
d1c46c04 2711 },
0c63576e
JA
2712 {
2713 .name = "replay_scale",
2714 .lname = "Replace offset scale factor",
2715 .type = FIO_OPT_INT,
2716 .off1 = td_var_offset(replay_scale),
2717 .parent = "read_iolog",
2718 .def = "1",
2719 .help = "Align offsets to this blocksize",
2720 .category = FIO_OPT_C_IO,
2721 .group = FIO_OPT_G_IOLOG,
2722 },
2723 {
2724 .name = "replay_align",
2725 .lname = "Replace alignment",
2726 .type = FIO_OPT_INT,
2727 .off1 = td_var_offset(replay_align),
2728 .parent = "read_iolog",
2729 .help = "Scale offset down by this factor",
2730 .category = FIO_OPT_C_IO,
2731 .group = FIO_OPT_G_IOLOG,
2732 .pow2 = 1,
2733 },
214e1eca
JA
2734 {
2735 .name = "exec_prerun",
e8b0e958 2736 .lname = "Pre-execute runnable",
214e1eca
JA
2737 .type = FIO_OPT_STR_STORE,
2738 .off1 = td_var_offset(exec_prerun),
2739 .help = "Execute this file prior to running job",
e8b0e958
JA
2740 .category = FIO_OPT_C_GENERAL,
2741 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2742 },
2743 {
2744 .name = "exec_postrun",
e8b0e958 2745 .lname = "Post-execute runnable",
214e1eca
JA
2746 .type = FIO_OPT_STR_STORE,
2747 .off1 = td_var_offset(exec_postrun),
2748 .help = "Execute this file after running job",
e8b0e958
JA
2749 .category = FIO_OPT_C_GENERAL,
2750 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2751 },
2752#ifdef FIO_HAVE_IOSCHED_SWITCH
2753 {
2754 .name = "ioscheduler",
e8b0e958 2755 .lname = "I/O scheduler",
214e1eca
JA
2756 .type = FIO_OPT_STR_STORE,
2757 .off1 = td_var_offset(ioscheduler),
2758 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
2759 .category = FIO_OPT_C_FILE,
2760 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2761 },
2762#endif
2763 {
2764 .name = "zonesize",
e8b0e958 2765 .lname = "Zone size",
214e1eca
JA
2766 .type = FIO_OPT_STR_VAL,
2767 .off1 = td_var_offset(zone_size),
ed335855
SN
2768 .help = "Amount of data to read per zone",
2769 .def = "0",
20eb06bd 2770 .interval = 1024 * 1024,
e8b0e958
JA
2771 .category = FIO_OPT_C_IO,
2772 .group = FIO_OPT_G_ZONE,
ed335855
SN
2773 },
2774 {
2775 .name = "zonerange",
e8b0e958 2776 .lname = "Zone range",
ed335855
SN
2777 .type = FIO_OPT_STR_VAL,
2778 .off1 = td_var_offset(zone_range),
214e1eca
JA
2779 .help = "Give size of an IO zone",
2780 .def = "0",
20eb06bd 2781 .interval = 1024 * 1024,
e8b0e958
JA
2782 .category = FIO_OPT_C_IO,
2783 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2784 },
2785 {
2786 .name = "zoneskip",
e8b0e958 2787 .lname = "Zone skip",
214e1eca
JA
2788 .type = FIO_OPT_STR_VAL,
2789 .off1 = td_var_offset(zone_skip),
2790 .help = "Space between IO zones",
2791 .def = "0",
20eb06bd 2792 .interval = 1024 * 1024,
e8b0e958
JA
2793 .category = FIO_OPT_C_IO,
2794 .group = FIO_OPT_G_ZONE,
214e1eca
JA
2795 },
2796 {
2797 .name = "lockmem",
e8b0e958 2798 .lname = "Lock memory",
214e1eca 2799 .type = FIO_OPT_STR_VAL,
1b79a070 2800 .off1 = td_var_offset(lockmem),
81c6b6cd 2801 .help = "Lock down this amount of memory (per worker)",
214e1eca 2802 .def = "0",
20eb06bd 2803 .interval = 1024 * 1024,
e8b0e958
JA
2804 .category = FIO_OPT_C_GENERAL,
2805 .group = FIO_OPT_G_INVALID,
214e1eca 2806 },
214e1eca
JA
2807 {
2808 .name = "rwmixread",
e8b0e958 2809 .lname = "Read/write mix read",
214e1eca 2810 .type = FIO_OPT_INT,
cb499fc4 2811 .cb = str_rwmix_read_cb,
a8523a6a 2812 .off1 = td_var_offset(rwmix[DDIR_READ]),
214e1eca
JA
2813 .maxval = 100,
2814 .help = "Percentage of mixed workload that is reads",
2815 .def = "50",
20eb06bd 2816 .interval = 5,
90265353 2817 .inverse = "rwmixwrite",
e8b0e958
JA
2818 .category = FIO_OPT_C_IO,
2819 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
2820 },
2821 {
2822 .name = "rwmixwrite",
e8b0e958 2823 .lname = "Read/write mix write",
214e1eca 2824 .type = FIO_OPT_INT,
cb499fc4 2825 .cb = str_rwmix_write_cb,
a8523a6a 2826 .off1 = td_var_offset(rwmix[DDIR_WRITE]),
214e1eca
JA
2827 .maxval = 100,
2828 .help = "Percentage of mixed workload that is writes",
2829 .def = "50",
20eb06bd 2830 .interval = 5,
90265353 2831 .inverse = "rwmixread",
e8b0e958
JA
2832 .category = FIO_OPT_C_IO,
2833 .group = FIO_OPT_G_RWMIX,
214e1eca 2834 },
afdf9352
JA
2835 {
2836 .name = "rwmixcycle",
e8b0e958 2837 .lname = "Read/write mix cycle",
15ca150e 2838 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
2839 .category = FIO_OPT_C_IO,
2840 .group = FIO_OPT_G_RWMIX,
afdf9352 2841 },
214e1eca
JA
2842 {
2843 .name = "nice",
e8b0e958 2844 .lname = "Nice",
214e1eca
JA
2845 .type = FIO_OPT_INT,
2846 .off1 = td_var_offset(nice),
2847 .help = "Set job CPU nice value",
2848 .minval = -19,
2849 .maxval = 20,
2850 .def = "0",
20eb06bd 2851 .interval = 1,
e8b0e958 2852 .category = FIO_OPT_C_GENERAL,
10860056 2853 .group = FIO_OPT_G_CRED,
214e1eca
JA
2854 },
2855#ifdef FIO_HAVE_IOPRIO
2856 {
2857 .name = "prio",
e8b0e958 2858 .lname = "I/O nice priority",
214e1eca 2859 .type = FIO_OPT_INT,
28727df7 2860 .off1 = td_var_offset(ioprio),
214e1eca
JA
2861 .help = "Set job IO priority value",
2862 .minval = 0,
2863 .maxval = 7,
20eb06bd 2864 .interval = 1,
e8b0e958 2865 .category = FIO_OPT_C_GENERAL,
10860056 2866 .group = FIO_OPT_G_CRED,
214e1eca
JA
2867 },
2868 {
2869 .name = "prioclass",
e8b0e958 2870 .lname = "I/O nice priority class",
214e1eca 2871 .type = FIO_OPT_INT,
28727df7 2872 .off1 = td_var_offset(ioprio_class),
214e1eca
JA
2873 .help = "Set job IO priority class",
2874 .minval = 0,
2875 .maxval = 3,
20eb06bd 2876 .interval = 1,
e8b0e958 2877 .category = FIO_OPT_C_GENERAL,
10860056 2878 .group = FIO_OPT_G_CRED,
214e1eca
JA
2879 },
2880#endif
2881 {
2882 .name = "thinktime",
e8b0e958 2883 .lname = "Thinktime",
214e1eca
JA
2884 .type = FIO_OPT_INT,
2885 .off1 = td_var_offset(thinktime),
2886 .help = "Idle time between IO buffers (usec)",
2887 .def = "0",
88038bc7 2888 .is_time = 1,
e8b0e958 2889 .category = FIO_OPT_C_IO,
3ceb458f 2890 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2891 },
2892 {
2893 .name = "thinktime_spin",
e8b0e958 2894 .lname = "Thinktime spin",
214e1eca
JA
2895 .type = FIO_OPT_INT,
2896 .off1 = td_var_offset(thinktime_spin),
2897 .help = "Start think time by spinning this amount (usec)",
2898 .def = "0",
88038bc7 2899 .is_time = 1,
afdf9352 2900 .parent = "thinktime",
d71c154c 2901 .hide = 1,
e8b0e958 2902 .category = FIO_OPT_C_IO,
3ceb458f 2903 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2904 },
2905 {
2906 .name = "thinktime_blocks",
e8b0e958 2907 .lname = "Thinktime blocks",
214e1eca
JA
2908 .type = FIO_OPT_INT,
2909 .off1 = td_var_offset(thinktime_blocks),
2910 .help = "IO buffer period between 'thinktime'",
2911 .def = "1",
afdf9352 2912 .parent = "thinktime",
d71c154c 2913 .hide = 1,
e8b0e958 2914 .category = FIO_OPT_C_IO,
3ceb458f 2915 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
2916 },
2917 {
2918 .name = "rate",
e8b0e958 2919 .lname = "I/O rate",
e01b22b8 2920 .type = FIO_OPT_INT,
6eaf09d6
SL
2921 .off1 = td_var_offset(rate[DDIR_READ]),
2922 .off2 = td_var_offset(rate[DDIR_WRITE]),
2923 .off3 = td_var_offset(rate[DDIR_TRIM]),
214e1eca 2924 .help = "Set bandwidth rate",
e8b0e958
JA
2925 .category = FIO_OPT_C_IO,
2926 .group = FIO_OPT_G_RATE,
214e1eca
JA
2927 },
2928 {
6d428bcd
JA
2929 .name = "rate_min",
2930 .alias = "ratemin",
e8b0e958 2931 .lname = "I/O min rate",
e01b22b8 2932 .type = FIO_OPT_INT,
6eaf09d6
SL
2933 .off1 = td_var_offset(ratemin[DDIR_READ]),
2934 .off2 = td_var_offset(ratemin[DDIR_WRITE]),
2935 .off3 = td_var_offset(ratemin[DDIR_TRIM]),
4e991c23 2936 .help = "Job must meet this rate or it will be shutdown",
afdf9352 2937 .parent = "rate",
d71c154c 2938 .hide = 1,
e8b0e958
JA
2939 .category = FIO_OPT_C_IO,
2940 .group = FIO_OPT_G_RATE,
4e991c23
JA
2941 },
2942 {
2943 .name = "rate_iops",
e8b0e958 2944 .lname = "I/O rate IOPS",
e01b22b8 2945 .type = FIO_OPT_INT,
6eaf09d6
SL
2946 .off1 = td_var_offset(rate_iops[DDIR_READ]),
2947 .off2 = td_var_offset(rate_iops[DDIR_WRITE]),
2948 .off3 = td_var_offset(rate_iops[DDIR_TRIM]),
4e991c23 2949 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 2950 .hide = 1,
e8b0e958
JA
2951 .category = FIO_OPT_C_IO,
2952 .group = FIO_OPT_G_RATE,
4e991c23
JA
2953 },
2954 {
2955 .name = "rate_iops_min",
e8b0e958 2956 .lname = "I/O min rate IOPS",
e01b22b8 2957 .type = FIO_OPT_INT,
6eaf09d6
SL
2958 .off1 = td_var_offset(rate_iops_min[DDIR_READ]),
2959 .off2 = td_var_offset(rate_iops_min[DDIR_WRITE]),
2960 .off3 = td_var_offset(rate_iops_min[DDIR_TRIM]),
03e20d68 2961 .help = "Job must meet this rate or it will be shut down",
afdf9352 2962 .parent = "rate_iops",
d71c154c 2963 .hide = 1,
e8b0e958
JA
2964 .category = FIO_OPT_C_IO,
2965 .group = FIO_OPT_G_RATE,
214e1eca 2966 },
ff6bb260 2967 {
6de65959
JA
2968 .name = "rate_process",
2969 .lname = "Rate Process",
2970 .type = FIO_OPT_STR,
2971 .off1 = td_var_offset(rate_process),
2972 .help = "What process controls how rated IO is managed",
2973 .def = "linear",
ff6bb260
SL
2974 .category = FIO_OPT_C_IO,
2975 .group = FIO_OPT_G_RATE,
6de65959
JA
2976 .posval = {
2977 { .ival = "linear",
2978 .oval = RATE_PROCESS_LINEAR,
2979 .help = "Linear rate of IO",
2980 },
2981 {
2982 .ival = "poisson",
2983 .oval = RATE_PROCESS_POISSON,
2984 .help = "Rate follows Poisson process",
2985 },
2986 },
2987 .parent = "rate",
ff6bb260 2988 },
214e1eca 2989 {
6d428bcd
JA
2990 .name = "rate_cycle",
2991 .alias = "ratecycle",
e8b0e958 2992 .lname = "I/O rate cycle",
214e1eca
JA
2993 .type = FIO_OPT_INT,
2994 .off1 = td_var_offset(ratecycle),
2995 .help = "Window average for rate limits (msec)",
2996 .def = "1000",
afdf9352 2997 .parent = "rate",
d71c154c 2998 .hide = 1,
e8b0e958
JA
2999 .category = FIO_OPT_C_IO,
3000 .group = FIO_OPT_G_RATE,
214e1eca 3001 },
15501535
JA
3002 {
3003 .name = "max_latency",
3004 .type = FIO_OPT_INT,
3005 .off1 = td_var_offset(max_latency),
3006 .help = "Maximum tolerated IO latency (usec)",
88038bc7 3007 .is_time = 1,
1e5324e7 3008 .category = FIO_OPT_C_IO,
3e260a46
JA
3009 .group = FIO_OPT_G_LATPROF,
3010 },
3011 {
3012 .name = "latency_target",
3013 .lname = "Latency Target (usec)",
3014 .type = FIO_OPT_STR_VAL_TIME,
3015 .off1 = td_var_offset(latency_target),
3016 .help = "Ramp to max queue depth supporting this latency",
88038bc7 3017 .is_time = 1,
3e260a46
JA
3018 .category = FIO_OPT_C_IO,
3019 .group = FIO_OPT_G_LATPROF,
3020 },
3021 {
3022 .name = "latency_window",
3023 .lname = "Latency Window (usec)",
3024 .type = FIO_OPT_STR_VAL_TIME,
3025 .off1 = td_var_offset(latency_window),
3026 .help = "Time to sustain latency_target",
88038bc7 3027 .is_time = 1,
3e260a46
JA
3028 .category = FIO_OPT_C_IO,
3029 .group = FIO_OPT_G_LATPROF,
3030 },
3031 {
3032 .name = "latency_percentile",
3033 .lname = "Latency Percentile",
3034 .type = FIO_OPT_FLOAT_LIST,
3035 .off1 = td_var_offset(latency_percentile),
3036 .help = "Percentile of IOs must be below latency_target",
3037 .def = "100",
3038 .maxlen = 1,
3039 .minfp = 0.0,
3040 .maxfp = 100.0,
3041 .category = FIO_OPT_C_IO,
3042 .group = FIO_OPT_G_LATPROF,
15501535 3043 },
214e1eca
JA
3044 {
3045 .name = "invalidate",
e8b0e958 3046 .lname = "Cache invalidate",
214e1eca
JA
3047 .type = FIO_OPT_BOOL,
3048 .off1 = td_var_offset(invalidate_cache),
3049 .help = "Invalidate buffer/page cache prior to running job",
3050 .def = "1",
e8b0e958 3051 .category = FIO_OPT_C_IO,
3ceb458f 3052 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
3053 },
3054 {
3055 .name = "sync",
e8b0e958 3056 .lname = "Synchronous I/O",
214e1eca
JA
3057 .type = FIO_OPT_BOOL,
3058 .off1 = td_var_offset(sync_io),
3059 .help = "Use O_SYNC for buffered writes",
3060 .def = "0",
67a1000f 3061 .parent = "buffered",
d71c154c 3062 .hide = 1,
e8b0e958 3063 .category = FIO_OPT_C_IO,
3ceb458f 3064 .group = FIO_OPT_G_IO_TYPE,
214e1eca 3065 },
214e1eca
JA
3066 {
3067 .name = "create_serialize",
e8b0e958 3068 .lname = "Create serialize",
214e1eca
JA
3069 .type = FIO_OPT_BOOL,
3070 .off1 = td_var_offset(create_serialize),
3071 .help = "Serialize creating of job files",
3072 .def = "1",
e8b0e958
JA
3073 .category = FIO_OPT_C_FILE,
3074 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3075 },
3076 {
3077 .name = "create_fsync",
e8b0e958 3078 .lname = "Create fsync",
214e1eca
JA
3079 .type = FIO_OPT_BOOL,
3080 .off1 = td_var_offset(create_fsync),
03e20d68 3081 .help = "fsync file after creation",
214e1eca 3082 .def = "1",
e8b0e958
JA
3083 .category = FIO_OPT_C_FILE,
3084 .group = FIO_OPT_G_INVALID,
214e1eca 3085 },
814452bd
JA
3086 {
3087 .name = "create_on_open",
e8b0e958 3088 .lname = "Create on open",
814452bd
JA
3089 .type = FIO_OPT_BOOL,
3090 .off1 = td_var_offset(create_on_open),
3091 .help = "Create files when they are opened for IO",
3092 .def = "0",
e8b0e958
JA
3093 .category = FIO_OPT_C_FILE,
3094 .group = FIO_OPT_G_INVALID,
814452bd 3095 },
25460cf6
JA
3096 {
3097 .name = "create_only",
3098 .type = FIO_OPT_BOOL,
3099 .off1 = td_var_offset(create_only),
3100 .help = "Only perform file creation phase",
d17fda71 3101 .category = FIO_OPT_C_FILE,
25460cf6
JA
3102 .def = "0",
3103 },
2378826d
JA
3104 {
3105 .name = "allow_file_create",
e81ecca3 3106 .lname = "Allow file create",
2378826d
JA
3107 .type = FIO_OPT_BOOL,
3108 .off1 = td_var_offset(allow_create),
3109 .help = "Permit fio to create files, if they don't exist",
3110 .def = "1",
3111 .category = FIO_OPT_C_FILE,
3112 .group = FIO_OPT_G_FILENAME,
3113 },
e81ecca3
JA
3114 {
3115 .name = "allow_mounted_write",
3116 .lname = "Allow mounted write",
3117 .type = FIO_OPT_BOOL,
3118 .off1 = td_var_offset(allow_mounted_write),
3119 .help = "Allow writes to a mounted partition",
3120 .def = "0",
3121 .category = FIO_OPT_C_FILE,
3122 .group = FIO_OPT_G_FILENAME,
3123 },
0b9d69ec 3124 {
afad68f7 3125 .name = "pre_read",
e8b0e958 3126 .lname = "Pre-read files",
afad68f7
ZY
3127 .type = FIO_OPT_BOOL,
3128 .off1 = td_var_offset(pre_read),
03e20d68 3129 .help = "Pre-read files before starting official testing",
afad68f7 3130 .def = "0",
e8b0e958
JA
3131 .category = FIO_OPT_C_FILE,
3132 .group = FIO_OPT_G_INVALID,
afad68f7 3133 },
214e1eca
JA
3134#ifdef FIO_HAVE_CPU_AFFINITY
3135 {
3136 .name = "cpumask",
e8b0e958 3137 .lname = "CPU mask",
214e1eca
JA
3138 .type = FIO_OPT_INT,
3139 .cb = str_cpumask_cb,
a8523a6a 3140 .off1 = td_var_offset(cpumask),
214e1eca 3141 .help = "CPU affinity mask",
e8b0e958 3142 .category = FIO_OPT_C_GENERAL,
10860056 3143 .group = FIO_OPT_G_CRED,
214e1eca 3144 },
d2e268b0
JA
3145 {
3146 .name = "cpus_allowed",
e8b0e958 3147 .lname = "CPUs allowed",
d2e268b0
JA
3148 .type = FIO_OPT_STR,
3149 .cb = str_cpus_allowed_cb,
a8523a6a 3150 .off1 = td_var_offset(cpumask),
d2e268b0 3151 .help = "Set CPUs allowed",
e8b0e958 3152 .category = FIO_OPT_C_GENERAL,
10860056 3153 .group = FIO_OPT_G_CRED,
d2e268b0 3154 },
c2acfbac
JA
3155 {
3156 .name = "cpus_allowed_policy",
3157 .lname = "CPUs allowed distribution policy",
3158 .type = FIO_OPT_STR,
3159 .off1 = td_var_offset(cpus_allowed_policy),
3160 .help = "Distribution policy for cpus_allowed",
3161 .parent = "cpus_allowed",
3162 .prio = 1,
3163 .posval = {
3164 { .ival = "shared",
3165 .oval = FIO_CPUS_SHARED,
3166 .help = "Mask shared between threads",
3167 },
3168 { .ival = "split",
3169 .oval = FIO_CPUS_SPLIT,
3170 .help = "Mask split between threads",
3171 },
3172 },
3173 .category = FIO_OPT_C_GENERAL,
3174 .group = FIO_OPT_G_CRED,
3175 },
d0b937ed 3176#endif
67bf9823 3177#ifdef CONFIG_LIBNUMA
d0b937ed
YR
3178 {
3179 .name = "numa_cpu_nodes",
3180 .type = FIO_OPT_STR,
3181 .cb = str_numa_cpunodes_cb,
b2a9e649 3182 .off1 = td_var_offset(numa_cpunodes),
d0b937ed 3183 .help = "NUMA CPU nodes bind",
6be54b2d
JA
3184 .category = FIO_OPT_C_GENERAL,
3185 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
3186 },
3187 {
3188 .name = "numa_mem_policy",
3189 .type = FIO_OPT_STR,
3190 .cb = str_numa_mpol_cb,
b2a9e649 3191 .off1 = td_var_offset(numa_memnodes),
d0b937ed 3192 .help = "NUMA memory policy setup",
6be54b2d
JA
3193 .category = FIO_OPT_C_GENERAL,
3194 .group = FIO_OPT_G_INVALID,
d0b937ed 3195 },
214e1eca
JA
3196#endif
3197 {
3198 .name = "end_fsync",
e8b0e958 3199 .lname = "End fsync",
214e1eca
JA
3200 .type = FIO_OPT_BOOL,
3201 .off1 = td_var_offset(end_fsync),
3202 .help = "Include fsync at the end of job",
3203 .def = "0",
e8b0e958
JA
3204 .category = FIO_OPT_C_FILE,
3205 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3206 },
3207 {
3208 .name = "fsync_on_close",
e8b0e958 3209 .lname = "Fsync on close",
214e1eca
JA
3210 .type = FIO_OPT_BOOL,
3211 .off1 = td_var_offset(fsync_on_close),
3212 .help = "fsync files on close",
3213 .def = "0",
e8b0e958
JA
3214 .category = FIO_OPT_C_FILE,
3215 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3216 },
3217 {
3218 .name = "unlink",
e8b0e958 3219 .lname = "Unlink file",
214e1eca
JA
3220 .type = FIO_OPT_BOOL,
3221 .off1 = td_var_offset(unlink),
3222 .help = "Unlink created files after job has completed",
3223 .def = "0",
e8b0e958
JA
3224 .category = FIO_OPT_C_FILE,
3225 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3226 },
3227 {
3228 .name = "exitall",
e8b0e958 3229 .lname = "Exit-all on terminate",
214e1eca
JA
3230 .type = FIO_OPT_STR_SET,
3231 .cb = str_exitall_cb,
3232 .help = "Terminate all jobs when one exits",
e8b0e958 3233 .category = FIO_OPT_C_GENERAL,
a1f6afec 3234 .group = FIO_OPT_G_PROCESS,
214e1eca 3235 },
f9cafb12
JA
3236 {
3237 .name = "exitall_on_error",
3238 .lname = "Exit-all on terminate in error",
3239 .type = FIO_OPT_BOOL,
3240 .off1 = td_var_offset(unlink),
3241 .help = "Terminate all jobs when one exits in error",
3242 .category = FIO_OPT_C_GENERAL,
3243 .group = FIO_OPT_G_PROCESS,
3244 },
214e1eca
JA
3245 {
3246 .name = "stonewall",
e8b0e958 3247 .lname = "Wait for previous",
d392365e 3248 .alias = "wait_for_previous",
214e1eca
JA
3249 .type = FIO_OPT_STR_SET,
3250 .off1 = td_var_offset(stonewall),
3251 .help = "Insert a hard barrier between this job and previous",
e8b0e958 3252 .category = FIO_OPT_C_GENERAL,
a1f6afec 3253 .group = FIO_OPT_G_PROCESS,
214e1eca 3254 },
b3d62a75
JA
3255 {
3256 .name = "new_group",
e8b0e958 3257 .lname = "New group",
b3d62a75
JA
3258 .type = FIO_OPT_STR_SET,
3259 .off1 = td_var_offset(new_group),
3260 .help = "Mark the start of a new group (for reporting)",
e8b0e958 3261 .category = FIO_OPT_C_GENERAL,
a1f6afec 3262 .group = FIO_OPT_G_PROCESS,
b3d62a75 3263 },
214e1eca
JA
3264 {
3265 .name = "thread",
e8b0e958 3266 .lname = "Thread",
214e1eca
JA
3267 .type = FIO_OPT_STR_SET,
3268 .off1 = td_var_offset(use_thread),
20eb06bd 3269 .help = "Use threads instead of processes",
c8931876
JA
3270#ifdef CONFIG_NO_SHM
3271 .def = "1",
3272 .no_warn_def = 1,
3273#endif
e8b0e958 3274 .category = FIO_OPT_C_GENERAL,
a1f6afec 3275 .group = FIO_OPT_G_PROCESS,
214e1eca 3276 },
3a5db920
JA
3277 {
3278 .name = "per_job_logs",
3279 .type = FIO_OPT_BOOL,
3280 .off1 = td_var_offset(per_job_logs),
3281 .help = "Include job number in generated log files or not",
3282 .def = "1",
3283 .category = FIO_OPT_C_LOG,
3284 .group = FIO_OPT_G_INVALID,
3285 },
214e1eca
JA
3286 {
3287 .name = "write_bw_log",
e8b0e958 3288 .lname = "Write bandwidth log",
203160d5
JA
3289 .type = FIO_OPT_STR_STORE,
3290 .off1 = td_var_offset(bw_log_file),
214e1eca 3291 .help = "Write log of bandwidth during run",
e8b0e958
JA
3292 .category = FIO_OPT_C_LOG,
3293 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3294 },
3295 {
3296 .name = "write_lat_log",
e8b0e958 3297 .lname = "Write latency log",
203160d5
JA
3298 .type = FIO_OPT_STR_STORE,
3299 .off1 = td_var_offset(lat_log_file),
214e1eca 3300 .help = "Write log of latency during run",
e8b0e958
JA
3301 .category = FIO_OPT_C_LOG,
3302 .group = FIO_OPT_G_INVALID,
214e1eca 3303 },
c8eeb9df
JA
3304 {
3305 .name = "write_iops_log",
e8b0e958 3306 .lname = "Write IOPS log",
577c83bd 3307 .type = FIO_OPT_STR_STORE,
203160d5 3308 .off1 = td_var_offset(iops_log_file),
c8eeb9df 3309 .help = "Write log of IOPS during run",
e8b0e958
JA
3310 .category = FIO_OPT_C_LOG,
3311 .group = FIO_OPT_G_INVALID,
c8eeb9df 3312 },
b8bc8cba
JA
3313 {
3314 .name = "log_avg_msec",
e8b0e958 3315 .lname = "Log averaging (msec)",
b8bc8cba
JA
3316 .type = FIO_OPT_INT,
3317 .off1 = td_var_offset(log_avg_msec),
3318 .help = "Average bw/iops/lat logs over this period of time",
3319 .def = "0",
e8b0e958
JA
3320 .category = FIO_OPT_C_LOG,
3321 .group = FIO_OPT_G_INVALID,
b8bc8cba 3322 },
e6989e10
JA
3323 {
3324 .name = "log_max_value",
3325 .lname = "Log maximum instead of average",
3326 .type = FIO_OPT_BOOL,
3327 .off1 = td_var_offset(log_max),
3328 .help = "Log max sample in a window instead of average",
3329 .def = "0",
3330 .category = FIO_OPT_C_LOG,
3331 .group = FIO_OPT_G_INVALID,
3332 },
ae588852
JA
3333 {
3334 .name = "log_offset",
3335 .lname = "Log offset of IO",
3336 .type = FIO_OPT_BOOL,
3337 .off1 = td_var_offset(log_offset),
3338 .help = "Include offset of IO for each log entry",
3339 .def = "0",
3340 .category = FIO_OPT_C_LOG,
3341 .group = FIO_OPT_G_INVALID,
3342 },
aee2ab67
JA
3343#ifdef CONFIG_ZLIB
3344 {
3345 .name = "log_compression",
3346 .lname = "Log compression",
3347 .type = FIO_OPT_INT,
3348 .off1 = td_var_offset(log_gz),
3349 .help = "Log in compressed chunks of this size",
9919b27b 3350 .minval = 1024ULL,
aee2ab67
JA
3351 .maxval = 512 * 1024 * 1024ULL,
3352 .category = FIO_OPT_C_LOG,
3353 .group = FIO_OPT_G_INVALID,
3354 },
c08f9fe2
JA
3355#ifdef FIO_HAVE_CPU_AFFINITY
3356 {
3357 .name = "log_compression_cpus",
3358 .lname = "Log Compression CPUs",
3359 .type = FIO_OPT_STR,
3360 .cb = str_log_cpus_allowed_cb,
3361 .off1 = td_var_offset(log_gz_cpumask),
3362 .parent = "log_compression",
3363 .help = "Limit log compression to these CPUs",
3364 .category = FIO_OPT_C_LOG,
3365 .group = FIO_OPT_G_INVALID,
3366 },
3367#endif
b26317c9
JA
3368 {
3369 .name = "log_store_compressed",
3370 .lname = "Log store compressed",
3371 .type = FIO_OPT_BOOL,
3372 .off1 = td_var_offset(log_gz_store),
3373 .help = "Store logs in a compressed format",
3374 .category = FIO_OPT_C_LOG,
3375 .group = FIO_OPT_G_INVALID,
3376 },
aee2ab67 3377#endif
66347cfa
DE
3378 {
3379 .name = "block_error_percentiles",
3380 .lname = "Block error percentiles",
3381 .type = FIO_OPT_BOOL,
3382 .off1 = td_var_offset(block_error_hist),
3383 .help = "Record trim block errors and make a histogram",
3384 .def = "0",
3385 .category = FIO_OPT_C_LOG,
3386 .group = FIO_OPT_G_INVALID,
3387 },
c504ee55
JA
3388 {
3389 .name = "bwavgtime",
3390 .lname = "Bandwidth average time",
3391 .type = FIO_OPT_INT,
3392 .off1 = td_var_offset(bw_avg_time),
3393 .help = "Time window over which to calculate bandwidth"
3394 " (msec)",
3395 .def = "500",
3396 .parent = "write_bw_log",
3397 .hide = 1,
3398 .interval = 100,
3399 .category = FIO_OPT_C_LOG,
3400 .group = FIO_OPT_G_INVALID,
3401 },
3402 {
3403 .name = "iopsavgtime",
3404 .lname = "IOPS average time",
3405 .type = FIO_OPT_INT,
3406 .off1 = td_var_offset(iops_avg_time),
3407 .help = "Time window over which to calculate IOPS (msec)",
3408 .def = "500",
3409 .parent = "write_iops_log",
3410 .hide = 1,
3411 .interval = 100,
3412 .category = FIO_OPT_C_LOG,
3413 .group = FIO_OPT_G_INVALID,
3414 },
214e1eca
JA
3415 {
3416 .name = "group_reporting",
e8b0e958 3417 .lname = "Group reporting",
d2507043 3418 .type = FIO_OPT_STR_SET,
214e1eca
JA
3419 .off1 = td_var_offset(group_reporting),
3420 .help = "Do reporting on a per-group basis",
10860056 3421 .category = FIO_OPT_C_STAT,
e8b0e958 3422 .group = FIO_OPT_G_INVALID,
214e1eca 3423 },
e9459e5a
JA
3424 {
3425 .name = "zero_buffers",
e8b0e958 3426 .lname = "Zero I/O buffers",
e9459e5a
JA
3427 .type = FIO_OPT_STR_SET,
3428 .off1 = td_var_offset(zero_buffers),
3429 .help = "Init IO buffers to all zeroes",
e8b0e958 3430 .category = FIO_OPT_C_IO,
3ceb458f 3431 .group = FIO_OPT_G_IO_BUF,
e9459e5a 3432 },
5973cafb
JA
3433 {
3434 .name = "refill_buffers",
e8b0e958 3435 .lname = "Refill I/O buffers",
5973cafb
JA
3436 .type = FIO_OPT_STR_SET,
3437 .off1 = td_var_offset(refill_buffers),
3438 .help = "Refill IO buffers on every IO submit",
e8b0e958 3439 .category = FIO_OPT_C_IO,
3ceb458f 3440 .group = FIO_OPT_G_IO_BUF,
5973cafb 3441 },
fd68418e
JA
3442 {
3443 .name = "scramble_buffers",
e8b0e958 3444 .lname = "Scramble I/O buffers",
fd68418e
JA
3445 .type = FIO_OPT_BOOL,
3446 .off1 = td_var_offset(scramble_buffers),
3447 .help = "Slightly scramble buffers on every IO submit",
3448 .def = "1",
e8b0e958 3449 .category = FIO_OPT_C_IO,
3ceb458f 3450 .group = FIO_OPT_G_IO_BUF,
fd68418e 3451 },
ce35b1ec
JA
3452 {
3453 .name = "buffer_pattern",
3454 .lname = "Buffer pattern",
3455 .type = FIO_OPT_STR,
3456 .cb = str_buffer_pattern_cb,
a8523a6a 3457 .off1 = td_var_offset(buffer_pattern),
ce35b1ec
JA
3458 .help = "Fill pattern for IO buffers",
3459 .category = FIO_OPT_C_IO,
3460 .group = FIO_OPT_G_IO_BUF,
3461 },
9c42684e
JA
3462 {
3463 .name = "buffer_compress_percentage",
e8b0e958 3464 .lname = "Buffer compression percentage",
9c42684e 3465 .type = FIO_OPT_INT,
bedc9dc2 3466 .cb = str_buffer_compress_cb,
a8523a6a 3467 .off1 = td_var_offset(compress_percentage),
9c42684e 3468 .maxval = 100,
e7f5de90 3469 .minval = 0,
9c42684e 3470 .help = "How compressible the buffer is (approximately)",
20eb06bd 3471 .interval = 5,
e8b0e958 3472 .category = FIO_OPT_C_IO,
3ceb458f 3473 .group = FIO_OPT_G_IO_BUF,
9c42684e 3474 },
f97a43a1
JA
3475 {
3476 .name = "buffer_compress_chunk",
e8b0e958 3477 .lname = "Buffer compression chunk size",
f97a43a1
JA
3478 .type = FIO_OPT_INT,
3479 .off1 = td_var_offset(compress_chunk),
207b18e4 3480 .parent = "buffer_compress_percentage",
d71c154c 3481 .hide = 1,
f97a43a1 3482 .help = "Size of compressible region in buffer",
20eb06bd 3483 .interval = 256,
e8b0e958 3484 .category = FIO_OPT_C_IO,
3ceb458f 3485 .group = FIO_OPT_G_IO_BUF,
f97a43a1 3486 },
5c94b008
JA
3487 {
3488 .name = "dedupe_percentage",
3489 .lname = "Dedupe percentage",
3490 .type = FIO_OPT_INT,
3491 .cb = str_dedupe_cb,
a8523a6a 3492 .off1 = td_var_offset(dedupe_percentage),
5c94b008
JA
3493 .maxval = 100,
3494 .minval = 0,
3495 .help = "Percentage of buffers that are dedupable",
3496 .interval = 1,
3497 .category = FIO_OPT_C_IO,
3498 .group = FIO_OPT_G_IO_BUF,
3499 },
83349190
YH
3500 {
3501 .name = "clat_percentiles",
e8b0e958 3502 .lname = "Completion latency percentiles",
83349190
YH
3503 .type = FIO_OPT_BOOL,
3504 .off1 = td_var_offset(clat_percentiles),
3505 .help = "Enable the reporting of completion latency percentiles",
467b35ed 3506 .def = "1",
e8b0e958
JA
3507 .category = FIO_OPT_C_STAT,
3508 .group = FIO_OPT_G_INVALID,
83349190
YH
3509 },
3510 {
3511 .name = "percentile_list",
66347cfa 3512 .lname = "Percentile list",
83349190
YH
3513 .type = FIO_OPT_FLOAT_LIST,
3514 .off1 = td_var_offset(percentile_list),
435d195a 3515 .off2 = td_var_offset(percentile_precision),
66347cfa
DE
3516 .help = "Specify a custom list of percentiles to report for "
3517 "completion latency and block errors",
fd112d34 3518 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
3519 .maxlen = FIO_IO_U_LIST_MAX_LEN,
3520 .minfp = 0.0,
3521 .maxfp = 100.0,
e8b0e958
JA
3522 .category = FIO_OPT_C_STAT,
3523 .group = FIO_OPT_G_INVALID,
83349190
YH
3524 },
3525
0a839f30
JA
3526#ifdef FIO_HAVE_DISK_UTIL
3527 {
3528 .name = "disk_util",
e8b0e958 3529 .lname = "Disk utilization",
0a839f30
JA
3530 .type = FIO_OPT_BOOL,
3531 .off1 = td_var_offset(do_disk_util),
f66ab3c8 3532 .help = "Log disk utilization statistics",
0a839f30 3533 .def = "1",
e8b0e958
JA
3534 .category = FIO_OPT_C_STAT,
3535 .group = FIO_OPT_G_INVALID,
0a839f30
JA
3536 },
3537#endif
993bf48b
JA
3538 {
3539 .name = "gtod_reduce",
e8b0e958 3540 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
3541 .type = FIO_OPT_BOOL,
3542 .help = "Greatly reduce number of gettimeofday() calls",
3543 .cb = str_gtod_reduce_cb,
3544 .def = "0",
a4ed77fe 3545 .hide_on_set = 1,
e8b0e958
JA
3546 .category = FIO_OPT_C_STAT,
3547 .group = FIO_OPT_G_INVALID,
993bf48b 3548 },
02af0988
JA
3549 {
3550 .name = "disable_lat",
e8b0e958 3551 .lname = "Disable all latency stats",
02af0988
JA
3552 .type = FIO_OPT_BOOL,
3553 .off1 = td_var_offset(disable_lat),
3554 .help = "Disable latency numbers",
3555 .parent = "gtod_reduce",
d71c154c 3556 .hide = 1,
02af0988 3557 .def = "0",
e8b0e958
JA
3558 .category = FIO_OPT_C_STAT,
3559 .group = FIO_OPT_G_INVALID,
02af0988 3560 },
9520ebb9
JA
3561 {
3562 .name = "disable_clat",
e8b0e958 3563 .lname = "Disable completion latency stats",
9520ebb9
JA
3564 .type = FIO_OPT_BOOL,
3565 .off1 = td_var_offset(disable_clat),
3566 .help = "Disable completion latency numbers",
993bf48b 3567 .parent = "gtod_reduce",
d71c154c 3568 .hide = 1,
9520ebb9 3569 .def = "0",
e8b0e958
JA
3570 .category = FIO_OPT_C_STAT,
3571 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3572 },
3573 {
3574 .name = "disable_slat",
e8b0e958 3575 .lname = "Disable submission latency stats",
9520ebb9
JA
3576 .type = FIO_OPT_BOOL,
3577 .off1 = td_var_offset(disable_slat),
03e20d68 3578 .help = "Disable submission latency numbers",
993bf48b 3579 .parent = "gtod_reduce",
d71c154c 3580 .hide = 1,
9520ebb9 3581 .def = "0",
e8b0e958
JA
3582 .category = FIO_OPT_C_STAT,
3583 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
3584 },
3585 {
3586 .name = "disable_bw_measurement",
e8b0e958 3587 .lname = "Disable bandwidth stats",
9520ebb9
JA
3588 .type = FIO_OPT_BOOL,
3589 .off1 = td_var_offset(disable_bw),
3590 .help = "Disable bandwidth logging",
993bf48b 3591 .parent = "gtod_reduce",
d71c154c 3592 .hide = 1,
9520ebb9 3593 .def = "0",
e8b0e958
JA
3594 .category = FIO_OPT_C_STAT,
3595 .group = FIO_OPT_G_INVALID,
9520ebb9 3596 },
be4ecfdf
JA
3597 {
3598 .name = "gtod_cpu",
e8b0e958 3599 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 3600 .type = FIO_OPT_INT,
79c896a1 3601 .off1 = td_var_offset(gtod_cpu),
03e20d68 3602 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 3603 .verify = gtod_cpu_verify,
e8b0e958 3604 .category = FIO_OPT_C_GENERAL,
10860056 3605 .group = FIO_OPT_G_CLOCK,
be4ecfdf 3606 },
771e58be
JA
3607 {
3608 .name = "unified_rw_reporting",
3609 .type = FIO_OPT_BOOL,
3610 .off1 = td_var_offset(unified_rw_rep),
3611 .help = "Unify reporting across data direction",
3612 .def = "0",
90b7a96d
JA
3613 .category = FIO_OPT_C_GENERAL,
3614 .group = FIO_OPT_G_INVALID,
771e58be 3615 },
f2bba182
RR
3616 {
3617 .name = "continue_on_error",
e8b0e958 3618 .lname = "Continue on error",
06842027 3619 .type = FIO_OPT_STR,
f2bba182 3620 .off1 = td_var_offset(continue_on_error),
03e20d68 3621 .help = "Continue on non-fatal errors during IO",
06842027 3622 .def = "none",
e8b0e958 3623 .category = FIO_OPT_C_GENERAL,
bc3f552f 3624 .group = FIO_OPT_G_ERR,
06842027
SL
3625 .posval = {
3626 { .ival = "none",
3627 .oval = ERROR_TYPE_NONE,
3628 .help = "Exit when an error is encountered",
3629 },
3630 { .ival = "read",
3631 .oval = ERROR_TYPE_READ,
3632 .help = "Continue on read errors only",
3633 },
3634 { .ival = "write",
3635 .oval = ERROR_TYPE_WRITE,
3636 .help = "Continue on write errors only",
3637 },
3638 { .ival = "io",
3639 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
3640 .help = "Continue on any IO errors",
3641 },
3642 { .ival = "verify",
3643 .oval = ERROR_TYPE_VERIFY,
3644 .help = "Continue on verify errors only",
3645 },
3646 { .ival = "all",
3647 .oval = ERROR_TYPE_ANY,
3648 .help = "Continue on all io and verify errors",
3649 },
3650 { .ival = "0",
3651 .oval = ERROR_TYPE_NONE,
3652 .help = "Alias for 'none'",
3653 },
3654 { .ival = "1",
3655 .oval = ERROR_TYPE_ANY,
3656 .help = "Alias for 'all'",
3657 },
3658 },
f2bba182 3659 },
8b28bd41
DM
3660 {
3661 .name = "ignore_error",
3662 .type = FIO_OPT_STR,
3663 .cb = str_ignore_error_cb,
a8523a6a 3664 .off1 = td_var_offset(ignore_error_nr),
8b28bd41
DM
3665 .help = "Set a specific list of errors to ignore",
3666 .parent = "rw",
a94eb99a 3667 .category = FIO_OPT_C_GENERAL,
bc3f552f 3668 .group = FIO_OPT_G_ERR,
8b28bd41
DM
3669 },
3670 {
3671 .name = "error_dump",
3672 .type = FIO_OPT_BOOL,
3673 .off1 = td_var_offset(error_dump),
3674 .def = "0",
3675 .help = "Dump info on each error",
a94eb99a 3676 .category = FIO_OPT_C_GENERAL,
bc3f552f 3677 .group = FIO_OPT_G_ERR,
8b28bd41 3678 },
9ac8a797
JA
3679 {
3680 .name = "profile",
e8b0e958 3681 .lname = "Profile",
79d16311 3682 .type = FIO_OPT_STR_STORE,
9ac8a797 3683 .off1 = td_var_offset(profile),
9ac8a797 3684 .help = "Select a specific builtin performance test",
13fca827 3685 .category = FIO_OPT_C_PROFILE,
e8b0e958 3686 .group = FIO_OPT_G_INVALID,
9ac8a797 3687 },
a696fa2a
JA
3688 {
3689 .name = "cgroup",
e8b0e958 3690 .lname = "Cgroup",
a696fa2a
JA
3691 .type = FIO_OPT_STR_STORE,
3692 .off1 = td_var_offset(cgroup),
3693 .help = "Add job to cgroup of this name",
e8b0e958 3694 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
3695 .group = FIO_OPT_G_CGROUP,
3696 },
3697 {
3698 .name = "cgroup_nodelete",
3699 .lname = "Cgroup no-delete",
3700 .type = FIO_OPT_BOOL,
3701 .off1 = td_var_offset(cgroup_nodelete),
3702 .help = "Do not delete cgroups after job completion",
3703 .def = "0",
3704 .parent = "cgroup",
3705 .category = FIO_OPT_C_GENERAL,
3706 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
3707 },
3708 {
3709 .name = "cgroup_weight",
e8b0e958 3710 .lname = "Cgroup weight",
a696fa2a
JA
3711 .type = FIO_OPT_INT,
3712 .off1 = td_var_offset(cgroup_weight),
3713 .help = "Use given weight for cgroup",
3714 .minval = 100,
3715 .maxval = 1000,
a1f6afec 3716 .parent = "cgroup",
e8b0e958 3717 .category = FIO_OPT_C_GENERAL,
a1f6afec 3718 .group = FIO_OPT_G_CGROUP,
7de87099 3719 },
e0b0d892
JA
3720 {
3721 .name = "uid",
e8b0e958 3722 .lname = "User ID",
e0b0d892
JA
3723 .type = FIO_OPT_INT,
3724 .off1 = td_var_offset(uid),
3725 .help = "Run job with this user ID",
e8b0e958 3726 .category = FIO_OPT_C_GENERAL,
10860056 3727 .group = FIO_OPT_G_CRED,
e0b0d892
JA
3728 },
3729 {
3730 .name = "gid",
e8b0e958 3731 .lname = "Group ID",
e0b0d892
JA
3732 .type = FIO_OPT_INT,
3733 .off1 = td_var_offset(gid),
3734 .help = "Run job with this group ID",
e8b0e958 3735 .category = FIO_OPT_C_GENERAL,
10860056 3736 .group = FIO_OPT_G_CRED,
e0b0d892 3737 },
a1f6afec
JA
3738 {
3739 .name = "kb_base",
3740 .lname = "KB Base",
3741 .type = FIO_OPT_INT,
3742 .off1 = td_var_offset(kb_base),
a1f6afec
JA
3743 .prio = 1,
3744 .def = "1024",
ba9c7219
JA
3745 .posval = {
3746 { .ival = "1024",
3747 .oval = 1024,
3748 .help = "Use 1024 as the K base",
3749 },
3750 { .ival = "1000",
3751 .oval = 1000,
3752 .help = "Use 1000 as the K base",
3753 },
3754 },
a1f6afec
JA
3755 .help = "How many bytes per KB for reporting (1000 or 1024)",
3756 .category = FIO_OPT_C_GENERAL,
3757 .group = FIO_OPT_G_INVALID,
3758 },
cf3a0518
JA
3759 {
3760 .name = "unit_base",
ba9c7219 3761 .lname = "Base unit for reporting (Bits or Bytes)",
cf3a0518
JA
3762 .type = FIO_OPT_INT,
3763 .off1 = td_var_offset(unit_base),
cf3a0518 3764 .prio = 1,
71a08258
JA
3765 .posval = {
3766 { .ival = "0",
3767 .oval = 0,
3768 .help = "Auto-detect",
3769 },
3770 { .ival = "8",
3771 .oval = 8,
3772 .help = "Normal (byte based)",
3773 },
3774 { .ival = "1",
3775 .oval = 1,
3776 .help = "Bit based",
3777 },
3778 },
cf3a0518
JA
3779 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
3780 .category = FIO_OPT_C_GENERAL,
3781 .group = FIO_OPT_G_INVALID,
3782 },
3ceb458f
JA
3783 {
3784 .name = "hugepage-size",
3785 .lname = "Hugepage size",
3786 .type = FIO_OPT_INT,
3787 .off1 = td_var_offset(hugepage_size),
3788 .help = "When using hugepages, specify size of each page",
3789 .def = __fio_stringify(FIO_HUGE_PAGE),
3790 .interval = 1024 * 1024,
3791 .category = FIO_OPT_C_GENERAL,
3792 .group = FIO_OPT_G_INVALID,
3793 },
9e684a49
DE
3794 {
3795 .name = "flow_id",
e8b0e958 3796 .lname = "I/O flow ID",
9e684a49
DE
3797 .type = FIO_OPT_INT,
3798 .off1 = td_var_offset(flow_id),
3799 .help = "The flow index ID to use",
3800 .def = "0",
e8b0e958
JA
3801 .category = FIO_OPT_C_IO,
3802 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3803 },
3804 {
3805 .name = "flow",
e8b0e958 3806 .lname = "I/O flow weight",
9e684a49
DE
3807 .type = FIO_OPT_INT,
3808 .off1 = td_var_offset(flow),
3809 .help = "Weight for flow control of this job",
3810 .parent = "flow_id",
d71c154c 3811 .hide = 1,
9e684a49 3812 .def = "0",
e8b0e958
JA
3813 .category = FIO_OPT_C_IO,
3814 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3815 },
3816 {
3817 .name = "flow_watermark",
e8b0e958 3818 .lname = "I/O flow watermark",
9e684a49
DE
3819 .type = FIO_OPT_INT,
3820 .off1 = td_var_offset(flow_watermark),
3821 .help = "High watermark for flow control. This option"
3822 " should be set to the same value for all threads"
3823 " with non-zero flow.",
3824 .parent = "flow_id",
d71c154c 3825 .hide = 1,
9e684a49 3826 .def = "1024",
e8b0e958
JA
3827 .category = FIO_OPT_C_IO,
3828 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
3829 },
3830 {
3831 .name = "flow_sleep",
e8b0e958 3832 .lname = "I/O flow sleep",
9e684a49
DE
3833 .type = FIO_OPT_INT,
3834 .off1 = td_var_offset(flow_sleep),
3835 .help = "How many microseconds to sleep after being held"
3836 " back by the flow control mechanism",
3837 .parent = "flow_id",
d71c154c 3838 .hide = 1,
9e684a49 3839 .def = "0",
e8b0e958
JA
3840 .category = FIO_OPT_C_IO,
3841 .group = FIO_OPT_G_IO_FLOW,
9e684a49 3842 },
65fa28ca
DE
3843 {
3844 .name = "skip_bad",
3845 .lname = "Skip operations against bad blocks",
3846 .type = FIO_OPT_BOOL,
3847 .off1 = td_var_offset(skip_bad),
3848 .help = "Skip operations against known bad blocks.",
3849 .hide = 1,
3850 .def = "0",
3851 .category = FIO_OPT_C_IO,
3852 .group = FIO_OPT_G_MTD,
3853 },
214e1eca
JA
3854 {
3855 .name = NULL,
3856 },
3857};
3858
17af15d4 3859static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 3860 const char *name, int val)
9f81736c 3861{
17af15d4 3862 lopt->name = (char *) name;
de890a1e 3863 lopt->val = val;
9f81736c 3864 if (o->type == FIO_OPT_STR_SET)
ff52be3d 3865 lopt->has_arg = optional_argument;
9f81736c
JA
3866 else
3867 lopt->has_arg = required_argument;
3868}
3869
de890a1e
SL
3870static void options_to_lopts(struct fio_option *opts,
3871 struct option *long_options,
3872 int i, int option_type)
214e1eca 3873{
de890a1e 3874 struct fio_option *o = &opts[0];
214e1eca 3875 while (o->name) {
de890a1e 3876 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
3877 if (o->alias) {
3878 i++;
de890a1e 3879 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 3880 }
214e1eca
JA
3881
3882 i++;
3883 o++;
3884 assert(i < FIO_NR_OPTIONS);
3885 }
3886}
3887
de890a1e
SL
3888void fio_options_set_ioengine_opts(struct option *long_options,
3889 struct thread_data *td)
3890{
3891 unsigned int i;
3892
3893 i = 0;
3894 while (long_options[i].name) {
3895 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
3896 memset(&long_options[i], 0, sizeof(*long_options));
3897 break;
3898 }
3899 i++;
3900 }
3901
3902 /*
3903 * Just clear out the prior ioengine options.
3904 */
3905 if (!td || !td->eo)
3906 return;
3907
3908 options_to_lopts(td->io_ops->options, long_options, i,
3909 FIO_GETOPT_IOENGINE);
3910}
3911
3912void fio_options_dup_and_init(struct option *long_options)
3913{
3914 unsigned int i;
3915
9af4a244 3916 options_init(fio_options);
de890a1e
SL
3917
3918 i = 0;
3919 while (long_options[i].name)
3920 i++;
3921
9af4a244 3922 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
3923}
3924
74929ac2
JA
3925struct fio_keyword {
3926 const char *word;
3927 const char *desc;
3928 char *replace;
3929};
3930
3931static struct fio_keyword fio_keywords[] = {
3932 {
3933 .word = "$pagesize",
3934 .desc = "Page size in the system",
3935 },
3936 {
3937 .word = "$mb_memory",
3938 .desc = "Megabytes of memory online",
3939 },
3940 {
3941 .word = "$ncpus",
3942 .desc = "Number of CPUs online in the system",
3943 },
3944 {
3945 .word = NULL,
3946 },
3947};
3948
af1dc266
JA
3949void fio_keywords_exit(void)
3950{
3951 struct fio_keyword *kw;
3952
3953 kw = &fio_keywords[0];
3954 while (kw->word) {
3955 free(kw->replace);
3956 kw->replace = NULL;
3957 kw++;
3958 }
3959}
3960
74929ac2
JA
3961void fio_keywords_init(void)
3962{
3b2e1464 3963 unsigned long long mb_memory;
74929ac2
JA
3964 char buf[128];
3965 long l;
3966
a4cfc477 3967 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
3968 fio_keywords[0].replace = strdup(buf);
3969
8eb016d3 3970 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 3971 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
3972 fio_keywords[1].replace = strdup(buf);
3973
c00a2289 3974 l = cpus_online();
74929ac2
JA
3975 sprintf(buf, "%lu", l);
3976 fio_keywords[2].replace = strdup(buf);
3977}
3978
892a6ffc
JA
3979#define BC_APP "bc"
3980
3981static char *bc_calc(char *str)
3982{
d0c814ec 3983 char buf[128], *tmp;
892a6ffc
JA
3984 FILE *f;
3985 int ret;
3986
3987 /*
3988 * No math, just return string
3989 */
d0c814ec
SL
3990 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
3991 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
3992 return str;
3993
3994 /*
3995 * Split option from value, we only need to calculate the value
3996 */
3997 tmp = strchr(str, '=');
3998 if (!tmp)
3999 return str;
4000
4001 tmp++;
892a6ffc 4002
d0c814ec
SL
4003 /*
4004 * Prevent buffer overflows; such a case isn't reasonable anyway
4005 */
4006 if (strlen(str) >= 128 || strlen(tmp) > 100)
4007 return str;
892a6ffc
JA
4008
4009 sprintf(buf, "which %s > /dev/null", BC_APP);
4010 if (system(buf)) {
4011 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
4012 return NULL;
4013 }
4014
d0c814ec 4015 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 4016 f = popen(buf, "r");
3c3ed070 4017 if (!f)
892a6ffc 4018 return NULL;
892a6ffc 4019
d0c814ec 4020 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
4021 if (ret <= 0) {
4022 pclose(f);
892a6ffc 4023 return NULL;
1d824f37 4024 }
892a6ffc 4025
892a6ffc 4026 pclose(f);
d0c814ec
SL
4027 buf[(tmp - str) + ret - 1] = '\0';
4028 memcpy(buf, str, tmp - str);
892a6ffc 4029 free(str);
d0c814ec
SL
4030 return strdup(buf);
4031}
4032
4033/*
4034 * Return a copy of the input string with substrings of the form ${VARNAME}
4035 * substituted with the value of the environment variable VARNAME. The
4036 * substitution always occurs, even if VARNAME is empty or the corresponding
4037 * environment variable undefined.
4038 */
4039static char *option_dup_subs(const char *opt)
4040{
4041 char out[OPT_LEN_MAX+1];
4042 char in[OPT_LEN_MAX+1];
4043 char *outptr = out;
4044 char *inptr = in;
4045 char *ch1, *ch2, *env;
4046 ssize_t nchr = OPT_LEN_MAX;
4047 size_t envlen;
4048
4049 if (strlen(opt) + 1 > OPT_LEN_MAX) {
4050 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
4051 return NULL;
4052 }
4053
4054 in[OPT_LEN_MAX] = '\0';
4055 strncpy(in, opt, OPT_LEN_MAX);
4056
4057 while (*inptr && nchr > 0) {
4058 if (inptr[0] == '$' && inptr[1] == '{') {
4059 ch2 = strchr(inptr, '}');
4060 if (ch2 && inptr+1 < ch2) {
4061 ch1 = inptr+2;
4062 inptr = ch2+1;
4063 *ch2 = '\0';
4064
4065 env = getenv(ch1);
4066 if (env) {
4067 envlen = strlen(env);
4068 if (envlen <= nchr) {
4069 memcpy(outptr, env, envlen);
4070 outptr += envlen;
4071 nchr -= envlen;
4072 }
4073 }
4074
4075 continue;
4076 }
4077 }
4078
4079 *outptr++ = *inptr++;
4080 --nchr;
4081 }
4082
4083 *outptr = '\0';
4084 return strdup(out);
892a6ffc
JA
4085}
4086
74929ac2
JA
4087/*
4088 * Look for reserved variable names and replace them with real values
4089 */
4090static char *fio_keyword_replace(char *opt)
4091{
4092 char *s;
4093 int i;
d0c814ec 4094 int docalc = 0;
74929ac2
JA
4095
4096 for (i = 0; fio_keywords[i].word != NULL; i++) {
4097 struct fio_keyword *kw = &fio_keywords[i];
4098
4099 while ((s = strstr(opt, kw->word)) != NULL) {
4100 char *new = malloc(strlen(opt) + 1);
4101 char *o_org = opt;
4102 int olen = s - opt;
4103 int len;
4104
4105 /*
4106 * Copy part of the string before the keyword and
4107 * sprintf() the replacement after it.
4108 */
4109 memcpy(new, opt, olen);
4110 len = sprintf(new + olen, "%s", kw->replace);
4111
4112 /*
4113 * If there's more in the original string, copy that
4114 * in too
4115 */
4116 opt += strlen(kw->word) + olen;
4117 if (strlen(opt))
4118 memcpy(new + olen + len, opt, opt - o_org - 1);
4119
4120 /*
4121 * replace opt and free the old opt
4122 */
4123 opt = new;
d0c814ec 4124 free(o_org);
7a958bd5 4125
d0c814ec 4126 docalc = 1;
74929ac2
JA
4127 }
4128 }
4129
d0c814ec
SL
4130 /*
4131 * Check for potential math and invoke bc, if possible
4132 */
4133 if (docalc)
4134 opt = bc_calc(opt);
4135
7a958bd5 4136 return opt;
74929ac2
JA
4137}
4138
d0c814ec
SL
4139static char **dup_and_sub_options(char **opts, int num_opts)
4140{
4141 int i;
4142 char **opts_copy = malloc(num_opts * sizeof(*opts));
4143 for (i = 0; i < num_opts; i++) {
4144 opts_copy[i] = option_dup_subs(opts[i]);
4145 if (!opts_copy[i])
4146 continue;
4147 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
4148 }
4149 return opts_copy;
4150}
4151
e15b023b 4152static void show_closest_option(const char *opt)
a2d027b9
JA
4153{
4154 int best_option, best_distance;
4155 int i, distance;
e15b023b
JA
4156 char *name;
4157
4158 if (!strlen(opt))
4159 return;
4160
4161 name = strdup(opt);
4162 i = 0;
4163 while (name[i] != '\0' && name[i] != '=')
4164 i++;
4165 name[i] = '\0';
a2d027b9
JA
4166
4167 best_option = -1;
4168 best_distance = INT_MAX;
4169 i = 0;
4170 while (fio_options[i].name) {
4171 distance = string_distance(name, fio_options[i].name);
4172 if (distance < best_distance) {
4173 best_distance = distance;
4174 best_option = i;
4175 }
4176 i++;
4177 }
4178
3701636d 4179 if (best_option != -1 && string_distance_ok(name, best_distance))
a2d027b9 4180 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
4181
4182 free(name);
a2d027b9
JA
4183}
4184
c2292325 4185int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 4186{
de890a1e 4187 int i, ret, unknown;
d0c814ec 4188 char **opts_copy;
3b8b7135 4189
9af4a244 4190 sort_options(opts, fio_options, num_opts);
d0c814ec 4191 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 4192
de890a1e
SL
4193 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
4194 struct fio_option *o;
9af4a244 4195 int newret = parse_option(opts_copy[i], opts[i], fio_options,
66e19a38 4196 &o, td, &td->opt_list);
d0c814ec 4197
a8523a6a
JA
4198 if (!newret && o)
4199 fio_option_mark_set(&td->o, o);
4200
de890a1e
SL
4201 if (opts_copy[i]) {
4202 if (newret && !o) {
4203 unknown++;
4204 continue;
4205 }
d0c814ec 4206 free(opts_copy[i]);
de890a1e
SL
4207 opts_copy[i] = NULL;
4208 }
4209
4210 ret |= newret;
4211 }
4212
4213 if (unknown) {
4214 ret |= ioengine_load(td);
4215 if (td->eo) {
4216 sort_options(opts_copy, td->io_ops->options, num_opts);
4217 opts = opts_copy;
4218 }
4219 for (i = 0; i < num_opts; i++) {
4220 struct fio_option *o = NULL;
4221 int newret = 1;
a2d027b9 4222
de890a1e
SL
4223 if (!opts_copy[i])
4224 continue;
4225
4226 if (td->eo)
4227 newret = parse_option(opts_copy[i], opts[i],
4228 td->io_ops->options, &o,
66e19a38 4229 td->eo, &td->opt_list);
de890a1e
SL
4230
4231 ret |= newret;
a2d027b9 4232 if (!o) {
de890a1e 4233 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
4234 show_closest_option(opts[i]);
4235 }
de890a1e
SL
4236 free(opts_copy[i]);
4237 opts_copy[i] = NULL;
4238 }
74929ac2 4239 }
3b8b7135 4240
d0c814ec 4241 free(opts_copy);
3b8b7135 4242 return ret;
214e1eca
JA
4243}
4244
4245int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
4246{
a8523a6a
JA
4247 int ret;
4248
d8b4f395 4249 ret = parse_cmd_option(opt, val, fio_options, td, &td->opt_list);
a8523a6a
JA
4250 if (!ret) {
4251 struct fio_option *o;
4252
4253 o = find_option(fio_options, opt);
4254 if (o)
4255 fio_option_mark_set(&td->o, o);
4256 }
4257
4258 return ret;
214e1eca
JA
4259}
4260
de890a1e
SL
4261int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
4262 char *val)
4263{
d8b4f395
JA
4264 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
4265 &td->opt_list);
de890a1e
SL
4266}
4267
214e1eca
JA
4268void fio_fill_default_options(struct thread_data *td)
4269{
cb1402d6 4270 td->o.magic = OPT_MAGIC;
9af4a244 4271 fill_default_options(td, fio_options);
214e1eca
JA
4272}
4273
4274int fio_show_option_help(const char *opt)
4275{
9af4a244 4276 return show_cmd_help(fio_options, opt);
214e1eca 4277}
d23bb327 4278
de890a1e 4279void options_mem_dupe(void *data, struct fio_option *options)
d23bb327 4280{
de890a1e 4281 struct fio_option *o;
d23bb327 4282 char **ptr;
d23bb327 4283
de890a1e
SL
4284 for (o = &options[0]; o->name; o++) {
4285 if (o->type != FIO_OPT_STR_STORE)
d23bb327
JA
4286 continue;
4287
f0fdbcaf 4288 ptr = td_var(data, o, o->off1);
7e356b2d
JA
4289 if (*ptr)
4290 *ptr = strdup(*ptr);
d23bb327
JA
4291 }
4292}
4293
de890a1e
SL
4294/*
4295 * dupe FIO_OPT_STR_STORE options
4296 */
4297void fio_options_mem_dupe(struct thread_data *td)
4298{
9af4a244 4299 options_mem_dupe(&td->o, fio_options);
1647f592
JA
4300
4301 if (td->eo && td->io_ops) {
de890a1e 4302 void *oldeo = td->eo;
1647f592 4303
de890a1e
SL
4304 td->eo = malloc(td->io_ops->option_struct_size);
4305 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
4306 options_mem_dupe(td->eo, td->io_ops->options);
4307 }
4308}
4309
d6978a32
JA
4310unsigned int fio_get_kb_base(void *data)
4311{
83ea422a 4312 struct thread_options *o = data;
d6978a32
JA
4313 unsigned int kb_base = 0;
4314
cb1402d6
JA
4315 /*
4316 * This is a hack... For private options, *data is not holding
4317 * a pointer to the thread_options, but to private data. This means
4318 * we can't safely dereference it, but magic is first so mem wise
4319 * it is valid. But this also means that if the job first sets
4320 * kb_base and expects that to be honored by private options,
4321 * it will be disappointed. We will return the global default
4322 * for this.
4323 */
4324 if (o && o->magic == OPT_MAGIC)
83ea422a 4325 kb_base = o->kb_base;
d6978a32
JA
4326 if (!kb_base)
4327 kb_base = 1024;
4328
4329 return kb_base;
4330}
9f988e2e 4331
07b3232d 4332int add_option(struct fio_option *o)
9f988e2e 4333{
07b3232d
JA
4334 struct fio_option *__o;
4335 int opt_index = 0;
4336
9af4a244 4337 __o = fio_options;
07b3232d
JA
4338 while (__o->name) {
4339 opt_index++;
4340 __o++;
4341 }
4342
7b504edd
JA
4343 if (opt_index + 1 == FIO_MAX_OPTS) {
4344 log_err("fio: FIO_MAX_OPTS is too small\n");
4345 return 1;
4346 }
4347
9af4a244 4348 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 4349 fio_options[opt_index + 1].name = NULL;
07b3232d 4350 return 0;
9f988e2e 4351}
e2de69da 4352
07b3232d 4353void invalidate_profile_options(const char *prof_name)
e2de69da 4354{
07b3232d 4355 struct fio_option *o;
e2de69da 4356
9af4a244 4357 o = fio_options;
07b3232d
JA
4358 while (o->name) {
4359 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
4360 o->type = FIO_OPT_INVALID;
4361 o->prof_name = NULL;
4362 }
4363 o++;
e2de69da
JA
4364 }
4365}
f5b6bb85
JA
4366
4367void add_opt_posval(const char *optname, const char *ival, const char *help)
4368{
4369 struct fio_option *o;
4370 unsigned int i;
4371
9af4a244 4372 o = find_option(fio_options, optname);
f5b6bb85
JA
4373 if (!o)
4374 return;
4375
4376 for (i = 0; i < PARSE_MAX_VP; i++) {
4377 if (o->posval[i].ival)
4378 continue;
4379
4380 o->posval[i].ival = ival;
4381 o->posval[i].help = help;
4382 break;
4383 }
4384}
4385
4386void del_opt_posval(const char *optname, const char *ival)
4387{
4388 struct fio_option *o;
4389 unsigned int i;
4390
9af4a244 4391 o = find_option(fio_options, optname);
f5b6bb85
JA
4392 if (!o)
4393 return;
4394
4395 for (i = 0; i < PARSE_MAX_VP; i++) {
4396 if (!o->posval[i].ival)
4397 continue;
4398 if (strcmp(o->posval[i].ival, ival))
4399 continue;
4400
4401 o->posval[i].ival = NULL;
4402 o->posval[i].help = NULL;
4403 }
4404}
7e356b2d
JA
4405
4406void fio_options_free(struct thread_data *td)
4407{
9af4a244 4408 options_free(fio_options, td);
de890a1e
SL
4409 if (td->eo && td->io_ops && td->io_ops->options) {
4410 options_free(td->io_ops->options, td->eo);
4411 free(td->eo);
4412 td->eo = NULL;
4413 }
7e356b2d 4414}
c504ee55
JA
4415
4416struct fio_option *fio_option_find(const char *name)
4417{
4418 return find_option(fio_options, name);
4419}
4420
f0e7f45a
JA
4421static struct fio_option *find_next_opt(struct thread_options *o,
4422 struct fio_option *from,
4423 unsigned int off1)
a8523a6a 4424{
f0e7f45a 4425 struct fio_option *opt;
a8523a6a 4426
f0e7f45a
JA
4427 if (!from)
4428 from = &fio_options[0];
4429 else
4430 from++;
4431
4432 opt = NULL;
4433 do {
4434 if (off1 == from->off1) {
4435 opt = from;
a8523a6a
JA
4436 break;
4437 }
f0e7f45a
JA
4438 from++;
4439 } while (from->name);
a8523a6a 4440
f0e7f45a
JA
4441 return opt;
4442}
4443
4444static int opt_is_set(struct thread_options *o, struct fio_option *opt)
4445{
4446 unsigned int opt_off, index, offset;
a8523a6a
JA
4447
4448 opt_off = opt - &fio_options[0];
4449 index = opt_off / (8 * sizeof(uint64_t));
4450 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 4451 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
4452}
4453
72f39748 4454bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
4455{
4456 struct fio_option *opt, *next;
4457
4458 next = NULL;
4459 while ((opt = find_next_opt(o, next, off1)) != NULL) {
4460 if (opt_is_set(o, opt))
72f39748 4461 return true;
f0e7f45a
JA
4462
4463 next = opt;
4464 }
4465
72f39748 4466 return false;
f0e7f45a
JA
4467}
4468
a8523a6a
JA
4469void fio_option_mark_set(struct thread_options *o, struct fio_option *opt)
4470{
4471 unsigned int opt_off, index, offset;
4472
4473 opt_off = opt - &fio_options[0];
4474 index = opt_off / (8 * sizeof(uint64_t));
4475 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 4476 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 4477}