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