Deprecate verifysort and verifysort_nr
[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
9109883a 1520static int rw_verify(const struct fio_option *o, void *data)
896cac2a 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
9109883a 1533static int gtod_cpu_verify(const 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 1818#endif
67bf9823 1819#ifdef CONFIG_RDMA
21b8aee8 1820 { .ival = "rdma",
1821 .help = "RDMA IO engine",
1822 },
8200b8c7 1823#endif
67bf9823 1824#ifdef CONFIG_FUSION_AW
8200b8c7
JA
1825 { .ival = "fusion-aw-sync",
1826 .help = "Fusion-io atomic write engine",
1827 },
1ecc95ca 1828#endif
997843cb 1829#ifdef CONFIG_LINUX_EXT4_MOVE_EXTENT
1ecc95ca
JA
1830 { .ival = "e4defrag",
1831 .help = "ext4 defrag engine",
1832 },
1833#endif
997843cb 1834#ifdef CONFIG_LINUX_FALLOCATE
1ecc95ca
JA
1835 { .ival = "falloc",
1836 .help = "fallocate() file based engine",
1837 },
b8c82a46 1838#endif
a7c386f4 1839#ifdef CONFIG_GFAPI
1840 { .ival = "gfapi",
cc47f094 1841 .help = "Glusterfs libgfapi(sync) based engine"
1842 },
1843 { .ival = "gfapi_async",
1844 .help = "Glusterfs libgfapi(async) based engine"
a7c386f4 1845 },
1846#endif
1b10477b 1847#ifdef CONFIG_LIBHDFS
b74e419e 1848 { .ival = "libhdfs",
1b10477b
MM
1849 .help = "Hadoop Distributed Filesystem (HDFS) engine"
1850 },
5c4ef02e
JA
1851#endif
1852#ifdef CONFIG_PMEMBLK
1853 { .ival = "pmemblk",
363a5f65 1854 .help = "PMDK libpmemblk based IO engine",
5c4ef02e
JA
1855 },
1856
104ee4de
DJ
1857#endif
1858#ifdef CONFIG_LINUX_DEVDAX
1859 { .ival = "dev-dax",
1860 .help = "DAX Device based IO engine",
1861 },
1b10477b 1862#endif
edc5fa12
JA
1863 {
1864 .ival = "filecreate",
1865 .help = "File creation engine",
1866 },
214e1eca
JA
1867 { .ival = "external",
1868 .help = "Load external engine (append name)",
6730b40f 1869 .cb = str_ioengine_external_cb,
214e1eca 1870 },
ae0db592
TI
1871#ifdef CONFIG_LIBPMEM
1872 { .ival = "libpmem",
363a5f65 1873 .help = "PMDK libpmem based IO engine",
ae0db592
TI
1874 },
1875#endif
214e1eca
JA
1876 },
1877 },
1878 {
1879 .name = "iodepth",
e8b0e958 1880 .lname = "IO Depth",
214e1eca 1881 .type = FIO_OPT_INT,
a609f12a 1882 .off1 = offsetof(struct thread_options, iodepth),
03e20d68 1883 .help = "Number of IO buffers to keep in flight",
757aff4f 1884 .minval = 1,
20eb06bd 1885 .interval = 1,
214e1eca 1886 .def = "1",
e8b0e958 1887 .category = FIO_OPT_C_IO,
0626037e 1888 .group = FIO_OPT_G_IO_BASIC,
214e1eca
JA
1889 },
1890 {
1891 .name = "iodepth_batch",
e8b0e958 1892 .lname = "IO Depth batch",
4950421a 1893 .alias = "iodepth_batch_submit",
214e1eca 1894 .type = FIO_OPT_INT,
a609f12a 1895 .off1 = offsetof(struct thread_options, iodepth_batch),
d65db441 1896 .help = "Number of IO buffers to submit in one go",
afdf9352 1897 .parent = "iodepth",
d71c154c 1898 .hide = 1,
20eb06bd 1899 .interval = 1,
a2e6f8ac 1900 .def = "1",
e8b0e958 1901 .category = FIO_OPT_C_IO,
0626037e 1902 .group = FIO_OPT_G_IO_BASIC,
4950421a
JA
1903 },
1904 {
82407585
RP
1905 .name = "iodepth_batch_complete_min",
1906 .lname = "Min IO depth batch complete",
1907 .alias = "iodepth_batch_complete",
4950421a 1908 .type = FIO_OPT_INT,
a609f12a 1909 .off1 = offsetof(struct thread_options, iodepth_batch_complete_min),
82407585 1910 .help = "Min number of IO buffers to retrieve in one go",
4950421a 1911 .parent = "iodepth",
d71c154c 1912 .hide = 1,
4950421a 1913 .minval = 0,
20eb06bd 1914 .interval = 1,
4950421a 1915 .def = "1",
e8b0e958 1916 .category = FIO_OPT_C_IO,
0626037e 1917 .group = FIO_OPT_G_IO_BASIC,
214e1eca 1918 },
82407585
RP
1919 {
1920 .name = "iodepth_batch_complete_max",
1921 .lname = "Max IO depth batch complete",
1922 .type = FIO_OPT_INT,
a609f12a 1923 .off1 = offsetof(struct thread_options, iodepth_batch_complete_max),
82407585
RP
1924 .help = "Max number of IO buffers to retrieve in one go",
1925 .parent = "iodepth",
1926 .hide = 1,
1927 .minval = 0,
1928 .interval = 1,
1929 .category = FIO_OPT_C_IO,
1930 .group = FIO_OPT_G_IO_BASIC,
1931 },
214e1eca
JA
1932 {
1933 .name = "iodepth_low",
e8b0e958 1934 .lname = "IO Depth batch low",
214e1eca 1935 .type = FIO_OPT_INT,
a609f12a 1936 .off1 = offsetof(struct thread_options, iodepth_low),
214e1eca 1937 .help = "Low water mark for queuing depth",
afdf9352 1938 .parent = "iodepth",
d71c154c 1939 .hide = 1,
20eb06bd 1940 .interval = 1,
e8b0e958 1941 .category = FIO_OPT_C_IO,
0626037e 1942 .group = FIO_OPT_G_IO_BASIC,
214e1eca 1943 },
997b5680
SW
1944 {
1945 .name = "serialize_overlap",
1946 .lname = "Serialize overlap",
1947 .off1 = offsetof(struct thread_options, serialize_overlap),
1948 .type = FIO_OPT_BOOL,
1949 .help = "Wait for in-flight IOs that collide to complete",
1950 .parent = "iodepth",
1951 .def = "0",
1952 .category = FIO_OPT_C_IO,
1953 .group = FIO_OPT_G_IO_BASIC,
1954 },
a9da8ab2
JA
1955 {
1956 .name = "io_submit_mode",
1957 .lname = "IO submit mode",
1958 .type = FIO_OPT_STR,
a609f12a 1959 .off1 = offsetof(struct thread_options, io_submit_mode),
a9da8ab2
JA
1960 .help = "How IO submissions and completions are done",
1961 .def = "inline",
1962 .category = FIO_OPT_C_IO,
1963 .group = FIO_OPT_G_IO_BASIC,
1964 .posval = {
1965 { .ival = "inline",
1966 .oval = IO_MODE_INLINE,
1967 .help = "Submit and complete IO inline",
1968 },
1969 { .ival = "offload",
1970 .oval = IO_MODE_OFFLOAD,
1971 .help = "Offload submit and complete to threads",
1972 },
1973 },
1974 },
214e1eca
JA
1975 {
1976 .name = "size",
e8b0e958 1977 .lname = "Size",
214e1eca 1978 .type = FIO_OPT_STR_VAL,
7bb59102 1979 .cb = str_size_cb,
a609f12a 1980 .off1 = offsetof(struct thread_options, size),
214e1eca 1981 .help = "Total size of device or files",
20eb06bd 1982 .interval = 1024 * 1024,
e8b0e958
JA
1983 .category = FIO_OPT_C_IO,
1984 .group = FIO_OPT_G_INVALID,
214e1eca 1985 },
77731b29 1986 {
a4d3b4db
JA
1987 .name = "io_size",
1988 .alias = "io_limit",
1989 .lname = "IO Size",
77731b29 1990 .type = FIO_OPT_STR_VAL,
5be9bf09 1991 .off1 = offsetof(struct thread_options, io_size),
1684f7fd 1992 .help = "Total size of I/O to be performed",
77731b29
JA
1993 .interval = 1024 * 1024,
1994 .category = FIO_OPT_C_IO,
1995 .group = FIO_OPT_G_INVALID,
1996 },
aa31f1f1
SL
1997 {
1998 .name = "fill_device",
e8b0e958 1999 .lname = "Fill device",
74586c1e 2000 .alias = "fill_fs",
aa31f1f1 2001 .type = FIO_OPT_BOOL,
a609f12a 2002 .off1 = offsetof(struct thread_options, fill_device),
aa31f1f1
SL
2003 .help = "Write until an ENOSPC error occurs",
2004 .def = "0",
e8b0e958
JA
2005 .category = FIO_OPT_C_FILE,
2006 .group = FIO_OPT_G_INVALID,
aa31f1f1 2007 },
214e1eca
JA
2008 {
2009 .name = "filesize",
e8b0e958 2010 .lname = "File size",
214e1eca 2011 .type = FIO_OPT_STR_VAL,
a609f12a
JA
2012 .off1 = offsetof(struct thread_options, file_size_low),
2013 .off2 = offsetof(struct thread_options, file_size_high),
c3edbdba 2014 .minval = 1,
214e1eca 2015 .help = "Size of individual files",
20eb06bd 2016 .interval = 1024 * 1024,
e8b0e958
JA
2017 .category = FIO_OPT_C_FILE,
2018 .group = FIO_OPT_G_INVALID,
214e1eca 2019 },
bedc9dc2
JA
2020 {
2021 .name = "file_append",
2022 .lname = "File append",
2023 .type = FIO_OPT_BOOL,
a609f12a 2024 .off1 = offsetof(struct thread_options, file_append),
bedc9dc2
JA
2025 .help = "IO will start at the end of the file(s)",
2026 .def = "0",
2027 .category = FIO_OPT_C_FILE,
2028 .group = FIO_OPT_G_INVALID,
2029 },
67a1000f
JA
2030 {
2031 .name = "offset",
e8b0e958 2032 .lname = "IO offset",
67a1000f
JA
2033 .alias = "fileoffset",
2034 .type = FIO_OPT_STR_VAL,
89978a6b 2035 .cb = str_offset_cb,
a609f12a 2036 .off1 = offsetof(struct thread_options, start_offset),
67a1000f
JA
2037 .help = "Start IO from this offset",
2038 .def = "0",
20eb06bd 2039 .interval = 1024 * 1024,
e8b0e958
JA
2040 .category = FIO_OPT_C_IO,
2041 .group = FIO_OPT_G_INVALID,
67a1000f 2042 },
83c8b093
JF
2043 {
2044 .name = "offset_align",
2045 .lname = "IO offset alignment",
2046 .type = FIO_OPT_INT,
2047 .off1 = offsetof(struct thread_options, start_offset_align),
2048 .help = "Start IO from this offset alignment",
2049 .def = "0",
2050 .interval = 512,
2051 .category = FIO_OPT_C_IO,
2052 .group = FIO_OPT_G_INVALID,
2053 },
2d7cd868
JA
2054 {
2055 .name = "offset_increment",
e8b0e958 2056 .lname = "IO offset increment",
2d7cd868 2057 .type = FIO_OPT_STR_VAL,
a609f12a 2058 .off1 = offsetof(struct thread_options, offset_increment),
2d7cd868
JA
2059 .help = "What is the increment from one offset to the next",
2060 .parent = "offset",
d71c154c 2061 .hide = 1,
2d7cd868 2062 .def = "0",
20eb06bd 2063 .interval = 1024 * 1024,
e8b0e958
JA
2064 .category = FIO_OPT_C_IO,
2065 .group = FIO_OPT_G_INVALID,
2d7cd868 2066 },
ddf24e42
JA
2067 {
2068 .name = "number_ios",
2069 .lname = "Number of IOs to perform",
2070 .type = FIO_OPT_STR_VAL,
a609f12a 2071 .off1 = offsetof(struct thread_options, number_ios),
be3fec7d 2072 .help = "Force job completion after this number of IOs",
ddf24e42
JA
2073 .def = "0",
2074 .category = FIO_OPT_C_IO,
2075 .group = FIO_OPT_G_INVALID,
2076 },
214e1eca
JA
2077 {
2078 .name = "bs",
e8b0e958 2079 .lname = "Block size",
d3aad8f2 2080 .alias = "blocksize",
e01b22b8 2081 .type = FIO_OPT_INT,
a609f12a
JA
2082 .off1 = offsetof(struct thread_options, bs[DDIR_READ]),
2083 .off2 = offsetof(struct thread_options, bs[DDIR_WRITE]),
2084 .off3 = offsetof(struct thread_options, bs[DDIR_TRIM]),
c3edbdba 2085 .minval = 1,
214e1eca 2086 .help = "Block size unit",
2b9136a3 2087 .def = "4096",
67a1000f 2088 .parent = "rw",
d71c154c 2089 .hide = 1,
20eb06bd 2090 .interval = 512,
e8b0e958
JA
2091 .category = FIO_OPT_C_IO,
2092 .group = FIO_OPT_G_INVALID,
214e1eca 2093 },
2b7a01d0
JA
2094 {
2095 .name = "ba",
e8b0e958 2096 .lname = "Block size align",
2b7a01d0 2097 .alias = "blockalign",
e01b22b8 2098 .type = FIO_OPT_INT,
a609f12a
JA
2099 .off1 = offsetof(struct thread_options, ba[DDIR_READ]),
2100 .off2 = offsetof(struct thread_options, ba[DDIR_WRITE]),
2101 .off3 = offsetof(struct thread_options, ba[DDIR_TRIM]),
2b7a01d0
JA
2102 .minval = 1,
2103 .help = "IO block offset alignment",
2104 .parent = "rw",
d71c154c 2105 .hide = 1,
20eb06bd 2106 .interval = 512,
e8b0e958
JA
2107 .category = FIO_OPT_C_IO,
2108 .group = FIO_OPT_G_INVALID,
2b7a01d0 2109 },
214e1eca
JA
2110 {
2111 .name = "bsrange",
e8b0e958 2112 .lname = "Block size range",
d3aad8f2 2113 .alias = "blocksize_range",
214e1eca 2114 .type = FIO_OPT_RANGE,
a609f12a
JA
2115 .off1 = offsetof(struct thread_options, min_bs[DDIR_READ]),
2116 .off2 = offsetof(struct thread_options, max_bs[DDIR_READ]),
2117 .off3 = offsetof(struct thread_options, min_bs[DDIR_WRITE]),
2118 .off4 = offsetof(struct thread_options, max_bs[DDIR_WRITE]),
2119 .off5 = offsetof(struct thread_options, min_bs[DDIR_TRIM]),
2120 .off6 = offsetof(struct thread_options, max_bs[DDIR_TRIM]),
c3edbdba 2121 .minval = 1,
214e1eca 2122 .help = "Set block size range (in more detail than bs)",
67a1000f 2123 .parent = "rw",
d71c154c 2124 .hide = 1,
20eb06bd 2125 .interval = 4096,
e8b0e958
JA
2126 .category = FIO_OPT_C_IO,
2127 .group = FIO_OPT_G_INVALID,
214e1eca 2128 },
564ca972
JA
2129 {
2130 .name = "bssplit",
e8b0e958 2131 .lname = "Block size split",
564ca972
JA
2132 .type = FIO_OPT_STR,
2133 .cb = str_bssplit_cb,
a609f12a 2134 .off1 = offsetof(struct thread_options, bssplit),
564ca972
JA
2135 .help = "Set a specific mix of block sizes",
2136 .parent = "rw",
d71c154c 2137 .hide = 1,
e8b0e958
JA
2138 .category = FIO_OPT_C_IO,
2139 .group = FIO_OPT_G_INVALID,
564ca972 2140 },
214e1eca
JA
2141 {
2142 .name = "bs_unaligned",
e8b0e958 2143 .lname = "Block size unaligned",
d3aad8f2 2144 .alias = "blocksize_unaligned",
214e1eca 2145 .type = FIO_OPT_STR_SET,
a609f12a 2146 .off1 = offsetof(struct thread_options, bs_unaligned),
214e1eca 2147 .help = "Don't sector align IO buffer sizes",
67a1000f 2148 .parent = "rw",
d71c154c 2149 .hide = 1,
e8b0e958
JA
2150 .category = FIO_OPT_C_IO,
2151 .group = FIO_OPT_G_INVALID,
214e1eca 2152 },
6aca9b3d
JA
2153 {
2154 .name = "bs_is_seq_rand",
2155 .lname = "Block size division is seq/random (not read/write)",
2156 .type = FIO_OPT_BOOL,
a609f12a 2157 .off1 = offsetof(struct thread_options, bs_is_seq_rand),
86d59660 2158 .help = "Consider any blocksize setting to be sequential,random",
6aca9b3d
JA
2159 .def = "0",
2160 .parent = "blocksize",
2161 .category = FIO_OPT_C_IO,
2162 .group = FIO_OPT_G_INVALID,
2163 },
214e1eca
JA
2164 {
2165 .name = "randrepeat",
e8b0e958 2166 .lname = "Random repeatable",
214e1eca 2167 .type = FIO_OPT_BOOL,
a609f12a 2168 .off1 = offsetof(struct thread_options, rand_repeatable),
214e1eca
JA
2169 .help = "Use repeatable random IO pattern",
2170 .def = "1",
67a1000f 2171 .parent = "rw",
d71c154c 2172 .hide = 1,
e8b0e958 2173 .category = FIO_OPT_C_IO,
3ceb458f 2174 .group = FIO_OPT_G_RANDOM,
214e1eca 2175 },
04778baf
JA
2176 {
2177 .name = "randseed",
2178 .lname = "The random generator seed",
363cffa7 2179 .type = FIO_OPT_STR_VAL,
a609f12a 2180 .off1 = offsetof(struct thread_options, rand_seed),
04778baf 2181 .help = "Set the random generator seed value",
40fe5e7b 2182 .def = "0x89",
04778baf
JA
2183 .parent = "rw",
2184 .category = FIO_OPT_C_IO,
2185 .group = FIO_OPT_G_RANDOM,
2186 },
2615cc4b
JA
2187 {
2188 .name = "use_os_rand",
e8b0e958 2189 .lname = "Use OS random",
54a21917 2190 .type = FIO_OPT_DEPRECATED,
a609f12a 2191 .off1 = offsetof(struct thread_options, dep_use_os_rand),
e8b0e958 2192 .category = FIO_OPT_C_IO,
3ceb458f 2193 .group = FIO_OPT_G_RANDOM,
2615cc4b 2194 },
214e1eca
JA
2195 {
2196 .name = "norandommap",
e8b0e958 2197 .lname = "No randommap",
214e1eca 2198 .type = FIO_OPT_STR_SET,
a609f12a 2199 .off1 = offsetof(struct thread_options, norandommap),
214e1eca 2200 .help = "Accept potential duplicate random blocks",
67a1000f 2201 .parent = "rw",
d71c154c 2202 .hide = 1,
b2452a43 2203 .hide_on_set = 1,
e8b0e958 2204 .category = FIO_OPT_C_IO,
3ceb458f 2205 .group = FIO_OPT_G_RANDOM,
214e1eca 2206 },
2b386d25
JA
2207 {
2208 .name = "softrandommap",
e8b0e958 2209 .lname = "Soft randommap",
2b386d25 2210 .type = FIO_OPT_BOOL,
a609f12a 2211 .off1 = offsetof(struct thread_options, softrandommap),
f66ab3c8 2212 .help = "Set norandommap if randommap allocation fails",
2b386d25 2213 .parent = "norandommap",
d71c154c 2214 .hide = 1,
2b386d25 2215 .def = "0",
e8b0e958 2216 .category = FIO_OPT_C_IO,
3ceb458f 2217 .group = FIO_OPT_G_RANDOM,
2b386d25 2218 },
8055e41d
JA
2219 {
2220 .name = "random_generator",
cce2fdfe 2221 .lname = "Random Generator",
8055e41d 2222 .type = FIO_OPT_STR,
a609f12a 2223 .off1 = offsetof(struct thread_options, random_generator),
8055e41d
JA
2224 .help = "Type of random number generator to use",
2225 .def = "tausworthe",
2226 .posval = {
2227 { .ival = "tausworthe",
2228 .oval = FIO_RAND_GEN_TAUSWORTHE,
2229 .help = "Strong Tausworthe generator",
2230 },
2231 { .ival = "lfsr",
2232 .oval = FIO_RAND_GEN_LFSR,
2233 .help = "Variable length LFSR",
2234 },
c3546b53
JA
2235 {
2236 .ival = "tausworthe64",
2237 .oval = FIO_RAND_GEN_TAUSWORTHE64,
2238 .help = "64-bit Tausworthe variant",
2239 },
8055e41d 2240 },
48107598
JA
2241 .category = FIO_OPT_C_IO,
2242 .group = FIO_OPT_G_RANDOM,
8055e41d 2243 },
e25839d4
JA
2244 {
2245 .name = "random_distribution",
cce2fdfe 2246 .lname = "Random Distribution",
e25839d4 2247 .type = FIO_OPT_STR,
a609f12a 2248 .off1 = offsetof(struct thread_options, random_distribution),
e25839d4
JA
2249 .cb = str_random_distribution_cb,
2250 .help = "Random offset distribution generator",
2251 .def = "random",
2252 .posval = {
2253 { .ival = "random",
2254 .oval = FIO_RAND_DIST_RANDOM,
2255 .help = "Completely random",
2256 },
2257 { .ival = "zipf",
2258 .oval = FIO_RAND_DIST_ZIPF,
2259 .help = "Zipf distribution",
2260 },
925fee33
JA
2261 { .ival = "pareto",
2262 .oval = FIO_RAND_DIST_PARETO,
2263 .help = "Pareto distribution",
2264 },
56d9fa4b
JA
2265 { .ival = "normal",
2266 .oval = FIO_RAND_DIST_GAUSS,
ba2b3b07 2267 .help = "Normal (Gaussian) distribution",
56d9fa4b 2268 },
e0a04ac1
JA
2269 { .ival = "zoned",
2270 .oval = FIO_RAND_DIST_ZONED,
2271 .help = "Zoned random distribution",
2272 },
59466396
JA
2273 { .ival = "zoned_abs",
2274 .oval = FIO_RAND_DIST_ZONED_ABS,
2275 .help = "Zoned absolute random distribution",
2276 },
e25839d4 2277 },
48107598
JA
2278 .category = FIO_OPT_C_IO,
2279 .group = FIO_OPT_G_RANDOM,
e25839d4 2280 },
211c9b89
JA
2281 {
2282 .name = "percentage_random",
2283 .lname = "Percentage Random",
2284 .type = FIO_OPT_INT,
a609f12a
JA
2285 .off1 = offsetof(struct thread_options, perc_rand[DDIR_READ]),
2286 .off2 = offsetof(struct thread_options, perc_rand[DDIR_WRITE]),
2287 .off3 = offsetof(struct thread_options, perc_rand[DDIR_TRIM]),
211c9b89
JA
2288 .maxval = 100,
2289 .help = "Percentage of seq/random mix that should be random",
d9472271 2290 .def = "100,100,100",
211c9b89
JA
2291 .interval = 5,
2292 .inverse = "percentage_sequential",
2293 .category = FIO_OPT_C_IO,
2294 .group = FIO_OPT_G_RANDOM,
2295 },
2296 {
2297 .name = "percentage_sequential",
2298 .lname = "Percentage Sequential",
d9472271 2299 .type = FIO_OPT_DEPRECATED,
211c9b89
JA
2300 .category = FIO_OPT_C_IO,
2301 .group = FIO_OPT_G_RANDOM,
2302 },
56e2a5fc
CE
2303 {
2304 .name = "allrandrepeat",
cce2fdfe 2305 .lname = "All Random Repeat",
56e2a5fc 2306 .type = FIO_OPT_BOOL,
a609f12a 2307 .off1 = offsetof(struct thread_options, allrand_repeatable),
56e2a5fc
CE
2308 .help = "Use repeatable random numbers for everything",
2309 .def = "0",
a869d9c6
JA
2310 .category = FIO_OPT_C_IO,
2311 .group = FIO_OPT_G_RANDOM,
56e2a5fc 2312 },
214e1eca
JA
2313 {
2314 .name = "nrfiles",
e8b0e958 2315 .lname = "Number of files",
d7c8be03 2316 .alias = "nr_files",
214e1eca 2317 .type = FIO_OPT_INT,
a609f12a 2318 .off1 = offsetof(struct thread_options, nr_files),
214e1eca
JA
2319 .help = "Split job workload between this number of files",
2320 .def = "1",
20eb06bd 2321 .interval = 1,
e8b0e958
JA
2322 .category = FIO_OPT_C_FILE,
2323 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2324 },
2325 {
2326 .name = "openfiles",
e8b0e958 2327 .lname = "Number of open files",
214e1eca 2328 .type = FIO_OPT_INT,
a609f12a 2329 .off1 = offsetof(struct thread_options, open_files),
214e1eca 2330 .help = "Number of files to keep open at the same time",
e8b0e958
JA
2331 .category = FIO_OPT_C_FILE,
2332 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2333 },
2334 {
2335 .name = "file_service_type",
e8b0e958 2336 .lname = "File service type",
214e1eca
JA
2337 .type = FIO_OPT_STR,
2338 .cb = str_fst_cb,
a609f12a 2339 .off1 = offsetof(struct thread_options, file_service_type),
214e1eca
JA
2340 .help = "How to select which file to service next",
2341 .def = "roundrobin",
e8b0e958
JA
2342 .category = FIO_OPT_C_FILE,
2343 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2344 .posval = {
2345 { .ival = "random",
2346 .oval = FIO_FSERVICE_RANDOM,
8c07860d
JA
2347 .help = "Choose a file at random (uniform)",
2348 },
2349 { .ival = "zipf",
2350 .oval = FIO_FSERVICE_ZIPF,
2351 .help = "Zipf randomized",
2352 },
2353 { .ival = "pareto",
2354 .oval = FIO_FSERVICE_PARETO,
2355 .help = "Pareto randomized",
2356 },
dd3503d3
SW
2357 { .ival = "normal",
2358 .oval = FIO_FSERVICE_GAUSS,
2359 .help = "Normal (Gaussian) randomized",
2360 },
8c07860d
JA
2361 { .ival = "gauss",
2362 .oval = FIO_FSERVICE_GAUSS,
dd3503d3 2363 .help = "Alias for normal",
214e1eca
JA
2364 },
2365 { .ival = "roundrobin",
2366 .oval = FIO_FSERVICE_RR,
2367 .help = "Round robin select files",
2368 },
a086c257
JA
2369 { .ival = "sequential",
2370 .oval = FIO_FSERVICE_SEQ,
2371 .help = "Finish one file before moving to the next",
2372 },
214e1eca 2373 },
67a1000f 2374 .parent = "nrfiles",
d71c154c 2375 .hide = 1,
67a1000f 2376 },
cbbdf1c8 2377#ifdef FIO_HAVE_ANY_FALLOCATE
7bc8c2cf
JA
2378 {
2379 .name = "fallocate",
e8b0e958 2380 .lname = "Fallocate",
a596f047 2381 .type = FIO_OPT_STR,
a609f12a 2382 .off1 = offsetof(struct thread_options, fallocate_mode),
a596f047 2383 .help = "Whether pre-allocation is performed when laying out files",
2c3e17be 2384 .def = "native",
e8b0e958
JA
2385 .category = FIO_OPT_C_FILE,
2386 .group = FIO_OPT_G_INVALID,
a596f047
EG
2387 .posval = {
2388 { .ival = "none",
2389 .oval = FIO_FALLOCATE_NONE,
2390 .help = "Do not pre-allocate space",
2391 },
2c3e17be
SW
2392 { .ival = "native",
2393 .oval = FIO_FALLOCATE_NATIVE,
2394 .help = "Use native pre-allocation if possible",
2395 },
2396#ifdef CONFIG_POSIX_FALLOCATE
a596f047
EG
2397 { .ival = "posix",
2398 .oval = FIO_FALLOCATE_POSIX,
2399 .help = "Use posix_fallocate()",
2400 },
2c3e17be 2401#endif
97ac992c 2402#ifdef CONFIG_LINUX_FALLOCATE
a596f047
EG
2403 { .ival = "keep",
2404 .oval = FIO_FALLOCATE_KEEP_SIZE,
2405 .help = "Use fallocate(..., FALLOC_FL_KEEP_SIZE, ...)",
2406 },
7bc8c2cf 2407#endif
a596f047
EG
2408 /* Compatibility with former boolean values */
2409 { .ival = "0",
2410 .oval = FIO_FALLOCATE_NONE,
2411 .help = "Alias for 'none'",
2412 },
2c3e17be 2413#ifdef CONFIG_POSIX_FALLOCATE
a596f047
EG
2414 { .ival = "1",
2415 .oval = FIO_FALLOCATE_POSIX,
2416 .help = "Alias for 'posix'",
2417 },
2c3e17be 2418#endif
a596f047
EG
2419 },
2420 },
cbbdf1c8 2421#else /* FIO_HAVE_ANY_FALLOCATE */
a275c37a
JA
2422 {
2423 .name = "fallocate",
2424 .lname = "Fallocate",
2425 .type = FIO_OPT_UNSUPPORTED,
2426 .help = "Your platform does not support fallocate",
2427 },
cbbdf1c8 2428#endif /* FIO_HAVE_ANY_FALLOCATE */
67a1000f
JA
2429 {
2430 .name = "fadvise_hint",
e8b0e958 2431 .lname = "Fadvise hint",
ecb2083d 2432 .type = FIO_OPT_STR,
a609f12a 2433 .off1 = offsetof(struct thread_options, fadvise_hint),
ecb2083d
JA
2434 .posval = {
2435 { .ival = "0",
2436 .oval = F_ADV_NONE,
c712c97a 2437 .help = "Don't issue fadvise/madvise",
ecb2083d
JA
2438 },
2439 { .ival = "1",
2440 .oval = F_ADV_TYPE,
2441 .help = "Advise using fio IO pattern",
2442 },
2443 { .ival = "random",
2444 .oval = F_ADV_RANDOM,
2445 .help = "Advise using FADV_RANDOM",
2446 },
2447 { .ival = "sequential",
2448 .oval = F_ADV_SEQUENTIAL,
2449 .help = "Advise using FADV_SEQUENTIAL",
2450 },
2451 },
67a1000f
JA
2452 .help = "Use fadvise() to advise the kernel on IO pattern",
2453 .def = "1",
e8b0e958
JA
2454 .category = FIO_OPT_C_FILE,
2455 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2456 },
2457 {
2458 .name = "fsync",
e8b0e958 2459 .lname = "Fsync",
214e1eca 2460 .type = FIO_OPT_INT,
a609f12a 2461 .off1 = offsetof(struct thread_options, fsync_blocks),
214e1eca
JA
2462 .help = "Issue fsync for writes every given number of blocks",
2463 .def = "0",
20eb06bd 2464 .interval = 1,
e8b0e958
JA
2465 .category = FIO_OPT_C_FILE,
2466 .group = FIO_OPT_G_INVALID,
214e1eca 2467 },
5f9099ea
JA
2468 {
2469 .name = "fdatasync",
e8b0e958 2470 .lname = "Fdatasync",
5f9099ea 2471 .type = FIO_OPT_INT,
a609f12a 2472 .off1 = offsetof(struct thread_options, fdatasync_blocks),
5f9099ea
JA
2473 .help = "Issue fdatasync for writes every given number of blocks",
2474 .def = "0",
20eb06bd 2475 .interval = 1,
e8b0e958
JA
2476 .category = FIO_OPT_C_FILE,
2477 .group = FIO_OPT_G_INVALID,
5f9099ea 2478 },
1ef2b6be
JA
2479 {
2480 .name = "write_barrier",
e8b0e958 2481 .lname = "Write barrier",
1ef2b6be 2482 .type = FIO_OPT_INT,
a609f12a 2483 .off1 = offsetof(struct thread_options, barrier_blocks),
1ef2b6be
JA
2484 .help = "Make every Nth write a barrier write",
2485 .def = "0",
20eb06bd 2486 .interval = 1,
e8b0e958
JA
2487 .category = FIO_OPT_C_IO,
2488 .group = FIO_OPT_G_INVALID,
1ef2b6be 2489 },
67bf9823 2490#ifdef CONFIG_SYNC_FILE_RANGE
44f29692
JA
2491 {
2492 .name = "sync_file_range",
e8b0e958 2493 .lname = "Sync file range",
44f29692
JA
2494 .posval = {
2495 { .ival = "wait_before",
2496 .oval = SYNC_FILE_RANGE_WAIT_BEFORE,
2497 .help = "SYNC_FILE_RANGE_WAIT_BEFORE",
ebadc0ce 2498 .orval = 1,
44f29692
JA
2499 },
2500 { .ival = "write",
2501 .oval = SYNC_FILE_RANGE_WRITE,
2502 .help = "SYNC_FILE_RANGE_WRITE",
ebadc0ce 2503 .orval = 1,
44f29692
JA
2504 },
2505 {
2506 .ival = "wait_after",
2507 .oval = SYNC_FILE_RANGE_WAIT_AFTER,
2508 .help = "SYNC_FILE_RANGE_WAIT_AFTER",
ebadc0ce 2509 .orval = 1,
44f29692
JA
2510 },
2511 },
3843deb3 2512 .type = FIO_OPT_STR_MULTI,
44f29692 2513 .cb = str_sfr_cb,
a609f12a 2514 .off1 = offsetof(struct thread_options, sync_file_range),
44f29692 2515 .help = "Use sync_file_range()",
e8b0e958
JA
2516 .category = FIO_OPT_C_FILE,
2517 .group = FIO_OPT_G_INVALID,
44f29692 2518 },
a275c37a 2519#else
54d0a315 2520 {
a275c37a
JA
2521 .name = "sync_file_range",
2522 .lname = "Sync file range",
2523 .type = FIO_OPT_UNSUPPORTED,
2524 .help = "Your platform does not support sync_file_range",
2525 },
44f29692 2526#endif
214e1eca
JA
2527 {
2528 .name = "direct",
e8b0e958 2529 .lname = "Direct I/O",
214e1eca 2530 .type = FIO_OPT_BOOL,
a609f12a 2531 .off1 = offsetof(struct thread_options, odirect),
214e1eca
JA
2532 .help = "Use O_DIRECT IO (negates buffered)",
2533 .def = "0",
a01a1bc5 2534 .inverse = "buffered",
e8b0e958 2535 .category = FIO_OPT_C_IO,
3ceb458f 2536 .group = FIO_OPT_G_IO_TYPE,
214e1eca 2537 },
d01612f3
CM
2538 {
2539 .name = "atomic",
2540 .lname = "Atomic I/O",
2541 .type = FIO_OPT_BOOL,
a609f12a 2542 .off1 = offsetof(struct thread_options, oatomic),
d01612f3
CM
2543 .help = "Use Atomic IO with O_DIRECT (implies O_DIRECT)",
2544 .def = "0",
2545 .category = FIO_OPT_C_IO,
2546 .group = FIO_OPT_G_IO_TYPE,
2547 },
214e1eca
JA
2548 {
2549 .name = "buffered",
e8b0e958 2550 .lname = "Buffered I/O",
214e1eca 2551 .type = FIO_OPT_BOOL,
a609f12a 2552 .off1 = offsetof(struct thread_options, odirect),
214e1eca
JA
2553 .neg = 1,
2554 .help = "Use buffered IO (negates direct)",
2555 .def = "1",
a01a1bc5 2556 .inverse = "direct",
e8b0e958 2557 .category = FIO_OPT_C_IO,
3ceb458f 2558 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
2559 },
2560 {
2561 .name = "overwrite",
e8b0e958 2562 .lname = "Overwrite",
214e1eca 2563 .type = FIO_OPT_BOOL,
a609f12a 2564 .off1 = offsetof(struct thread_options, overwrite),
214e1eca
JA
2565 .help = "When writing, set whether to overwrite current data",
2566 .def = "0",
e8b0e958
JA
2567 .category = FIO_OPT_C_FILE,
2568 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2569 },
2570 {
2571 .name = "loops",
e8b0e958 2572 .lname = "Loops",
214e1eca 2573 .type = FIO_OPT_INT,
a609f12a 2574 .off1 = offsetof(struct thread_options, loops),
214e1eca
JA
2575 .help = "Number of times to run the job",
2576 .def = "1",
20eb06bd 2577 .interval = 1,
e8b0e958 2578 .category = FIO_OPT_C_GENERAL,
a1f6afec 2579 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2580 },
2581 {
2582 .name = "numjobs",
e8b0e958 2583 .lname = "Number of jobs",
214e1eca 2584 .type = FIO_OPT_INT,
a609f12a 2585 .off1 = offsetof(struct thread_options, numjobs),
214e1eca
JA
2586 .help = "Duplicate this job this many times",
2587 .def = "1",
20eb06bd 2588 .interval = 1,
e8b0e958 2589 .category = FIO_OPT_C_GENERAL,
a1f6afec 2590 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2591 },
2592 {
2593 .name = "startdelay",
e8b0e958 2594 .lname = "Start delay",
a5737c93 2595 .type = FIO_OPT_STR_VAL_TIME,
a609f12a
JA
2596 .off1 = offsetof(struct thread_options, start_delay),
2597 .off2 = offsetof(struct thread_options, start_delay_high),
214e1eca
JA
2598 .help = "Only start job when this period has passed",
2599 .def = "0",
0de5b26f 2600 .is_seconds = 1,
88038bc7 2601 .is_time = 1,
e8b0e958 2602 .category = FIO_OPT_C_GENERAL,
a1f6afec 2603 .group = FIO_OPT_G_RUNTIME,
214e1eca
JA
2604 },
2605 {
2606 .name = "runtime",
e8b0e958 2607 .lname = "Runtime",
214e1eca
JA
2608 .alias = "timeout",
2609 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 2610 .off1 = offsetof(struct thread_options, timeout),
214e1eca
JA
2611 .help = "Stop workload when this amount of time has passed",
2612 .def = "0",
0de5b26f 2613 .is_seconds = 1,
88038bc7 2614 .is_time = 1,
e8b0e958 2615 .category = FIO_OPT_C_GENERAL,
a1f6afec 2616 .group = FIO_OPT_G_RUNTIME,
214e1eca 2617 },
cf4464ca
JA
2618 {
2619 .name = "time_based",
e8b0e958 2620 .lname = "Time based",
cf4464ca 2621 .type = FIO_OPT_STR_SET,
a609f12a 2622 .off1 = offsetof(struct thread_options, time_based),
cf4464ca 2623 .help = "Keep running until runtime/timeout is met",
e8b0e958 2624 .category = FIO_OPT_C_GENERAL,
a1f6afec 2625 .group = FIO_OPT_G_RUNTIME,
cf4464ca 2626 },
62167762
JC
2627 {
2628 .name = "verify_only",
2629 .lname = "Verify only",
2630 .type = FIO_OPT_STR_SET,
a609f12a 2631 .off1 = offsetof(struct thread_options, verify_only),
62167762
JC
2632 .help = "Verifies previously written data is still valid",
2633 .category = FIO_OPT_C_GENERAL,
2634 .group = FIO_OPT_G_RUNTIME,
2635 },
721938ae
JA
2636 {
2637 .name = "ramp_time",
e8b0e958 2638 .lname = "Ramp time",
721938ae 2639 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 2640 .off1 = offsetof(struct thread_options, ramp_time),
721938ae 2641 .help = "Ramp up time before measuring performance",
0de5b26f 2642 .is_seconds = 1,
88038bc7 2643 .is_time = 1,
e8b0e958 2644 .category = FIO_OPT_C_GENERAL,
a1f6afec 2645 .group = FIO_OPT_G_RUNTIME,
721938ae 2646 },
c223da83
JA
2647 {
2648 .name = "clocksource",
e8b0e958 2649 .lname = "Clock source",
c223da83
JA
2650 .type = FIO_OPT_STR,
2651 .cb = fio_clock_source_cb,
a609f12a 2652 .off1 = offsetof(struct thread_options, clocksource),
c223da83 2653 .help = "What type of timing source to use",
e8b0e958 2654 .category = FIO_OPT_C_GENERAL,
10860056 2655 .group = FIO_OPT_G_CLOCK,
c223da83 2656 .posval = {
67bf9823 2657#ifdef CONFIG_GETTIMEOFDAY
c223da83
JA
2658 { .ival = "gettimeofday",
2659 .oval = CS_GTOD,
2660 .help = "Use gettimeofday(2) for timing",
2661 },
67bf9823
JA
2662#endif
2663#ifdef CONFIG_CLOCK_GETTIME
c223da83
JA
2664 { .ival = "clock_gettime",
2665 .oval = CS_CGETTIME,
2666 .help = "Use clock_gettime(2) for timing",
2667 },
67bf9823 2668#endif
c223da83
JA
2669#ifdef ARCH_HAVE_CPU_CLOCK
2670 { .ival = "cpu",
2671 .oval = CS_CPUCLOCK,
2672 .help = "Use CPU private clock",
2673 },
2674#endif
2675 },
2676 },
214e1eca
JA
2677 {
2678 .name = "mem",
d3aad8f2 2679 .alias = "iomem",
e8b0e958 2680 .lname = "I/O Memory",
214e1eca
JA
2681 .type = FIO_OPT_STR,
2682 .cb = str_mem_cb,
a609f12a 2683 .off1 = offsetof(struct thread_options, mem_type),
214e1eca
JA
2684 .help = "Backing type for IO buffers",
2685 .def = "malloc",
e8b0e958
JA
2686 .category = FIO_OPT_C_IO,
2687 .group = FIO_OPT_G_INVALID,
214e1eca
JA
2688 .posval = {
2689 { .ival = "malloc",
2690 .oval = MEM_MALLOC,
2691 .help = "Use malloc(3) for IO buffers",
2692 },
c8931876 2693#ifndef CONFIG_NO_SHM
37c8cdfe
JA
2694 { .ival = "shm",
2695 .oval = MEM_SHM,
2696 .help = "Use shared memory segments for IO buffers",
2697 },
214e1eca
JA
2698#ifdef FIO_HAVE_HUGETLB
2699 { .ival = "shmhuge",
2700 .oval = MEM_SHMHUGE,
2701 .help = "Like shm, but use huge pages",
2702 },
c8931876 2703#endif
b370e46a 2704#endif
37c8cdfe
JA
2705 { .ival = "mmap",
2706 .oval = MEM_MMAP,
2707 .help = "Use mmap(2) (file or anon) for IO buffers",
2708 },
217b0f1d
LG
2709 { .ival = "mmapshared",
2710 .oval = MEM_MMAPSHARED,
2711 .help = "Like mmap, but use the shared flag",
2712 },
214e1eca
JA
2713#ifdef FIO_HAVE_HUGETLB
2714 { .ival = "mmaphuge",
2715 .oval = MEM_MMAPHUGE,
2716 .help = "Like mmap, but use huge pages",
2717 },
03553853
YR
2718#endif
2719#ifdef CONFIG_CUDA
2720 { .ival = "cudamalloc",
2721 .oval = MEM_CUDA_MALLOC,
2722 .help = "Allocate GPU device memory for GPUDirect RDMA",
2723 },
214e1eca
JA
2724#endif
2725 },
2726 },
d529ee19
JA
2727 {
2728 .name = "iomem_align",
2729 .alias = "mem_align",
e8b0e958 2730 .lname = "I/O memory alignment",
d529ee19 2731 .type = FIO_OPT_INT,
a609f12a 2732 .off1 = offsetof(struct thread_options, mem_align),
d529ee19
JA
2733 .minval = 0,
2734 .help = "IO memory buffer offset alignment",
2735 .def = "0",
2736 .parent = "iomem",
d71c154c 2737 .hide = 1,
e8b0e958
JA
2738 .category = FIO_OPT_C_IO,
2739 .group = FIO_OPT_G_INVALID,
d529ee19 2740 },
214e1eca
JA
2741 {
2742 .name = "verify",
e8b0e958 2743 .lname = "Verify",
214e1eca 2744 .type = FIO_OPT_STR,
a609f12a 2745 .off1 = offsetof(struct thread_options, verify),
214e1eca
JA
2746 .help = "Verify data written",
2747 .def = "0",
e8b0e958 2748 .category = FIO_OPT_C_IO,
3ceb458f 2749 .group = FIO_OPT_G_VERIFY,
214e1eca
JA
2750 .posval = {
2751 { .ival = "0",
2752 .oval = VERIFY_NONE,
2753 .help = "Don't do IO verification",
2754 },
fcca4b58
JA
2755 { .ival = "md5",
2756 .oval = VERIFY_MD5,
2757 .help = "Use md5 checksums for verification",
2758 },
d77a7af3
JA
2759 { .ival = "crc64",
2760 .oval = VERIFY_CRC64,
2761 .help = "Use crc64 checksums for verification",
2762 },
214e1eca
JA
2763 { .ival = "crc32",
2764 .oval = VERIFY_CRC32,
2765 .help = "Use crc32 checksums for verification",
2766 },
af497e6a 2767 { .ival = "crc32c-intel",
e3aaafc4
JA
2768 .oval = VERIFY_CRC32C,
2769 .help = "Use crc32c checksums for verification (hw assisted, if available)",
af497e6a 2770 },
bac39e0e
JA
2771 { .ival = "crc32c",
2772 .oval = VERIFY_CRC32C,
e3aaafc4 2773 .help = "Use crc32c checksums for verification (hw assisted, if available)",
bac39e0e 2774 },
969f7ed3
JA
2775 { .ival = "crc16",
2776 .oval = VERIFY_CRC16,
2777 .help = "Use crc16 checksums for verification",
2778 },
1e154bdb
JA
2779 { .ival = "crc7",
2780 .oval = VERIFY_CRC7,
2781 .help = "Use crc7 checksums for verification",
2782 },
7c353ceb
JA
2783 { .ival = "sha1",
2784 .oval = VERIFY_SHA1,
2785 .help = "Use sha1 checksums for verification",
2786 },
cd14cc10
JA
2787 { .ival = "sha256",
2788 .oval = VERIFY_SHA256,
2789 .help = "Use sha256 checksums for verification",
2790 },
2791 { .ival = "sha512",
2792 .oval = VERIFY_SHA512,
2793 .help = "Use sha512 checksums for verification",
ae3a5acc
JA
2794 },
2795 { .ival = "sha3-224",
2796 .oval = VERIFY_SHA3_224,
2797 .help = "Use sha3-224 checksums for verification",
2798 },
2799 { .ival = "sha3-256",
2800 .oval = VERIFY_SHA3_256,
2801 .help = "Use sha3-256 checksums for verification",
2802 },
2803 { .ival = "sha3-384",
2804 .oval = VERIFY_SHA3_384,
2805 .help = "Use sha3-384 checksums for verification",
2806 },
2807 { .ival = "sha3-512",
2808 .oval = VERIFY_SHA3_512,
2809 .help = "Use sha3-512 checksums for verification",
cd14cc10 2810 },
844ea602
JA
2811 { .ival = "xxhash",
2812 .oval = VERIFY_XXHASH,
2813 .help = "Use xxhash checksums for verification",
2814 },
b638d82f
RP
2815 /* Meta information was included into verify_header,
2816 * 'meta' verification is implied by default. */
7437ee87 2817 { .ival = "meta",
b638d82f
RP
2818 .oval = VERIFY_HDR_ONLY,
2819 .help = "Use io information for verification. "
2820 "Now is implied by default, thus option is obsolete, "
2821 "don't use it",
7437ee87 2822 },
59245381
JA
2823 { .ival = "pattern",
2824 .oval = VERIFY_PATTERN_NO_HDR,
2825 .help = "Verify strict pattern",
2826 },
36690c9b
JA
2827 {
2828 .ival = "null",
2829 .oval = VERIFY_NULL,
2830 .help = "Pretend to verify",
2831 },
214e1eca
JA
2832 },
2833 },
005c565a
JA
2834 {
2835 .name = "do_verify",
e8b0e958 2836 .lname = "Perform verify step",
68e1f29a 2837 .type = FIO_OPT_BOOL,
a609f12a 2838 .off1 = offsetof(struct thread_options, do_verify),
005c565a
JA
2839 .help = "Run verification stage after write",
2840 .def = "1",
2841 .parent = "verify",
d71c154c 2842 .hide = 1,
e8b0e958
JA
2843 .category = FIO_OPT_C_IO,
2844 .group = FIO_OPT_G_VERIFY,
005c565a 2845 },
160b966d
JA
2846 {
2847 .name = "verifysort",
e8b0e958 2848 .lname = "Verify sort",
f31feaa2 2849 .type = FIO_OPT_SOFT_DEPRECATED,
e8b0e958
JA
2850 .category = FIO_OPT_C_IO,
2851 .group = FIO_OPT_G_VERIFY,
160b966d 2852 },
1ae83d45
JA
2853 {
2854 .name = "verifysort_nr",
cce2fdfe 2855 .lname = "Verify Sort Nr",
f31feaa2 2856 .type = FIO_OPT_SOFT_DEPRECATED,
836fcc0f
JA
2857 .category = FIO_OPT_C_IO,
2858 .group = FIO_OPT_G_VERIFY,
1ae83d45 2859 },
3f9f4e26 2860 {
a59e170d 2861 .name = "verify_interval",
e8b0e958 2862 .lname = "Verify interval",
e01b22b8 2863 .type = FIO_OPT_INT,
a609f12a 2864 .off1 = offsetof(struct thread_options, verify_interval),
819a9680 2865 .minval = 2 * sizeof(struct verify_header),
a59e170d 2866 .help = "Store verify buffer header every N bytes",
afdf9352 2867 .parent = "verify",
d71c154c 2868 .hide = 1,
20eb06bd 2869 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
2870 .category = FIO_OPT_C_IO,
2871 .group = FIO_OPT_G_VERIFY,
3f9f4e26 2872 },
546a9142 2873 {
a59e170d 2874 .name = "verify_offset",
e8b0e958 2875 .lname = "Verify offset",
e01b22b8 2876 .type = FIO_OPT_INT,
a59e170d 2877 .help = "Offset verify header location by N bytes",
a609f12a 2878 .off1 = offsetof(struct thread_options, verify_offset),
203160d5 2879 .minval = sizeof(struct verify_header),
afdf9352 2880 .parent = "verify",
d71c154c 2881 .hide = 1,
e8b0e958
JA
2882 .category = FIO_OPT_C_IO,
2883 .group = FIO_OPT_G_VERIFY,
546a9142 2884 },
e28218f3
SL
2885 {
2886 .name = "verify_pattern",
e8b0e958 2887 .lname = "Verify pattern",
0e92f873 2888 .type = FIO_OPT_STR,
e28218f3 2889 .cb = str_verify_pattern_cb,
a609f12a 2890 .off1 = offsetof(struct thread_options, verify_pattern),
e28218f3
SL
2891 .help = "Fill pattern for IO buffers",
2892 .parent = "verify",
d71c154c 2893 .hide = 1,
e8b0e958
JA
2894 .category = FIO_OPT_C_IO,
2895 .group = FIO_OPT_G_VERIFY,
e28218f3 2896 },
a12a3b4d
JA
2897 {
2898 .name = "verify_fatal",
e8b0e958 2899 .lname = "Verify fatal",
68e1f29a 2900 .type = FIO_OPT_BOOL,
a609f12a 2901 .off1 = offsetof(struct thread_options, verify_fatal),
a12a3b4d
JA
2902 .def = "0",
2903 .help = "Exit on a single verify failure, don't continue",
2904 .parent = "verify",
d71c154c 2905 .hide = 1,
e8b0e958
JA
2906 .category = FIO_OPT_C_IO,
2907 .group = FIO_OPT_G_VERIFY,
a12a3b4d 2908 },
b463e936
JA
2909 {
2910 .name = "verify_dump",
e8b0e958 2911 .lname = "Verify dump",
b463e936 2912 .type = FIO_OPT_BOOL,
a609f12a 2913 .off1 = offsetof(struct thread_options, verify_dump),
ef71e317 2914 .def = "0",
b463e936
JA
2915 .help = "Dump contents of good and bad blocks on failure",
2916 .parent = "verify",
d71c154c 2917 .hide = 1,
e8b0e958
JA
2918 .category = FIO_OPT_C_IO,
2919 .group = FIO_OPT_G_VERIFY,
b463e936 2920 },
e8462bd8
JA
2921 {
2922 .name = "verify_async",
e8b0e958 2923 .lname = "Verify asynchronously",
e8462bd8 2924 .type = FIO_OPT_INT,
a609f12a 2925 .off1 = offsetof(struct thread_options, verify_async),
e8462bd8
JA
2926 .def = "0",
2927 .help = "Number of async verifier threads to use",
2928 .parent = "verify",
d71c154c 2929 .hide = 1,
e8b0e958
JA
2930 .category = FIO_OPT_C_IO,
2931 .group = FIO_OPT_G_VERIFY,
e8462bd8 2932 },
9e144189
JA
2933 {
2934 .name = "verify_backlog",
e8b0e958 2935 .lname = "Verify backlog",
9e144189 2936 .type = FIO_OPT_STR_VAL,
a609f12a 2937 .off1 = offsetof(struct thread_options, verify_backlog),
9e144189
JA
2938 .help = "Verify after this number of blocks are written",
2939 .parent = "verify",
d71c154c 2940 .hide = 1,
e8b0e958
JA
2941 .category = FIO_OPT_C_IO,
2942 .group = FIO_OPT_G_VERIFY,
9e144189
JA
2943 },
2944 {
2945 .name = "verify_backlog_batch",
e8b0e958 2946 .lname = "Verify backlog batch",
9e144189 2947 .type = FIO_OPT_INT,
a609f12a 2948 .off1 = offsetof(struct thread_options, verify_batch),
9e144189 2949 .help = "Verify this number of IO blocks",
0d29de83 2950 .parent = "verify",
d71c154c 2951 .hide = 1,
e8b0e958
JA
2952 .category = FIO_OPT_C_IO,
2953 .group = FIO_OPT_G_VERIFY,
9e144189 2954 },
e8462bd8
JA
2955#ifdef FIO_HAVE_CPU_AFFINITY
2956 {
2957 .name = "verify_async_cpus",
e8b0e958 2958 .lname = "Async verify CPUs",
e8462bd8
JA
2959 .type = FIO_OPT_STR,
2960 .cb = str_verify_cpus_allowed_cb,
a609f12a 2961 .off1 = offsetof(struct thread_options, verify_cpumask),
e8462bd8
JA
2962 .help = "Set CPUs allowed for async verify threads",
2963 .parent = "verify_async",
d71c154c 2964 .hide = 1,
e8b0e958
JA
2965 .category = FIO_OPT_C_IO,
2966 .group = FIO_OPT_G_VERIFY,
e8462bd8 2967 },
a275c37a
JA
2968#else
2969 {
2970 .name = "verify_async_cpus",
2971 .lname = "Async verify CPUs",
2972 .type = FIO_OPT_UNSUPPORTED,
54d0a315 2973 .help = "Your platform does not support CPU affinities",
a275c37a 2974 },
0d29de83 2975#endif
51aa2da8
JA
2976 {
2977 .name = "experimental_verify",
cce2fdfe 2978 .lname = "Experimental Verify",
a609f12a 2979 .off1 = offsetof(struct thread_options, experimental_verify),
51aa2da8 2980 .type = FIO_OPT_BOOL,
b31eaac9 2981 .help = "Enable experimental verification",
ca09be4b
JA
2982 .parent = "verify",
2983 .category = FIO_OPT_C_IO,
2984 .group = FIO_OPT_G_VERIFY,
2985 },
2986 {
2987 .name = "verify_state_load",
2988 .lname = "Load verify state",
a609f12a 2989 .off1 = offsetof(struct thread_options, verify_state),
ca09be4b
JA
2990 .type = FIO_OPT_BOOL,
2991 .help = "Load verify termination state",
2992 .parent = "verify",
2993 .category = FIO_OPT_C_IO,
2994 .group = FIO_OPT_G_VERIFY,
2995 },
2996 {
2997 .name = "verify_state_save",
2998 .lname = "Save verify state",
a609f12a 2999 .off1 = offsetof(struct thread_options, verify_state_save),
ca09be4b
JA
3000 .type = FIO_OPT_BOOL,
3001 .def = "1",
3002 .help = "Save verify state on termination",
3003 .parent = "verify",
836fcc0f
JA
3004 .category = FIO_OPT_C_IO,
3005 .group = FIO_OPT_G_VERIFY,
51aa2da8 3006 },
0d29de83
JA
3007#ifdef FIO_HAVE_TRIM
3008 {
3009 .name = "trim_percentage",
e8b0e958 3010 .lname = "Trim percentage",
0d29de83 3011 .type = FIO_OPT_INT,
a609f12a 3012 .off1 = offsetof(struct thread_options, trim_percentage),
20eb06bd 3013 .minval = 0,
0d29de83 3014 .maxval = 100,
169c098d 3015 .help = "Number of verify blocks to trim (i.e., discard)",
0d29de83
JA
3016 .parent = "verify",
3017 .def = "0",
20eb06bd 3018 .interval = 1,
d71c154c 3019 .hide = 1,
e8b0e958
JA
3020 .category = FIO_OPT_C_IO,
3021 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3022 },
3023 {
3024 .name = "trim_verify_zero",
e8b0e958 3025 .lname = "Verify trim zero",
20eb06bd 3026 .type = FIO_OPT_BOOL,
169c098d 3027 .help = "Verify that trimmed (i.e., discarded) blocks are returned as zeroes",
a609f12a 3028 .off1 = offsetof(struct thread_options, trim_zero),
0d29de83 3029 .parent = "trim_percentage",
d71c154c 3030 .hide = 1,
0d29de83 3031 .def = "1",
e8b0e958
JA
3032 .category = FIO_OPT_C_IO,
3033 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3034 },
3035 {
3036 .name = "trim_backlog",
e8b0e958 3037 .lname = "Trim backlog",
0d29de83 3038 .type = FIO_OPT_STR_VAL,
a609f12a 3039 .off1 = offsetof(struct thread_options, trim_backlog),
0d29de83
JA
3040 .help = "Trim after this number of blocks are written",
3041 .parent = "trim_percentage",
d71c154c 3042 .hide = 1,
20eb06bd 3043 .interval = 1,
e8b0e958
JA
3044 .category = FIO_OPT_C_IO,
3045 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3046 },
3047 {
3048 .name = "trim_backlog_batch",
e8b0e958 3049 .lname = "Trim backlog batch",
0d29de83 3050 .type = FIO_OPT_INT,
a609f12a 3051 .off1 = offsetof(struct thread_options, trim_batch),
0d29de83
JA
3052 .help = "Trim this number of IO blocks",
3053 .parent = "trim_percentage",
d71c154c 3054 .hide = 1,
20eb06bd 3055 .interval = 1,
e8b0e958
JA
3056 .category = FIO_OPT_C_IO,
3057 .group = FIO_OPT_G_TRIM,
0d29de83 3058 },
a275c37a
JA
3059#else
3060 {
3061 .name = "trim_percentage",
3062 .lname = "Trim percentage",
3063 .type = FIO_OPT_UNSUPPORTED,
3064 .help = "Fio does not support TRIM on your platform",
3065 },
3066 {
3067 .name = "trim_verify_zero",
3068 .lname = "Verify trim zero",
3069 .type = FIO_OPT_UNSUPPORTED,
3070 .help = "Fio does not support TRIM on your platform",
3071 },
3072 {
3073 .name = "trim_backlog",
3074 .lname = "Trim backlog",
3075 .type = FIO_OPT_UNSUPPORTED,
3076 .help = "Fio does not support TRIM on your platform",
3077 },
3078 {
3079 .name = "trim_backlog_batch",
3080 .lname = "Trim backlog batch",
3081 .type = FIO_OPT_UNSUPPORTED,
3082 .help = "Fio does not support TRIM on your platform",
3083 },
e8462bd8 3084#endif
214e1eca
JA
3085 {
3086 .name = "write_iolog",
e8b0e958 3087 .lname = "Write I/O log",
214e1eca 3088 .type = FIO_OPT_STR_STORE,
a609f12a 3089 .off1 = offsetof(struct thread_options, write_iolog_file),
214e1eca 3090 .help = "Store IO pattern to file",
e8b0e958
JA
3091 .category = FIO_OPT_C_IO,
3092 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
3093 },
3094 {
3095 .name = "read_iolog",
e8b0e958 3096 .lname = "Read I/O log",
214e1eca 3097 .type = FIO_OPT_STR_STORE,
a609f12a 3098 .off1 = offsetof(struct thread_options, read_iolog_file),
214e1eca 3099 .help = "Playback IO pattern from file",
e8b0e958
JA
3100 .category = FIO_OPT_C_IO,
3101 .group = FIO_OPT_G_IOLOG,
214e1eca 3102 },
64bbb865
DN
3103 {
3104 .name = "replay_no_stall",
e8b0e958 3105 .lname = "Don't stall on replay",
20eb06bd 3106 .type = FIO_OPT_BOOL,
a609f12a 3107 .off1 = offsetof(struct thread_options, no_stall),
64bbb865 3108 .def = "0",
87e7a972 3109 .parent = "read_iolog",
d71c154c 3110 .hide = 1,
64bbb865 3111 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
3112 .category = FIO_OPT_C_IO,
3113 .group = FIO_OPT_G_IOLOG,
64bbb865 3114 },
d1c46c04
DN
3115 {
3116 .name = "replay_redirect",
e8b0e958 3117 .lname = "Redirect device for replay",
d1c46c04 3118 .type = FIO_OPT_STR_STORE,
a609f12a 3119 .off1 = offsetof(struct thread_options, replay_redirect),
d1c46c04 3120 .parent = "read_iolog",
d71c154c 3121 .hide = 1,
d1c46c04 3122 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
3123 .category = FIO_OPT_C_IO,
3124 .group = FIO_OPT_G_IOLOG,
d1c46c04 3125 },
0c63576e
JA
3126 {
3127 .name = "replay_scale",
3128 .lname = "Replace offset scale factor",
3129 .type = FIO_OPT_INT,
a609f12a 3130 .off1 = offsetof(struct thread_options, replay_scale),
0c63576e
JA
3131 .parent = "read_iolog",
3132 .def = "1",
3133 .help = "Align offsets to this blocksize",
3134 .category = FIO_OPT_C_IO,
3135 .group = FIO_OPT_G_IOLOG,
3136 },
3137 {
3138 .name = "replay_align",
3139 .lname = "Replace alignment",
3140 .type = FIO_OPT_INT,
a609f12a 3141 .off1 = offsetof(struct thread_options, replay_align),
0c63576e
JA
3142 .parent = "read_iolog",
3143 .help = "Scale offset down by this factor",
3144 .category = FIO_OPT_C_IO,
3145 .group = FIO_OPT_G_IOLOG,
3146 .pow2 = 1,
3147 },
6dd7fa77
JA
3148 {
3149 .name = "replay_time_scale",
3150 .lname = "Replay Time Scale",
3151 .type = FIO_OPT_INT,
3152 .off1 = offsetof(struct thread_options, replay_time_scale),
3153 .def = "100",
3154 .minval = 1,
3155 .parent = "read_iolog",
3156 .hide = 1,
3157 .help = "Scale time for replay events",
3158 .category = FIO_OPT_C_IO,
3159 .group = FIO_OPT_G_IOLOG,
3160 },
214e1eca
JA
3161 {
3162 .name = "exec_prerun",
e8b0e958 3163 .lname = "Pre-execute runnable",
214e1eca 3164 .type = FIO_OPT_STR_STORE,
a609f12a 3165 .off1 = offsetof(struct thread_options, exec_prerun),
214e1eca 3166 .help = "Execute this file prior to running job",
e8b0e958
JA
3167 .category = FIO_OPT_C_GENERAL,
3168 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3169 },
3170 {
3171 .name = "exec_postrun",
e8b0e958 3172 .lname = "Post-execute runnable",
214e1eca 3173 .type = FIO_OPT_STR_STORE,
a609f12a 3174 .off1 = offsetof(struct thread_options, exec_postrun),
214e1eca 3175 .help = "Execute this file after running job",
e8b0e958
JA
3176 .category = FIO_OPT_C_GENERAL,
3177 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3178 },
3179#ifdef FIO_HAVE_IOSCHED_SWITCH
3180 {
3181 .name = "ioscheduler",
e8b0e958 3182 .lname = "I/O scheduler",
214e1eca 3183 .type = FIO_OPT_STR_STORE,
a609f12a 3184 .off1 = offsetof(struct thread_options, ioscheduler),
214e1eca 3185 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
3186 .category = FIO_OPT_C_FILE,
3187 .group = FIO_OPT_G_INVALID,
214e1eca 3188 },
a275c37a
JA
3189#else
3190 {
3191 .name = "ioscheduler",
3192 .lname = "I/O scheduler",
3193 .type = FIO_OPT_UNSUPPORTED,
3194 .help = "Your platform does not support IO scheduler switching",
3195 },
214e1eca
JA
3196#endif
3197 {
3198 .name = "zonesize",
e8b0e958 3199 .lname = "Zone size",
214e1eca 3200 .type = FIO_OPT_STR_VAL,
a609f12a 3201 .off1 = offsetof(struct thread_options, zone_size),
ed335855
SN
3202 .help = "Amount of data to read per zone",
3203 .def = "0",
20eb06bd 3204 .interval = 1024 * 1024,
e8b0e958
JA
3205 .category = FIO_OPT_C_IO,
3206 .group = FIO_OPT_G_ZONE,
ed335855
SN
3207 },
3208 {
3209 .name = "zonerange",
e8b0e958 3210 .lname = "Zone range",
ed335855 3211 .type = FIO_OPT_STR_VAL,
a609f12a 3212 .off1 = offsetof(struct thread_options, zone_range),
214e1eca
JA
3213 .help = "Give size of an IO zone",
3214 .def = "0",
20eb06bd 3215 .interval = 1024 * 1024,
e8b0e958
JA
3216 .category = FIO_OPT_C_IO,
3217 .group = FIO_OPT_G_ZONE,
214e1eca
JA
3218 },
3219 {
3220 .name = "zoneskip",
e8b0e958 3221 .lname = "Zone skip",
214e1eca 3222 .type = FIO_OPT_STR_VAL,
a609f12a 3223 .off1 = offsetof(struct thread_options, zone_skip),
214e1eca
JA
3224 .help = "Space between IO zones",
3225 .def = "0",
20eb06bd 3226 .interval = 1024 * 1024,
e8b0e958
JA
3227 .category = FIO_OPT_C_IO,
3228 .group = FIO_OPT_G_ZONE,
214e1eca
JA
3229 },
3230 {
3231 .name = "lockmem",
e8b0e958 3232 .lname = "Lock memory",
214e1eca 3233 .type = FIO_OPT_STR_VAL,
a609f12a 3234 .off1 = offsetof(struct thread_options, lockmem),
81c6b6cd 3235 .help = "Lock down this amount of memory (per worker)",
214e1eca 3236 .def = "0",
20eb06bd 3237 .interval = 1024 * 1024,
e8b0e958
JA
3238 .category = FIO_OPT_C_GENERAL,
3239 .group = FIO_OPT_G_INVALID,
214e1eca 3240 },
214e1eca
JA
3241 {
3242 .name = "rwmixread",
e8b0e958 3243 .lname = "Read/write mix read",
214e1eca 3244 .type = FIO_OPT_INT,
cb499fc4 3245 .cb = str_rwmix_read_cb,
a609f12a 3246 .off1 = offsetof(struct thread_options, rwmix[DDIR_READ]),
214e1eca
JA
3247 .maxval = 100,
3248 .help = "Percentage of mixed workload that is reads",
3249 .def = "50",
20eb06bd 3250 .interval = 5,
90265353 3251 .inverse = "rwmixwrite",
e8b0e958
JA
3252 .category = FIO_OPT_C_IO,
3253 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
3254 },
3255 {
3256 .name = "rwmixwrite",
e8b0e958 3257 .lname = "Read/write mix write",
214e1eca 3258 .type = FIO_OPT_INT,
cb499fc4 3259 .cb = str_rwmix_write_cb,
a609f12a 3260 .off1 = offsetof(struct thread_options, rwmix[DDIR_WRITE]),
214e1eca
JA
3261 .maxval = 100,
3262 .help = "Percentage of mixed workload that is writes",
3263 .def = "50",
20eb06bd 3264 .interval = 5,
90265353 3265 .inverse = "rwmixread",
e8b0e958
JA
3266 .category = FIO_OPT_C_IO,
3267 .group = FIO_OPT_G_RWMIX,
214e1eca 3268 },
afdf9352
JA
3269 {
3270 .name = "rwmixcycle",
e8b0e958 3271 .lname = "Read/write mix cycle",
15ca150e 3272 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
3273 .category = FIO_OPT_C_IO,
3274 .group = FIO_OPT_G_RWMIX,
afdf9352 3275 },
214e1eca
JA
3276 {
3277 .name = "nice",
e8b0e958 3278 .lname = "Nice",
214e1eca 3279 .type = FIO_OPT_INT,
a609f12a 3280 .off1 = offsetof(struct thread_options, nice),
214e1eca 3281 .help = "Set job CPU nice value",
11fd6aa8
RC
3282 .minval = -20,
3283 .maxval = 19,
214e1eca 3284 .def = "0",
20eb06bd 3285 .interval = 1,
e8b0e958 3286 .category = FIO_OPT_C_GENERAL,
10860056 3287 .group = FIO_OPT_G_CRED,
214e1eca
JA
3288 },
3289#ifdef FIO_HAVE_IOPRIO
3290 {
3291 .name = "prio",
e8b0e958 3292 .lname = "I/O nice priority",
214e1eca 3293 .type = FIO_OPT_INT,
a609f12a 3294 .off1 = offsetof(struct thread_options, ioprio),
214e1eca 3295 .help = "Set job IO priority value",
1767bd34
TK
3296 .minval = IOPRIO_MIN_PRIO,
3297 .maxval = IOPRIO_MAX_PRIO,
20eb06bd 3298 .interval = 1,
e8b0e958 3299 .category = FIO_OPT_C_GENERAL,
10860056 3300 .group = FIO_OPT_G_CRED,
214e1eca 3301 },
32ef447a
TK
3302#else
3303 {
3304 .name = "prio",
3305 .lname = "I/O nice priority",
3306 .type = FIO_OPT_UNSUPPORTED,
3307 .help = "Your platform does not support IO priorities",
3308 },
3309#endif
3310#ifdef FIO_HAVE_IOPRIO_CLASS
3311#ifndef FIO_HAVE_IOPRIO
3312#error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
3313#endif
214e1eca
JA
3314 {
3315 .name = "prioclass",
e8b0e958 3316 .lname = "I/O nice priority class",
214e1eca 3317 .type = FIO_OPT_INT,
a609f12a 3318 .off1 = offsetof(struct thread_options, ioprio_class),
214e1eca 3319 .help = "Set job IO priority class",
1767bd34
TK
3320 .minval = IOPRIO_MIN_PRIO_CLASS,
3321 .maxval = IOPRIO_MAX_PRIO_CLASS,
20eb06bd 3322 .interval = 1,
e8b0e958 3323 .category = FIO_OPT_C_GENERAL,
10860056 3324 .group = FIO_OPT_G_CRED,
214e1eca 3325 },
a275c37a 3326#else
a275c37a
JA
3327 {
3328 .name = "prioclass",
3329 .lname = "I/O nice priority class",
3330 .type = FIO_OPT_UNSUPPORTED,
32ef447a 3331 .help = "Your platform does not support IO priority classes",
a275c37a 3332 },
214e1eca
JA
3333#endif
3334 {
3335 .name = "thinktime",
e8b0e958 3336 .lname = "Thinktime",
214e1eca 3337 .type = FIO_OPT_INT,
a609f12a 3338 .off1 = offsetof(struct thread_options, thinktime),
214e1eca
JA
3339 .help = "Idle time between IO buffers (usec)",
3340 .def = "0",
88038bc7 3341 .is_time = 1,
e8b0e958 3342 .category = FIO_OPT_C_IO,
3ceb458f 3343 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3344 },
3345 {
3346 .name = "thinktime_spin",
e8b0e958 3347 .lname = "Thinktime spin",
214e1eca 3348 .type = FIO_OPT_INT,
a609f12a 3349 .off1 = offsetof(struct thread_options, thinktime_spin),
214e1eca
JA
3350 .help = "Start think time by spinning this amount (usec)",
3351 .def = "0",
88038bc7 3352 .is_time = 1,
afdf9352 3353 .parent = "thinktime",
d71c154c 3354 .hide = 1,
e8b0e958 3355 .category = FIO_OPT_C_IO,
3ceb458f 3356 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3357 },
3358 {
3359 .name = "thinktime_blocks",
e8b0e958 3360 .lname = "Thinktime blocks",
214e1eca 3361 .type = FIO_OPT_INT,
a609f12a 3362 .off1 = offsetof(struct thread_options, thinktime_blocks),
214e1eca
JA
3363 .help = "IO buffer period between 'thinktime'",
3364 .def = "1",
afdf9352 3365 .parent = "thinktime",
d71c154c 3366 .hide = 1,
e8b0e958 3367 .category = FIO_OPT_C_IO,
3ceb458f 3368 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3369 },
3370 {
3371 .name = "rate",
e8b0e958 3372 .lname = "I/O rate",
e01b22b8 3373 .type = FIO_OPT_INT,
a609f12a
JA
3374 .off1 = offsetof(struct thread_options, rate[DDIR_READ]),
3375 .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]),
3376 .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]),
214e1eca 3377 .help = "Set bandwidth rate",
e8b0e958
JA
3378 .category = FIO_OPT_C_IO,
3379 .group = FIO_OPT_G_RATE,
214e1eca
JA
3380 },
3381 {
6d428bcd
JA
3382 .name = "rate_min",
3383 .alias = "ratemin",
e8b0e958 3384 .lname = "I/O min rate",
e01b22b8 3385 .type = FIO_OPT_INT,
a609f12a
JA
3386 .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]),
3387 .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]),
3388 .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]),
4e991c23 3389 .help = "Job must meet this rate or it will be shutdown",
afdf9352 3390 .parent = "rate",
d71c154c 3391 .hide = 1,
e8b0e958
JA
3392 .category = FIO_OPT_C_IO,
3393 .group = FIO_OPT_G_RATE,
4e991c23
JA
3394 },
3395 {
3396 .name = "rate_iops",
e8b0e958 3397 .lname = "I/O rate IOPS",
e01b22b8 3398 .type = FIO_OPT_INT,
a609f12a
JA
3399 .off1 = offsetof(struct thread_options, rate_iops[DDIR_READ]),
3400 .off2 = offsetof(struct thread_options, rate_iops[DDIR_WRITE]),
3401 .off3 = offsetof(struct thread_options, rate_iops[DDIR_TRIM]),
4e991c23 3402 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 3403 .hide = 1,
e8b0e958
JA
3404 .category = FIO_OPT_C_IO,
3405 .group = FIO_OPT_G_RATE,
4e991c23
JA
3406 },
3407 {
3408 .name = "rate_iops_min",
e8b0e958 3409 .lname = "I/O min rate IOPS",
e01b22b8 3410 .type = FIO_OPT_INT,
a609f12a
JA
3411 .off1 = offsetof(struct thread_options, rate_iops_min[DDIR_READ]),
3412 .off2 = offsetof(struct thread_options, rate_iops_min[DDIR_WRITE]),
3413 .off3 = offsetof(struct thread_options, rate_iops_min[DDIR_TRIM]),
03e20d68 3414 .help = "Job must meet this rate or it will be shut down",
afdf9352 3415 .parent = "rate_iops",
d71c154c 3416 .hide = 1,
e8b0e958
JA
3417 .category = FIO_OPT_C_IO,
3418 .group = FIO_OPT_G_RATE,
214e1eca 3419 },
ff6bb260 3420 {
6de65959
JA
3421 .name = "rate_process",
3422 .lname = "Rate Process",
3423 .type = FIO_OPT_STR,
a609f12a 3424 .off1 = offsetof(struct thread_options, rate_process),
6de65959
JA
3425 .help = "What process controls how rated IO is managed",
3426 .def = "linear",
ff6bb260
SL
3427 .category = FIO_OPT_C_IO,
3428 .group = FIO_OPT_G_RATE,
6de65959
JA
3429 .posval = {
3430 { .ival = "linear",
3431 .oval = RATE_PROCESS_LINEAR,
3432 .help = "Linear rate of IO",
3433 },
3434 {
3435 .ival = "poisson",
3436 .oval = RATE_PROCESS_POISSON,
3437 .help = "Rate follows Poisson process",
3438 },
3439 },
3440 .parent = "rate",
ff6bb260 3441 },
214e1eca 3442 {
6d428bcd
JA
3443 .name = "rate_cycle",
3444 .alias = "ratecycle",
e8b0e958 3445 .lname = "I/O rate cycle",
214e1eca 3446 .type = FIO_OPT_INT,
a609f12a 3447 .off1 = offsetof(struct thread_options, ratecycle),
214e1eca
JA
3448 .help = "Window average for rate limits (msec)",
3449 .def = "1000",
afdf9352 3450 .parent = "rate",
d71c154c 3451 .hide = 1,
e8b0e958
JA
3452 .category = FIO_OPT_C_IO,
3453 .group = FIO_OPT_G_RATE,
214e1eca 3454 },
1a9bf814
JA
3455 {
3456 .name = "rate_ignore_thinktime",
3457 .lname = "Rate ignore thinktime",
3458 .type = FIO_OPT_BOOL,
3459 .off1 = offsetof(struct thread_options, rate_ign_think),
3460 .help = "Rated IO ignores thinktime settings",
3461 .parent = "rate",
3462 .category = FIO_OPT_C_IO,
3463 .group = FIO_OPT_G_RATE,
3464 },
15501535
JA
3465 {
3466 .name = "max_latency",
dd97d866 3467 .lname = "Max Latency (usec)",
6c3fb04c 3468 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3469 .off1 = offsetof(struct thread_options, max_latency),
15501535 3470 .help = "Maximum tolerated IO latency (usec)",
88038bc7 3471 .is_time = 1,
1e5324e7 3472 .category = FIO_OPT_C_IO,
3e260a46
JA
3473 .group = FIO_OPT_G_LATPROF,
3474 },
3475 {
3476 .name = "latency_target",
3477 .lname = "Latency Target (usec)",
3478 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3479 .off1 = offsetof(struct thread_options, latency_target),
3e260a46 3480 .help = "Ramp to max queue depth supporting this latency",
88038bc7 3481 .is_time = 1,
3e260a46
JA
3482 .category = FIO_OPT_C_IO,
3483 .group = FIO_OPT_G_LATPROF,
3484 },
3485 {
3486 .name = "latency_window",
3487 .lname = "Latency Window (usec)",
3488 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3489 .off1 = offsetof(struct thread_options, latency_window),
3e260a46 3490 .help = "Time to sustain latency_target",
88038bc7 3491 .is_time = 1,
3e260a46
JA
3492 .category = FIO_OPT_C_IO,
3493 .group = FIO_OPT_G_LATPROF,
3494 },
3495 {
3496 .name = "latency_percentile",
3497 .lname = "Latency Percentile",
3498 .type = FIO_OPT_FLOAT_LIST,
a609f12a 3499 .off1 = offsetof(struct thread_options, latency_percentile),
3e260a46
JA
3500 .help = "Percentile of IOs must be below latency_target",
3501 .def = "100",
3502 .maxlen = 1,
3503 .minfp = 0.0,
3504 .maxfp = 100.0,
3505 .category = FIO_OPT_C_IO,
3506 .group = FIO_OPT_G_LATPROF,
15501535 3507 },
214e1eca
JA
3508 {
3509 .name = "invalidate",
e8b0e958 3510 .lname = "Cache invalidate",
214e1eca 3511 .type = FIO_OPT_BOOL,
a609f12a 3512 .off1 = offsetof(struct thread_options, invalidate_cache),
214e1eca
JA
3513 .help = "Invalidate buffer/page cache prior to running job",
3514 .def = "1",
e8b0e958 3515 .category = FIO_OPT_C_IO,
3ceb458f 3516 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
3517 },
3518 {
3519 .name = "sync",
e8b0e958 3520 .lname = "Synchronous I/O",
214e1eca 3521 .type = FIO_OPT_BOOL,
a609f12a 3522 .off1 = offsetof(struct thread_options, sync_io),
214e1eca
JA
3523 .help = "Use O_SYNC for buffered writes",
3524 .def = "0",
67a1000f 3525 .parent = "buffered",
d71c154c 3526 .hide = 1,
e8b0e958 3527 .category = FIO_OPT_C_IO,
3ceb458f 3528 .group = FIO_OPT_G_IO_TYPE,
214e1eca 3529 },
ae8e559e
JA
3530#ifdef FIO_HAVE_WRITE_HINT
3531 {
3532 .name = "write_hint",
3533 .lname = "Write hint",
3534 .type = FIO_OPT_STR,
3535 .off1 = offsetof(struct thread_options, write_hint),
3536 .help = "Set expected write life time",
3537 .category = FIO_OPT_C_ENGINE,
3538 .group = FIO_OPT_G_INVALID,
3539 .posval = {
3540 { .ival = "none",
3541 .oval = RWH_WRITE_LIFE_NONE,
3542 },
3543 { .ival = "short",
3544 .oval = RWH_WRITE_LIFE_SHORT,
3545 },
3546 { .ival = "medium",
3547 .oval = RWH_WRITE_LIFE_MEDIUM,
3548 },
3549 { .ival = "long",
3550 .oval = RWH_WRITE_LIFE_LONG,
3551 },
3552 { .ival = "extreme",
3553 .oval = RWH_WRITE_LIFE_EXTREME,
3554 },
3555 },
3556 },
3557#endif
214e1eca
JA
3558 {
3559 .name = "create_serialize",
e8b0e958 3560 .lname = "Create serialize",
214e1eca 3561 .type = FIO_OPT_BOOL,
a609f12a 3562 .off1 = offsetof(struct thread_options, create_serialize),
c2b8035f 3563 .help = "Serialize creation of job files",
214e1eca 3564 .def = "1",
e8b0e958
JA
3565 .category = FIO_OPT_C_FILE,
3566 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3567 },
3568 {
3569 .name = "create_fsync",
e8b0e958 3570 .lname = "Create fsync",
214e1eca 3571 .type = FIO_OPT_BOOL,
a609f12a 3572 .off1 = offsetof(struct thread_options, create_fsync),
03e20d68 3573 .help = "fsync file after creation",
214e1eca 3574 .def = "1",
e8b0e958
JA
3575 .category = FIO_OPT_C_FILE,
3576 .group = FIO_OPT_G_INVALID,
214e1eca 3577 },
814452bd
JA
3578 {
3579 .name = "create_on_open",
e8b0e958 3580 .lname = "Create on open",
814452bd 3581 .type = FIO_OPT_BOOL,
a609f12a 3582 .off1 = offsetof(struct thread_options, create_on_open),
814452bd
JA
3583 .help = "Create files when they are opened for IO",
3584 .def = "0",
e8b0e958
JA
3585 .category = FIO_OPT_C_FILE,
3586 .group = FIO_OPT_G_INVALID,
814452bd 3587 },
25460cf6
JA
3588 {
3589 .name = "create_only",
cce2fdfe 3590 .lname = "Create Only",
25460cf6 3591 .type = FIO_OPT_BOOL,
a609f12a 3592 .off1 = offsetof(struct thread_options, create_only),
25460cf6 3593 .help = "Only perform file creation phase",
d17fda71 3594 .category = FIO_OPT_C_FILE,
25460cf6
JA
3595 .def = "0",
3596 },
2378826d
JA
3597 {
3598 .name = "allow_file_create",
e81ecca3 3599 .lname = "Allow file create",
2378826d 3600 .type = FIO_OPT_BOOL,
a609f12a 3601 .off1 = offsetof(struct thread_options, allow_create),
2378826d
JA
3602 .help = "Permit fio to create files, if they don't exist",
3603 .def = "1",
3604 .category = FIO_OPT_C_FILE,
3605 .group = FIO_OPT_G_FILENAME,
3606 },
e81ecca3
JA
3607 {
3608 .name = "allow_mounted_write",
3609 .lname = "Allow mounted write",
3610 .type = FIO_OPT_BOOL,
a609f12a 3611 .off1 = offsetof(struct thread_options, allow_mounted_write),
e81ecca3
JA
3612 .help = "Allow writes to a mounted partition",
3613 .def = "0",
3614 .category = FIO_OPT_C_FILE,
3615 .group = FIO_OPT_G_FILENAME,
3616 },
0b9d69ec 3617 {
afad68f7 3618 .name = "pre_read",
e8b0e958 3619 .lname = "Pre-read files",
afad68f7 3620 .type = FIO_OPT_BOOL,
a609f12a 3621 .off1 = offsetof(struct thread_options, pre_read),
03e20d68 3622 .help = "Pre-read files before starting official testing",
afad68f7 3623 .def = "0",
e8b0e958
JA
3624 .category = FIO_OPT_C_FILE,
3625 .group = FIO_OPT_G_INVALID,
afad68f7 3626 },
214e1eca
JA
3627#ifdef FIO_HAVE_CPU_AFFINITY
3628 {
3629 .name = "cpumask",
e8b0e958 3630 .lname = "CPU mask",
214e1eca
JA
3631 .type = FIO_OPT_INT,
3632 .cb = str_cpumask_cb,
a609f12a 3633 .off1 = offsetof(struct thread_options, cpumask),
214e1eca 3634 .help = "CPU affinity mask",
e8b0e958 3635 .category = FIO_OPT_C_GENERAL,
10860056 3636 .group = FIO_OPT_G_CRED,
214e1eca 3637 },
d2e268b0
JA
3638 {
3639 .name = "cpus_allowed",
e8b0e958 3640 .lname = "CPUs allowed",
d2e268b0
JA
3641 .type = FIO_OPT_STR,
3642 .cb = str_cpus_allowed_cb,
a609f12a 3643 .off1 = offsetof(struct thread_options, cpumask),
d2e268b0 3644 .help = "Set CPUs allowed",
e8b0e958 3645 .category = FIO_OPT_C_GENERAL,
10860056 3646 .group = FIO_OPT_G_CRED,
d2e268b0 3647 },
c2acfbac
JA
3648 {
3649 .name = "cpus_allowed_policy",
3650 .lname = "CPUs allowed distribution policy",
3651 .type = FIO_OPT_STR,
a609f12a 3652 .off1 = offsetof(struct thread_options, cpus_allowed_policy),
c2acfbac
JA
3653 .help = "Distribution policy for cpus_allowed",
3654 .parent = "cpus_allowed",
3655 .prio = 1,
3656 .posval = {
3657 { .ival = "shared",
3658 .oval = FIO_CPUS_SHARED,
3659 .help = "Mask shared between threads",
3660 },
3661 { .ival = "split",
3662 .oval = FIO_CPUS_SPLIT,
3663 .help = "Mask split between threads",
3664 },
3665 },
3666 .category = FIO_OPT_C_GENERAL,
3667 .group = FIO_OPT_G_CRED,
3668 },
a275c37a
JA
3669#else
3670 {
3671 .name = "cpumask",
3672 .lname = "CPU mask",
3673 .type = FIO_OPT_UNSUPPORTED,
3674 .help = "Your platform does not support CPU affinities",
3675 },
3676 {
3677 .name = "cpus_allowed",
3678 .lname = "CPUs allowed",
3679 .type = FIO_OPT_UNSUPPORTED,
3680 .help = "Your platform does not support CPU affinities",
3681 },
3682 {
3683 .name = "cpus_allowed_policy",
3684 .lname = "CPUs allowed distribution policy",
3685 .type = FIO_OPT_UNSUPPORTED,
3686 .help = "Your platform does not support CPU affinities",
3687 },
d0b937ed 3688#endif
67bf9823 3689#ifdef CONFIG_LIBNUMA
d0b937ed
YR
3690 {
3691 .name = "numa_cpu_nodes",
cce2fdfe 3692 .lname = "NUMA CPU Nodes",
d0b937ed
YR
3693 .type = FIO_OPT_STR,
3694 .cb = str_numa_cpunodes_cb,
a609f12a 3695 .off1 = offsetof(struct thread_options, numa_cpunodes),
d0b937ed 3696 .help = "NUMA CPU nodes bind",
6be54b2d
JA
3697 .category = FIO_OPT_C_GENERAL,
3698 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
3699 },
3700 {
3701 .name = "numa_mem_policy",
cce2fdfe 3702 .lname = "NUMA Memory Policy",
d0b937ed
YR
3703 .type = FIO_OPT_STR,
3704 .cb = str_numa_mpol_cb,
a609f12a 3705 .off1 = offsetof(struct thread_options, numa_memnodes),
d0b937ed 3706 .help = "NUMA memory policy setup",
6be54b2d
JA
3707 .category = FIO_OPT_C_GENERAL,
3708 .group = FIO_OPT_G_INVALID,
d0b937ed 3709 },
a275c37a
JA
3710#else
3711 {
3712 .name = "numa_cpu_nodes",
3713 .lname = "NUMA CPU Nodes",
3714 .type = FIO_OPT_UNSUPPORTED,
3715 .help = "Build fio with libnuma-dev(el) to enable this option",
3716 },
3717 {
3718 .name = "numa_mem_policy",
3719 .lname = "NUMA Memory Policy",
3720 .type = FIO_OPT_UNSUPPORTED,
3721 .help = "Build fio with libnuma-dev(el) to enable this option",
3722 },
03553853
YR
3723#endif
3724#ifdef CONFIG_CUDA
3725 {
3726 .name = "gpu_dev_id",
3727 .lname = "GPU device ID",
3728 .type = FIO_OPT_INT,
3729 .off1 = offsetof(struct thread_options, gpu_dev_id),
3730 .help = "Set GPU device ID for GPUDirect RDMA",
3731 .def = "0",
3732 .category = FIO_OPT_C_GENERAL,
3733 .group = FIO_OPT_G_INVALID,
3734 },
214e1eca
JA
3735#endif
3736 {
3737 .name = "end_fsync",
e8b0e958 3738 .lname = "End fsync",
214e1eca 3739 .type = FIO_OPT_BOOL,
a609f12a 3740 .off1 = offsetof(struct thread_options, end_fsync),
214e1eca
JA
3741 .help = "Include fsync at the end of job",
3742 .def = "0",
e8b0e958
JA
3743 .category = FIO_OPT_C_FILE,
3744 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3745 },
3746 {
3747 .name = "fsync_on_close",
e8b0e958 3748 .lname = "Fsync on close",
214e1eca 3749 .type = FIO_OPT_BOOL,
a609f12a 3750 .off1 = offsetof(struct thread_options, fsync_on_close),
214e1eca
JA
3751 .help = "fsync files on close",
3752 .def = "0",
e8b0e958
JA
3753 .category = FIO_OPT_C_FILE,
3754 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3755 },
3756 {
3757 .name = "unlink",
e8b0e958 3758 .lname = "Unlink file",
214e1eca 3759 .type = FIO_OPT_BOOL,
a609f12a 3760 .off1 = offsetof(struct thread_options, unlink),
214e1eca
JA
3761 .help = "Unlink created files after job has completed",
3762 .def = "0",
e8b0e958
JA
3763 .category = FIO_OPT_C_FILE,
3764 .group = FIO_OPT_G_INVALID,
214e1eca 3765 },
39c1c323 3766 {
3767 .name = "unlink_each_loop",
3768 .lname = "Unlink file after each loop of a job",
3769 .type = FIO_OPT_BOOL,
a609f12a 3770 .off1 = offsetof(struct thread_options, unlink_each_loop),
39c1c323 3771 .help = "Unlink created files after each loop in a job has completed",
3772 .def = "0",
3773 .category = FIO_OPT_C_FILE,
3774 .group = FIO_OPT_G_INVALID,
3775 },
214e1eca
JA
3776 {
3777 .name = "exitall",
e8b0e958 3778 .lname = "Exit-all on terminate",
214e1eca
JA
3779 .type = FIO_OPT_STR_SET,
3780 .cb = str_exitall_cb,
3781 .help = "Terminate all jobs when one exits",
e8b0e958 3782 .category = FIO_OPT_C_GENERAL,
a1f6afec 3783 .group = FIO_OPT_G_PROCESS,
214e1eca 3784 },
f9cafb12
JA
3785 {
3786 .name = "exitall_on_error",
3787 .lname = "Exit-all on terminate in error",
78abcf9b 3788 .type = FIO_OPT_STR_SET,
a609f12a 3789 .off1 = offsetof(struct thread_options, exitall_error),
f9cafb12
JA
3790 .help = "Terminate all jobs when one exits in error",
3791 .category = FIO_OPT_C_GENERAL,
3792 .group = FIO_OPT_G_PROCESS,
3793 },
214e1eca
JA
3794 {
3795 .name = "stonewall",
e8b0e958 3796 .lname = "Wait for previous",
d392365e 3797 .alias = "wait_for_previous",
214e1eca 3798 .type = FIO_OPT_STR_SET,
a609f12a 3799 .off1 = offsetof(struct thread_options, stonewall),
214e1eca 3800 .help = "Insert a hard barrier between this job and previous",
e8b0e958 3801 .category = FIO_OPT_C_GENERAL,
a1f6afec 3802 .group = FIO_OPT_G_PROCESS,
214e1eca 3803 },
b3d62a75
JA
3804 {
3805 .name = "new_group",
e8b0e958 3806 .lname = "New group",
b3d62a75 3807 .type = FIO_OPT_STR_SET,
a609f12a 3808 .off1 = offsetof(struct thread_options, new_group),
b3d62a75 3809 .help = "Mark the start of a new group (for reporting)",
e8b0e958 3810 .category = FIO_OPT_C_GENERAL,
a1f6afec 3811 .group = FIO_OPT_G_PROCESS,
b3d62a75 3812 },
214e1eca
JA
3813 {
3814 .name = "thread",
e8b0e958 3815 .lname = "Thread",
214e1eca 3816 .type = FIO_OPT_STR_SET,
a609f12a 3817 .off1 = offsetof(struct thread_options, use_thread),
20eb06bd 3818 .help = "Use threads instead of processes",
c8931876
JA
3819#ifdef CONFIG_NO_SHM
3820 .def = "1",
3821 .no_warn_def = 1,
3822#endif
e8b0e958 3823 .category = FIO_OPT_C_GENERAL,
a1f6afec 3824 .group = FIO_OPT_G_PROCESS,
214e1eca 3825 },
3a5db920
JA
3826 {
3827 .name = "per_job_logs",
cce2fdfe 3828 .lname = "Per Job Logs",
3a5db920 3829 .type = FIO_OPT_BOOL,
a609f12a 3830 .off1 = offsetof(struct thread_options, per_job_logs),
3a5db920
JA
3831 .help = "Include job number in generated log files or not",
3832 .def = "1",
3833 .category = FIO_OPT_C_LOG,
3834 .group = FIO_OPT_G_INVALID,
3835 },
214e1eca
JA
3836 {
3837 .name = "write_bw_log",
e8b0e958 3838 .lname = "Write bandwidth log",
dded427c 3839 .type = FIO_OPT_STR,
a609f12a 3840 .off1 = offsetof(struct thread_options, bw_log_file),
dded427c 3841 .cb = str_write_bw_log_cb,
214e1eca 3842 .help = "Write log of bandwidth during run",
e8b0e958
JA
3843 .category = FIO_OPT_C_LOG,
3844 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3845 },
3846 {
3847 .name = "write_lat_log",
e8b0e958 3848 .lname = "Write latency log",
dded427c 3849 .type = FIO_OPT_STR,
a609f12a 3850 .off1 = offsetof(struct thread_options, lat_log_file),
dded427c 3851 .cb = str_write_lat_log_cb,
214e1eca 3852 .help = "Write log of latency during run",
e8b0e958
JA
3853 .category = FIO_OPT_C_LOG,
3854 .group = FIO_OPT_G_INVALID,
214e1eca 3855 },
c8eeb9df
JA
3856 {
3857 .name = "write_iops_log",
e8b0e958 3858 .lname = "Write IOPS log",
dded427c 3859 .type = FIO_OPT_STR,
a609f12a 3860 .off1 = offsetof(struct thread_options, iops_log_file),
dded427c 3861 .cb = str_write_iops_log_cb,
c8eeb9df 3862 .help = "Write log of IOPS during run",
e8b0e958
JA
3863 .category = FIO_OPT_C_LOG,
3864 .group = FIO_OPT_G_INVALID,
c8eeb9df 3865 },
b8bc8cba
JA
3866 {
3867 .name = "log_avg_msec",
e8b0e958 3868 .lname = "Log averaging (msec)",
b8bc8cba 3869 .type = FIO_OPT_INT,
a609f12a 3870 .off1 = offsetof(struct thread_options, log_avg_msec),
b8bc8cba
JA
3871 .help = "Average bw/iops/lat logs over this period of time",
3872 .def = "0",
e8b0e958 3873 .category = FIO_OPT_C_LOG,
1e613c9c
KC
3874 .group = FIO_OPT_G_INVALID,
3875 },
3876 {
3877 .name = "log_hist_msec",
3878 .lname = "Log histograms (msec)",
3879 .type = FIO_OPT_INT,
a609f12a 3880 .off1 = offsetof(struct thread_options, log_hist_msec),
1e613c9c
KC
3881 .help = "Dump completion latency histograms at frequency of this time value",
3882 .def = "0",
3883 .category = FIO_OPT_C_LOG,
3884 .group = FIO_OPT_G_INVALID,
3885 },
3886 {
3887 .name = "log_hist_coarseness",
3888 .lname = "Histogram logs coarseness",
3889 .type = FIO_OPT_INT,
a609f12a 3890 .off1 = offsetof(struct thread_options, log_hist_coarseness),
1e613c9c
KC
3891 .help = "Integer in range [0,6]. Higher coarseness outputs"
3892 " fewer histogram bins per sample. The number of bins for"
3893 " these are [1216, 608, 304, 152, 76, 38, 19] respectively.",
3894 .def = "0",
3895 .category = FIO_OPT_C_LOG,
3896 .group = FIO_OPT_G_INVALID,
3897 },
3898 {
3899 .name = "write_hist_log",
3900 .lname = "Write latency histogram logs",
dded427c 3901 .type = FIO_OPT_STR,
a609f12a 3902 .off1 = offsetof(struct thread_options, hist_log_file),
dded427c 3903 .cb = str_write_hist_log_cb,
1e613c9c
KC
3904 .help = "Write log of latency histograms during run",
3905 .category = FIO_OPT_C_LOG,
e8b0e958 3906 .group = FIO_OPT_G_INVALID,
b8bc8cba 3907 },
e6989e10
JA
3908 {
3909 .name = "log_max_value",
3910 .lname = "Log maximum instead of average",
3911 .type = FIO_OPT_BOOL,
a609f12a 3912 .off1 = offsetof(struct thread_options, log_max),
e6989e10
JA
3913 .help = "Log max sample in a window instead of average",
3914 .def = "0",
3915 .category = FIO_OPT_C_LOG,
3916 .group = FIO_OPT_G_INVALID,
3917 },
ae588852
JA
3918 {
3919 .name = "log_offset",
3920 .lname = "Log offset of IO",
3921 .type = FIO_OPT_BOOL,
a609f12a 3922 .off1 = offsetof(struct thread_options, log_offset),
ae588852
JA
3923 .help = "Include offset of IO for each log entry",
3924 .def = "0",
3925 .category = FIO_OPT_C_LOG,
3926 .group = FIO_OPT_G_INVALID,
3927 },
aee2ab67
JA
3928#ifdef CONFIG_ZLIB
3929 {
3930 .name = "log_compression",
3931 .lname = "Log compression",
3932 .type = FIO_OPT_INT,
a609f12a 3933 .off1 = offsetof(struct thread_options, log_gz),
aee2ab67 3934 .help = "Log in compressed chunks of this size",
9919b27b 3935 .minval = 1024ULL,
aee2ab67
JA
3936 .maxval = 512 * 1024 * 1024ULL,
3937 .category = FIO_OPT_C_LOG,
3938 .group = FIO_OPT_G_INVALID,
3939 },
c08f9fe2
JA
3940#ifdef FIO_HAVE_CPU_AFFINITY
3941 {
3942 .name = "log_compression_cpus",
3943 .lname = "Log Compression CPUs",
3944 .type = FIO_OPT_STR,
3945 .cb = str_log_cpus_allowed_cb,
a609f12a 3946 .off1 = offsetof(struct thread_options, log_gz_cpumask),
c08f9fe2
JA
3947 .parent = "log_compression",
3948 .help = "Limit log compression to these CPUs",
3949 .category = FIO_OPT_C_LOG,
3950 .group = FIO_OPT_G_INVALID,
3951 },
a275c37a
JA
3952#else
3953 {
3954 .name = "log_compression_cpus",
3955 .lname = "Log Compression CPUs",
3956 .type = FIO_OPT_UNSUPPORTED,
3957 .help = "Your platform does not support CPU affinities",
3958 },
c08f9fe2 3959#endif
b26317c9
JA
3960 {
3961 .name = "log_store_compressed",
3962 .lname = "Log store compressed",
3963 .type = FIO_OPT_BOOL,
a609f12a 3964 .off1 = offsetof(struct thread_options, log_gz_store),
b26317c9
JA
3965 .help = "Store logs in a compressed format",
3966 .category = FIO_OPT_C_LOG,
3967 .group = FIO_OPT_G_INVALID,
3968 },
a275c37a
JA
3969#else
3970 {
3971 .name = "log_compression",
3972 .lname = "Log compression",
3973 .type = FIO_OPT_UNSUPPORTED,
3974 .help = "Install libz-dev(el) to get compression support",
3975 },
3976 {
3977 .name = "log_store_compressed",
3978 .lname = "Log store compressed",
3979 .type = FIO_OPT_UNSUPPORTED,
3980 .help = "Install libz-dev(el) to get compression support",
3981 },
aee2ab67 3982#endif
3aea75b1
KC
3983 {
3984 .name = "log_unix_epoch",
3985 .lname = "Log epoch unix",
3986 .type = FIO_OPT_BOOL,
3987 .off1 = offsetof(struct thread_options, log_unix_epoch),
3988 .help = "Use Unix time in log files",
3989 .category = FIO_OPT_C_LOG,
3990 .group = FIO_OPT_G_INVALID,
3991 },
66347cfa
DE
3992 {
3993 .name = "block_error_percentiles",
3994 .lname = "Block error percentiles",
3995 .type = FIO_OPT_BOOL,
a609f12a 3996 .off1 = offsetof(struct thread_options, block_error_hist),
66347cfa
DE
3997 .help = "Record trim block errors and make a histogram",
3998 .def = "0",
3999 .category = FIO_OPT_C_LOG,
4000 .group = FIO_OPT_G_INVALID,
4001 },
c504ee55
JA
4002 {
4003 .name = "bwavgtime",
4004 .lname = "Bandwidth average time",
4005 .type = FIO_OPT_INT,
a609f12a 4006 .off1 = offsetof(struct thread_options, bw_avg_time),
c504ee55
JA
4007 .help = "Time window over which to calculate bandwidth"
4008 " (msec)",
4009 .def = "500",
4010 .parent = "write_bw_log",
4011 .hide = 1,
4012 .interval = 100,
4013 .category = FIO_OPT_C_LOG,
4014 .group = FIO_OPT_G_INVALID,
4015 },
4016 {
4017 .name = "iopsavgtime",
4018 .lname = "IOPS average time",
4019 .type = FIO_OPT_INT,
a609f12a 4020 .off1 = offsetof(struct thread_options, iops_avg_time),
c504ee55
JA
4021 .help = "Time window over which to calculate IOPS (msec)",
4022 .def = "500",
4023 .parent = "write_iops_log",
4024 .hide = 1,
4025 .interval = 100,
4026 .category = FIO_OPT_C_LOG,
4027 .group = FIO_OPT_G_INVALID,
4028 },
214e1eca
JA
4029 {
4030 .name = "group_reporting",
e8b0e958 4031 .lname = "Group reporting",
d2507043 4032 .type = FIO_OPT_STR_SET,
a609f12a 4033 .off1 = offsetof(struct thread_options, group_reporting),
214e1eca 4034 .help = "Do reporting on a per-group basis",
10860056 4035 .category = FIO_OPT_C_STAT,
e8b0e958 4036 .group = FIO_OPT_G_INVALID,
214e1eca 4037 },
8243be59
JA
4038 {
4039 .name = "stats",
4040 .lname = "Stats",
4041 .type = FIO_OPT_BOOL,
4042 .off1 = offsetof(struct thread_options, stats),
4043 .help = "Enable collection of stats",
4044 .def = "1",
4045 .category = FIO_OPT_C_STAT,
4046 .group = FIO_OPT_G_INVALID,
4047 },
e9459e5a
JA
4048 {
4049 .name = "zero_buffers",
e8b0e958 4050 .lname = "Zero I/O buffers",
e9459e5a 4051 .type = FIO_OPT_STR_SET,
a609f12a 4052 .off1 = offsetof(struct thread_options, zero_buffers),
e9459e5a 4053 .help = "Init IO buffers to all zeroes",
e8b0e958 4054 .category = FIO_OPT_C_IO,
3ceb458f 4055 .group = FIO_OPT_G_IO_BUF,
e9459e5a 4056 },
5973cafb
JA
4057 {
4058 .name = "refill_buffers",
e8b0e958 4059 .lname = "Refill I/O buffers",
5973cafb 4060 .type = FIO_OPT_STR_SET,
a609f12a 4061 .off1 = offsetof(struct thread_options, refill_buffers),
5973cafb 4062 .help = "Refill IO buffers on every IO submit",
e8b0e958 4063 .category = FIO_OPT_C_IO,
3ceb458f 4064 .group = FIO_OPT_G_IO_BUF,
5973cafb 4065 },
fd68418e
JA
4066 {
4067 .name = "scramble_buffers",
e8b0e958 4068 .lname = "Scramble I/O buffers",
fd68418e 4069 .type = FIO_OPT_BOOL,
a609f12a 4070 .off1 = offsetof(struct thread_options, scramble_buffers),
fd68418e
JA
4071 .help = "Slightly scramble buffers on every IO submit",
4072 .def = "1",
e8b0e958 4073 .category = FIO_OPT_C_IO,
3ceb458f 4074 .group = FIO_OPT_G_IO_BUF,
fd68418e 4075 },
ce35b1ec
JA
4076 {
4077 .name = "buffer_pattern",
4078 .lname = "Buffer pattern",
4079 .type = FIO_OPT_STR,
4080 .cb = str_buffer_pattern_cb,
a609f12a 4081 .off1 = offsetof(struct thread_options, buffer_pattern),
ce35b1ec
JA
4082 .help = "Fill pattern for IO buffers",
4083 .category = FIO_OPT_C_IO,
4084 .group = FIO_OPT_G_IO_BUF,
4085 },
9c42684e
JA
4086 {
4087 .name = "buffer_compress_percentage",
e8b0e958 4088 .lname = "Buffer compression percentage",
9c42684e 4089 .type = FIO_OPT_INT,
bedc9dc2 4090 .cb = str_buffer_compress_cb,
a609f12a 4091 .off1 = offsetof(struct thread_options, compress_percentage),
9c42684e 4092 .maxval = 100,
e7f5de90 4093 .minval = 0,
9c42684e 4094 .help = "How compressible the buffer is (approximately)",
20eb06bd 4095 .interval = 5,
e8b0e958 4096 .category = FIO_OPT_C_IO,
3ceb458f 4097 .group = FIO_OPT_G_IO_BUF,
9c42684e 4098 },
f97a43a1
JA
4099 {
4100 .name = "buffer_compress_chunk",
e8b0e958 4101 .lname = "Buffer compression chunk size",
f97a43a1 4102 .type = FIO_OPT_INT,
a609f12a 4103 .off1 = offsetof(struct thread_options, compress_chunk),
207b18e4 4104 .parent = "buffer_compress_percentage",
d71c154c 4105 .hide = 1,
f97a43a1 4106 .help = "Size of compressible region in buffer",
1de80624 4107 .def = "512",
20eb06bd 4108 .interval = 256,
e8b0e958 4109 .category = FIO_OPT_C_IO,
3ceb458f 4110 .group = FIO_OPT_G_IO_BUF,
f97a43a1 4111 },
5c94b008
JA
4112 {
4113 .name = "dedupe_percentage",
4114 .lname = "Dedupe percentage",
4115 .type = FIO_OPT_INT,
4116 .cb = str_dedupe_cb,
a609f12a 4117 .off1 = offsetof(struct thread_options, dedupe_percentage),
5c94b008
JA
4118 .maxval = 100,
4119 .minval = 0,
4120 .help = "Percentage of buffers that are dedupable",
4121 .interval = 1,
4122 .category = FIO_OPT_C_IO,
4123 .group = FIO_OPT_G_IO_BUF,
4124 },
83349190
YH
4125 {
4126 .name = "clat_percentiles",
e8b0e958 4127 .lname = "Completion latency percentiles",
83349190 4128 .type = FIO_OPT_BOOL,
a609f12a 4129 .off1 = offsetof(struct thread_options, clat_percentiles),
83349190 4130 .help = "Enable the reporting of completion latency percentiles",
467b35ed 4131 .def = "1",
b599759b
JA
4132 .inverse = "lat_percentiles",
4133 .category = FIO_OPT_C_STAT,
4134 .group = FIO_OPT_G_INVALID,
4135 },
4136 {
4137 .name = "lat_percentiles",
4138 .lname = "IO latency percentiles",
4139 .type = FIO_OPT_BOOL,
4140 .off1 = offsetof(struct thread_options, lat_percentiles),
4141 .help = "Enable the reporting of IO latency percentiles",
4142 .def = "0",
4143 .inverse = "clat_percentiles",
e8b0e958
JA
4144 .category = FIO_OPT_C_STAT,
4145 .group = FIO_OPT_G_INVALID,
83349190
YH
4146 },
4147 {
4148 .name = "percentile_list",
66347cfa 4149 .lname = "Percentile list",
83349190 4150 .type = FIO_OPT_FLOAT_LIST,
a609f12a
JA
4151 .off1 = offsetof(struct thread_options, percentile_list),
4152 .off2 = offsetof(struct thread_options, percentile_precision),
66347cfa
DE
4153 .help = "Specify a custom list of percentiles to report for "
4154 "completion latency and block errors",
fd112d34 4155 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
4156 .maxlen = FIO_IO_U_LIST_MAX_LEN,
4157 .minfp = 0.0,
4158 .maxfp = 100.0,
e8b0e958
JA
4159 .category = FIO_OPT_C_STAT,
4160 .group = FIO_OPT_G_INVALID,
e883cb35
JF
4161 },
4162 {
4163 .name = "significant_figures",
4164 .lname = "Significant figures",
4165 .type = FIO_OPT_INT,
4166 .off1 = offsetof(struct thread_options, sig_figs),
4167 .maxval = 10,
4168 .minval = 1,
4169 .help = "Significant figures for output-format set to normal",
4170 .def = "4",
4171 .interval = 1,
4172 .category = FIO_OPT_C_STAT,
4173 .group = FIO_OPT_G_INVALID,
83349190
YH
4174 },
4175
0a839f30
JA
4176#ifdef FIO_HAVE_DISK_UTIL
4177 {
4178 .name = "disk_util",
e8b0e958 4179 .lname = "Disk utilization",
0a839f30 4180 .type = FIO_OPT_BOOL,
a609f12a 4181 .off1 = offsetof(struct thread_options, do_disk_util),
f66ab3c8 4182 .help = "Log disk utilization statistics",
0a839f30 4183 .def = "1",
e8b0e958
JA
4184 .category = FIO_OPT_C_STAT,
4185 .group = FIO_OPT_G_INVALID,
0a839f30 4186 },
a275c37a
JA
4187#else
4188 {
4189 .name = "disk_util",
4190 .lname = "Disk utilization",
4191 .type = FIO_OPT_UNSUPPORTED,
4192 .help = "Your platform does not support disk utilization",
4193 },
0a839f30 4194#endif
993bf48b
JA
4195 {
4196 .name = "gtod_reduce",
e8b0e958 4197 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
4198 .type = FIO_OPT_BOOL,
4199 .help = "Greatly reduce number of gettimeofday() calls",
4200 .cb = str_gtod_reduce_cb,
4201 .def = "0",
a4ed77fe 4202 .hide_on_set = 1,
e8b0e958
JA
4203 .category = FIO_OPT_C_STAT,
4204 .group = FIO_OPT_G_INVALID,
993bf48b 4205 },
02af0988
JA
4206 {
4207 .name = "disable_lat",
e8b0e958 4208 .lname = "Disable all latency stats",
02af0988 4209 .type = FIO_OPT_BOOL,
a609f12a 4210 .off1 = offsetof(struct thread_options, disable_lat),
02af0988
JA
4211 .help = "Disable latency numbers",
4212 .parent = "gtod_reduce",
d71c154c 4213 .hide = 1,
02af0988 4214 .def = "0",
e8b0e958
JA
4215 .category = FIO_OPT_C_STAT,
4216 .group = FIO_OPT_G_INVALID,
02af0988 4217 },
9520ebb9
JA
4218 {
4219 .name = "disable_clat",
e8b0e958 4220 .lname = "Disable completion latency stats",
9520ebb9 4221 .type = FIO_OPT_BOOL,
a609f12a 4222 .off1 = offsetof(struct thread_options, disable_clat),
9520ebb9 4223 .help = "Disable completion latency numbers",
993bf48b 4224 .parent = "gtod_reduce",
d71c154c 4225 .hide = 1,
9520ebb9 4226 .def = "0",
e8b0e958
JA
4227 .category = FIO_OPT_C_STAT,
4228 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
4229 },
4230 {
4231 .name = "disable_slat",
e8b0e958 4232 .lname = "Disable submission latency stats",
9520ebb9 4233 .type = FIO_OPT_BOOL,
a609f12a 4234 .off1 = offsetof(struct thread_options, disable_slat),
03e20d68 4235 .help = "Disable submission latency numbers",
993bf48b 4236 .parent = "gtod_reduce",
d71c154c 4237 .hide = 1,
9520ebb9 4238 .def = "0",
e8b0e958
JA
4239 .category = FIO_OPT_C_STAT,
4240 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
4241 },
4242 {
4243 .name = "disable_bw_measurement",
afd2ceff 4244 .alias = "disable_bw",
e8b0e958 4245 .lname = "Disable bandwidth stats",
9520ebb9 4246 .type = FIO_OPT_BOOL,
a609f12a 4247 .off1 = offsetof(struct thread_options, disable_bw),
9520ebb9 4248 .help = "Disable bandwidth logging",
993bf48b 4249 .parent = "gtod_reduce",
d71c154c 4250 .hide = 1,
9520ebb9 4251 .def = "0",
e8b0e958
JA
4252 .category = FIO_OPT_C_STAT,
4253 .group = FIO_OPT_G_INVALID,
9520ebb9 4254 },
be4ecfdf
JA
4255 {
4256 .name = "gtod_cpu",
e8b0e958 4257 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 4258 .type = FIO_OPT_INT,
a609f12a 4259 .off1 = offsetof(struct thread_options, gtod_cpu),
03e20d68 4260 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 4261 .verify = gtod_cpu_verify,
e8b0e958 4262 .category = FIO_OPT_C_GENERAL,
10860056 4263 .group = FIO_OPT_G_CLOCK,
be4ecfdf 4264 },
771e58be
JA
4265 {
4266 .name = "unified_rw_reporting",
cce2fdfe 4267 .lname = "Unified RW Reporting",
771e58be 4268 .type = FIO_OPT_BOOL,
a609f12a 4269 .off1 = offsetof(struct thread_options, unified_rw_rep),
771e58be
JA
4270 .help = "Unify reporting across data direction",
4271 .def = "0",
90b7a96d
JA
4272 .category = FIO_OPT_C_GENERAL,
4273 .group = FIO_OPT_G_INVALID,
771e58be 4274 },
f2bba182
RR
4275 {
4276 .name = "continue_on_error",
e8b0e958 4277 .lname = "Continue on error",
06842027 4278 .type = FIO_OPT_STR,
a609f12a 4279 .off1 = offsetof(struct thread_options, continue_on_error),
03e20d68 4280 .help = "Continue on non-fatal errors during IO",
06842027 4281 .def = "none",
e8b0e958 4282 .category = FIO_OPT_C_GENERAL,
bc3f552f 4283 .group = FIO_OPT_G_ERR,
06842027
SL
4284 .posval = {
4285 { .ival = "none",
4286 .oval = ERROR_TYPE_NONE,
4287 .help = "Exit when an error is encountered",
4288 },
4289 { .ival = "read",
4290 .oval = ERROR_TYPE_READ,
4291 .help = "Continue on read errors only",
4292 },
4293 { .ival = "write",
4294 .oval = ERROR_TYPE_WRITE,
4295 .help = "Continue on write errors only",
4296 },
4297 { .ival = "io",
4298 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
4299 .help = "Continue on any IO errors",
4300 },
4301 { .ival = "verify",
4302 .oval = ERROR_TYPE_VERIFY,
4303 .help = "Continue on verify errors only",
4304 },
4305 { .ival = "all",
4306 .oval = ERROR_TYPE_ANY,
4307 .help = "Continue on all io and verify errors",
4308 },
4309 { .ival = "0",
4310 .oval = ERROR_TYPE_NONE,
4311 .help = "Alias for 'none'",
4312 },
4313 { .ival = "1",
4314 .oval = ERROR_TYPE_ANY,
4315 .help = "Alias for 'all'",
4316 },
4317 },
f2bba182 4318 },
8b28bd41
DM
4319 {
4320 .name = "ignore_error",
cce2fdfe 4321 .lname = "Ignore Error",
8b28bd41
DM
4322 .type = FIO_OPT_STR,
4323 .cb = str_ignore_error_cb,
a609f12a 4324 .off1 = offsetof(struct thread_options, ignore_error_nr),
8b28bd41
DM
4325 .help = "Set a specific list of errors to ignore",
4326 .parent = "rw",
a94eb99a 4327 .category = FIO_OPT_C_GENERAL,
bc3f552f 4328 .group = FIO_OPT_G_ERR,
8b28bd41
DM
4329 },
4330 {
4331 .name = "error_dump",
cce2fdfe 4332 .lname = "Error Dump",
8b28bd41 4333 .type = FIO_OPT_BOOL,
a609f12a 4334 .off1 = offsetof(struct thread_options, error_dump),
8b28bd41
DM
4335 .def = "0",
4336 .help = "Dump info on each error",
a94eb99a 4337 .category = FIO_OPT_C_GENERAL,
bc3f552f 4338 .group = FIO_OPT_G_ERR,
8b28bd41 4339 },
9ac8a797
JA
4340 {
4341 .name = "profile",
e8b0e958 4342 .lname = "Profile",
79d16311 4343 .type = FIO_OPT_STR_STORE,
a609f12a 4344 .off1 = offsetof(struct thread_options, profile),
9ac8a797 4345 .help = "Select a specific builtin performance test",
13fca827 4346 .category = FIO_OPT_C_PROFILE,
e8b0e958 4347 .group = FIO_OPT_G_INVALID,
9ac8a797 4348 },
a696fa2a
JA
4349 {
4350 .name = "cgroup",
e8b0e958 4351 .lname = "Cgroup",
a696fa2a 4352 .type = FIO_OPT_STR_STORE,
a609f12a 4353 .off1 = offsetof(struct thread_options, cgroup),
a696fa2a 4354 .help = "Add job to cgroup of this name",
e8b0e958 4355 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
4356 .group = FIO_OPT_G_CGROUP,
4357 },
4358 {
4359 .name = "cgroup_nodelete",
4360 .lname = "Cgroup no-delete",
4361 .type = FIO_OPT_BOOL,
a609f12a 4362 .off1 = offsetof(struct thread_options, cgroup_nodelete),
a1f6afec
JA
4363 .help = "Do not delete cgroups after job completion",
4364 .def = "0",
4365 .parent = "cgroup",
4366 .category = FIO_OPT_C_GENERAL,
4367 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
4368 },
4369 {
4370 .name = "cgroup_weight",
e8b0e958 4371 .lname = "Cgroup weight",
a696fa2a 4372 .type = FIO_OPT_INT,
a609f12a 4373 .off1 = offsetof(struct thread_options, cgroup_weight),
a696fa2a
JA
4374 .help = "Use given weight for cgroup",
4375 .minval = 100,
4376 .maxval = 1000,
a1f6afec 4377 .parent = "cgroup",
e8b0e958 4378 .category = FIO_OPT_C_GENERAL,
a1f6afec 4379 .group = FIO_OPT_G_CGROUP,
7de87099 4380 },
e0b0d892
JA
4381 {
4382 .name = "uid",
e8b0e958 4383 .lname = "User ID",
e0b0d892 4384 .type = FIO_OPT_INT,
a609f12a 4385 .off1 = offsetof(struct thread_options, uid),
e0b0d892 4386 .help = "Run job with this user ID",
e8b0e958 4387 .category = FIO_OPT_C_GENERAL,
10860056 4388 .group = FIO_OPT_G_CRED,
e0b0d892
JA
4389 },
4390 {
4391 .name = "gid",
e8b0e958 4392 .lname = "Group ID",
e0b0d892 4393 .type = FIO_OPT_INT,
a609f12a 4394 .off1 = offsetof(struct thread_options, gid),
e0b0d892 4395 .help = "Run job with this group ID",
e8b0e958 4396 .category = FIO_OPT_C_GENERAL,
10860056 4397 .group = FIO_OPT_G_CRED,
e0b0d892 4398 },
a1f6afec
JA
4399 {
4400 .name = "kb_base",
4401 .lname = "KB Base",
4402 .type = FIO_OPT_INT,
a609f12a 4403 .off1 = offsetof(struct thread_options, kb_base),
a1f6afec
JA
4404 .prio = 1,
4405 .def = "1024",
ba9c7219
JA
4406 .posval = {
4407 { .ival = "1024",
4408 .oval = 1024,
d694a6a7 4409 .help = "Inputs invert IEC and SI prefixes (for compatibility); outputs prefer binary",
ba9c7219
JA
4410 },
4411 { .ival = "1000",
4412 .oval = 1000,
d694a6a7 4413 .help = "Inputs use IEC and SI prefixes; outputs prefer SI",
ba9c7219
JA
4414 },
4415 },
d694a6a7 4416 .help = "Unit prefix interpretation for quantities of data (IEC and SI)",
a1f6afec
JA
4417 .category = FIO_OPT_C_GENERAL,
4418 .group = FIO_OPT_G_INVALID,
4419 },
cf3a0518
JA
4420 {
4421 .name = "unit_base",
d694a6a7 4422 .lname = "Unit for quantities of data (Bits or Bytes)",
cf3a0518 4423 .type = FIO_OPT_INT,
a609f12a 4424 .off1 = offsetof(struct thread_options, unit_base),
cf3a0518 4425 .prio = 1,
71a08258
JA
4426 .posval = {
4427 { .ival = "0",
4428 .oval = 0,
4429 .help = "Auto-detect",
4430 },
4431 { .ival = "8",
4432 .oval = 8,
4433 .help = "Normal (byte based)",
4434 },
4435 { .ival = "1",
4436 .oval = 1,
4437 .help = "Bit based",
4438 },
4439 },
cf3a0518
JA
4440 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
4441 .category = FIO_OPT_C_GENERAL,
4442 .group = FIO_OPT_G_INVALID,
4443 },
3ceb458f
JA
4444 {
4445 .name = "hugepage-size",
4446 .lname = "Hugepage size",
4447 .type = FIO_OPT_INT,
a609f12a 4448 .off1 = offsetof(struct thread_options, hugepage_size),
3ceb458f
JA
4449 .help = "When using hugepages, specify size of each page",
4450 .def = __fio_stringify(FIO_HUGE_PAGE),
4451 .interval = 1024 * 1024,
4452 .category = FIO_OPT_C_GENERAL,
4453 .group = FIO_OPT_G_INVALID,
4454 },
9e684a49
DE
4455 {
4456 .name = "flow_id",
e8b0e958 4457 .lname = "I/O flow ID",
9e684a49 4458 .type = FIO_OPT_INT,
a609f12a 4459 .off1 = offsetof(struct thread_options, flow_id),
9e684a49
DE
4460 .help = "The flow index ID to use",
4461 .def = "0",
e8b0e958
JA
4462 .category = FIO_OPT_C_IO,
4463 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
4464 },
4465 {
4466 .name = "flow",
e8b0e958 4467 .lname = "I/O flow weight",
9e684a49 4468 .type = FIO_OPT_INT,
a609f12a 4469 .off1 = offsetof(struct thread_options, flow),
9e684a49
DE
4470 .help = "Weight for flow control of this job",
4471 .parent = "flow_id",
d71c154c 4472 .hide = 1,
9e684a49 4473 .def = "0",
e8b0e958
JA
4474 .category = FIO_OPT_C_IO,
4475 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
4476 },
4477 {
4478 .name = "flow_watermark",
e8b0e958 4479 .lname = "I/O flow watermark",
9e684a49 4480 .type = FIO_OPT_INT,
a609f12a 4481 .off1 = offsetof(struct thread_options, flow_watermark),
9e684a49
DE
4482 .help = "High watermark for flow control. This option"
4483 " should be set to the same value for all threads"
4484 " with non-zero flow.",
4485 .parent = "flow_id",
d71c154c 4486 .hide = 1,
9e684a49 4487 .def = "1024",
e8b0e958
JA
4488 .category = FIO_OPT_C_IO,
4489 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
4490 },
4491 {
4492 .name = "flow_sleep",
e8b0e958 4493 .lname = "I/O flow sleep",
9e684a49 4494 .type = FIO_OPT_INT,
a609f12a 4495 .off1 = offsetof(struct thread_options, flow_sleep),
9e684a49
DE
4496 .help = "How many microseconds to sleep after being held"
4497 " back by the flow control mechanism",
4498 .parent = "flow_id",
d71c154c 4499 .hide = 1,
9e684a49 4500 .def = "0",
e8b0e958
JA
4501 .category = FIO_OPT_C_IO,
4502 .group = FIO_OPT_G_IO_FLOW,
9e684a49 4503 },
16e56d25
VF
4504 {
4505 .name = "steadystate",
4506 .lname = "Steady state threshold",
4507 .alias = "ss",
4508 .type = FIO_OPT_STR,
2c5d94bc 4509 .off1 = offsetof(struct thread_options, ss_state),
16e56d25
VF
4510 .cb = str_steadystate_cb,
4511 .help = "Define the criterion and limit to judge when a job has reached steady state",
4512 .def = "iops_slope:0.01%",
4513 .posval = {
4514 { .ival = "iops",
f0c50c66 4515 .oval = FIO_SS_IOPS,
16e56d25
VF
4516 .help = "maximum mean deviation of IOPS measurements",
4517 },
4518 { .ival = "iops_slope",
f0c50c66 4519 .oval = FIO_SS_IOPS_SLOPE,
16e56d25
VF
4520 .help = "slope calculated from IOPS measurements",
4521 },
4522 { .ival = "bw",
f0c50c66 4523 .oval = FIO_SS_BW,
16e56d25
VF
4524 .help = "maximum mean deviation of bandwidth measurements",
4525 },
4526 {
4527 .ival = "bw_slope",
f0c50c66 4528 .oval = FIO_SS_BW_SLOPE,
16e56d25
VF
4529 .help = "slope calculated from bandwidth measurements",
4530 },
4531 },
4532 .category = FIO_OPT_C_GENERAL,
4533 .group = FIO_OPT_G_RUNTIME,
4534 },
4535 {
4536 .name = "steadystate_duration",
4537 .lname = "Steady state duration",
4538 .alias = "ss_dur",
915ca980 4539 .parent = "steadystate",
16e56d25
VF
4540 .type = FIO_OPT_STR_VAL_TIME,
4541 .off1 = offsetof(struct thread_options, ss_dur),
4542 .help = "Stop workload upon attaining steady state for specified duration",
4543 .def = "0",
4544 .is_seconds = 1,
4545 .is_time = 1,
4546 .category = FIO_OPT_C_GENERAL,
4547 .group = FIO_OPT_G_RUNTIME,
4548 },
4549 {
4550 .name = "steadystate_ramp_time",
4551 .lname = "Steady state ramp time",
4552 .alias = "ss_ramp",
915ca980 4553 .parent = "steadystate",
16e56d25
VF
4554 .type = FIO_OPT_STR_VAL_TIME,
4555 .off1 = offsetof(struct thread_options, ss_ramp_time),
4556 .help = "Delay before initiation of data collection for steady state job termination testing",
4557 .def = "0",
4558 .is_seconds = 1,
4559 .is_time = 1,
4560 .category = FIO_OPT_C_GENERAL,
4561 .group = FIO_OPT_G_RUNTIME,
4562 },
214e1eca
JA
4563 {
4564 .name = NULL,
4565 },
4566};
4567
17af15d4 4568static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 4569 const char *name, int val)
9f81736c 4570{
17af15d4 4571 lopt->name = (char *) name;
de890a1e 4572 lopt->val = val;
9f81736c 4573 if (o->type == FIO_OPT_STR_SET)
ff52be3d 4574 lopt->has_arg = optional_argument;
9f81736c
JA
4575 else
4576 lopt->has_arg = required_argument;
4577}
4578
de890a1e
SL
4579static void options_to_lopts(struct fio_option *opts,
4580 struct option *long_options,
4581 int i, int option_type)
214e1eca 4582{
de890a1e 4583 struct fio_option *o = &opts[0];
214e1eca 4584 while (o->name) {
de890a1e 4585 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
4586 if (o->alias) {
4587 i++;
de890a1e 4588 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 4589 }
214e1eca
JA
4590
4591 i++;
4592 o++;
4593 assert(i < FIO_NR_OPTIONS);
4594 }
4595}
4596
de890a1e
SL
4597void fio_options_set_ioengine_opts(struct option *long_options,
4598 struct thread_data *td)
4599{
4600 unsigned int i;
4601
4602 i = 0;
4603 while (long_options[i].name) {
4604 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
4605 memset(&long_options[i], 0, sizeof(*long_options));
4606 break;
4607 }
4608 i++;
4609 }
4610
4611 /*
4612 * Just clear out the prior ioengine options.
4613 */
4614 if (!td || !td->eo)
4615 return;
4616
4617 options_to_lopts(td->io_ops->options, long_options, i,
4618 FIO_GETOPT_IOENGINE);
4619}
4620
4621void fio_options_dup_and_init(struct option *long_options)
4622{
4623 unsigned int i;
4624
9af4a244 4625 options_init(fio_options);
de890a1e
SL
4626
4627 i = 0;
4628 while (long_options[i].name)
4629 i++;
4630
9af4a244 4631 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
4632}
4633
74929ac2
JA
4634struct fio_keyword {
4635 const char *word;
4636 const char *desc;
4637 char *replace;
4638};
4639
4640static struct fio_keyword fio_keywords[] = {
4641 {
4642 .word = "$pagesize",
4643 .desc = "Page size in the system",
4644 },
4645 {
4646 .word = "$mb_memory",
4647 .desc = "Megabytes of memory online",
4648 },
4649 {
4650 .word = "$ncpus",
4651 .desc = "Number of CPUs online in the system",
4652 },
4653 {
4654 .word = NULL,
4655 },
4656};
4657
af1dc266
JA
4658void fio_keywords_exit(void)
4659{
4660 struct fio_keyword *kw;
4661
4662 kw = &fio_keywords[0];
4663 while (kw->word) {
4664 free(kw->replace);
4665 kw->replace = NULL;
4666 kw++;
4667 }
4668}
4669
74929ac2
JA
4670void fio_keywords_init(void)
4671{
3b2e1464 4672 unsigned long long mb_memory;
74929ac2
JA
4673 char buf[128];
4674 long l;
4675
a4cfc477 4676 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
4677 fio_keywords[0].replace = strdup(buf);
4678
8eb016d3 4679 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 4680 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
4681 fio_keywords[1].replace = strdup(buf);
4682
c00a2289 4683 l = cpus_online();
74929ac2
JA
4684 sprintf(buf, "%lu", l);
4685 fio_keywords[2].replace = strdup(buf);
4686}
4687
892a6ffc
JA
4688#define BC_APP "bc"
4689
4690static char *bc_calc(char *str)
4691{
d0c814ec 4692 char buf[128], *tmp;
892a6ffc
JA
4693 FILE *f;
4694 int ret;
4695
4696 /*
4697 * No math, just return string
4698 */
d0c814ec
SL
4699 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
4700 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
4701 return str;
4702
4703 /*
4704 * Split option from value, we only need to calculate the value
4705 */
4706 tmp = strchr(str, '=');
4707 if (!tmp)
4708 return str;
4709
4710 tmp++;
892a6ffc 4711
d0c814ec
SL
4712 /*
4713 * Prevent buffer overflows; such a case isn't reasonable anyway
4714 */
4715 if (strlen(str) >= 128 || strlen(tmp) > 100)
4716 return str;
892a6ffc
JA
4717
4718 sprintf(buf, "which %s > /dev/null", BC_APP);
4719 if (system(buf)) {
4720 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
4721 return NULL;
4722 }
4723
d0c814ec 4724 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 4725 f = popen(buf, "r");
3c3ed070 4726 if (!f)
892a6ffc 4727 return NULL;
892a6ffc 4728
d0c814ec 4729 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
4730 if (ret <= 0) {
4731 pclose(f);
892a6ffc 4732 return NULL;
1d824f37 4733 }
892a6ffc 4734
892a6ffc 4735 pclose(f);
d0c814ec
SL
4736 buf[(tmp - str) + ret - 1] = '\0';
4737 memcpy(buf, str, tmp - str);
892a6ffc 4738 free(str);
d0c814ec
SL
4739 return strdup(buf);
4740}
4741
4742/*
4743 * Return a copy of the input string with substrings of the form ${VARNAME}
4744 * substituted with the value of the environment variable VARNAME. The
4745 * substitution always occurs, even if VARNAME is empty or the corresponding
4746 * environment variable undefined.
4747 */
4748static char *option_dup_subs(const char *opt)
4749{
4750 char out[OPT_LEN_MAX+1];
4751 char in[OPT_LEN_MAX+1];
4752 char *outptr = out;
4753 char *inptr = in;
4754 char *ch1, *ch2, *env;
4755 ssize_t nchr = OPT_LEN_MAX;
4756 size_t envlen;
4757
4758 if (strlen(opt) + 1 > OPT_LEN_MAX) {
4759 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
4760 return NULL;
4761 }
4762
4763 in[OPT_LEN_MAX] = '\0';
4764 strncpy(in, opt, OPT_LEN_MAX);
4765
4766 while (*inptr && nchr > 0) {
4767 if (inptr[0] == '$' && inptr[1] == '{') {
4768 ch2 = strchr(inptr, '}');
4769 if (ch2 && inptr+1 < ch2) {
4770 ch1 = inptr+2;
4771 inptr = ch2+1;
4772 *ch2 = '\0';
4773
4774 env = getenv(ch1);
4775 if (env) {
4776 envlen = strlen(env);
4777 if (envlen <= nchr) {
4778 memcpy(outptr, env, envlen);
4779 outptr += envlen;
4780 nchr -= envlen;
4781 }
4782 }
4783
4784 continue;
4785 }
4786 }
4787
4788 *outptr++ = *inptr++;
4789 --nchr;
4790 }
4791
4792 *outptr = '\0';
4793 return strdup(out);
892a6ffc
JA
4794}
4795
74929ac2
JA
4796/*
4797 * Look for reserved variable names and replace them with real values
4798 */
4799static char *fio_keyword_replace(char *opt)
4800{
4801 char *s;
4802 int i;
d0c814ec 4803 int docalc = 0;
74929ac2
JA
4804
4805 for (i = 0; fio_keywords[i].word != NULL; i++) {
4806 struct fio_keyword *kw = &fio_keywords[i];
4807
4808 while ((s = strstr(opt, kw->word)) != NULL) {
4809 char *new = malloc(strlen(opt) + 1);
4810 char *o_org = opt;
4811 int olen = s - opt;
4812 int len;
4813
4814 /*
4815 * Copy part of the string before the keyword and
4816 * sprintf() the replacement after it.
4817 */
4818 memcpy(new, opt, olen);
4819 len = sprintf(new + olen, "%s", kw->replace);
4820
4821 /*
4822 * If there's more in the original string, copy that
4823 * in too
4824 */
4825 opt += strlen(kw->word) + olen;
4826 if (strlen(opt))
4827 memcpy(new + olen + len, opt, opt - o_org - 1);
4828
4829 /*
4830 * replace opt and free the old opt
4831 */
4832 opt = new;
d0c814ec 4833 free(o_org);
7a958bd5 4834
d0c814ec 4835 docalc = 1;
74929ac2
JA
4836 }
4837 }
4838
d0c814ec
SL
4839 /*
4840 * Check for potential math and invoke bc, if possible
4841 */
4842 if (docalc)
4843 opt = bc_calc(opt);
4844
7a958bd5 4845 return opt;
74929ac2
JA
4846}
4847
d0c814ec
SL
4848static char **dup_and_sub_options(char **opts, int num_opts)
4849{
4850 int i;
4851 char **opts_copy = malloc(num_opts * sizeof(*opts));
4852 for (i = 0; i < num_opts; i++) {
4853 opts_copy[i] = option_dup_subs(opts[i]);
4854 if (!opts_copy[i])
4855 continue;
4856 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
4857 }
4858 return opts_copy;
4859}
4860
e15b023b 4861static void show_closest_option(const char *opt)
a2d027b9
JA
4862{
4863 int best_option, best_distance;
4864 int i, distance;
e15b023b
JA
4865 char *name;
4866
4867 if (!strlen(opt))
4868 return;
4869
4870 name = strdup(opt);
4871 i = 0;
4872 while (name[i] != '\0' && name[i] != '=')
4873 i++;
4874 name[i] = '\0';
a2d027b9
JA
4875
4876 best_option = -1;
4877 best_distance = INT_MAX;
4878 i = 0;
4879 while (fio_options[i].name) {
4880 distance = string_distance(name, fio_options[i].name);
4881 if (distance < best_distance) {
4882 best_distance = distance;
4883 best_option = i;
4884 }
4885 i++;
4886 }
4887
75e6bcba
JA
4888 if (best_option != -1 && string_distance_ok(name, best_distance) &&
4889 fio_options[best_option].type != FIO_OPT_UNSUPPORTED)
a2d027b9 4890 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
4891
4892 free(name);
a2d027b9
JA
4893}
4894
c2292325 4895int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 4896{
de890a1e 4897 int i, ret, unknown;
d0c814ec 4898 char **opts_copy;
3b8b7135 4899
9af4a244 4900 sort_options(opts, fio_options, num_opts);
d0c814ec 4901 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 4902
de890a1e 4903 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
9109883a 4904 const struct fio_option *o;
9af4a244 4905 int newret = parse_option(opts_copy[i], opts[i], fio_options,
a609f12a 4906 &o, &td->o, &td->opt_list);
d0c814ec 4907
a8523a6a
JA
4908 if (!newret && o)
4909 fio_option_mark_set(&td->o, o);
4910
de890a1e
SL
4911 if (opts_copy[i]) {
4912 if (newret && !o) {
4913 unknown++;
4914 continue;
4915 }
d0c814ec 4916 free(opts_copy[i]);
de890a1e
SL
4917 opts_copy[i] = NULL;
4918 }
4919
4920 ret |= newret;
4921 }
4922
4923 if (unknown) {
4924 ret |= ioengine_load(td);
4925 if (td->eo) {
4926 sort_options(opts_copy, td->io_ops->options, num_opts);
4927 opts = opts_copy;
4928 }
4929 for (i = 0; i < num_opts; i++) {
9109883a 4930 const struct fio_option *o = NULL;
de890a1e 4931 int newret = 1;
a2d027b9 4932
de890a1e
SL
4933 if (!opts_copy[i])
4934 continue;
4935
4936 if (td->eo)
4937 newret = parse_option(opts_copy[i], opts[i],
4938 td->io_ops->options, &o,
66e19a38 4939 td->eo, &td->opt_list);
de890a1e
SL
4940
4941 ret |= newret;
a2d027b9 4942 if (!o) {
de890a1e 4943 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
4944 show_closest_option(opts[i]);
4945 }
de890a1e
SL
4946 free(opts_copy[i]);
4947 opts_copy[i] = NULL;
4948 }
74929ac2 4949 }
3b8b7135 4950
d0c814ec 4951 free(opts_copy);
3b8b7135 4952 return ret;
214e1eca
JA
4953}
4954
4955int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
4956{
a8523a6a
JA
4957 int ret;
4958
a609f12a 4959 ret = parse_cmd_option(opt, val, fio_options, &td->o, &td->opt_list);
a8523a6a 4960 if (!ret) {
9109883a 4961 const struct fio_option *o;
a8523a6a 4962
9109883a 4963 o = find_option_c(fio_options, opt);
a8523a6a
JA
4964 if (o)
4965 fio_option_mark_set(&td->o, o);
4966 }
4967
4968 return ret;
214e1eca
JA
4969}
4970
de890a1e
SL
4971int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
4972 char *val)
4973{
d8b4f395
JA
4974 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
4975 &td->opt_list);
de890a1e
SL
4976}
4977
214e1eca
JA
4978void fio_fill_default_options(struct thread_data *td)
4979{
cb1402d6 4980 td->o.magic = OPT_MAGIC;
a609f12a 4981 fill_default_options(&td->o, fio_options);
214e1eca
JA
4982}
4983
4984int fio_show_option_help(const char *opt)
4985{
9af4a244 4986 return show_cmd_help(fio_options, opt);
214e1eca 4987}
d23bb327 4988
de890a1e
SL
4989/*
4990 * dupe FIO_OPT_STR_STORE options
4991 */
4992void fio_options_mem_dupe(struct thread_data *td)
4993{
53b5693d 4994 options_mem_dupe(fio_options, &td->o);
1647f592
JA
4995
4996 if (td->eo && td->io_ops) {
de890a1e 4997 void *oldeo = td->eo;
1647f592 4998
de890a1e
SL
4999 td->eo = malloc(td->io_ops->option_struct_size);
5000 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
53b5693d 5001 options_mem_dupe(td->io_ops->options, td->eo);
de890a1e
SL
5002 }
5003}
5004
d6978a32
JA
5005unsigned int fio_get_kb_base(void *data)
5006{
a609f12a
JA
5007 struct thread_data *td = cb_data_to_td(data);
5008 struct thread_options *o = &td->o;
d6978a32
JA
5009 unsigned int kb_base = 0;
5010
cb1402d6
JA
5011 /*
5012 * This is a hack... For private options, *data is not holding
5013 * a pointer to the thread_options, but to private data. This means
5014 * we can't safely dereference it, but magic is first so mem wise
5015 * it is valid. But this also means that if the job first sets
5016 * kb_base and expects that to be honored by private options,
5017 * it will be disappointed. We will return the global default
5018 * for this.
5019 */
5020 if (o && o->magic == OPT_MAGIC)
83ea422a 5021 kb_base = o->kb_base;
d6978a32
JA
5022 if (!kb_base)
5023 kb_base = 1024;
5024
5025 return kb_base;
5026}
9f988e2e 5027
9109883a 5028int add_option(const struct fio_option *o)
9f988e2e 5029{
07b3232d
JA
5030 struct fio_option *__o;
5031 int opt_index = 0;
5032
9af4a244 5033 __o = fio_options;
07b3232d
JA
5034 while (__o->name) {
5035 opt_index++;
5036 __o++;
5037 }
5038
7b504edd
JA
5039 if (opt_index + 1 == FIO_MAX_OPTS) {
5040 log_err("fio: FIO_MAX_OPTS is too small\n");
5041 return 1;
5042 }
5043
9af4a244 5044 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 5045 fio_options[opt_index + 1].name = NULL;
07b3232d 5046 return 0;
9f988e2e 5047}
e2de69da 5048
07b3232d 5049void invalidate_profile_options(const char *prof_name)
e2de69da 5050{
07b3232d 5051 struct fio_option *o;
e2de69da 5052
9af4a244 5053 o = fio_options;
07b3232d
JA
5054 while (o->name) {
5055 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
5056 o->type = FIO_OPT_INVALID;
5057 o->prof_name = NULL;
5058 }
5059 o++;
e2de69da
JA
5060 }
5061}
f5b6bb85
JA
5062
5063void add_opt_posval(const char *optname, const char *ival, const char *help)
5064{
5065 struct fio_option *o;
5066 unsigned int i;
5067
9af4a244 5068 o = find_option(fio_options, optname);
f5b6bb85
JA
5069 if (!o)
5070 return;
5071
5072 for (i = 0; i < PARSE_MAX_VP; i++) {
5073 if (o->posval[i].ival)
5074 continue;
5075
5076 o->posval[i].ival = ival;
5077 o->posval[i].help = help;
5078 break;
5079 }
5080}
5081
5082void del_opt_posval(const char *optname, const char *ival)
5083{
5084 struct fio_option *o;
5085 unsigned int i;
5086
9af4a244 5087 o = find_option(fio_options, optname);
f5b6bb85
JA
5088 if (!o)
5089 return;
5090
5091 for (i = 0; i < PARSE_MAX_VP; i++) {
5092 if (!o->posval[i].ival)
5093 continue;
5094 if (strcmp(o->posval[i].ival, ival))
5095 continue;
5096
5097 o->posval[i].ival = NULL;
5098 o->posval[i].help = NULL;
5099 }
5100}
7e356b2d
JA
5101
5102void fio_options_free(struct thread_data *td)
5103{
ca6336a8 5104 options_free(fio_options, &td->o);
de890a1e
SL
5105 if (td->eo && td->io_ops && td->io_ops->options) {
5106 options_free(td->io_ops->options, td->eo);
5107 free(td->eo);
5108 td->eo = NULL;
5109 }
7e356b2d 5110}
c504ee55
JA
5111
5112struct fio_option *fio_option_find(const char *name)
5113{
5114 return find_option(fio_options, name);
5115}
5116
f0e7f45a
JA
5117static struct fio_option *find_next_opt(struct thread_options *o,
5118 struct fio_option *from,
5119 unsigned int off1)
a8523a6a 5120{
f0e7f45a 5121 struct fio_option *opt;
a8523a6a 5122
f0e7f45a
JA
5123 if (!from)
5124 from = &fio_options[0];
5125 else
5126 from++;
5127
5128 opt = NULL;
5129 do {
5130 if (off1 == from->off1) {
5131 opt = from;
a8523a6a
JA
5132 break;
5133 }
f0e7f45a
JA
5134 from++;
5135 } while (from->name);
a8523a6a 5136
f0e7f45a
JA
5137 return opt;
5138}
5139
5140static int opt_is_set(struct thread_options *o, struct fio_option *opt)
5141{
5142 unsigned int opt_off, index, offset;
a8523a6a
JA
5143
5144 opt_off = opt - &fio_options[0];
5145 index = opt_off / (8 * sizeof(uint64_t));
5146 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 5147 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
5148}
5149
72f39748 5150bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
5151{
5152 struct fio_option *opt, *next;
5153
5154 next = NULL;
5155 while ((opt = find_next_opt(o, next, off1)) != NULL) {
5156 if (opt_is_set(o, opt))
72f39748 5157 return true;
f0e7f45a
JA
5158
5159 next = opt;
5160 }
5161
72f39748 5162 return false;
f0e7f45a
JA
5163}
5164
9109883a 5165void fio_option_mark_set(struct thread_options *o, const struct fio_option *opt)
a8523a6a
JA
5166{
5167 unsigned int opt_off, index, offset;
5168
5169 opt_off = opt - &fio_options[0];
5170 index = opt_off / (8 * sizeof(uint64_t));
5171 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 5172 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 5173}