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