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