Add 'replay_time_scale' option
[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",
1854 .help = "NVML libpmemblk based IO engine",
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",
1873 .help = "NVML libpmem based IO engine",
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",
160b966d 2849 .type = FIO_OPT_BOOL,
a609f12a 2850 .off1 = offsetof(struct thread_options, verifysort),
160b966d
JA
2851 .help = "Sort written verify blocks for read back",
2852 .def = "1",
c83f2df1 2853 .parent = "verify",
d71c154c 2854 .hide = 1,
e8b0e958
JA
2855 .category = FIO_OPT_C_IO,
2856 .group = FIO_OPT_G_VERIFY,
160b966d 2857 },
1ae83d45
JA
2858 {
2859 .name = "verifysort_nr",
cce2fdfe 2860 .lname = "Verify Sort Nr",
1ae83d45 2861 .type = FIO_OPT_INT,
a609f12a 2862 .off1 = offsetof(struct thread_options, verifysort_nr),
1ae83d45
JA
2863 .help = "Pre-load and sort verify blocks for a read workload",
2864 .minval = 0,
2865 .maxval = 131072,
2866 .def = "1024",
2867 .parent = "verify",
836fcc0f
JA
2868 .category = FIO_OPT_C_IO,
2869 .group = FIO_OPT_G_VERIFY,
1ae83d45 2870 },
3f9f4e26 2871 {
a59e170d 2872 .name = "verify_interval",
e8b0e958 2873 .lname = "Verify interval",
e01b22b8 2874 .type = FIO_OPT_INT,
a609f12a 2875 .off1 = offsetof(struct thread_options, verify_interval),
819a9680 2876 .minval = 2 * sizeof(struct verify_header),
a59e170d 2877 .help = "Store verify buffer header every N bytes",
afdf9352 2878 .parent = "verify",
d71c154c 2879 .hide = 1,
20eb06bd 2880 .interval = 2 * sizeof(struct verify_header),
e8b0e958
JA
2881 .category = FIO_OPT_C_IO,
2882 .group = FIO_OPT_G_VERIFY,
3f9f4e26 2883 },
546a9142 2884 {
a59e170d 2885 .name = "verify_offset",
e8b0e958 2886 .lname = "Verify offset",
e01b22b8 2887 .type = FIO_OPT_INT,
a59e170d 2888 .help = "Offset verify header location by N bytes",
a609f12a 2889 .off1 = offsetof(struct thread_options, verify_offset),
203160d5 2890 .minval = sizeof(struct verify_header),
afdf9352 2891 .parent = "verify",
d71c154c 2892 .hide = 1,
e8b0e958
JA
2893 .category = FIO_OPT_C_IO,
2894 .group = FIO_OPT_G_VERIFY,
546a9142 2895 },
e28218f3
SL
2896 {
2897 .name = "verify_pattern",
e8b0e958 2898 .lname = "Verify pattern",
0e92f873 2899 .type = FIO_OPT_STR,
e28218f3 2900 .cb = str_verify_pattern_cb,
a609f12a 2901 .off1 = offsetof(struct thread_options, verify_pattern),
e28218f3
SL
2902 .help = "Fill pattern for IO buffers",
2903 .parent = "verify",
d71c154c 2904 .hide = 1,
e8b0e958
JA
2905 .category = FIO_OPT_C_IO,
2906 .group = FIO_OPT_G_VERIFY,
e28218f3 2907 },
a12a3b4d
JA
2908 {
2909 .name = "verify_fatal",
e8b0e958 2910 .lname = "Verify fatal",
68e1f29a 2911 .type = FIO_OPT_BOOL,
a609f12a 2912 .off1 = offsetof(struct thread_options, verify_fatal),
a12a3b4d
JA
2913 .def = "0",
2914 .help = "Exit on a single verify failure, don't continue",
2915 .parent = "verify",
d71c154c 2916 .hide = 1,
e8b0e958
JA
2917 .category = FIO_OPT_C_IO,
2918 .group = FIO_OPT_G_VERIFY,
a12a3b4d 2919 },
b463e936
JA
2920 {
2921 .name = "verify_dump",
e8b0e958 2922 .lname = "Verify dump",
b463e936 2923 .type = FIO_OPT_BOOL,
a609f12a 2924 .off1 = offsetof(struct thread_options, verify_dump),
ef71e317 2925 .def = "0",
b463e936
JA
2926 .help = "Dump contents of good and bad blocks on failure",
2927 .parent = "verify",
d71c154c 2928 .hide = 1,
e8b0e958
JA
2929 .category = FIO_OPT_C_IO,
2930 .group = FIO_OPT_G_VERIFY,
b463e936 2931 },
e8462bd8
JA
2932 {
2933 .name = "verify_async",
e8b0e958 2934 .lname = "Verify asynchronously",
e8462bd8 2935 .type = FIO_OPT_INT,
a609f12a 2936 .off1 = offsetof(struct thread_options, verify_async),
e8462bd8
JA
2937 .def = "0",
2938 .help = "Number of async verifier threads to use",
2939 .parent = "verify",
d71c154c 2940 .hide = 1,
e8b0e958
JA
2941 .category = FIO_OPT_C_IO,
2942 .group = FIO_OPT_G_VERIFY,
e8462bd8 2943 },
9e144189
JA
2944 {
2945 .name = "verify_backlog",
e8b0e958 2946 .lname = "Verify backlog",
9e144189 2947 .type = FIO_OPT_STR_VAL,
a609f12a 2948 .off1 = offsetof(struct thread_options, verify_backlog),
9e144189
JA
2949 .help = "Verify after this number of blocks are written",
2950 .parent = "verify",
d71c154c 2951 .hide = 1,
e8b0e958
JA
2952 .category = FIO_OPT_C_IO,
2953 .group = FIO_OPT_G_VERIFY,
9e144189
JA
2954 },
2955 {
2956 .name = "verify_backlog_batch",
e8b0e958 2957 .lname = "Verify backlog batch",
9e144189 2958 .type = FIO_OPT_INT,
a609f12a 2959 .off1 = offsetof(struct thread_options, verify_batch),
9e144189 2960 .help = "Verify this number of IO blocks",
0d29de83 2961 .parent = "verify",
d71c154c 2962 .hide = 1,
e8b0e958
JA
2963 .category = FIO_OPT_C_IO,
2964 .group = FIO_OPT_G_VERIFY,
9e144189 2965 },
e8462bd8
JA
2966#ifdef FIO_HAVE_CPU_AFFINITY
2967 {
2968 .name = "verify_async_cpus",
e8b0e958 2969 .lname = "Async verify CPUs",
e8462bd8
JA
2970 .type = FIO_OPT_STR,
2971 .cb = str_verify_cpus_allowed_cb,
a609f12a 2972 .off1 = offsetof(struct thread_options, verify_cpumask),
e8462bd8
JA
2973 .help = "Set CPUs allowed for async verify threads",
2974 .parent = "verify_async",
d71c154c 2975 .hide = 1,
e8b0e958
JA
2976 .category = FIO_OPT_C_IO,
2977 .group = FIO_OPT_G_VERIFY,
e8462bd8 2978 },
a275c37a
JA
2979#else
2980 {
2981 .name = "verify_async_cpus",
2982 .lname = "Async verify CPUs",
2983 .type = FIO_OPT_UNSUPPORTED,
54d0a315 2984 .help = "Your platform does not support CPU affinities",
a275c37a 2985 },
0d29de83 2986#endif
51aa2da8
JA
2987 {
2988 .name = "experimental_verify",
cce2fdfe 2989 .lname = "Experimental Verify",
a609f12a 2990 .off1 = offsetof(struct thread_options, experimental_verify),
51aa2da8 2991 .type = FIO_OPT_BOOL,
b31eaac9 2992 .help = "Enable experimental verification",
ca09be4b
JA
2993 .parent = "verify",
2994 .category = FIO_OPT_C_IO,
2995 .group = FIO_OPT_G_VERIFY,
2996 },
2997 {
2998 .name = "verify_state_load",
2999 .lname = "Load verify state",
a609f12a 3000 .off1 = offsetof(struct thread_options, verify_state),
ca09be4b
JA
3001 .type = FIO_OPT_BOOL,
3002 .help = "Load verify termination state",
3003 .parent = "verify",
3004 .category = FIO_OPT_C_IO,
3005 .group = FIO_OPT_G_VERIFY,
3006 },
3007 {
3008 .name = "verify_state_save",
3009 .lname = "Save verify state",
a609f12a 3010 .off1 = offsetof(struct thread_options, verify_state_save),
ca09be4b
JA
3011 .type = FIO_OPT_BOOL,
3012 .def = "1",
3013 .help = "Save verify state on termination",
3014 .parent = "verify",
836fcc0f
JA
3015 .category = FIO_OPT_C_IO,
3016 .group = FIO_OPT_G_VERIFY,
51aa2da8 3017 },
0d29de83
JA
3018#ifdef FIO_HAVE_TRIM
3019 {
3020 .name = "trim_percentage",
e8b0e958 3021 .lname = "Trim percentage",
0d29de83 3022 .type = FIO_OPT_INT,
a609f12a 3023 .off1 = offsetof(struct thread_options, trim_percentage),
20eb06bd 3024 .minval = 0,
0d29de83 3025 .maxval = 100,
169c098d 3026 .help = "Number of verify blocks to trim (i.e., discard)",
0d29de83
JA
3027 .parent = "verify",
3028 .def = "0",
20eb06bd 3029 .interval = 1,
d71c154c 3030 .hide = 1,
e8b0e958
JA
3031 .category = FIO_OPT_C_IO,
3032 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3033 },
3034 {
3035 .name = "trim_verify_zero",
e8b0e958 3036 .lname = "Verify trim zero",
20eb06bd 3037 .type = FIO_OPT_BOOL,
169c098d 3038 .help = "Verify that trimmed (i.e., discarded) blocks are returned as zeroes",
a609f12a 3039 .off1 = offsetof(struct thread_options, trim_zero),
0d29de83 3040 .parent = "trim_percentage",
d71c154c 3041 .hide = 1,
0d29de83 3042 .def = "1",
e8b0e958
JA
3043 .category = FIO_OPT_C_IO,
3044 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3045 },
3046 {
3047 .name = "trim_backlog",
e8b0e958 3048 .lname = "Trim backlog",
0d29de83 3049 .type = FIO_OPT_STR_VAL,
a609f12a 3050 .off1 = offsetof(struct thread_options, trim_backlog),
0d29de83
JA
3051 .help = "Trim after this number of blocks are written",
3052 .parent = "trim_percentage",
d71c154c 3053 .hide = 1,
20eb06bd 3054 .interval = 1,
e8b0e958
JA
3055 .category = FIO_OPT_C_IO,
3056 .group = FIO_OPT_G_TRIM,
0d29de83
JA
3057 },
3058 {
3059 .name = "trim_backlog_batch",
e8b0e958 3060 .lname = "Trim backlog batch",
0d29de83 3061 .type = FIO_OPT_INT,
a609f12a 3062 .off1 = offsetof(struct thread_options, trim_batch),
0d29de83
JA
3063 .help = "Trim this number of IO blocks",
3064 .parent = "trim_percentage",
d71c154c 3065 .hide = 1,
20eb06bd 3066 .interval = 1,
e8b0e958
JA
3067 .category = FIO_OPT_C_IO,
3068 .group = FIO_OPT_G_TRIM,
0d29de83 3069 },
a275c37a
JA
3070#else
3071 {
3072 .name = "trim_percentage",
3073 .lname = "Trim percentage",
3074 .type = FIO_OPT_UNSUPPORTED,
3075 .help = "Fio does not support TRIM on your platform",
3076 },
3077 {
3078 .name = "trim_verify_zero",
3079 .lname = "Verify trim zero",
3080 .type = FIO_OPT_UNSUPPORTED,
3081 .help = "Fio does not support TRIM on your platform",
3082 },
3083 {
3084 .name = "trim_backlog",
3085 .lname = "Trim backlog",
3086 .type = FIO_OPT_UNSUPPORTED,
3087 .help = "Fio does not support TRIM on your platform",
3088 },
3089 {
3090 .name = "trim_backlog_batch",
3091 .lname = "Trim backlog batch",
3092 .type = FIO_OPT_UNSUPPORTED,
3093 .help = "Fio does not support TRIM on your platform",
3094 },
e8462bd8 3095#endif
214e1eca
JA
3096 {
3097 .name = "write_iolog",
e8b0e958 3098 .lname = "Write I/O log",
214e1eca 3099 .type = FIO_OPT_STR_STORE,
a609f12a 3100 .off1 = offsetof(struct thread_options, write_iolog_file),
214e1eca 3101 .help = "Store IO pattern to file",
e8b0e958
JA
3102 .category = FIO_OPT_C_IO,
3103 .group = FIO_OPT_G_IOLOG,
214e1eca
JA
3104 },
3105 {
3106 .name = "read_iolog",
e8b0e958 3107 .lname = "Read I/O log",
214e1eca 3108 .type = FIO_OPT_STR_STORE,
a609f12a 3109 .off1 = offsetof(struct thread_options, read_iolog_file),
214e1eca 3110 .help = "Playback IO pattern from file",
e8b0e958
JA
3111 .category = FIO_OPT_C_IO,
3112 .group = FIO_OPT_G_IOLOG,
214e1eca 3113 },
64bbb865
DN
3114 {
3115 .name = "replay_no_stall",
e8b0e958 3116 .lname = "Don't stall on replay",
20eb06bd 3117 .type = FIO_OPT_BOOL,
a609f12a 3118 .off1 = offsetof(struct thread_options, no_stall),
64bbb865 3119 .def = "0",
87e7a972 3120 .parent = "read_iolog",
d71c154c 3121 .hide = 1,
64bbb865 3122 .help = "Playback IO pattern file as fast as possible without stalls",
e8b0e958
JA
3123 .category = FIO_OPT_C_IO,
3124 .group = FIO_OPT_G_IOLOG,
64bbb865 3125 },
d1c46c04
DN
3126 {
3127 .name = "replay_redirect",
e8b0e958 3128 .lname = "Redirect device for replay",
d1c46c04 3129 .type = FIO_OPT_STR_STORE,
a609f12a 3130 .off1 = offsetof(struct thread_options, replay_redirect),
d1c46c04 3131 .parent = "read_iolog",
d71c154c 3132 .hide = 1,
d1c46c04 3133 .help = "Replay all I/O onto this device, regardless of trace device",
e8b0e958
JA
3134 .category = FIO_OPT_C_IO,
3135 .group = FIO_OPT_G_IOLOG,
d1c46c04 3136 },
0c63576e
JA
3137 {
3138 .name = "replay_scale",
3139 .lname = "Replace offset scale factor",
3140 .type = FIO_OPT_INT,
a609f12a 3141 .off1 = offsetof(struct thread_options, replay_scale),
0c63576e
JA
3142 .parent = "read_iolog",
3143 .def = "1",
3144 .help = "Align offsets to this blocksize",
3145 .category = FIO_OPT_C_IO,
3146 .group = FIO_OPT_G_IOLOG,
3147 },
3148 {
3149 .name = "replay_align",
3150 .lname = "Replace alignment",
3151 .type = FIO_OPT_INT,
a609f12a 3152 .off1 = offsetof(struct thread_options, replay_align),
0c63576e
JA
3153 .parent = "read_iolog",
3154 .help = "Scale offset down by this factor",
3155 .category = FIO_OPT_C_IO,
3156 .group = FIO_OPT_G_IOLOG,
3157 .pow2 = 1,
3158 },
6dd7fa77
JA
3159 {
3160 .name = "replay_time_scale",
3161 .lname = "Replay Time Scale",
3162 .type = FIO_OPT_INT,
3163 .off1 = offsetof(struct thread_options, replay_time_scale),
3164 .def = "100",
3165 .minval = 1,
3166 .parent = "read_iolog",
3167 .hide = 1,
3168 .help = "Scale time for replay events",
3169 .category = FIO_OPT_C_IO,
3170 .group = FIO_OPT_G_IOLOG,
3171 },
214e1eca
JA
3172 {
3173 .name = "exec_prerun",
e8b0e958 3174 .lname = "Pre-execute runnable",
214e1eca 3175 .type = FIO_OPT_STR_STORE,
a609f12a 3176 .off1 = offsetof(struct thread_options, exec_prerun),
214e1eca 3177 .help = "Execute this file prior to running job",
e8b0e958
JA
3178 .category = FIO_OPT_C_GENERAL,
3179 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3180 },
3181 {
3182 .name = "exec_postrun",
e8b0e958 3183 .lname = "Post-execute runnable",
214e1eca 3184 .type = FIO_OPT_STR_STORE,
a609f12a 3185 .off1 = offsetof(struct thread_options, exec_postrun),
214e1eca 3186 .help = "Execute this file after running job",
e8b0e958
JA
3187 .category = FIO_OPT_C_GENERAL,
3188 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3189 },
3190#ifdef FIO_HAVE_IOSCHED_SWITCH
3191 {
3192 .name = "ioscheduler",
e8b0e958 3193 .lname = "I/O scheduler",
214e1eca 3194 .type = FIO_OPT_STR_STORE,
a609f12a 3195 .off1 = offsetof(struct thread_options, ioscheduler),
214e1eca 3196 .help = "Use this IO scheduler on the backing device",
e8b0e958
JA
3197 .category = FIO_OPT_C_FILE,
3198 .group = FIO_OPT_G_INVALID,
214e1eca 3199 },
a275c37a
JA
3200#else
3201 {
3202 .name = "ioscheduler",
3203 .lname = "I/O scheduler",
3204 .type = FIO_OPT_UNSUPPORTED,
3205 .help = "Your platform does not support IO scheduler switching",
3206 },
214e1eca
JA
3207#endif
3208 {
3209 .name = "zonesize",
e8b0e958 3210 .lname = "Zone size",
214e1eca 3211 .type = FIO_OPT_STR_VAL,
a609f12a 3212 .off1 = offsetof(struct thread_options, zone_size),
ed335855
SN
3213 .help = "Amount of data to read per zone",
3214 .def = "0",
20eb06bd 3215 .interval = 1024 * 1024,
e8b0e958
JA
3216 .category = FIO_OPT_C_IO,
3217 .group = FIO_OPT_G_ZONE,
ed335855
SN
3218 },
3219 {
3220 .name = "zonerange",
e8b0e958 3221 .lname = "Zone range",
ed335855 3222 .type = FIO_OPT_STR_VAL,
a609f12a 3223 .off1 = offsetof(struct thread_options, zone_range),
214e1eca
JA
3224 .help = "Give size of an IO zone",
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 = "zoneskip",
e8b0e958 3232 .lname = "Zone skip",
214e1eca 3233 .type = FIO_OPT_STR_VAL,
a609f12a 3234 .off1 = offsetof(struct thread_options, zone_skip),
214e1eca
JA
3235 .help = "Space between IO zones",
3236 .def = "0",
20eb06bd 3237 .interval = 1024 * 1024,
e8b0e958
JA
3238 .category = FIO_OPT_C_IO,
3239 .group = FIO_OPT_G_ZONE,
214e1eca
JA
3240 },
3241 {
3242 .name = "lockmem",
e8b0e958 3243 .lname = "Lock memory",
214e1eca 3244 .type = FIO_OPT_STR_VAL,
a609f12a 3245 .off1 = offsetof(struct thread_options, lockmem),
81c6b6cd 3246 .help = "Lock down this amount of memory (per worker)",
214e1eca 3247 .def = "0",
20eb06bd 3248 .interval = 1024 * 1024,
e8b0e958
JA
3249 .category = FIO_OPT_C_GENERAL,
3250 .group = FIO_OPT_G_INVALID,
214e1eca 3251 },
214e1eca
JA
3252 {
3253 .name = "rwmixread",
e8b0e958 3254 .lname = "Read/write mix read",
214e1eca 3255 .type = FIO_OPT_INT,
cb499fc4 3256 .cb = str_rwmix_read_cb,
a609f12a 3257 .off1 = offsetof(struct thread_options, rwmix[DDIR_READ]),
214e1eca
JA
3258 .maxval = 100,
3259 .help = "Percentage of mixed workload that is reads",
3260 .def = "50",
20eb06bd 3261 .interval = 5,
90265353 3262 .inverse = "rwmixwrite",
e8b0e958
JA
3263 .category = FIO_OPT_C_IO,
3264 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
3265 },
3266 {
3267 .name = "rwmixwrite",
e8b0e958 3268 .lname = "Read/write mix write",
214e1eca 3269 .type = FIO_OPT_INT,
cb499fc4 3270 .cb = str_rwmix_write_cb,
a609f12a 3271 .off1 = offsetof(struct thread_options, rwmix[DDIR_WRITE]),
214e1eca
JA
3272 .maxval = 100,
3273 .help = "Percentage of mixed workload that is writes",
3274 .def = "50",
20eb06bd 3275 .interval = 5,
90265353 3276 .inverse = "rwmixread",
e8b0e958
JA
3277 .category = FIO_OPT_C_IO,
3278 .group = FIO_OPT_G_RWMIX,
214e1eca 3279 },
afdf9352
JA
3280 {
3281 .name = "rwmixcycle",
e8b0e958 3282 .lname = "Read/write mix cycle",
15ca150e 3283 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
3284 .category = FIO_OPT_C_IO,
3285 .group = FIO_OPT_G_RWMIX,
afdf9352 3286 },
214e1eca
JA
3287 {
3288 .name = "nice",
e8b0e958 3289 .lname = "Nice",
214e1eca 3290 .type = FIO_OPT_INT,
a609f12a 3291 .off1 = offsetof(struct thread_options, nice),
214e1eca 3292 .help = "Set job CPU nice value",
11fd6aa8
RC
3293 .minval = -20,
3294 .maxval = 19,
214e1eca 3295 .def = "0",
20eb06bd 3296 .interval = 1,
e8b0e958 3297 .category = FIO_OPT_C_GENERAL,
10860056 3298 .group = FIO_OPT_G_CRED,
214e1eca
JA
3299 },
3300#ifdef FIO_HAVE_IOPRIO
3301 {
3302 .name = "prio",
e8b0e958 3303 .lname = "I/O nice priority",
214e1eca 3304 .type = FIO_OPT_INT,
a609f12a 3305 .off1 = offsetof(struct thread_options, ioprio),
214e1eca 3306 .help = "Set job IO priority value",
1767bd34
TK
3307 .minval = IOPRIO_MIN_PRIO,
3308 .maxval = IOPRIO_MAX_PRIO,
20eb06bd 3309 .interval = 1,
e8b0e958 3310 .category = FIO_OPT_C_GENERAL,
10860056 3311 .group = FIO_OPT_G_CRED,
214e1eca 3312 },
32ef447a
TK
3313#else
3314 {
3315 .name = "prio",
3316 .lname = "I/O nice priority",
3317 .type = FIO_OPT_UNSUPPORTED,
3318 .help = "Your platform does not support IO priorities",
3319 },
3320#endif
3321#ifdef FIO_HAVE_IOPRIO_CLASS
3322#ifndef FIO_HAVE_IOPRIO
3323#error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
3324#endif
214e1eca
JA
3325 {
3326 .name = "prioclass",
e8b0e958 3327 .lname = "I/O nice priority class",
214e1eca 3328 .type = FIO_OPT_INT,
a609f12a 3329 .off1 = offsetof(struct thread_options, ioprio_class),
214e1eca 3330 .help = "Set job IO priority class",
1767bd34
TK
3331 .minval = IOPRIO_MIN_PRIO_CLASS,
3332 .maxval = IOPRIO_MAX_PRIO_CLASS,
20eb06bd 3333 .interval = 1,
e8b0e958 3334 .category = FIO_OPT_C_GENERAL,
10860056 3335 .group = FIO_OPT_G_CRED,
214e1eca 3336 },
a275c37a 3337#else
a275c37a
JA
3338 {
3339 .name = "prioclass",
3340 .lname = "I/O nice priority class",
3341 .type = FIO_OPT_UNSUPPORTED,
32ef447a 3342 .help = "Your platform does not support IO priority classes",
a275c37a 3343 },
214e1eca
JA
3344#endif
3345 {
3346 .name = "thinktime",
e8b0e958 3347 .lname = "Thinktime",
214e1eca 3348 .type = FIO_OPT_INT,
a609f12a 3349 .off1 = offsetof(struct thread_options, thinktime),
214e1eca
JA
3350 .help = "Idle time between IO buffers (usec)",
3351 .def = "0",
88038bc7 3352 .is_time = 1,
e8b0e958 3353 .category = FIO_OPT_C_IO,
3ceb458f 3354 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3355 },
3356 {
3357 .name = "thinktime_spin",
e8b0e958 3358 .lname = "Thinktime spin",
214e1eca 3359 .type = FIO_OPT_INT,
a609f12a 3360 .off1 = offsetof(struct thread_options, thinktime_spin),
214e1eca
JA
3361 .help = "Start think time by spinning this amount (usec)",
3362 .def = "0",
88038bc7 3363 .is_time = 1,
afdf9352 3364 .parent = "thinktime",
d71c154c 3365 .hide = 1,
e8b0e958 3366 .category = FIO_OPT_C_IO,
3ceb458f 3367 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3368 },
3369 {
3370 .name = "thinktime_blocks",
e8b0e958 3371 .lname = "Thinktime blocks",
214e1eca 3372 .type = FIO_OPT_INT,
a609f12a 3373 .off1 = offsetof(struct thread_options, thinktime_blocks),
214e1eca
JA
3374 .help = "IO buffer period between 'thinktime'",
3375 .def = "1",
afdf9352 3376 .parent = "thinktime",
d71c154c 3377 .hide = 1,
e8b0e958 3378 .category = FIO_OPT_C_IO,
3ceb458f 3379 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3380 },
3381 {
3382 .name = "rate",
e8b0e958 3383 .lname = "I/O rate",
e01b22b8 3384 .type = FIO_OPT_INT,
a609f12a
JA
3385 .off1 = offsetof(struct thread_options, rate[DDIR_READ]),
3386 .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]),
3387 .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]),
214e1eca 3388 .help = "Set bandwidth rate",
e8b0e958
JA
3389 .category = FIO_OPT_C_IO,
3390 .group = FIO_OPT_G_RATE,
214e1eca
JA
3391 },
3392 {
6d428bcd
JA
3393 .name = "rate_min",
3394 .alias = "ratemin",
e8b0e958 3395 .lname = "I/O min rate",
e01b22b8 3396 .type = FIO_OPT_INT,
a609f12a
JA
3397 .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]),
3398 .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]),
3399 .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]),
4e991c23 3400 .help = "Job must meet this rate or it will be shutdown",
afdf9352 3401 .parent = "rate",
d71c154c 3402 .hide = 1,
e8b0e958
JA
3403 .category = FIO_OPT_C_IO,
3404 .group = FIO_OPT_G_RATE,
4e991c23
JA
3405 },
3406 {
3407 .name = "rate_iops",
e8b0e958 3408 .lname = "I/O rate IOPS",
e01b22b8 3409 .type = FIO_OPT_INT,
a609f12a
JA
3410 .off1 = offsetof(struct thread_options, rate_iops[DDIR_READ]),
3411 .off2 = offsetof(struct thread_options, rate_iops[DDIR_WRITE]),
3412 .off3 = offsetof(struct thread_options, rate_iops[DDIR_TRIM]),
4e991c23 3413 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 3414 .hide = 1,
e8b0e958
JA
3415 .category = FIO_OPT_C_IO,
3416 .group = FIO_OPT_G_RATE,
4e991c23
JA
3417 },
3418 {
3419 .name = "rate_iops_min",
e8b0e958 3420 .lname = "I/O min rate IOPS",
e01b22b8 3421 .type = FIO_OPT_INT,
a609f12a
JA
3422 .off1 = offsetof(struct thread_options, rate_iops_min[DDIR_READ]),
3423 .off2 = offsetof(struct thread_options, rate_iops_min[DDIR_WRITE]),
3424 .off3 = offsetof(struct thread_options, rate_iops_min[DDIR_TRIM]),
03e20d68 3425 .help = "Job must meet this rate or it will be shut down",
afdf9352 3426 .parent = "rate_iops",
d71c154c 3427 .hide = 1,
e8b0e958
JA
3428 .category = FIO_OPT_C_IO,
3429 .group = FIO_OPT_G_RATE,
214e1eca 3430 },
ff6bb260 3431 {
6de65959
JA
3432 .name = "rate_process",
3433 .lname = "Rate Process",
3434 .type = FIO_OPT_STR,
a609f12a 3435 .off1 = offsetof(struct thread_options, rate_process),
6de65959
JA
3436 .help = "What process controls how rated IO is managed",
3437 .def = "linear",
ff6bb260
SL
3438 .category = FIO_OPT_C_IO,
3439 .group = FIO_OPT_G_RATE,
6de65959
JA
3440 .posval = {
3441 { .ival = "linear",
3442 .oval = RATE_PROCESS_LINEAR,
3443 .help = "Linear rate of IO",
3444 },
3445 {
3446 .ival = "poisson",
3447 .oval = RATE_PROCESS_POISSON,
3448 .help = "Rate follows Poisson process",
3449 },
3450 },
3451 .parent = "rate",
ff6bb260 3452 },
214e1eca 3453 {
6d428bcd
JA
3454 .name = "rate_cycle",
3455 .alias = "ratecycle",
e8b0e958 3456 .lname = "I/O rate cycle",
214e1eca 3457 .type = FIO_OPT_INT,
a609f12a 3458 .off1 = offsetof(struct thread_options, ratecycle),
214e1eca
JA
3459 .help = "Window average for rate limits (msec)",
3460 .def = "1000",
afdf9352 3461 .parent = "rate",
d71c154c 3462 .hide = 1,
e8b0e958
JA
3463 .category = FIO_OPT_C_IO,
3464 .group = FIO_OPT_G_RATE,
214e1eca 3465 },
1a9bf814
JA
3466 {
3467 .name = "rate_ignore_thinktime",
3468 .lname = "Rate ignore thinktime",
3469 .type = FIO_OPT_BOOL,
3470 .off1 = offsetof(struct thread_options, rate_ign_think),
3471 .help = "Rated IO ignores thinktime settings",
3472 .parent = "rate",
3473 .category = FIO_OPT_C_IO,
3474 .group = FIO_OPT_G_RATE,
3475 },
15501535
JA
3476 {
3477 .name = "max_latency",
dd97d866 3478 .lname = "Max Latency (usec)",
6c3fb04c 3479 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3480 .off1 = offsetof(struct thread_options, max_latency),
15501535 3481 .help = "Maximum tolerated IO latency (usec)",
88038bc7 3482 .is_time = 1,
1e5324e7 3483 .category = FIO_OPT_C_IO,
3e260a46
JA
3484 .group = FIO_OPT_G_LATPROF,
3485 },
3486 {
3487 .name = "latency_target",
3488 .lname = "Latency Target (usec)",
3489 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3490 .off1 = offsetof(struct thread_options, latency_target),
3e260a46 3491 .help = "Ramp to max queue depth supporting this latency",
88038bc7 3492 .is_time = 1,
3e260a46
JA
3493 .category = FIO_OPT_C_IO,
3494 .group = FIO_OPT_G_LATPROF,
3495 },
3496 {
3497 .name = "latency_window",
3498 .lname = "Latency Window (usec)",
3499 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 3500 .off1 = offsetof(struct thread_options, latency_window),
3e260a46 3501 .help = "Time to sustain latency_target",
88038bc7 3502 .is_time = 1,
3e260a46
JA
3503 .category = FIO_OPT_C_IO,
3504 .group = FIO_OPT_G_LATPROF,
3505 },
3506 {
3507 .name = "latency_percentile",
3508 .lname = "Latency Percentile",
3509 .type = FIO_OPT_FLOAT_LIST,
a609f12a 3510 .off1 = offsetof(struct thread_options, latency_percentile),
3e260a46
JA
3511 .help = "Percentile of IOs must be below latency_target",
3512 .def = "100",
3513 .maxlen = 1,
3514 .minfp = 0.0,
3515 .maxfp = 100.0,
3516 .category = FIO_OPT_C_IO,
3517 .group = FIO_OPT_G_LATPROF,
15501535 3518 },
214e1eca
JA
3519 {
3520 .name = "invalidate",
e8b0e958 3521 .lname = "Cache invalidate",
214e1eca 3522 .type = FIO_OPT_BOOL,
a609f12a 3523 .off1 = offsetof(struct thread_options, invalidate_cache),
214e1eca
JA
3524 .help = "Invalidate buffer/page cache prior to running job",
3525 .def = "1",
e8b0e958 3526 .category = FIO_OPT_C_IO,
3ceb458f 3527 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
3528 },
3529 {
3530 .name = "sync",
e8b0e958 3531 .lname = "Synchronous I/O",
214e1eca 3532 .type = FIO_OPT_BOOL,
a609f12a 3533 .off1 = offsetof(struct thread_options, sync_io),
214e1eca
JA
3534 .help = "Use O_SYNC for buffered writes",
3535 .def = "0",
67a1000f 3536 .parent = "buffered",
d71c154c 3537 .hide = 1,
e8b0e958 3538 .category = FIO_OPT_C_IO,
3ceb458f 3539 .group = FIO_OPT_G_IO_TYPE,
214e1eca 3540 },
ae8e559e
JA
3541#ifdef FIO_HAVE_WRITE_HINT
3542 {
3543 .name = "write_hint",
3544 .lname = "Write hint",
3545 .type = FIO_OPT_STR,
3546 .off1 = offsetof(struct thread_options, write_hint),
3547 .help = "Set expected write life time",
3548 .category = FIO_OPT_C_ENGINE,
3549 .group = FIO_OPT_G_INVALID,
3550 .posval = {
3551 { .ival = "none",
3552 .oval = RWH_WRITE_LIFE_NONE,
3553 },
3554 { .ival = "short",
3555 .oval = RWH_WRITE_LIFE_SHORT,
3556 },
3557 { .ival = "medium",
3558 .oval = RWH_WRITE_LIFE_MEDIUM,
3559 },
3560 { .ival = "long",
3561 .oval = RWH_WRITE_LIFE_LONG,
3562 },
3563 { .ival = "extreme",
3564 .oval = RWH_WRITE_LIFE_EXTREME,
3565 },
3566 },
3567 },
3568#endif
214e1eca
JA
3569 {
3570 .name = "create_serialize",
e8b0e958 3571 .lname = "Create serialize",
214e1eca 3572 .type = FIO_OPT_BOOL,
a609f12a 3573 .off1 = offsetof(struct thread_options, create_serialize),
c2b8035f 3574 .help = "Serialize creation of job files",
214e1eca 3575 .def = "1",
e8b0e958
JA
3576 .category = FIO_OPT_C_FILE,
3577 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3578 },
3579 {
3580 .name = "create_fsync",
e8b0e958 3581 .lname = "Create fsync",
214e1eca 3582 .type = FIO_OPT_BOOL,
a609f12a 3583 .off1 = offsetof(struct thread_options, create_fsync),
03e20d68 3584 .help = "fsync file after creation",
214e1eca 3585 .def = "1",
e8b0e958
JA
3586 .category = FIO_OPT_C_FILE,
3587 .group = FIO_OPT_G_INVALID,
214e1eca 3588 },
814452bd
JA
3589 {
3590 .name = "create_on_open",
e8b0e958 3591 .lname = "Create on open",
814452bd 3592 .type = FIO_OPT_BOOL,
a609f12a 3593 .off1 = offsetof(struct thread_options, create_on_open),
814452bd
JA
3594 .help = "Create files when they are opened for IO",
3595 .def = "0",
e8b0e958
JA
3596 .category = FIO_OPT_C_FILE,
3597 .group = FIO_OPT_G_INVALID,
814452bd 3598 },
25460cf6
JA
3599 {
3600 .name = "create_only",
cce2fdfe 3601 .lname = "Create Only",
25460cf6 3602 .type = FIO_OPT_BOOL,
a609f12a 3603 .off1 = offsetof(struct thread_options, create_only),
25460cf6 3604 .help = "Only perform file creation phase",
d17fda71 3605 .category = FIO_OPT_C_FILE,
25460cf6
JA
3606 .def = "0",
3607 },
2378826d
JA
3608 {
3609 .name = "allow_file_create",
e81ecca3 3610 .lname = "Allow file create",
2378826d 3611 .type = FIO_OPT_BOOL,
a609f12a 3612 .off1 = offsetof(struct thread_options, allow_create),
2378826d
JA
3613 .help = "Permit fio to create files, if they don't exist",
3614 .def = "1",
3615 .category = FIO_OPT_C_FILE,
3616 .group = FIO_OPT_G_FILENAME,
3617 },
e81ecca3
JA
3618 {
3619 .name = "allow_mounted_write",
3620 .lname = "Allow mounted write",
3621 .type = FIO_OPT_BOOL,
a609f12a 3622 .off1 = offsetof(struct thread_options, allow_mounted_write),
e81ecca3
JA
3623 .help = "Allow writes to a mounted partition",
3624 .def = "0",
3625 .category = FIO_OPT_C_FILE,
3626 .group = FIO_OPT_G_FILENAME,
3627 },
0b9d69ec 3628 {
afad68f7 3629 .name = "pre_read",
e8b0e958 3630 .lname = "Pre-read files",
afad68f7 3631 .type = FIO_OPT_BOOL,
a609f12a 3632 .off1 = offsetof(struct thread_options, pre_read),
03e20d68 3633 .help = "Pre-read files before starting official testing",
afad68f7 3634 .def = "0",
e8b0e958
JA
3635 .category = FIO_OPT_C_FILE,
3636 .group = FIO_OPT_G_INVALID,
afad68f7 3637 },
214e1eca
JA
3638#ifdef FIO_HAVE_CPU_AFFINITY
3639 {
3640 .name = "cpumask",
e8b0e958 3641 .lname = "CPU mask",
214e1eca
JA
3642 .type = FIO_OPT_INT,
3643 .cb = str_cpumask_cb,
a609f12a 3644 .off1 = offsetof(struct thread_options, cpumask),
214e1eca 3645 .help = "CPU affinity mask",
e8b0e958 3646 .category = FIO_OPT_C_GENERAL,
10860056 3647 .group = FIO_OPT_G_CRED,
214e1eca 3648 },
d2e268b0
JA
3649 {
3650 .name = "cpus_allowed",
e8b0e958 3651 .lname = "CPUs allowed",
d2e268b0
JA
3652 .type = FIO_OPT_STR,
3653 .cb = str_cpus_allowed_cb,
a609f12a 3654 .off1 = offsetof(struct thread_options, cpumask),
d2e268b0 3655 .help = "Set CPUs allowed",
e8b0e958 3656 .category = FIO_OPT_C_GENERAL,
10860056 3657 .group = FIO_OPT_G_CRED,
d2e268b0 3658 },
c2acfbac
JA
3659 {
3660 .name = "cpus_allowed_policy",
3661 .lname = "CPUs allowed distribution policy",
3662 .type = FIO_OPT_STR,
a609f12a 3663 .off1 = offsetof(struct thread_options, cpus_allowed_policy),
c2acfbac
JA
3664 .help = "Distribution policy for cpus_allowed",
3665 .parent = "cpus_allowed",
3666 .prio = 1,
3667 .posval = {
3668 { .ival = "shared",
3669 .oval = FIO_CPUS_SHARED,
3670 .help = "Mask shared between threads",
3671 },
3672 { .ival = "split",
3673 .oval = FIO_CPUS_SPLIT,
3674 .help = "Mask split between threads",
3675 },
3676 },
3677 .category = FIO_OPT_C_GENERAL,
3678 .group = FIO_OPT_G_CRED,
3679 },
a275c37a
JA
3680#else
3681 {
3682 .name = "cpumask",
3683 .lname = "CPU mask",
3684 .type = FIO_OPT_UNSUPPORTED,
3685 .help = "Your platform does not support CPU affinities",
3686 },
3687 {
3688 .name = "cpus_allowed",
3689 .lname = "CPUs allowed",
3690 .type = FIO_OPT_UNSUPPORTED,
3691 .help = "Your platform does not support CPU affinities",
3692 },
3693 {
3694 .name = "cpus_allowed_policy",
3695 .lname = "CPUs allowed distribution policy",
3696 .type = FIO_OPT_UNSUPPORTED,
3697 .help = "Your platform does not support CPU affinities",
3698 },
d0b937ed 3699#endif
67bf9823 3700#ifdef CONFIG_LIBNUMA
d0b937ed
YR
3701 {
3702 .name = "numa_cpu_nodes",
cce2fdfe 3703 .lname = "NUMA CPU Nodes",
d0b937ed
YR
3704 .type = FIO_OPT_STR,
3705 .cb = str_numa_cpunodes_cb,
a609f12a 3706 .off1 = offsetof(struct thread_options, numa_cpunodes),
d0b937ed 3707 .help = "NUMA CPU nodes bind",
6be54b2d
JA
3708 .category = FIO_OPT_C_GENERAL,
3709 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
3710 },
3711 {
3712 .name = "numa_mem_policy",
cce2fdfe 3713 .lname = "NUMA Memory Policy",
d0b937ed
YR
3714 .type = FIO_OPT_STR,
3715 .cb = str_numa_mpol_cb,
a609f12a 3716 .off1 = offsetof(struct thread_options, numa_memnodes),
d0b937ed 3717 .help = "NUMA memory policy setup",
6be54b2d
JA
3718 .category = FIO_OPT_C_GENERAL,
3719 .group = FIO_OPT_G_INVALID,
d0b937ed 3720 },
a275c37a
JA
3721#else
3722 {
3723 .name = "numa_cpu_nodes",
3724 .lname = "NUMA CPU Nodes",
3725 .type = FIO_OPT_UNSUPPORTED,
3726 .help = "Build fio with libnuma-dev(el) to enable this option",
3727 },
3728 {
3729 .name = "numa_mem_policy",
3730 .lname = "NUMA Memory Policy",
3731 .type = FIO_OPT_UNSUPPORTED,
3732 .help = "Build fio with libnuma-dev(el) to enable this option",
3733 },
03553853
YR
3734#endif
3735#ifdef CONFIG_CUDA
3736 {
3737 .name = "gpu_dev_id",
3738 .lname = "GPU device ID",
3739 .type = FIO_OPT_INT,
3740 .off1 = offsetof(struct thread_options, gpu_dev_id),
3741 .help = "Set GPU device ID for GPUDirect RDMA",
3742 .def = "0",
3743 .category = FIO_OPT_C_GENERAL,
3744 .group = FIO_OPT_G_INVALID,
3745 },
214e1eca
JA
3746#endif
3747 {
3748 .name = "end_fsync",
e8b0e958 3749 .lname = "End fsync",
214e1eca 3750 .type = FIO_OPT_BOOL,
a609f12a 3751 .off1 = offsetof(struct thread_options, end_fsync),
214e1eca
JA
3752 .help = "Include fsync at the end of job",
3753 .def = "0",
e8b0e958
JA
3754 .category = FIO_OPT_C_FILE,
3755 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3756 },
3757 {
3758 .name = "fsync_on_close",
e8b0e958 3759 .lname = "Fsync on close",
214e1eca 3760 .type = FIO_OPT_BOOL,
a609f12a 3761 .off1 = offsetof(struct thread_options, fsync_on_close),
214e1eca
JA
3762 .help = "fsync files on close",
3763 .def = "0",
e8b0e958
JA
3764 .category = FIO_OPT_C_FILE,
3765 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3766 },
3767 {
3768 .name = "unlink",
e8b0e958 3769 .lname = "Unlink file",
214e1eca 3770 .type = FIO_OPT_BOOL,
a609f12a 3771 .off1 = offsetof(struct thread_options, unlink),
214e1eca
JA
3772 .help = "Unlink created files after job has completed",
3773 .def = "0",
e8b0e958
JA
3774 .category = FIO_OPT_C_FILE,
3775 .group = FIO_OPT_G_INVALID,
214e1eca 3776 },
39c1c323 3777 {
3778 .name = "unlink_each_loop",
3779 .lname = "Unlink file after each loop of a job",
3780 .type = FIO_OPT_BOOL,
a609f12a 3781 .off1 = offsetof(struct thread_options, unlink_each_loop),
39c1c323 3782 .help = "Unlink created files after each loop in a job has completed",
3783 .def = "0",
3784 .category = FIO_OPT_C_FILE,
3785 .group = FIO_OPT_G_INVALID,
3786 },
214e1eca
JA
3787 {
3788 .name = "exitall",
e8b0e958 3789 .lname = "Exit-all on terminate",
214e1eca
JA
3790 .type = FIO_OPT_STR_SET,
3791 .cb = str_exitall_cb,
3792 .help = "Terminate all jobs when one exits",
e8b0e958 3793 .category = FIO_OPT_C_GENERAL,
a1f6afec 3794 .group = FIO_OPT_G_PROCESS,
214e1eca 3795 },
f9cafb12
JA
3796 {
3797 .name = "exitall_on_error",
3798 .lname = "Exit-all on terminate in error",
78abcf9b 3799 .type = FIO_OPT_STR_SET,
a609f12a 3800 .off1 = offsetof(struct thread_options, exitall_error),
f9cafb12
JA
3801 .help = "Terminate all jobs when one exits in error",
3802 .category = FIO_OPT_C_GENERAL,
3803 .group = FIO_OPT_G_PROCESS,
3804 },
214e1eca
JA
3805 {
3806 .name = "stonewall",
e8b0e958 3807 .lname = "Wait for previous",
d392365e 3808 .alias = "wait_for_previous",
214e1eca 3809 .type = FIO_OPT_STR_SET,
a609f12a 3810 .off1 = offsetof(struct thread_options, stonewall),
214e1eca 3811 .help = "Insert a hard barrier between this job and previous",
e8b0e958 3812 .category = FIO_OPT_C_GENERAL,
a1f6afec 3813 .group = FIO_OPT_G_PROCESS,
214e1eca 3814 },
b3d62a75
JA
3815 {
3816 .name = "new_group",
e8b0e958 3817 .lname = "New group",
b3d62a75 3818 .type = FIO_OPT_STR_SET,
a609f12a 3819 .off1 = offsetof(struct thread_options, new_group),
b3d62a75 3820 .help = "Mark the start of a new group (for reporting)",
e8b0e958 3821 .category = FIO_OPT_C_GENERAL,
a1f6afec 3822 .group = FIO_OPT_G_PROCESS,
b3d62a75 3823 },
214e1eca
JA
3824 {
3825 .name = "thread",
e8b0e958 3826 .lname = "Thread",
214e1eca 3827 .type = FIO_OPT_STR_SET,
a609f12a 3828 .off1 = offsetof(struct thread_options, use_thread),
20eb06bd 3829 .help = "Use threads instead of processes",
c8931876
JA
3830#ifdef CONFIG_NO_SHM
3831 .def = "1",
3832 .no_warn_def = 1,
3833#endif
e8b0e958 3834 .category = FIO_OPT_C_GENERAL,
a1f6afec 3835 .group = FIO_OPT_G_PROCESS,
214e1eca 3836 },
3a5db920
JA
3837 {
3838 .name = "per_job_logs",
cce2fdfe 3839 .lname = "Per Job Logs",
3a5db920 3840 .type = FIO_OPT_BOOL,
a609f12a 3841 .off1 = offsetof(struct thread_options, per_job_logs),
3a5db920
JA
3842 .help = "Include job number in generated log files or not",
3843 .def = "1",
3844 .category = FIO_OPT_C_LOG,
3845 .group = FIO_OPT_G_INVALID,
3846 },
214e1eca
JA
3847 {
3848 .name = "write_bw_log",
e8b0e958 3849 .lname = "Write bandwidth log",
dded427c 3850 .type = FIO_OPT_STR,
a609f12a 3851 .off1 = offsetof(struct thread_options, bw_log_file),
dded427c 3852 .cb = str_write_bw_log_cb,
214e1eca 3853 .help = "Write log of bandwidth during run",
e8b0e958
JA
3854 .category = FIO_OPT_C_LOG,
3855 .group = FIO_OPT_G_INVALID,
214e1eca
JA
3856 },
3857 {
3858 .name = "write_lat_log",
e8b0e958 3859 .lname = "Write latency log",
dded427c 3860 .type = FIO_OPT_STR,
a609f12a 3861 .off1 = offsetof(struct thread_options, lat_log_file),
dded427c 3862 .cb = str_write_lat_log_cb,
214e1eca 3863 .help = "Write log of latency during run",
e8b0e958
JA
3864 .category = FIO_OPT_C_LOG,
3865 .group = FIO_OPT_G_INVALID,
214e1eca 3866 },
c8eeb9df
JA
3867 {
3868 .name = "write_iops_log",
e8b0e958 3869 .lname = "Write IOPS log",
dded427c 3870 .type = FIO_OPT_STR,
a609f12a 3871 .off1 = offsetof(struct thread_options, iops_log_file),
dded427c 3872 .cb = str_write_iops_log_cb,
c8eeb9df 3873 .help = "Write log of IOPS during run",
e8b0e958
JA
3874 .category = FIO_OPT_C_LOG,
3875 .group = FIO_OPT_G_INVALID,
c8eeb9df 3876 },
b8bc8cba
JA
3877 {
3878 .name = "log_avg_msec",
e8b0e958 3879 .lname = "Log averaging (msec)",
b8bc8cba 3880 .type = FIO_OPT_INT,
a609f12a 3881 .off1 = offsetof(struct thread_options, log_avg_msec),
b8bc8cba
JA
3882 .help = "Average bw/iops/lat logs over this period of time",
3883 .def = "0",
e8b0e958 3884 .category = FIO_OPT_C_LOG,
1e613c9c
KC
3885 .group = FIO_OPT_G_INVALID,
3886 },
3887 {
3888 .name = "log_hist_msec",
3889 .lname = "Log histograms (msec)",
3890 .type = FIO_OPT_INT,
a609f12a 3891 .off1 = offsetof(struct thread_options, log_hist_msec),
1e613c9c
KC
3892 .help = "Dump completion latency histograms at frequency of this time value",
3893 .def = "0",
3894 .category = FIO_OPT_C_LOG,
3895 .group = FIO_OPT_G_INVALID,
3896 },
3897 {
3898 .name = "log_hist_coarseness",
3899 .lname = "Histogram logs coarseness",
3900 .type = FIO_OPT_INT,
a609f12a 3901 .off1 = offsetof(struct thread_options, log_hist_coarseness),
1e613c9c
KC
3902 .help = "Integer in range [0,6]. Higher coarseness outputs"
3903 " fewer histogram bins per sample. The number of bins for"
3904 " these are [1216, 608, 304, 152, 76, 38, 19] respectively.",
3905 .def = "0",
3906 .category = FIO_OPT_C_LOG,
3907 .group = FIO_OPT_G_INVALID,
3908 },
3909 {
3910 .name = "write_hist_log",
3911 .lname = "Write latency histogram logs",
dded427c 3912 .type = FIO_OPT_STR,
a609f12a 3913 .off1 = offsetof(struct thread_options, hist_log_file),
dded427c 3914 .cb = str_write_hist_log_cb,
1e613c9c
KC
3915 .help = "Write log of latency histograms during run",
3916 .category = FIO_OPT_C_LOG,
e8b0e958 3917 .group = FIO_OPT_G_INVALID,
b8bc8cba 3918 },
e6989e10
JA
3919 {
3920 .name = "log_max_value",
3921 .lname = "Log maximum instead of average",
3922 .type = FIO_OPT_BOOL,
a609f12a 3923 .off1 = offsetof(struct thread_options, log_max),
e6989e10
JA
3924 .help = "Log max sample in a window instead of average",
3925 .def = "0",
3926 .category = FIO_OPT_C_LOG,
3927 .group = FIO_OPT_G_INVALID,
3928 },
ae588852
JA
3929 {
3930 .name = "log_offset",
3931 .lname = "Log offset of IO",
3932 .type = FIO_OPT_BOOL,
a609f12a 3933 .off1 = offsetof(struct thread_options, log_offset),
ae588852
JA
3934 .help = "Include offset of IO for each log entry",
3935 .def = "0",
3936 .category = FIO_OPT_C_LOG,
3937 .group = FIO_OPT_G_INVALID,
3938 },
aee2ab67
JA
3939#ifdef CONFIG_ZLIB
3940 {
3941 .name = "log_compression",
3942 .lname = "Log compression",
3943 .type = FIO_OPT_INT,
a609f12a 3944 .off1 = offsetof(struct thread_options, log_gz),
aee2ab67 3945 .help = "Log in compressed chunks of this size",
9919b27b 3946 .minval = 1024ULL,
aee2ab67
JA
3947 .maxval = 512 * 1024 * 1024ULL,
3948 .category = FIO_OPT_C_LOG,
3949 .group = FIO_OPT_G_INVALID,
3950 },
c08f9fe2
JA
3951#ifdef FIO_HAVE_CPU_AFFINITY
3952 {
3953 .name = "log_compression_cpus",
3954 .lname = "Log Compression CPUs",
3955 .type = FIO_OPT_STR,
3956 .cb = str_log_cpus_allowed_cb,
a609f12a 3957 .off1 = offsetof(struct thread_options, log_gz_cpumask),
c08f9fe2
JA
3958 .parent = "log_compression",
3959 .help = "Limit log compression to these CPUs",
3960 .category = FIO_OPT_C_LOG,
3961 .group = FIO_OPT_G_INVALID,
3962 },
a275c37a
JA
3963#else
3964 {
3965 .name = "log_compression_cpus",
3966 .lname = "Log Compression CPUs",
3967 .type = FIO_OPT_UNSUPPORTED,
3968 .help = "Your platform does not support CPU affinities",
3969 },
c08f9fe2 3970#endif
b26317c9
JA
3971 {
3972 .name = "log_store_compressed",
3973 .lname = "Log store compressed",
3974 .type = FIO_OPT_BOOL,
a609f12a 3975 .off1 = offsetof(struct thread_options, log_gz_store),
b26317c9
JA
3976 .help = "Store logs in a compressed format",
3977 .category = FIO_OPT_C_LOG,
3978 .group = FIO_OPT_G_INVALID,
3979 },
a275c37a
JA
3980#else
3981 {
3982 .name = "log_compression",
3983 .lname = "Log compression",
3984 .type = FIO_OPT_UNSUPPORTED,
3985 .help = "Install libz-dev(el) to get compression support",
3986 },
3987 {
3988 .name = "log_store_compressed",
3989 .lname = "Log store compressed",
3990 .type = FIO_OPT_UNSUPPORTED,
3991 .help = "Install libz-dev(el) to get compression support",
3992 },
aee2ab67 3993#endif
3aea75b1
KC
3994 {
3995 .name = "log_unix_epoch",
3996 .lname = "Log epoch unix",
3997 .type = FIO_OPT_BOOL,
3998 .off1 = offsetof(struct thread_options, log_unix_epoch),
3999 .help = "Use Unix time in log files",
4000 .category = FIO_OPT_C_LOG,
4001 .group = FIO_OPT_G_INVALID,
4002 },
66347cfa
DE
4003 {
4004 .name = "block_error_percentiles",
4005 .lname = "Block error percentiles",
4006 .type = FIO_OPT_BOOL,
a609f12a 4007 .off1 = offsetof(struct thread_options, block_error_hist),
66347cfa
DE
4008 .help = "Record trim block errors and make a histogram",
4009 .def = "0",
4010 .category = FIO_OPT_C_LOG,
4011 .group = FIO_OPT_G_INVALID,
4012 },
c504ee55
JA
4013 {
4014 .name = "bwavgtime",
4015 .lname = "Bandwidth average time",
4016 .type = FIO_OPT_INT,
a609f12a 4017 .off1 = offsetof(struct thread_options, bw_avg_time),
c504ee55
JA
4018 .help = "Time window over which to calculate bandwidth"
4019 " (msec)",
4020 .def = "500",
4021 .parent = "write_bw_log",
4022 .hide = 1,
4023 .interval = 100,
4024 .category = FIO_OPT_C_LOG,
4025 .group = FIO_OPT_G_INVALID,
4026 },
4027 {
4028 .name = "iopsavgtime",
4029 .lname = "IOPS average time",
4030 .type = FIO_OPT_INT,
a609f12a 4031 .off1 = offsetof(struct thread_options, iops_avg_time),
c504ee55
JA
4032 .help = "Time window over which to calculate IOPS (msec)",
4033 .def = "500",
4034 .parent = "write_iops_log",
4035 .hide = 1,
4036 .interval = 100,
4037 .category = FIO_OPT_C_LOG,
4038 .group = FIO_OPT_G_INVALID,
4039 },
214e1eca
JA
4040 {
4041 .name = "group_reporting",
e8b0e958 4042 .lname = "Group reporting",
d2507043 4043 .type = FIO_OPT_STR_SET,
a609f12a 4044 .off1 = offsetof(struct thread_options, group_reporting),
214e1eca 4045 .help = "Do reporting on a per-group basis",
10860056 4046 .category = FIO_OPT_C_STAT,
e8b0e958 4047 .group = FIO_OPT_G_INVALID,
214e1eca 4048 },
8243be59
JA
4049 {
4050 .name = "stats",
4051 .lname = "Stats",
4052 .type = FIO_OPT_BOOL,
4053 .off1 = offsetof(struct thread_options, stats),
4054 .help = "Enable collection of stats",
4055 .def = "1",
4056 .category = FIO_OPT_C_STAT,
4057 .group = FIO_OPT_G_INVALID,
4058 },
e9459e5a
JA
4059 {
4060 .name = "zero_buffers",
e8b0e958 4061 .lname = "Zero I/O buffers",
e9459e5a 4062 .type = FIO_OPT_STR_SET,
a609f12a 4063 .off1 = offsetof(struct thread_options, zero_buffers),
e9459e5a 4064 .help = "Init IO buffers to all zeroes",
e8b0e958 4065 .category = FIO_OPT_C_IO,
3ceb458f 4066 .group = FIO_OPT_G_IO_BUF,
e9459e5a 4067 },
5973cafb
JA
4068 {
4069 .name = "refill_buffers",
e8b0e958 4070 .lname = "Refill I/O buffers",
5973cafb 4071 .type = FIO_OPT_STR_SET,
a609f12a 4072 .off1 = offsetof(struct thread_options, refill_buffers),
5973cafb 4073 .help = "Refill IO buffers on every IO submit",
e8b0e958 4074 .category = FIO_OPT_C_IO,
3ceb458f 4075 .group = FIO_OPT_G_IO_BUF,
5973cafb 4076 },
fd68418e
JA
4077 {
4078 .name = "scramble_buffers",
e8b0e958 4079 .lname = "Scramble I/O buffers",
fd68418e 4080 .type = FIO_OPT_BOOL,
a609f12a 4081 .off1 = offsetof(struct thread_options, scramble_buffers),
fd68418e
JA
4082 .help = "Slightly scramble buffers on every IO submit",
4083 .def = "1",
e8b0e958 4084 .category = FIO_OPT_C_IO,
3ceb458f 4085 .group = FIO_OPT_G_IO_BUF,
fd68418e 4086 },
ce35b1ec
JA
4087 {
4088 .name = "buffer_pattern",
4089 .lname = "Buffer pattern",
4090 .type = FIO_OPT_STR,
4091 .cb = str_buffer_pattern_cb,
a609f12a 4092 .off1 = offsetof(struct thread_options, buffer_pattern),
ce35b1ec
JA
4093 .help = "Fill pattern for IO buffers",
4094 .category = FIO_OPT_C_IO,
4095 .group = FIO_OPT_G_IO_BUF,
4096 },
9c42684e
JA
4097 {
4098 .name = "buffer_compress_percentage",
e8b0e958 4099 .lname = "Buffer compression percentage",
9c42684e 4100 .type = FIO_OPT_INT,
bedc9dc2 4101 .cb = str_buffer_compress_cb,
a609f12a 4102 .off1 = offsetof(struct thread_options, compress_percentage),
9c42684e 4103 .maxval = 100,
e7f5de90 4104 .minval = 0,
9c42684e 4105 .help = "How compressible the buffer is (approximately)",
20eb06bd 4106 .interval = 5,
e8b0e958 4107 .category = FIO_OPT_C_IO,
3ceb458f 4108 .group = FIO_OPT_G_IO_BUF,
9c42684e 4109 },
f97a43a1
JA
4110 {
4111 .name = "buffer_compress_chunk",
e8b0e958 4112 .lname = "Buffer compression chunk size",
f97a43a1 4113 .type = FIO_OPT_INT,
a609f12a 4114 .off1 = offsetof(struct thread_options, compress_chunk),
207b18e4 4115 .parent = "buffer_compress_percentage",
d71c154c 4116 .hide = 1,
f97a43a1 4117 .help = "Size of compressible region in buffer",
1de80624 4118 .def = "512",
20eb06bd 4119 .interval = 256,
e8b0e958 4120 .category = FIO_OPT_C_IO,
3ceb458f 4121 .group = FIO_OPT_G_IO_BUF,
f97a43a1 4122 },
5c94b008
JA
4123 {
4124 .name = "dedupe_percentage",
4125 .lname = "Dedupe percentage",
4126 .type = FIO_OPT_INT,
4127 .cb = str_dedupe_cb,
a609f12a 4128 .off1 = offsetof(struct thread_options, dedupe_percentage),
5c94b008
JA
4129 .maxval = 100,
4130 .minval = 0,
4131 .help = "Percentage of buffers that are dedupable",
4132 .interval = 1,
4133 .category = FIO_OPT_C_IO,
4134 .group = FIO_OPT_G_IO_BUF,
4135 },
83349190
YH
4136 {
4137 .name = "clat_percentiles",
e8b0e958 4138 .lname = "Completion latency percentiles",
83349190 4139 .type = FIO_OPT_BOOL,
a609f12a 4140 .off1 = offsetof(struct thread_options, clat_percentiles),
83349190 4141 .help = "Enable the reporting of completion latency percentiles",
467b35ed 4142 .def = "1",
b599759b
JA
4143 .inverse = "lat_percentiles",
4144 .category = FIO_OPT_C_STAT,
4145 .group = FIO_OPT_G_INVALID,
4146 },
4147 {
4148 .name = "lat_percentiles",
4149 .lname = "IO latency percentiles",
4150 .type = FIO_OPT_BOOL,
4151 .off1 = offsetof(struct thread_options, lat_percentiles),
4152 .help = "Enable the reporting of IO latency percentiles",
4153 .def = "0",
4154 .inverse = "clat_percentiles",
e8b0e958
JA
4155 .category = FIO_OPT_C_STAT,
4156 .group = FIO_OPT_G_INVALID,
83349190
YH
4157 },
4158 {
4159 .name = "percentile_list",
66347cfa 4160 .lname = "Percentile list",
83349190 4161 .type = FIO_OPT_FLOAT_LIST,
a609f12a
JA
4162 .off1 = offsetof(struct thread_options, percentile_list),
4163 .off2 = offsetof(struct thread_options, percentile_precision),
66347cfa
DE
4164 .help = "Specify a custom list of percentiles to report for "
4165 "completion latency and block errors",
fd112d34 4166 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
4167 .maxlen = FIO_IO_U_LIST_MAX_LEN,
4168 .minfp = 0.0,
4169 .maxfp = 100.0,
e8b0e958
JA
4170 .category = FIO_OPT_C_STAT,
4171 .group = FIO_OPT_G_INVALID,
e883cb35
JF
4172 },
4173 {
4174 .name = "significant_figures",
4175 .lname = "Significant figures",
4176 .type = FIO_OPT_INT,
4177 .off1 = offsetof(struct thread_options, sig_figs),
4178 .maxval = 10,
4179 .minval = 1,
4180 .help = "Significant figures for output-format set to normal",
4181 .def = "4",
4182 .interval = 1,
4183 .category = FIO_OPT_C_STAT,
4184 .group = FIO_OPT_G_INVALID,
83349190
YH
4185 },
4186
0a839f30
JA
4187#ifdef FIO_HAVE_DISK_UTIL
4188 {
4189 .name = "disk_util",
e8b0e958 4190 .lname = "Disk utilization",
0a839f30 4191 .type = FIO_OPT_BOOL,
a609f12a 4192 .off1 = offsetof(struct thread_options, do_disk_util),
f66ab3c8 4193 .help = "Log disk utilization statistics",
0a839f30 4194 .def = "1",
e8b0e958
JA
4195 .category = FIO_OPT_C_STAT,
4196 .group = FIO_OPT_G_INVALID,
0a839f30 4197 },
a275c37a
JA
4198#else
4199 {
4200 .name = "disk_util",
4201 .lname = "Disk utilization",
4202 .type = FIO_OPT_UNSUPPORTED,
4203 .help = "Your platform does not support disk utilization",
4204 },
0a839f30 4205#endif
993bf48b
JA
4206 {
4207 .name = "gtod_reduce",
e8b0e958 4208 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
4209 .type = FIO_OPT_BOOL,
4210 .help = "Greatly reduce number of gettimeofday() calls",
4211 .cb = str_gtod_reduce_cb,
4212 .def = "0",
a4ed77fe 4213 .hide_on_set = 1,
e8b0e958
JA
4214 .category = FIO_OPT_C_STAT,
4215 .group = FIO_OPT_G_INVALID,
993bf48b 4216 },
02af0988
JA
4217 {
4218 .name = "disable_lat",
e8b0e958 4219 .lname = "Disable all latency stats",
02af0988 4220 .type = FIO_OPT_BOOL,
a609f12a 4221 .off1 = offsetof(struct thread_options, disable_lat),
02af0988
JA
4222 .help = "Disable latency numbers",
4223 .parent = "gtod_reduce",
d71c154c 4224 .hide = 1,
02af0988 4225 .def = "0",
e8b0e958
JA
4226 .category = FIO_OPT_C_STAT,
4227 .group = FIO_OPT_G_INVALID,
02af0988 4228 },
9520ebb9
JA
4229 {
4230 .name = "disable_clat",
e8b0e958 4231 .lname = "Disable completion latency stats",
9520ebb9 4232 .type = FIO_OPT_BOOL,
a609f12a 4233 .off1 = offsetof(struct thread_options, disable_clat),
9520ebb9 4234 .help = "Disable completion latency numbers",
993bf48b 4235 .parent = "gtod_reduce",
d71c154c 4236 .hide = 1,
9520ebb9 4237 .def = "0",
e8b0e958
JA
4238 .category = FIO_OPT_C_STAT,
4239 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
4240 },
4241 {
4242 .name = "disable_slat",
e8b0e958 4243 .lname = "Disable submission latency stats",
9520ebb9 4244 .type = FIO_OPT_BOOL,
a609f12a 4245 .off1 = offsetof(struct thread_options, disable_slat),
03e20d68 4246 .help = "Disable submission latency numbers",
993bf48b 4247 .parent = "gtod_reduce",
d71c154c 4248 .hide = 1,
9520ebb9 4249 .def = "0",
e8b0e958
JA
4250 .category = FIO_OPT_C_STAT,
4251 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
4252 },
4253 {
4254 .name = "disable_bw_measurement",
afd2ceff 4255 .alias = "disable_bw",
e8b0e958 4256 .lname = "Disable bandwidth stats",
9520ebb9 4257 .type = FIO_OPT_BOOL,
a609f12a 4258 .off1 = offsetof(struct thread_options, disable_bw),
9520ebb9 4259 .help = "Disable bandwidth logging",
993bf48b 4260 .parent = "gtod_reduce",
d71c154c 4261 .hide = 1,
9520ebb9 4262 .def = "0",
e8b0e958
JA
4263 .category = FIO_OPT_C_STAT,
4264 .group = FIO_OPT_G_INVALID,
9520ebb9 4265 },
be4ecfdf
JA
4266 {
4267 .name = "gtod_cpu",
e8b0e958 4268 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 4269 .type = FIO_OPT_INT,
a609f12a 4270 .off1 = offsetof(struct thread_options, gtod_cpu),
03e20d68 4271 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 4272 .verify = gtod_cpu_verify,
e8b0e958 4273 .category = FIO_OPT_C_GENERAL,
10860056 4274 .group = FIO_OPT_G_CLOCK,
be4ecfdf 4275 },
771e58be
JA
4276 {
4277 .name = "unified_rw_reporting",
cce2fdfe 4278 .lname = "Unified RW Reporting",
771e58be 4279 .type = FIO_OPT_BOOL,
a609f12a 4280 .off1 = offsetof(struct thread_options, unified_rw_rep),
771e58be
JA
4281 .help = "Unify reporting across data direction",
4282 .def = "0",
90b7a96d
JA
4283 .category = FIO_OPT_C_GENERAL,
4284 .group = FIO_OPT_G_INVALID,
771e58be 4285 },
f2bba182
RR
4286 {
4287 .name = "continue_on_error",
e8b0e958 4288 .lname = "Continue on error",
06842027 4289 .type = FIO_OPT_STR,
a609f12a 4290 .off1 = offsetof(struct thread_options, continue_on_error),
03e20d68 4291 .help = "Continue on non-fatal errors during IO",
06842027 4292 .def = "none",
e8b0e958 4293 .category = FIO_OPT_C_GENERAL,
bc3f552f 4294 .group = FIO_OPT_G_ERR,
06842027
SL
4295 .posval = {
4296 { .ival = "none",
4297 .oval = ERROR_TYPE_NONE,
4298 .help = "Exit when an error is encountered",
4299 },
4300 { .ival = "read",
4301 .oval = ERROR_TYPE_READ,
4302 .help = "Continue on read errors only",
4303 },
4304 { .ival = "write",
4305 .oval = ERROR_TYPE_WRITE,
4306 .help = "Continue on write errors only",
4307 },
4308 { .ival = "io",
4309 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
4310 .help = "Continue on any IO errors",
4311 },
4312 { .ival = "verify",
4313 .oval = ERROR_TYPE_VERIFY,
4314 .help = "Continue on verify errors only",
4315 },
4316 { .ival = "all",
4317 .oval = ERROR_TYPE_ANY,
4318 .help = "Continue on all io and verify errors",
4319 },
4320 { .ival = "0",
4321 .oval = ERROR_TYPE_NONE,
4322 .help = "Alias for 'none'",
4323 },
4324 { .ival = "1",
4325 .oval = ERROR_TYPE_ANY,
4326 .help = "Alias for 'all'",
4327 },
4328 },
f2bba182 4329 },
8b28bd41
DM
4330 {
4331 .name = "ignore_error",
cce2fdfe 4332 .lname = "Ignore Error",
8b28bd41
DM
4333 .type = FIO_OPT_STR,
4334 .cb = str_ignore_error_cb,
a609f12a 4335 .off1 = offsetof(struct thread_options, ignore_error_nr),
8b28bd41
DM
4336 .help = "Set a specific list of errors to ignore",
4337 .parent = "rw",
a94eb99a 4338 .category = FIO_OPT_C_GENERAL,
bc3f552f 4339 .group = FIO_OPT_G_ERR,
8b28bd41
DM
4340 },
4341 {
4342 .name = "error_dump",
cce2fdfe 4343 .lname = "Error Dump",
8b28bd41 4344 .type = FIO_OPT_BOOL,
a609f12a 4345 .off1 = offsetof(struct thread_options, error_dump),
8b28bd41
DM
4346 .def = "0",
4347 .help = "Dump info on each error",
a94eb99a 4348 .category = FIO_OPT_C_GENERAL,
bc3f552f 4349 .group = FIO_OPT_G_ERR,
8b28bd41 4350 },
9ac8a797
JA
4351 {
4352 .name = "profile",
e8b0e958 4353 .lname = "Profile",
79d16311 4354 .type = FIO_OPT_STR_STORE,
a609f12a 4355 .off1 = offsetof(struct thread_options, profile),
9ac8a797 4356 .help = "Select a specific builtin performance test",
13fca827 4357 .category = FIO_OPT_C_PROFILE,
e8b0e958 4358 .group = FIO_OPT_G_INVALID,
9ac8a797 4359 },
a696fa2a
JA
4360 {
4361 .name = "cgroup",
e8b0e958 4362 .lname = "Cgroup",
a696fa2a 4363 .type = FIO_OPT_STR_STORE,
a609f12a 4364 .off1 = offsetof(struct thread_options, cgroup),
a696fa2a 4365 .help = "Add job to cgroup of this name",
e8b0e958 4366 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
4367 .group = FIO_OPT_G_CGROUP,
4368 },
4369 {
4370 .name = "cgroup_nodelete",
4371 .lname = "Cgroup no-delete",
4372 .type = FIO_OPT_BOOL,
a609f12a 4373 .off1 = offsetof(struct thread_options, cgroup_nodelete),
a1f6afec
JA
4374 .help = "Do not delete cgroups after job completion",
4375 .def = "0",
4376 .parent = "cgroup",
4377 .category = FIO_OPT_C_GENERAL,
4378 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
4379 },
4380 {
4381 .name = "cgroup_weight",
e8b0e958 4382 .lname = "Cgroup weight",
a696fa2a 4383 .type = FIO_OPT_INT,
a609f12a 4384 .off1 = offsetof(struct thread_options, cgroup_weight),
a696fa2a
JA
4385 .help = "Use given weight for cgroup",
4386 .minval = 100,
4387 .maxval = 1000,
a1f6afec 4388 .parent = "cgroup",
e8b0e958 4389 .category = FIO_OPT_C_GENERAL,
a1f6afec 4390 .group = FIO_OPT_G_CGROUP,
7de87099 4391 },
e0b0d892
JA
4392 {
4393 .name = "uid",
e8b0e958 4394 .lname = "User ID",
e0b0d892 4395 .type = FIO_OPT_INT,
a609f12a 4396 .off1 = offsetof(struct thread_options, uid),
e0b0d892 4397 .help = "Run job with this user ID",
e8b0e958 4398 .category = FIO_OPT_C_GENERAL,
10860056 4399 .group = FIO_OPT_G_CRED,
e0b0d892
JA
4400 },
4401 {
4402 .name = "gid",
e8b0e958 4403 .lname = "Group ID",
e0b0d892 4404 .type = FIO_OPT_INT,
a609f12a 4405 .off1 = offsetof(struct thread_options, gid),
e0b0d892 4406 .help = "Run job with this group ID",
e8b0e958 4407 .category = FIO_OPT_C_GENERAL,
10860056 4408 .group = FIO_OPT_G_CRED,
e0b0d892 4409 },
a1f6afec
JA
4410 {
4411 .name = "kb_base",
4412 .lname = "KB Base",
4413 .type = FIO_OPT_INT,
a609f12a 4414 .off1 = offsetof(struct thread_options, kb_base),
a1f6afec
JA
4415 .prio = 1,
4416 .def = "1024",
ba9c7219
JA
4417 .posval = {
4418 { .ival = "1024",
4419 .oval = 1024,
d694a6a7 4420 .help = "Inputs invert IEC and SI prefixes (for compatibility); outputs prefer binary",
ba9c7219
JA
4421 },
4422 { .ival = "1000",
4423 .oval = 1000,
d694a6a7 4424 .help = "Inputs use IEC and SI prefixes; outputs prefer SI",
ba9c7219
JA
4425 },
4426 },
d694a6a7 4427 .help = "Unit prefix interpretation for quantities of data (IEC and SI)",
a1f6afec
JA
4428 .category = FIO_OPT_C_GENERAL,
4429 .group = FIO_OPT_G_INVALID,
4430 },
cf3a0518
JA
4431 {
4432 .name = "unit_base",
d694a6a7 4433 .lname = "Unit for quantities of data (Bits or Bytes)",
cf3a0518 4434 .type = FIO_OPT_INT,
a609f12a 4435 .off1 = offsetof(struct thread_options, unit_base),
cf3a0518 4436 .prio = 1,
71a08258
JA
4437 .posval = {
4438 { .ival = "0",
4439 .oval = 0,
4440 .help = "Auto-detect",
4441 },
4442 { .ival = "8",
4443 .oval = 8,
4444 .help = "Normal (byte based)",
4445 },
4446 { .ival = "1",
4447 .oval = 1,
4448 .help = "Bit based",
4449 },
4450 },
cf3a0518
JA
4451 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
4452 .category = FIO_OPT_C_GENERAL,
4453 .group = FIO_OPT_G_INVALID,
4454 },
3ceb458f
JA
4455 {
4456 .name = "hugepage-size",
4457 .lname = "Hugepage size",
4458 .type = FIO_OPT_INT,
a609f12a 4459 .off1 = offsetof(struct thread_options, hugepage_size),
3ceb458f
JA
4460 .help = "When using hugepages, specify size of each page",
4461 .def = __fio_stringify(FIO_HUGE_PAGE),
4462 .interval = 1024 * 1024,
4463 .category = FIO_OPT_C_GENERAL,
4464 .group = FIO_OPT_G_INVALID,
4465 },
9e684a49
DE
4466 {
4467 .name = "flow_id",
e8b0e958 4468 .lname = "I/O flow ID",
9e684a49 4469 .type = FIO_OPT_INT,
a609f12a 4470 .off1 = offsetof(struct thread_options, flow_id),
9e684a49
DE
4471 .help = "The flow index ID to use",
4472 .def = "0",
e8b0e958
JA
4473 .category = FIO_OPT_C_IO,
4474 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
4475 },
4476 {
4477 .name = "flow",
e8b0e958 4478 .lname = "I/O flow weight",
9e684a49 4479 .type = FIO_OPT_INT,
a609f12a 4480 .off1 = offsetof(struct thread_options, flow),
9e684a49
DE
4481 .help = "Weight for flow control of this job",
4482 .parent = "flow_id",
d71c154c 4483 .hide = 1,
9e684a49 4484 .def = "0",
e8b0e958
JA
4485 .category = FIO_OPT_C_IO,
4486 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
4487 },
4488 {
4489 .name = "flow_watermark",
e8b0e958 4490 .lname = "I/O flow watermark",
9e684a49 4491 .type = FIO_OPT_INT,
a609f12a 4492 .off1 = offsetof(struct thread_options, flow_watermark),
9e684a49
DE
4493 .help = "High watermark for flow control. This option"
4494 " should be set to the same value for all threads"
4495 " with non-zero flow.",
4496 .parent = "flow_id",
d71c154c 4497 .hide = 1,
9e684a49 4498 .def = "1024",
e8b0e958
JA
4499 .category = FIO_OPT_C_IO,
4500 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
4501 },
4502 {
4503 .name = "flow_sleep",
e8b0e958 4504 .lname = "I/O flow sleep",
9e684a49 4505 .type = FIO_OPT_INT,
a609f12a 4506 .off1 = offsetof(struct thread_options, flow_sleep),
9e684a49
DE
4507 .help = "How many microseconds to sleep after being held"
4508 " back by the flow control mechanism",
4509 .parent = "flow_id",
d71c154c 4510 .hide = 1,
9e684a49 4511 .def = "0",
e8b0e958
JA
4512 .category = FIO_OPT_C_IO,
4513 .group = FIO_OPT_G_IO_FLOW,
9e684a49 4514 },
16e56d25
VF
4515 {
4516 .name = "steadystate",
4517 .lname = "Steady state threshold",
4518 .alias = "ss",
4519 .type = FIO_OPT_STR,
2c5d94bc 4520 .off1 = offsetof(struct thread_options, ss_state),
16e56d25
VF
4521 .cb = str_steadystate_cb,
4522 .help = "Define the criterion and limit to judge when a job has reached steady state",
4523 .def = "iops_slope:0.01%",
4524 .posval = {
4525 { .ival = "iops",
f0c50c66 4526 .oval = FIO_SS_IOPS,
16e56d25
VF
4527 .help = "maximum mean deviation of IOPS measurements",
4528 },
4529 { .ival = "iops_slope",
f0c50c66 4530 .oval = FIO_SS_IOPS_SLOPE,
16e56d25
VF
4531 .help = "slope calculated from IOPS measurements",
4532 },
4533 { .ival = "bw",
f0c50c66 4534 .oval = FIO_SS_BW,
16e56d25
VF
4535 .help = "maximum mean deviation of bandwidth measurements",
4536 },
4537 {
4538 .ival = "bw_slope",
f0c50c66 4539 .oval = FIO_SS_BW_SLOPE,
16e56d25
VF
4540 .help = "slope calculated from bandwidth measurements",
4541 },
4542 },
4543 .category = FIO_OPT_C_GENERAL,
4544 .group = FIO_OPT_G_RUNTIME,
4545 },
4546 {
4547 .name = "steadystate_duration",
4548 .lname = "Steady state duration",
4549 .alias = "ss_dur",
915ca980 4550 .parent = "steadystate",
16e56d25
VF
4551 .type = FIO_OPT_STR_VAL_TIME,
4552 .off1 = offsetof(struct thread_options, ss_dur),
4553 .help = "Stop workload upon attaining steady state for specified duration",
4554 .def = "0",
4555 .is_seconds = 1,
4556 .is_time = 1,
4557 .category = FIO_OPT_C_GENERAL,
4558 .group = FIO_OPT_G_RUNTIME,
4559 },
4560 {
4561 .name = "steadystate_ramp_time",
4562 .lname = "Steady state ramp time",
4563 .alias = "ss_ramp",
915ca980 4564 .parent = "steadystate",
16e56d25
VF
4565 .type = FIO_OPT_STR_VAL_TIME,
4566 .off1 = offsetof(struct thread_options, ss_ramp_time),
4567 .help = "Delay before initiation of data collection for steady state job termination testing",
4568 .def = "0",
4569 .is_seconds = 1,
4570 .is_time = 1,
4571 .category = FIO_OPT_C_GENERAL,
4572 .group = FIO_OPT_G_RUNTIME,
4573 },
214e1eca
JA
4574 {
4575 .name = NULL,
4576 },
4577};
4578
17af15d4 4579static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 4580 const char *name, int val)
9f81736c 4581{
17af15d4 4582 lopt->name = (char *) name;
de890a1e 4583 lopt->val = val;
9f81736c 4584 if (o->type == FIO_OPT_STR_SET)
ff52be3d 4585 lopt->has_arg = optional_argument;
9f81736c
JA
4586 else
4587 lopt->has_arg = required_argument;
4588}
4589
de890a1e
SL
4590static void options_to_lopts(struct fio_option *opts,
4591 struct option *long_options,
4592 int i, int option_type)
214e1eca 4593{
de890a1e 4594 struct fio_option *o = &opts[0];
214e1eca 4595 while (o->name) {
de890a1e 4596 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
4597 if (o->alias) {
4598 i++;
de890a1e 4599 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 4600 }
214e1eca
JA
4601
4602 i++;
4603 o++;
4604 assert(i < FIO_NR_OPTIONS);
4605 }
4606}
4607
de890a1e
SL
4608void fio_options_set_ioengine_opts(struct option *long_options,
4609 struct thread_data *td)
4610{
4611 unsigned int i;
4612
4613 i = 0;
4614 while (long_options[i].name) {
4615 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
4616 memset(&long_options[i], 0, sizeof(*long_options));
4617 break;
4618 }
4619 i++;
4620 }
4621
4622 /*
4623 * Just clear out the prior ioengine options.
4624 */
4625 if (!td || !td->eo)
4626 return;
4627
4628 options_to_lopts(td->io_ops->options, long_options, i,
4629 FIO_GETOPT_IOENGINE);
4630}
4631
4632void fio_options_dup_and_init(struct option *long_options)
4633{
4634 unsigned int i;
4635
9af4a244 4636 options_init(fio_options);
de890a1e
SL
4637
4638 i = 0;
4639 while (long_options[i].name)
4640 i++;
4641
9af4a244 4642 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
4643}
4644
74929ac2
JA
4645struct fio_keyword {
4646 const char *word;
4647 const char *desc;
4648 char *replace;
4649};
4650
4651static struct fio_keyword fio_keywords[] = {
4652 {
4653 .word = "$pagesize",
4654 .desc = "Page size in the system",
4655 },
4656 {
4657 .word = "$mb_memory",
4658 .desc = "Megabytes of memory online",
4659 },
4660 {
4661 .word = "$ncpus",
4662 .desc = "Number of CPUs online in the system",
4663 },
4664 {
4665 .word = NULL,
4666 },
4667};
4668
af1dc266
JA
4669void fio_keywords_exit(void)
4670{
4671 struct fio_keyword *kw;
4672
4673 kw = &fio_keywords[0];
4674 while (kw->word) {
4675 free(kw->replace);
4676 kw->replace = NULL;
4677 kw++;
4678 }
4679}
4680
74929ac2
JA
4681void fio_keywords_init(void)
4682{
3b2e1464 4683 unsigned long long mb_memory;
74929ac2
JA
4684 char buf[128];
4685 long l;
4686
a4cfc477 4687 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
4688 fio_keywords[0].replace = strdup(buf);
4689
8eb016d3 4690 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 4691 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
4692 fio_keywords[1].replace = strdup(buf);
4693
c00a2289 4694 l = cpus_online();
74929ac2
JA
4695 sprintf(buf, "%lu", l);
4696 fio_keywords[2].replace = strdup(buf);
4697}
4698
892a6ffc
JA
4699#define BC_APP "bc"
4700
4701static char *bc_calc(char *str)
4702{
d0c814ec 4703 char buf[128], *tmp;
892a6ffc
JA
4704 FILE *f;
4705 int ret;
4706
4707 /*
4708 * No math, just return string
4709 */
d0c814ec
SL
4710 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
4711 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
4712 return str;
4713
4714 /*
4715 * Split option from value, we only need to calculate the value
4716 */
4717 tmp = strchr(str, '=');
4718 if (!tmp)
4719 return str;
4720
4721 tmp++;
892a6ffc 4722
d0c814ec
SL
4723 /*
4724 * Prevent buffer overflows; such a case isn't reasonable anyway
4725 */
4726 if (strlen(str) >= 128 || strlen(tmp) > 100)
4727 return str;
892a6ffc
JA
4728
4729 sprintf(buf, "which %s > /dev/null", BC_APP);
4730 if (system(buf)) {
4731 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
4732 return NULL;
4733 }
4734
d0c814ec 4735 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 4736 f = popen(buf, "r");
3c3ed070 4737 if (!f)
892a6ffc 4738 return NULL;
892a6ffc 4739
d0c814ec 4740 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
4741 if (ret <= 0) {
4742 pclose(f);
892a6ffc 4743 return NULL;
1d824f37 4744 }
892a6ffc 4745
892a6ffc 4746 pclose(f);
d0c814ec
SL
4747 buf[(tmp - str) + ret - 1] = '\0';
4748 memcpy(buf, str, tmp - str);
892a6ffc 4749 free(str);
d0c814ec
SL
4750 return strdup(buf);
4751}
4752
4753/*
4754 * Return a copy of the input string with substrings of the form ${VARNAME}
4755 * substituted with the value of the environment variable VARNAME. The
4756 * substitution always occurs, even if VARNAME is empty or the corresponding
4757 * environment variable undefined.
4758 */
4759static char *option_dup_subs(const char *opt)
4760{
4761 char out[OPT_LEN_MAX+1];
4762 char in[OPT_LEN_MAX+1];
4763 char *outptr = out;
4764 char *inptr = in;
4765 char *ch1, *ch2, *env;
4766 ssize_t nchr = OPT_LEN_MAX;
4767 size_t envlen;
4768
4769 if (strlen(opt) + 1 > OPT_LEN_MAX) {
4770 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
4771 return NULL;
4772 }
4773
4774 in[OPT_LEN_MAX] = '\0';
4775 strncpy(in, opt, OPT_LEN_MAX);
4776
4777 while (*inptr && nchr > 0) {
4778 if (inptr[0] == '$' && inptr[1] == '{') {
4779 ch2 = strchr(inptr, '}');
4780 if (ch2 && inptr+1 < ch2) {
4781 ch1 = inptr+2;
4782 inptr = ch2+1;
4783 *ch2 = '\0';
4784
4785 env = getenv(ch1);
4786 if (env) {
4787 envlen = strlen(env);
4788 if (envlen <= nchr) {
4789 memcpy(outptr, env, envlen);
4790 outptr += envlen;
4791 nchr -= envlen;
4792 }
4793 }
4794
4795 continue;
4796 }
4797 }
4798
4799 *outptr++ = *inptr++;
4800 --nchr;
4801 }
4802
4803 *outptr = '\0';
4804 return strdup(out);
892a6ffc
JA
4805}
4806
74929ac2
JA
4807/*
4808 * Look for reserved variable names and replace them with real values
4809 */
4810static char *fio_keyword_replace(char *opt)
4811{
4812 char *s;
4813 int i;
d0c814ec 4814 int docalc = 0;
74929ac2
JA
4815
4816 for (i = 0; fio_keywords[i].word != NULL; i++) {
4817 struct fio_keyword *kw = &fio_keywords[i];
4818
4819 while ((s = strstr(opt, kw->word)) != NULL) {
4820 char *new = malloc(strlen(opt) + 1);
4821 char *o_org = opt;
4822 int olen = s - opt;
4823 int len;
4824
4825 /*
4826 * Copy part of the string before the keyword and
4827 * sprintf() the replacement after it.
4828 */
4829 memcpy(new, opt, olen);
4830 len = sprintf(new + olen, "%s", kw->replace);
4831
4832 /*
4833 * If there's more in the original string, copy that
4834 * in too
4835 */
4836 opt += strlen(kw->word) + olen;
4837 if (strlen(opt))
4838 memcpy(new + olen + len, opt, opt - o_org - 1);
4839
4840 /*
4841 * replace opt and free the old opt
4842 */
4843 opt = new;
d0c814ec 4844 free(o_org);
7a958bd5 4845
d0c814ec 4846 docalc = 1;
74929ac2
JA
4847 }
4848 }
4849
d0c814ec
SL
4850 /*
4851 * Check for potential math and invoke bc, if possible
4852 */
4853 if (docalc)
4854 opt = bc_calc(opt);
4855
7a958bd5 4856 return opt;
74929ac2
JA
4857}
4858
d0c814ec
SL
4859static char **dup_and_sub_options(char **opts, int num_opts)
4860{
4861 int i;
4862 char **opts_copy = malloc(num_opts * sizeof(*opts));
4863 for (i = 0; i < num_opts; i++) {
4864 opts_copy[i] = option_dup_subs(opts[i]);
4865 if (!opts_copy[i])
4866 continue;
4867 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
4868 }
4869 return opts_copy;
4870}
4871
e15b023b 4872static void show_closest_option(const char *opt)
a2d027b9
JA
4873{
4874 int best_option, best_distance;
4875 int i, distance;
e15b023b
JA
4876 char *name;
4877
4878 if (!strlen(opt))
4879 return;
4880
4881 name = strdup(opt);
4882 i = 0;
4883 while (name[i] != '\0' && name[i] != '=')
4884 i++;
4885 name[i] = '\0';
a2d027b9
JA
4886
4887 best_option = -1;
4888 best_distance = INT_MAX;
4889 i = 0;
4890 while (fio_options[i].name) {
4891 distance = string_distance(name, fio_options[i].name);
4892 if (distance < best_distance) {
4893 best_distance = distance;
4894 best_option = i;
4895 }
4896 i++;
4897 }
4898
75e6bcba
JA
4899 if (best_option != -1 && string_distance_ok(name, best_distance) &&
4900 fio_options[best_option].type != FIO_OPT_UNSUPPORTED)
a2d027b9 4901 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
4902
4903 free(name);
a2d027b9
JA
4904}
4905
c2292325 4906int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 4907{
de890a1e 4908 int i, ret, unknown;
d0c814ec 4909 char **opts_copy;
3b8b7135 4910
9af4a244 4911 sort_options(opts, fio_options, num_opts);
d0c814ec 4912 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 4913
de890a1e 4914 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
9109883a 4915 const struct fio_option *o;
9af4a244 4916 int newret = parse_option(opts_copy[i], opts[i], fio_options,
a609f12a 4917 &o, &td->o, &td->opt_list);
d0c814ec 4918
a8523a6a
JA
4919 if (!newret && o)
4920 fio_option_mark_set(&td->o, o);
4921
de890a1e
SL
4922 if (opts_copy[i]) {
4923 if (newret && !o) {
4924 unknown++;
4925 continue;
4926 }
d0c814ec 4927 free(opts_copy[i]);
de890a1e
SL
4928 opts_copy[i] = NULL;
4929 }
4930
4931 ret |= newret;
4932 }
4933
4934 if (unknown) {
4935 ret |= ioengine_load(td);
4936 if (td->eo) {
4937 sort_options(opts_copy, td->io_ops->options, num_opts);
4938 opts = opts_copy;
4939 }
4940 for (i = 0; i < num_opts; i++) {
9109883a 4941 const struct fio_option *o = NULL;
de890a1e 4942 int newret = 1;
a2d027b9 4943
de890a1e
SL
4944 if (!opts_copy[i])
4945 continue;
4946
4947 if (td->eo)
4948 newret = parse_option(opts_copy[i], opts[i],
4949 td->io_ops->options, &o,
66e19a38 4950 td->eo, &td->opt_list);
de890a1e
SL
4951
4952 ret |= newret;
a2d027b9 4953 if (!o) {
de890a1e 4954 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
4955 show_closest_option(opts[i]);
4956 }
de890a1e
SL
4957 free(opts_copy[i]);
4958 opts_copy[i] = NULL;
4959 }
74929ac2 4960 }
3b8b7135 4961
d0c814ec 4962 free(opts_copy);
3b8b7135 4963 return ret;
214e1eca
JA
4964}
4965
4966int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
4967{
a8523a6a
JA
4968 int ret;
4969
a609f12a 4970 ret = parse_cmd_option(opt, val, fio_options, &td->o, &td->opt_list);
a8523a6a 4971 if (!ret) {
9109883a 4972 const struct fio_option *o;
a8523a6a 4973
9109883a 4974 o = find_option_c(fio_options, opt);
a8523a6a
JA
4975 if (o)
4976 fio_option_mark_set(&td->o, o);
4977 }
4978
4979 return ret;
214e1eca
JA
4980}
4981
de890a1e
SL
4982int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
4983 char *val)
4984{
d8b4f395
JA
4985 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
4986 &td->opt_list);
de890a1e
SL
4987}
4988
214e1eca
JA
4989void fio_fill_default_options(struct thread_data *td)
4990{
cb1402d6 4991 td->o.magic = OPT_MAGIC;
a609f12a 4992 fill_default_options(&td->o, fio_options);
214e1eca
JA
4993}
4994
4995int fio_show_option_help(const char *opt)
4996{
9af4a244 4997 return show_cmd_help(fio_options, opt);
214e1eca 4998}
d23bb327 4999
de890a1e
SL
5000/*
5001 * dupe FIO_OPT_STR_STORE options
5002 */
5003void fio_options_mem_dupe(struct thread_data *td)
5004{
53b5693d 5005 options_mem_dupe(fio_options, &td->o);
1647f592
JA
5006
5007 if (td->eo && td->io_ops) {
de890a1e 5008 void *oldeo = td->eo;
1647f592 5009
de890a1e
SL
5010 td->eo = malloc(td->io_ops->option_struct_size);
5011 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
53b5693d 5012 options_mem_dupe(td->io_ops->options, td->eo);
de890a1e
SL
5013 }
5014}
5015
d6978a32
JA
5016unsigned int fio_get_kb_base(void *data)
5017{
a609f12a
JA
5018 struct thread_data *td = cb_data_to_td(data);
5019 struct thread_options *o = &td->o;
d6978a32
JA
5020 unsigned int kb_base = 0;
5021
cb1402d6
JA
5022 /*
5023 * This is a hack... For private options, *data is not holding
5024 * a pointer to the thread_options, but to private data. This means
5025 * we can't safely dereference it, but magic is first so mem wise
5026 * it is valid. But this also means that if the job first sets
5027 * kb_base and expects that to be honored by private options,
5028 * it will be disappointed. We will return the global default
5029 * for this.
5030 */
5031 if (o && o->magic == OPT_MAGIC)
83ea422a 5032 kb_base = o->kb_base;
d6978a32
JA
5033 if (!kb_base)
5034 kb_base = 1024;
5035
5036 return kb_base;
5037}
9f988e2e 5038
9109883a 5039int add_option(const struct fio_option *o)
9f988e2e 5040{
07b3232d
JA
5041 struct fio_option *__o;
5042 int opt_index = 0;
5043
9af4a244 5044 __o = fio_options;
07b3232d
JA
5045 while (__o->name) {
5046 opt_index++;
5047 __o++;
5048 }
5049
7b504edd
JA
5050 if (opt_index + 1 == FIO_MAX_OPTS) {
5051 log_err("fio: FIO_MAX_OPTS is too small\n");
5052 return 1;
5053 }
5054
9af4a244 5055 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 5056 fio_options[opt_index + 1].name = NULL;
07b3232d 5057 return 0;
9f988e2e 5058}
e2de69da 5059
07b3232d 5060void invalidate_profile_options(const char *prof_name)
e2de69da 5061{
07b3232d 5062 struct fio_option *o;
e2de69da 5063
9af4a244 5064 o = fio_options;
07b3232d
JA
5065 while (o->name) {
5066 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
5067 o->type = FIO_OPT_INVALID;
5068 o->prof_name = NULL;
5069 }
5070 o++;
e2de69da
JA
5071 }
5072}
f5b6bb85
JA
5073
5074void add_opt_posval(const char *optname, const char *ival, const char *help)
5075{
5076 struct fio_option *o;
5077 unsigned int i;
5078
9af4a244 5079 o = find_option(fio_options, optname);
f5b6bb85
JA
5080 if (!o)
5081 return;
5082
5083 for (i = 0; i < PARSE_MAX_VP; i++) {
5084 if (o->posval[i].ival)
5085 continue;
5086
5087 o->posval[i].ival = ival;
5088 o->posval[i].help = help;
5089 break;
5090 }
5091}
5092
5093void del_opt_posval(const char *optname, const char *ival)
5094{
5095 struct fio_option *o;
5096 unsigned int i;
5097
9af4a244 5098 o = find_option(fio_options, optname);
f5b6bb85
JA
5099 if (!o)
5100 return;
5101
5102 for (i = 0; i < PARSE_MAX_VP; i++) {
5103 if (!o->posval[i].ival)
5104 continue;
5105 if (strcmp(o->posval[i].ival, ival))
5106 continue;
5107
5108 o->posval[i].ival = NULL;
5109 o->posval[i].help = NULL;
5110 }
5111}
7e356b2d
JA
5112
5113void fio_options_free(struct thread_data *td)
5114{
ca6336a8 5115 options_free(fio_options, &td->o);
de890a1e
SL
5116 if (td->eo && td->io_ops && td->io_ops->options) {
5117 options_free(td->io_ops->options, td->eo);
5118 free(td->eo);
5119 td->eo = NULL;
5120 }
7e356b2d 5121}
c504ee55
JA
5122
5123struct fio_option *fio_option_find(const char *name)
5124{
5125 return find_option(fio_options, name);
5126}
5127
f0e7f45a
JA
5128static struct fio_option *find_next_opt(struct thread_options *o,
5129 struct fio_option *from,
5130 unsigned int off1)
a8523a6a 5131{
f0e7f45a 5132 struct fio_option *opt;
a8523a6a 5133
f0e7f45a
JA
5134 if (!from)
5135 from = &fio_options[0];
5136 else
5137 from++;
5138
5139 opt = NULL;
5140 do {
5141 if (off1 == from->off1) {
5142 opt = from;
a8523a6a
JA
5143 break;
5144 }
f0e7f45a
JA
5145 from++;
5146 } while (from->name);
a8523a6a 5147
f0e7f45a
JA
5148 return opt;
5149}
5150
5151static int opt_is_set(struct thread_options *o, struct fio_option *opt)
5152{
5153 unsigned int opt_off, index, offset;
a8523a6a
JA
5154
5155 opt_off = opt - &fio_options[0];
5156 index = opt_off / (8 * sizeof(uint64_t));
5157 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 5158 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
5159}
5160
72f39748 5161bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
5162{
5163 struct fio_option *opt, *next;
5164
5165 next = NULL;
5166 while ((opt = find_next_opt(o, next, off1)) != NULL) {
5167 if (opt_is_set(o, opt))
72f39748 5168 return true;
f0e7f45a
JA
5169
5170 next = opt;
5171 }
5172
72f39748 5173 return false;
f0e7f45a
JA
5174}
5175
9109883a 5176void fio_option_mark_set(struct thread_options *o, const struct fio_option *opt)
a8523a6a
JA
5177{
5178 unsigned int opt_off, index, offset;
5179
5180 opt_off = opt - &fio_options[0];
5181 index = opt_off / (8 * sizeof(uint64_t));
5182 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 5183 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 5184}