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