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