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