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