fio: support NVMe streams
[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
65ca6791
VF
273 while ((v = strsep(&str, ",")) != NULL && i < FIO_MAX_DP_IDS)
274 td->o.dp_ids[i++] = strtoll(v, NULL, 0);
a7e8aae0
KB
275 free(p);
276
65ca6791
VF
277 qsort(td->o.dp_ids, i, sizeof(*td->o.dp_ids), fio_fdp_cmp);
278 td->o.dp_nr_ids = i;
a7e8aae0
KB
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 3712 {
65ca6791
VF
3713 .name = "dataplacement",
3714 .alias = "data_placement",
3715 .lname = "Data Placement interface",
d3e310c5 3716 .type = FIO_OPT_STR,
65ca6791
VF
3717 .off1 = offsetof(struct thread_options, dp_type),
3718 .help = "Data Placement interface to use",
3719 .def = "none",
3720 .category = FIO_OPT_C_IO,
3721 .group = FIO_OPT_G_INVALID,
3722 .posval = {
3723 { .ival = "none",
3724 .oval = FIO_DP_NONE,
3725 .help = "Do not specify a data placement interface",
3726 },
3727 { .ival = "fdp",
3728 .oval = FIO_DP_FDP,
3729 .help = "Use Flexible Data Placement interface",
3730 },
3731 { .ival = "streams",
3732 .oval = FIO_DP_STREAMS,
3733 .help = "Use Streams interface",
3734 },
3735 },
3736 },
3737 {
3738 .name = "plid_select",
3739 .alias = "fdp_pli_select",
3740 .lname = "Data Placement ID selection strategy",
3741 .type = FIO_OPT_STR,
3742 .off1 = offsetof(struct thread_options, dp_id_select),
3743 .help = "Strategy for selecting next Data Placement ID",
d3e310c5
AK
3744 .def = "roundrobin",
3745 .category = FIO_OPT_C_IO,
3746 .group = FIO_OPT_G_INVALID,
3747 .posval = {
3748 { .ival = "random",
65ca6791 3749 .oval = FIO_DP_RANDOM,
d3e310c5
AK
3750 .help = "Choose a Placement ID at random (uniform)",
3751 },
3752 { .ival = "roundrobin",
65ca6791 3753 .oval = FIO_DP_RR,
d3e310c5
AK
3754 .help = "Round robin select Placement IDs",
3755 },
3756 },
3757 },
a7e8aae0 3758 {
65ca6791
VF
3759 .name = "plids",
3760 .alias = "fdp_pli",
3761 .lname = "Stream IDs/Data Placement ID indices",
a7e8aae0
KB
3762 .type = FIO_OPT_STR,
3763 .cb = str_fdp_pli_cb,
65ca6791
VF
3764 .off1 = offsetof(struct thread_options, dp_ids),
3765 .help = "Sets which Data Placement ids to use (defaults to all for FDP)",
a7e8aae0
KB
3766 .hide = 1,
3767 .category = FIO_OPT_C_IO,
3768 .group = FIO_OPT_G_INVALID,
3769 },
214e1eca
JA
3770 {
3771 .name = "lockmem",
e8b0e958 3772 .lname = "Lock memory",
214e1eca 3773 .type = FIO_OPT_STR_VAL,
a609f12a 3774 .off1 = offsetof(struct thread_options, lockmem),
81c6b6cd 3775 .help = "Lock down this amount of memory (per worker)",
214e1eca 3776 .def = "0",
20eb06bd 3777 .interval = 1024 * 1024,
e8b0e958
JA
3778 .category = FIO_OPT_C_GENERAL,
3779 .group = FIO_OPT_G_INVALID,
214e1eca 3780 },
214e1eca
JA
3781 {
3782 .name = "rwmixread",
e8b0e958 3783 .lname = "Read/write mix read",
214e1eca 3784 .type = FIO_OPT_INT,
cb499fc4 3785 .cb = str_rwmix_read_cb,
a609f12a 3786 .off1 = offsetof(struct thread_options, rwmix[DDIR_READ]),
214e1eca
JA
3787 .maxval = 100,
3788 .help = "Percentage of mixed workload that is reads",
3789 .def = "50",
20eb06bd 3790 .interval = 5,
90265353 3791 .inverse = "rwmixwrite",
e8b0e958
JA
3792 .category = FIO_OPT_C_IO,
3793 .group = FIO_OPT_G_RWMIX,
214e1eca
JA
3794 },
3795 {
3796 .name = "rwmixwrite",
e8b0e958 3797 .lname = "Read/write mix write",
214e1eca 3798 .type = FIO_OPT_INT,
cb499fc4 3799 .cb = str_rwmix_write_cb,
a609f12a 3800 .off1 = offsetof(struct thread_options, rwmix[DDIR_WRITE]),
214e1eca
JA
3801 .maxval = 100,
3802 .help = "Percentage of mixed workload that is writes",
3803 .def = "50",
20eb06bd 3804 .interval = 5,
90265353 3805 .inverse = "rwmixread",
e8b0e958
JA
3806 .category = FIO_OPT_C_IO,
3807 .group = FIO_OPT_G_RWMIX,
214e1eca 3808 },
afdf9352
JA
3809 {
3810 .name = "rwmixcycle",
e8b0e958 3811 .lname = "Read/write mix cycle",
15ca150e 3812 .type = FIO_OPT_DEPRECATED,
e8b0e958
JA
3813 .category = FIO_OPT_C_IO,
3814 .group = FIO_OPT_G_RWMIX,
afdf9352 3815 },
214e1eca
JA
3816 {
3817 .name = "nice",
e8b0e958 3818 .lname = "Nice",
214e1eca 3819 .type = FIO_OPT_INT,
a609f12a 3820 .off1 = offsetof(struct thread_options, nice),
214e1eca 3821 .help = "Set job CPU nice value",
11fd6aa8
RC
3822 .minval = -20,
3823 .maxval = 19,
214e1eca 3824 .def = "0",
20eb06bd 3825 .interval = 1,
e8b0e958 3826 .category = FIO_OPT_C_GENERAL,
10860056 3827 .group = FIO_OPT_G_CRED,
214e1eca
JA
3828 },
3829#ifdef FIO_HAVE_IOPRIO
3830 {
3831 .name = "prio",
e8b0e958 3832 .lname = "I/O nice priority",
214e1eca 3833 .type = FIO_OPT_INT,
a609f12a 3834 .off1 = offsetof(struct thread_options, ioprio),
214e1eca 3835 .help = "Set job IO priority value",
1767bd34
TK
3836 .minval = IOPRIO_MIN_PRIO,
3837 .maxval = IOPRIO_MAX_PRIO,
20eb06bd 3838 .interval = 1,
e8b0e958 3839 .category = FIO_OPT_C_GENERAL,
10860056 3840 .group = FIO_OPT_G_CRED,
214e1eca 3841 },
32ef447a
TK
3842#else
3843 {
3844 .name = "prio",
3845 .lname = "I/O nice priority",
3846 .type = FIO_OPT_UNSUPPORTED,
3847 .help = "Your platform does not support IO priorities",
3848 },
3849#endif
3850#ifdef FIO_HAVE_IOPRIO_CLASS
3851#ifndef FIO_HAVE_IOPRIO
3852#error "FIO_HAVE_IOPRIO_CLASS requires FIO_HAVE_IOPRIO"
3853#endif
214e1eca
JA
3854 {
3855 .name = "prioclass",
e8b0e958 3856 .lname = "I/O nice priority class",
214e1eca 3857 .type = FIO_OPT_INT,
a609f12a 3858 .off1 = offsetof(struct thread_options, ioprio_class),
214e1eca 3859 .help = "Set job IO priority class",
1767bd34
TK
3860 .minval = IOPRIO_MIN_PRIO_CLASS,
3861 .maxval = IOPRIO_MAX_PRIO_CLASS,
20eb06bd 3862 .interval = 1,
e8b0e958 3863 .category = FIO_OPT_C_GENERAL,
10860056 3864 .group = FIO_OPT_G_CRED,
214e1eca 3865 },
860462da
DLM
3866 {
3867 .name = "priohint",
3868 .lname = "I/O nice priority hint",
3869 .type = FIO_OPT_INT,
3870 .off1 = offsetof(struct thread_options, ioprio_hint),
3871 .help = "Set job IO priority hint",
3872 .minval = IOPRIO_MIN_PRIO_HINT,
3873 .maxval = IOPRIO_MAX_PRIO_HINT,
3874 .interval = 1,
3875 .category = FIO_OPT_C_GENERAL,
3876 .group = FIO_OPT_G_CRED,
3877 },
a275c37a 3878#else
a275c37a
JA
3879 {
3880 .name = "prioclass",
3881 .lname = "I/O nice priority class",
3882 .type = FIO_OPT_UNSUPPORTED,
32ef447a 3883 .help = "Your platform does not support IO priority classes",
a275c37a 3884 },
860462da
DLM
3885 {
3886 .name = "priohint",
3887 .lname = "I/O nice priority hint",
3888 .type = FIO_OPT_UNSUPPORTED,
3889 .help = "Your platform does not support IO priority hints",
3890 },
214e1eca
JA
3891#endif
3892 {
3893 .name = "thinktime",
e8b0e958 3894 .lname = "Thinktime",
214e1eca 3895 .type = FIO_OPT_INT,
a609f12a 3896 .off1 = offsetof(struct thread_options, thinktime),
214e1eca
JA
3897 .help = "Idle time between IO buffers (usec)",
3898 .def = "0",
88038bc7 3899 .is_time = 1,
e8b0e958 3900 .category = FIO_OPT_C_IO,
3ceb458f 3901 .group = FIO_OPT_G_THINKTIME,
214e1eca
JA
3902 },
3903 {
3904 .name = "thinktime_spin",
e8b0e958 3905 .lname = "Thinktime spin",
214e1eca 3906 .type = FIO_OPT_INT,
a609f12a 3907 .off1 = offsetof(struct thread_options, thinktime_spin),
214e1eca
JA
3908 .help = "Start think time by spinning this amount (usec)",
3909 .def = "0",
88038bc7 3910 .is_time = 1,
afdf9352 3911 .parent = "thinktime",
d71c154c 3912 .hide = 1,
e8b0e958 3913 .category = FIO_OPT_C_IO,
3ceb458f 3914 .group = FIO_OPT_G_THINKTIME,
214e1eca 3915 },
0d8cc753
CL
3916 {
3917 .name = "thinkcycles",
3918 .lname = "Think cycles",
3919 .type = FIO_OPT_INT,
3920 .off1 = offsetof(struct thread_options, thinkcycles),
3921 .help = "Spin for a constant amount of cycles between requests",
3922 .def = "0",
3923 .parent = "thinktime",
3924 .hide = 1,
3925 .category = FIO_OPT_C_IO,
3926 .group = FIO_OPT_G_THINKTIME,
3927 },
214e1eca
JA
3928 {
3929 .name = "thinktime_blocks",
e8b0e958 3930 .lname = "Thinktime blocks",
214e1eca 3931 .type = FIO_OPT_INT,
a609f12a 3932 .off1 = offsetof(struct thread_options, thinktime_blocks),
214e1eca
JA
3933 .help = "IO buffer period between 'thinktime'",
3934 .def = "1",
afdf9352 3935 .parent = "thinktime",
d71c154c 3936 .hide = 1,
e8b0e958 3937 .category = FIO_OPT_C_IO,
3ceb458f 3938 .group = FIO_OPT_G_THINKTIME,
214e1eca 3939 },
33f42c20
HQ
3940 {
3941 .name = "thinktime_blocks_type",
3942 .lname = "Thinktime blocks type",
3943 .type = FIO_OPT_STR,
3944 .off1 = offsetof(struct thread_options, thinktime_blocks_type),
3945 .help = "How thinktime_blocks takes effect",
3946 .def = "complete",
3947 .category = FIO_OPT_C_IO,
3948 .group = FIO_OPT_G_THINKTIME,
3949 .posval = {
3950 { .ival = "complete",
3951 .oval = THINKTIME_BLOCKS_TYPE_COMPLETE,
3952 .help = "thinktime_blocks takes effect at the completion side",
3953 },
3954 {
3955 .ival = "issue",
3956 .oval = THINKTIME_BLOCKS_TYPE_ISSUE,
3957 .help = "thinktime_blocks takes effect at the issue side",
3958 },
3959 },
3960 .parent = "thinktime",
3961 },
f7942acd
SK
3962 {
3963 .name = "thinktime_iotime",
3964 .lname = "Thinktime interval",
3965 .type = FIO_OPT_INT,
3966 .off1 = offsetof(struct thread_options, thinktime_iotime),
3967 .help = "IO time interval between 'thinktime'",
3968 .def = "0",
3969 .parent = "thinktime",
3970 .hide = 1,
3971 .is_seconds = 1,
3972 .is_time = 1,
3973 .category = FIO_OPT_C_IO,
3974 .group = FIO_OPT_G_THINKTIME,
3975 },
214e1eca
JA
3976 {
3977 .name = "rate",
e8b0e958 3978 .lname = "I/O rate",
140a6888 3979 .type = FIO_OPT_ULL,
a609f12a
JA
3980 .off1 = offsetof(struct thread_options, rate[DDIR_READ]),
3981 .off2 = offsetof(struct thread_options, rate[DDIR_WRITE]),
3982 .off3 = offsetof(struct thread_options, rate[DDIR_TRIM]),
214e1eca 3983 .help = "Set bandwidth rate",
e8b0e958
JA
3984 .category = FIO_OPT_C_IO,
3985 .group = FIO_OPT_G_RATE,
214e1eca
JA
3986 },
3987 {
6d428bcd
JA
3988 .name = "rate_min",
3989 .alias = "ratemin",
e8b0e958 3990 .lname = "I/O min rate",
140a6888 3991 .type = FIO_OPT_ULL,
a609f12a
JA
3992 .off1 = offsetof(struct thread_options, ratemin[DDIR_READ]),
3993 .off2 = offsetof(struct thread_options, ratemin[DDIR_WRITE]),
3994 .off3 = offsetof(struct thread_options, ratemin[DDIR_TRIM]),
4e991c23 3995 .help = "Job must meet this rate or it will be shutdown",
afdf9352 3996 .parent = "rate",
d71c154c 3997 .hide = 1,
e8b0e958
JA
3998 .category = FIO_OPT_C_IO,
3999 .group = FIO_OPT_G_RATE,
4e991c23
JA
4000 },
4001 {
4002 .name = "rate_iops",
e8b0e958 4003 .lname = "I/O rate IOPS",
e01b22b8 4004 .type = FIO_OPT_INT,
a609f12a
JA
4005 .off1 = offsetof(struct thread_options, rate_iops[DDIR_READ]),
4006 .off2 = offsetof(struct thread_options, rate_iops[DDIR_WRITE]),
4007 .off3 = offsetof(struct thread_options, rate_iops[DDIR_TRIM]),
4e991c23 4008 .help = "Limit IO used to this number of IO operations/sec",
d71c154c 4009 .hide = 1,
e8b0e958
JA
4010 .category = FIO_OPT_C_IO,
4011 .group = FIO_OPT_G_RATE,
4e991c23
JA
4012 },
4013 {
4014 .name = "rate_iops_min",
e8b0e958 4015 .lname = "I/O min rate IOPS",
e01b22b8 4016 .type = FIO_OPT_INT,
a609f12a
JA
4017 .off1 = offsetof(struct thread_options, rate_iops_min[DDIR_READ]),
4018 .off2 = offsetof(struct thread_options, rate_iops_min[DDIR_WRITE]),
4019 .off3 = offsetof(struct thread_options, rate_iops_min[DDIR_TRIM]),
03e20d68 4020 .help = "Job must meet this rate or it will be shut down",
afdf9352 4021 .parent = "rate_iops",
d71c154c 4022 .hide = 1,
e8b0e958
JA
4023 .category = FIO_OPT_C_IO,
4024 .group = FIO_OPT_G_RATE,
214e1eca 4025 },
ff6bb260 4026 {
6de65959
JA
4027 .name = "rate_process",
4028 .lname = "Rate Process",
4029 .type = FIO_OPT_STR,
a609f12a 4030 .off1 = offsetof(struct thread_options, rate_process),
6de65959
JA
4031 .help = "What process controls how rated IO is managed",
4032 .def = "linear",
ff6bb260
SL
4033 .category = FIO_OPT_C_IO,
4034 .group = FIO_OPT_G_RATE,
6de65959
JA
4035 .posval = {
4036 { .ival = "linear",
4037 .oval = RATE_PROCESS_LINEAR,
4038 .help = "Linear rate of IO",
4039 },
4040 {
4041 .ival = "poisson",
4042 .oval = RATE_PROCESS_POISSON,
4043 .help = "Rate follows Poisson process",
4044 },
4045 },
4046 .parent = "rate",
ff6bb260 4047 },
214e1eca 4048 {
6d428bcd
JA
4049 .name = "rate_cycle",
4050 .alias = "ratecycle",
e8b0e958 4051 .lname = "I/O rate cycle",
214e1eca 4052 .type = FIO_OPT_INT,
a609f12a 4053 .off1 = offsetof(struct thread_options, ratecycle),
214e1eca
JA
4054 .help = "Window average for rate limits (msec)",
4055 .def = "1000",
afdf9352 4056 .parent = "rate",
d71c154c 4057 .hide = 1,
e8b0e958
JA
4058 .category = FIO_OPT_C_IO,
4059 .group = FIO_OPT_G_RATE,
214e1eca 4060 },
1a9bf814
JA
4061 {
4062 .name = "rate_ignore_thinktime",
4063 .lname = "Rate ignore thinktime",
4064 .type = FIO_OPT_BOOL,
4065 .off1 = offsetof(struct thread_options, rate_ign_think),
4066 .help = "Rated IO ignores thinktime settings",
4067 .parent = "rate",
4068 .category = FIO_OPT_C_IO,
4069 .group = FIO_OPT_G_RATE,
4070 },
15501535
JA
4071 {
4072 .name = "max_latency",
dd97d866 4073 .lname = "Max Latency (usec)",
f7cf63bf
VR
4074 .type = FIO_OPT_ULL,
4075 .off1 = offsetof(struct thread_options, max_latency[DDIR_READ]),
4076 .off2 = offsetof(struct thread_options, max_latency[DDIR_WRITE]),
4077 .off3 = offsetof(struct thread_options, max_latency[DDIR_TRIM]),
15501535 4078 .help = "Maximum tolerated IO latency (usec)",
88038bc7 4079 .is_time = 1,
1e5324e7 4080 .category = FIO_OPT_C_IO,
3e260a46
JA
4081 .group = FIO_OPT_G_LATPROF,
4082 },
4083 {
4084 .name = "latency_target",
4085 .lname = "Latency Target (usec)",
4086 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 4087 .off1 = offsetof(struct thread_options, latency_target),
3e260a46 4088 .help = "Ramp to max queue depth supporting this latency",
88038bc7 4089 .is_time = 1,
3e260a46
JA
4090 .category = FIO_OPT_C_IO,
4091 .group = FIO_OPT_G_LATPROF,
4092 },
4093 {
4094 .name = "latency_window",
4095 .lname = "Latency Window (usec)",
4096 .type = FIO_OPT_STR_VAL_TIME,
a609f12a 4097 .off1 = offsetof(struct thread_options, latency_window),
3e260a46 4098 .help = "Time to sustain latency_target",
88038bc7 4099 .is_time = 1,
3e260a46
JA
4100 .category = FIO_OPT_C_IO,
4101 .group = FIO_OPT_G_LATPROF,
4102 },
4103 {
4104 .name = "latency_percentile",
4105 .lname = "Latency Percentile",
4106 .type = FIO_OPT_FLOAT_LIST,
a609f12a 4107 .off1 = offsetof(struct thread_options, latency_percentile),
3e260a46
JA
4108 .help = "Percentile of IOs must be below latency_target",
4109 .def = "100",
4110 .maxlen = 1,
4111 .minfp = 0.0,
4112 .maxfp = 100.0,
4113 .category = FIO_OPT_C_IO,
4114 .group = FIO_OPT_G_LATPROF,
15501535 4115 },
e1bcd541
SL
4116 {
4117 .name = "latency_run",
4118 .lname = "Latency Run",
4119 .type = FIO_OPT_BOOL,
4120 .off1 = offsetof(struct thread_options, latency_run),
4121 .help = "Keep adjusting queue depth to match latency_target",
4122 .def = "0",
4123 .category = FIO_OPT_C_IO,
4124 .group = FIO_OPT_G_LATPROF,
4125 },
214e1eca
JA
4126 {
4127 .name = "invalidate",
e8b0e958 4128 .lname = "Cache invalidate",
214e1eca 4129 .type = FIO_OPT_BOOL,
a609f12a 4130 .off1 = offsetof(struct thread_options, invalidate_cache),
214e1eca
JA
4131 .help = "Invalidate buffer/page cache prior to running job",
4132 .def = "1",
e8b0e958 4133 .category = FIO_OPT_C_IO,
3ceb458f 4134 .group = FIO_OPT_G_IO_TYPE,
214e1eca
JA
4135 },
4136 {
4137 .name = "sync",
e8b0e958 4138 .lname = "Synchronous I/O",
eb9f8d7f 4139 .type = FIO_OPT_STR,
a609f12a 4140 .off1 = offsetof(struct thread_options, sync_io),
eb9f8d7f
AF
4141 .help = "Use synchronous write IO",
4142 .def = "none",
d71c154c 4143 .hide = 1,
e8b0e958 4144 .category = FIO_OPT_C_IO,
3ceb458f 4145 .group = FIO_OPT_G_IO_TYPE,
eb9f8d7f
AF
4146 .posval = {
4147 { .ival = "none",
4148 .oval = 0,
4149 },
4150 { .ival = "0",
4151 .oval = 0,
4152 },
4153 { .ival = "sync",
4154 .oval = O_SYNC,
4155 },
4156 { .ival = "1",
4157 .oval = O_SYNC,
4158 },
4159#ifdef O_DSYNC
4160 { .ival = "dsync",
4161 .oval = O_DSYNC,
4162 },
4163#endif
4164 },
214e1eca 4165 },
ae8e559e
JA
4166#ifdef FIO_HAVE_WRITE_HINT
4167 {
4168 .name = "write_hint",
4169 .lname = "Write hint",
4170 .type = FIO_OPT_STR,
4171 .off1 = offsetof(struct thread_options, write_hint),
4172 .help = "Set expected write life time",
4173 .category = FIO_OPT_C_ENGINE,
4174 .group = FIO_OPT_G_INVALID,
4175 .posval = {
4176 { .ival = "none",
4177 .oval = RWH_WRITE_LIFE_NONE,
4178 },
4179 { .ival = "short",
4180 .oval = RWH_WRITE_LIFE_SHORT,
4181 },
4182 { .ival = "medium",
4183 .oval = RWH_WRITE_LIFE_MEDIUM,
4184 },
4185 { .ival = "long",
4186 .oval = RWH_WRITE_LIFE_LONG,
4187 },
4188 { .ival = "extreme",
4189 .oval = RWH_WRITE_LIFE_EXTREME,
4190 },
4191 },
4192 },
4193#endif
214e1eca
JA
4194 {
4195 .name = "create_serialize",
e8b0e958 4196 .lname = "Create serialize",
214e1eca 4197 .type = FIO_OPT_BOOL,
a609f12a 4198 .off1 = offsetof(struct thread_options, create_serialize),
c2b8035f 4199 .help = "Serialize creation of job files",
214e1eca 4200 .def = "1",
e8b0e958
JA
4201 .category = FIO_OPT_C_FILE,
4202 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4203 },
4204 {
4205 .name = "create_fsync",
e8b0e958 4206 .lname = "Create fsync",
214e1eca 4207 .type = FIO_OPT_BOOL,
a609f12a 4208 .off1 = offsetof(struct thread_options, create_fsync),
03e20d68 4209 .help = "fsync file after creation",
214e1eca 4210 .def = "1",
e8b0e958
JA
4211 .category = FIO_OPT_C_FILE,
4212 .group = FIO_OPT_G_INVALID,
214e1eca 4213 },
814452bd
JA
4214 {
4215 .name = "create_on_open",
e8b0e958 4216 .lname = "Create on open",
814452bd 4217 .type = FIO_OPT_BOOL,
a609f12a 4218 .off1 = offsetof(struct thread_options, create_on_open),
814452bd
JA
4219 .help = "Create files when they are opened for IO",
4220 .def = "0",
e8b0e958
JA
4221 .category = FIO_OPT_C_FILE,
4222 .group = FIO_OPT_G_INVALID,
814452bd 4223 },
25460cf6
JA
4224 {
4225 .name = "create_only",
cce2fdfe 4226 .lname = "Create Only",
25460cf6 4227 .type = FIO_OPT_BOOL,
a609f12a 4228 .off1 = offsetof(struct thread_options, create_only),
25460cf6 4229 .help = "Only perform file creation phase",
d17fda71 4230 .category = FIO_OPT_C_FILE,
25460cf6
JA
4231 .def = "0",
4232 },
2378826d
JA
4233 {
4234 .name = "allow_file_create",
e81ecca3 4235 .lname = "Allow file create",
2378826d 4236 .type = FIO_OPT_BOOL,
a609f12a 4237 .off1 = offsetof(struct thread_options, allow_create),
2378826d
JA
4238 .help = "Permit fio to create files, if they don't exist",
4239 .def = "1",
4240 .category = FIO_OPT_C_FILE,
4241 .group = FIO_OPT_G_FILENAME,
4242 },
e81ecca3
JA
4243 {
4244 .name = "allow_mounted_write",
4245 .lname = "Allow mounted write",
4246 .type = FIO_OPT_BOOL,
a609f12a 4247 .off1 = offsetof(struct thread_options, allow_mounted_write),
e81ecca3
JA
4248 .help = "Allow writes to a mounted partition",
4249 .def = "0",
4250 .category = FIO_OPT_C_FILE,
4251 .group = FIO_OPT_G_FILENAME,
4252 },
0b9d69ec 4253 {
afad68f7 4254 .name = "pre_read",
e8b0e958 4255 .lname = "Pre-read files",
afad68f7 4256 .type = FIO_OPT_BOOL,
a609f12a 4257 .off1 = offsetof(struct thread_options, pre_read),
03e20d68 4258 .help = "Pre-read files before starting official testing",
afad68f7 4259 .def = "0",
e8b0e958
JA
4260 .category = FIO_OPT_C_FILE,
4261 .group = FIO_OPT_G_INVALID,
afad68f7 4262 },
214e1eca
JA
4263#ifdef FIO_HAVE_CPU_AFFINITY
4264 {
4265 .name = "cpumask",
e8b0e958 4266 .lname = "CPU mask",
214e1eca
JA
4267 .type = FIO_OPT_INT,
4268 .cb = str_cpumask_cb,
a609f12a 4269 .off1 = offsetof(struct thread_options, cpumask),
214e1eca 4270 .help = "CPU affinity mask",
e8b0e958 4271 .category = FIO_OPT_C_GENERAL,
10860056 4272 .group = FIO_OPT_G_CRED,
214e1eca 4273 },
d2e268b0
JA
4274 {
4275 .name = "cpus_allowed",
e8b0e958 4276 .lname = "CPUs allowed",
d2e268b0
JA
4277 .type = FIO_OPT_STR,
4278 .cb = str_cpus_allowed_cb,
a609f12a 4279 .off1 = offsetof(struct thread_options, cpumask),
d2e268b0 4280 .help = "Set CPUs allowed",
e8b0e958 4281 .category = FIO_OPT_C_GENERAL,
10860056 4282 .group = FIO_OPT_G_CRED,
d2e268b0 4283 },
c2acfbac
JA
4284 {
4285 .name = "cpus_allowed_policy",
4286 .lname = "CPUs allowed distribution policy",
4287 .type = FIO_OPT_STR,
a609f12a 4288 .off1 = offsetof(struct thread_options, cpus_allowed_policy),
c2acfbac
JA
4289 .help = "Distribution policy for cpus_allowed",
4290 .parent = "cpus_allowed",
4291 .prio = 1,
4292 .posval = {
4293 { .ival = "shared",
4294 .oval = FIO_CPUS_SHARED,
4295 .help = "Mask shared between threads",
4296 },
4297 { .ival = "split",
4298 .oval = FIO_CPUS_SPLIT,
4299 .help = "Mask split between threads",
4300 },
4301 },
4302 .category = FIO_OPT_C_GENERAL,
4303 .group = FIO_OPT_G_CRED,
4304 },
a275c37a
JA
4305#else
4306 {
4307 .name = "cpumask",
4308 .lname = "CPU mask",
4309 .type = FIO_OPT_UNSUPPORTED,
4310 .help = "Your platform does not support CPU affinities",
4311 },
4312 {
4313 .name = "cpus_allowed",
4314 .lname = "CPUs allowed",
4315 .type = FIO_OPT_UNSUPPORTED,
4316 .help = "Your platform does not support CPU affinities",
4317 },
4318 {
4319 .name = "cpus_allowed_policy",
4320 .lname = "CPUs allowed distribution policy",
4321 .type = FIO_OPT_UNSUPPORTED,
4322 .help = "Your platform does not support CPU affinities",
4323 },
d0b937ed 4324#endif
67bf9823 4325#ifdef CONFIG_LIBNUMA
d0b937ed
YR
4326 {
4327 .name = "numa_cpu_nodes",
cce2fdfe 4328 .lname = "NUMA CPU Nodes",
d0b937ed
YR
4329 .type = FIO_OPT_STR,
4330 .cb = str_numa_cpunodes_cb,
a609f12a 4331 .off1 = offsetof(struct thread_options, numa_cpunodes),
d0b937ed 4332 .help = "NUMA CPU nodes bind",
6be54b2d
JA
4333 .category = FIO_OPT_C_GENERAL,
4334 .group = FIO_OPT_G_INVALID,
d0b937ed
YR
4335 },
4336 {
4337 .name = "numa_mem_policy",
cce2fdfe 4338 .lname = "NUMA Memory Policy",
d0b937ed
YR
4339 .type = FIO_OPT_STR,
4340 .cb = str_numa_mpol_cb,
a609f12a 4341 .off1 = offsetof(struct thread_options, numa_memnodes),
d0b937ed 4342 .help = "NUMA memory policy setup",
6be54b2d
JA
4343 .category = FIO_OPT_C_GENERAL,
4344 .group = FIO_OPT_G_INVALID,
d0b937ed 4345 },
a275c37a
JA
4346#else
4347 {
4348 .name = "numa_cpu_nodes",
4349 .lname = "NUMA CPU Nodes",
4350 .type = FIO_OPT_UNSUPPORTED,
4351 .help = "Build fio with libnuma-dev(el) to enable this option",
4352 },
4353 {
4354 .name = "numa_mem_policy",
4355 .lname = "NUMA Memory Policy",
4356 .type = FIO_OPT_UNSUPPORTED,
4357 .help = "Build fio with libnuma-dev(el) to enable this option",
4358 },
03553853
YR
4359#endif
4360#ifdef CONFIG_CUDA
4361 {
4362 .name = "gpu_dev_id",
4363 .lname = "GPU device ID",
4364 .type = FIO_OPT_INT,
4365 .off1 = offsetof(struct thread_options, gpu_dev_id),
4366 .help = "Set GPU device ID for GPUDirect RDMA",
4367 .def = "0",
4368 .category = FIO_OPT_C_GENERAL,
4369 .group = FIO_OPT_G_INVALID,
4370 },
214e1eca
JA
4371#endif
4372 {
4373 .name = "end_fsync",
e8b0e958 4374 .lname = "End fsync",
214e1eca 4375 .type = FIO_OPT_BOOL,
a609f12a 4376 .off1 = offsetof(struct thread_options, end_fsync),
214e1eca
JA
4377 .help = "Include fsync at the end of job",
4378 .def = "0",
e8b0e958
JA
4379 .category = FIO_OPT_C_FILE,
4380 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4381 },
4382 {
4383 .name = "fsync_on_close",
e8b0e958 4384 .lname = "Fsync on close",
214e1eca 4385 .type = FIO_OPT_BOOL,
a609f12a 4386 .off1 = offsetof(struct thread_options, fsync_on_close),
214e1eca
JA
4387 .help = "fsync files on close",
4388 .def = "0",
e8b0e958
JA
4389 .category = FIO_OPT_C_FILE,
4390 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4391 },
4392 {
4393 .name = "unlink",
e8b0e958 4394 .lname = "Unlink file",
214e1eca 4395 .type = FIO_OPT_BOOL,
a609f12a 4396 .off1 = offsetof(struct thread_options, unlink),
214e1eca
JA
4397 .help = "Unlink created files after job has completed",
4398 .def = "0",
e8b0e958
JA
4399 .category = FIO_OPT_C_FILE,
4400 .group = FIO_OPT_G_INVALID,
214e1eca 4401 },
39c1c323 4402 {
4403 .name = "unlink_each_loop",
4404 .lname = "Unlink file after each loop of a job",
4405 .type = FIO_OPT_BOOL,
a609f12a 4406 .off1 = offsetof(struct thread_options, unlink_each_loop),
39c1c323 4407 .help = "Unlink created files after each loop in a job has completed",
4408 .def = "0",
4409 .category = FIO_OPT_C_FILE,
4410 .group = FIO_OPT_G_INVALID,
4411 },
214e1eca
JA
4412 {
4413 .name = "exitall",
e8b0e958 4414 .lname = "Exit-all on terminate",
214e1eca
JA
4415 .type = FIO_OPT_STR_SET,
4416 .cb = str_exitall_cb,
4417 .help = "Terminate all jobs when one exits",
e8b0e958 4418 .category = FIO_OPT_C_GENERAL,
a1f6afec 4419 .group = FIO_OPT_G_PROCESS,
214e1eca 4420 },
64402a8a
HW
4421 {
4422 .name = "exit_what",
4423 .lname = "What jobs to quit on terminate",
4424 .type = FIO_OPT_STR,
4425 .off1 = offsetof(struct thread_options, exit_what),
4426 .help = "Fine-grained control for exitall",
4427 .def = "group",
4428 .category = FIO_OPT_C_GENERAL,
4429 .group = FIO_OPT_G_PROCESS,
4430 .posval = {
4431 { .ival = "group",
4432 .oval = TERMINATE_GROUP,
4433 .help = "exit_all=1 default behaviour",
4434 },
4435 { .ival = "stonewall",
4436 .oval = TERMINATE_STONEWALL,
4437 .help = "quit all currently running jobs; continue with next stonewall",
4438 },
4439 { .ival = "all",
4440 .oval = TERMINATE_ALL,
4441 .help = "Quit everything",
4442 },
4443 },
4444 },
f9cafb12
JA
4445 {
4446 .name = "exitall_on_error",
4447 .lname = "Exit-all on terminate in error",
78abcf9b 4448 .type = FIO_OPT_STR_SET,
a609f12a 4449 .off1 = offsetof(struct thread_options, exitall_error),
f9cafb12
JA
4450 .help = "Terminate all jobs when one exits in error",
4451 .category = FIO_OPT_C_GENERAL,
4452 .group = FIO_OPT_G_PROCESS,
4453 },
214e1eca
JA
4454 {
4455 .name = "stonewall",
e8b0e958 4456 .lname = "Wait for previous",
d392365e 4457 .alias = "wait_for_previous",
214e1eca 4458 .type = FIO_OPT_STR_SET,
a609f12a 4459 .off1 = offsetof(struct thread_options, stonewall),
214e1eca 4460 .help = "Insert a hard barrier between this job and previous",
e8b0e958 4461 .category = FIO_OPT_C_GENERAL,
a1f6afec 4462 .group = FIO_OPT_G_PROCESS,
214e1eca 4463 },
b3d62a75
JA
4464 {
4465 .name = "new_group",
e8b0e958 4466 .lname = "New group",
b3d62a75 4467 .type = FIO_OPT_STR_SET,
a609f12a 4468 .off1 = offsetof(struct thread_options, new_group),
b3d62a75 4469 .help = "Mark the start of a new group (for reporting)",
e8b0e958 4470 .category = FIO_OPT_C_GENERAL,
a1f6afec 4471 .group = FIO_OPT_G_PROCESS,
b3d62a75 4472 },
214e1eca
JA
4473 {
4474 .name = "thread",
e8b0e958 4475 .lname = "Thread",
214e1eca 4476 .type = FIO_OPT_STR_SET,
a609f12a 4477 .off1 = offsetof(struct thread_options, use_thread),
20eb06bd 4478 .help = "Use threads instead of processes",
c8931876
JA
4479#ifdef CONFIG_NO_SHM
4480 .def = "1",
4481 .no_warn_def = 1,
4482#endif
e8b0e958 4483 .category = FIO_OPT_C_GENERAL,
a1f6afec 4484 .group = FIO_OPT_G_PROCESS,
214e1eca 4485 },
3a5db920
JA
4486 {
4487 .name = "per_job_logs",
cce2fdfe 4488 .lname = "Per Job Logs",
3a5db920 4489 .type = FIO_OPT_BOOL,
a609f12a 4490 .off1 = offsetof(struct thread_options, per_job_logs),
3a5db920
JA
4491 .help = "Include job number in generated log files or not",
4492 .def = "1",
4493 .category = FIO_OPT_C_LOG,
4494 .group = FIO_OPT_G_INVALID,
4495 },
214e1eca
JA
4496 {
4497 .name = "write_bw_log",
e8b0e958 4498 .lname = "Write bandwidth log",
dded427c 4499 .type = FIO_OPT_STR,
a609f12a 4500 .off1 = offsetof(struct thread_options, bw_log_file),
dded427c 4501 .cb = str_write_bw_log_cb,
214e1eca 4502 .help = "Write log of bandwidth during run",
e8b0e958
JA
4503 .category = FIO_OPT_C_LOG,
4504 .group = FIO_OPT_G_INVALID,
214e1eca
JA
4505 },
4506 {
4507 .name = "write_lat_log",
e8b0e958 4508 .lname = "Write latency log",
dded427c 4509 .type = FIO_OPT_STR,
a609f12a 4510 .off1 = offsetof(struct thread_options, lat_log_file),
dded427c 4511 .cb = str_write_lat_log_cb,
214e1eca 4512 .help = "Write log of latency during run",
e8b0e958
JA
4513 .category = FIO_OPT_C_LOG,
4514 .group = FIO_OPT_G_INVALID,
214e1eca 4515 },
c8eeb9df
JA
4516 {
4517 .name = "write_iops_log",
e8b0e958 4518 .lname = "Write IOPS log",
dded427c 4519 .type = FIO_OPT_STR,
a609f12a 4520 .off1 = offsetof(struct thread_options, iops_log_file),
dded427c 4521 .cb = str_write_iops_log_cb,
c8eeb9df 4522 .help = "Write log of IOPS during run",
e8b0e958
JA
4523 .category = FIO_OPT_C_LOG,
4524 .group = FIO_OPT_G_INVALID,
c8eeb9df 4525 },
0a852a50
DLM
4526 {
4527 .name = "log_entries",
4528 .lname = "Log entries",
4529 .type = FIO_OPT_INT,
4530 .off1 = offsetof(struct thread_options, log_entries),
4531 .help = "Initial number of entries in a job IO log",
4532 .def = __fio_stringify(DEF_LOG_ENTRIES),
4533 .minval = DEF_LOG_ENTRIES,
4534 .maxval = MAX_LOG_ENTRIES,
4535 .category = FIO_OPT_C_LOG,
4536 .group = FIO_OPT_G_INVALID,
4537 },
b8bc8cba
JA
4538 {
4539 .name = "log_avg_msec",
e8b0e958 4540 .lname = "Log averaging (msec)",
b8bc8cba 4541 .type = FIO_OPT_INT,
a609f12a 4542 .off1 = offsetof(struct thread_options, log_avg_msec),
b8bc8cba
JA
4543 .help = "Average bw/iops/lat logs over this period of time",
4544 .def = "0",
e8b0e958 4545 .category = FIO_OPT_C_LOG,
1e613c9c
KC
4546 .group = FIO_OPT_G_INVALID,
4547 },
4548 {
4549 .name = "log_hist_msec",
4550 .lname = "Log histograms (msec)",
4551 .type = FIO_OPT_INT,
a609f12a 4552 .off1 = offsetof(struct thread_options, log_hist_msec),
1e613c9c
KC
4553 .help = "Dump completion latency histograms at frequency of this time value",
4554 .def = "0",
4555 .category = FIO_OPT_C_LOG,
4556 .group = FIO_OPT_G_INVALID,
4557 },
4558 {
4559 .name = "log_hist_coarseness",
4560 .lname = "Histogram logs coarseness",
4561 .type = FIO_OPT_INT,
a609f12a 4562 .off1 = offsetof(struct thread_options, log_hist_coarseness),
1e613c9c
KC
4563 .help = "Integer in range [0,6]. Higher coarseness outputs"
4564 " fewer histogram bins per sample. The number of bins for"
4565 " these are [1216, 608, 304, 152, 76, 38, 19] respectively.",
4566 .def = "0",
4567 .category = FIO_OPT_C_LOG,
4568 .group = FIO_OPT_G_INVALID,
4569 },
4570 {
4571 .name = "write_hist_log",
4572 .lname = "Write latency histogram logs",
dded427c 4573 .type = FIO_OPT_STR,
a609f12a 4574 .off1 = offsetof(struct thread_options, hist_log_file),
dded427c 4575 .cb = str_write_hist_log_cb,
1e613c9c
KC
4576 .help = "Write log of latency histograms during run",
4577 .category = FIO_OPT_C_LOG,
e8b0e958 4578 .group = FIO_OPT_G_INVALID,
b8bc8cba 4579 },
e6989e10 4580 {
0e14633c
AK
4581 .name = "log_window_value",
4582 .alias = "log_max_value",
4583 .lname = "Log maximum, average or both values",
4584 .type = FIO_OPT_STR,
a609f12a 4585 .off1 = offsetof(struct thread_options, log_max),
0e14633c
AK
4586 .help = "Log max, average or both sample in a window",
4587 .def = "avg",
e6989e10
JA
4588 .category = FIO_OPT_C_LOG,
4589 .group = FIO_OPT_G_INVALID,
0e14633c
AK
4590 .posval = {
4591 { .ival = "avg",
4592 .oval = IO_LOG_SAMPLE_AVG,
4593 .help = "Log average value over the window",
4594 },
4595 { .ival = "max",
4596 .oval = IO_LOG_SAMPLE_MAX,
4597 .help = "Log maximum value in the window",
4598 },
4599 { .ival = "both",
4600 .oval = IO_LOG_SAMPLE_BOTH,
4601 .help = "Log both average and maximum values over the window"
4602 },
4603 /* Compatibility with former boolean values */
4604 { .ival = "0",
4605 .oval = IO_LOG_SAMPLE_AVG,
4606 .help = "Alias for 'avg'",
4607 },
4608 { .ival = "1",
4609 .oval = IO_LOG_SAMPLE_MAX,
4610 .help = "Alias for 'max'",
4611 },
4612 },
e6989e10 4613 },
ae588852
JA
4614 {
4615 .name = "log_offset",
4616 .lname = "Log offset of IO",
4617 .type = FIO_OPT_BOOL,
a609f12a 4618 .off1 = offsetof(struct thread_options, log_offset),
ae588852
JA
4619 .help = "Include offset of IO for each log entry",
4620 .def = "0",
4621 .category = FIO_OPT_C_LOG,
4622 .group = FIO_OPT_G_INVALID,
4623 },
03ec570f
DLM
4624 {
4625 .name = "log_prio",
4626 .lname = "Log priority of IO",
4627 .type = FIO_OPT_BOOL,
4628 .off1 = offsetof(struct thread_options, log_prio),
4629 .help = "Include priority value of IO for each log entry",
4630 .def = "0",
4631 .category = FIO_OPT_C_LOG,
4632 .group = FIO_OPT_G_INVALID,
4633 },
aee2ab67
JA
4634#ifdef CONFIG_ZLIB
4635 {
4636 .name = "log_compression",
4637 .lname = "Log compression",
4638 .type = FIO_OPT_INT,
a609f12a 4639 .off1 = offsetof(struct thread_options, log_gz),
aee2ab67 4640 .help = "Log in compressed chunks of this size",
9919b27b 4641 .minval = 1024ULL,
aee2ab67
JA
4642 .maxval = 512 * 1024 * 1024ULL,
4643 .category = FIO_OPT_C_LOG,
4644 .group = FIO_OPT_G_INVALID,
4645 },
c08f9fe2
JA
4646#ifdef FIO_HAVE_CPU_AFFINITY
4647 {
4648 .name = "log_compression_cpus",
4649 .lname = "Log Compression CPUs",
4650 .type = FIO_OPT_STR,
4651 .cb = str_log_cpus_allowed_cb,
a609f12a 4652 .off1 = offsetof(struct thread_options, log_gz_cpumask),
c08f9fe2
JA
4653 .parent = "log_compression",
4654 .help = "Limit log compression to these CPUs",
4655 .category = FIO_OPT_C_LOG,
4656 .group = FIO_OPT_G_INVALID,
4657 },
a275c37a
JA
4658#else
4659 {
4660 .name = "log_compression_cpus",
4661 .lname = "Log Compression CPUs",
4662 .type = FIO_OPT_UNSUPPORTED,
4663 .help = "Your platform does not support CPU affinities",
4664 },
c08f9fe2 4665#endif
b26317c9
JA
4666 {
4667 .name = "log_store_compressed",
4668 .lname = "Log store compressed",
4669 .type = FIO_OPT_BOOL,
a609f12a 4670 .off1 = offsetof(struct thread_options, log_gz_store),
b26317c9
JA
4671 .help = "Store logs in a compressed format",
4672 .category = FIO_OPT_C_LOG,
4673 .group = FIO_OPT_G_INVALID,
4674 },
a275c37a
JA
4675#else
4676 {
4677 .name = "log_compression",
4678 .lname = "Log compression",
4679 .type = FIO_OPT_UNSUPPORTED,
4680 .help = "Install libz-dev(el) to get compression support",
4681 },
4682 {
4683 .name = "log_store_compressed",
4684 .lname = "Log store compressed",
4685 .type = FIO_OPT_UNSUPPORTED,
4686 .help = "Install libz-dev(el) to get compression support",
4687 },
aee2ab67 4688#endif
d5b3cfd4 4689 {
4690 .name = "log_alternate_epoch",
d252275b 4691 .alias = "log_unix_epoch",
d5b3cfd4 4692 .lname = "Log epoch alternate",
4693 .type = FIO_OPT_BOOL,
4694 .off1 = offsetof(struct thread_options, log_alternate_epoch),
4695 .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.",
4696 .category = FIO_OPT_C_LOG,
4697 .group = FIO_OPT_G_INVALID,
4698 },
4699 {
4700 .name = "log_alternate_epoch_clock_id",
4701 .lname = "Log alternate epoch clock_id",
4702 .type = FIO_OPT_INT,
4703 .off1 = offsetof(struct thread_options, log_alternate_epoch_clock_id),
d252275b 4704 .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 4705 .category = FIO_OPT_C_LOG,
4706 .group = FIO_OPT_G_INVALID,
4707 },
66347cfa
DE
4708 {
4709 .name = "block_error_percentiles",
4710 .lname = "Block error percentiles",
4711 .type = FIO_OPT_BOOL,
a609f12a 4712 .off1 = offsetof(struct thread_options, block_error_hist),
66347cfa
DE
4713 .help = "Record trim block errors and make a histogram",
4714 .def = "0",
4715 .category = FIO_OPT_C_LOG,
4716 .group = FIO_OPT_G_INVALID,
4717 },
c504ee55
JA
4718 {
4719 .name = "bwavgtime",
4720 .lname = "Bandwidth average time",
4721 .type = FIO_OPT_INT,
a609f12a 4722 .off1 = offsetof(struct thread_options, bw_avg_time),
c504ee55
JA
4723 .help = "Time window over which to calculate bandwidth"
4724 " (msec)",
4725 .def = "500",
4726 .parent = "write_bw_log",
4727 .hide = 1,
4728 .interval = 100,
4729 .category = FIO_OPT_C_LOG,
4730 .group = FIO_OPT_G_INVALID,
4731 },
4732 {
4733 .name = "iopsavgtime",
4734 .lname = "IOPS average time",
4735 .type = FIO_OPT_INT,
a609f12a 4736 .off1 = offsetof(struct thread_options, iops_avg_time),
c504ee55
JA
4737 .help = "Time window over which to calculate IOPS (msec)",
4738 .def = "500",
4739 .parent = "write_iops_log",
4740 .hide = 1,
4741 .interval = 100,
4742 .category = FIO_OPT_C_LOG,
4743 .group = FIO_OPT_G_INVALID,
4744 },
214e1eca
JA
4745 {
4746 .name = "group_reporting",
e8b0e958 4747 .lname = "Group reporting",
d2507043 4748 .type = FIO_OPT_STR_SET,
a609f12a 4749 .off1 = offsetof(struct thread_options, group_reporting),
214e1eca 4750 .help = "Do reporting on a per-group basis",
10860056 4751 .category = FIO_OPT_C_STAT,
e8b0e958 4752 .group = FIO_OPT_G_INVALID,
214e1eca 4753 },
8243be59
JA
4754 {
4755 .name = "stats",
4756 .lname = "Stats",
4757 .type = FIO_OPT_BOOL,
4758 .off1 = offsetof(struct thread_options, stats),
4759 .help = "Enable collection of stats",
4760 .def = "1",
4761 .category = FIO_OPT_C_STAT,
4762 .group = FIO_OPT_G_INVALID,
4763 },
e9459e5a
JA
4764 {
4765 .name = "zero_buffers",
e8b0e958 4766 .lname = "Zero I/O buffers",
e9459e5a 4767 .type = FIO_OPT_STR_SET,
a609f12a 4768 .off1 = offsetof(struct thread_options, zero_buffers),
e9459e5a 4769 .help = "Init IO buffers to all zeroes",
e8b0e958 4770 .category = FIO_OPT_C_IO,
3ceb458f 4771 .group = FIO_OPT_G_IO_BUF,
e9459e5a 4772 },
5973cafb
JA
4773 {
4774 .name = "refill_buffers",
e8b0e958 4775 .lname = "Refill I/O buffers",
5973cafb 4776 .type = FIO_OPT_STR_SET,
a609f12a 4777 .off1 = offsetof(struct thread_options, refill_buffers),
5973cafb 4778 .help = "Refill IO buffers on every IO submit",
e8b0e958 4779 .category = FIO_OPT_C_IO,
3ceb458f 4780 .group = FIO_OPT_G_IO_BUF,
5973cafb 4781 },
fd68418e
JA
4782 {
4783 .name = "scramble_buffers",
e8b0e958 4784 .lname = "Scramble I/O buffers",
fd68418e 4785 .type = FIO_OPT_BOOL,
a609f12a 4786 .off1 = offsetof(struct thread_options, scramble_buffers),
fd68418e
JA
4787 .help = "Slightly scramble buffers on every IO submit",
4788 .def = "1",
e8b0e958 4789 .category = FIO_OPT_C_IO,
3ceb458f 4790 .group = FIO_OPT_G_IO_BUF,
fd68418e 4791 },
ce35b1ec
JA
4792 {
4793 .name = "buffer_pattern",
4794 .lname = "Buffer pattern",
4795 .type = FIO_OPT_STR,
4796 .cb = str_buffer_pattern_cb,
a609f12a 4797 .off1 = offsetof(struct thread_options, buffer_pattern),
ce35b1ec
JA
4798 .help = "Fill pattern for IO buffers",
4799 .category = FIO_OPT_C_IO,
4800 .group = FIO_OPT_G_IO_BUF,
4801 },
9c42684e
JA
4802 {
4803 .name = "buffer_compress_percentage",
e8b0e958 4804 .lname = "Buffer compression percentage",
9c42684e 4805 .type = FIO_OPT_INT,
bedc9dc2 4806 .cb = str_buffer_compress_cb,
a609f12a 4807 .off1 = offsetof(struct thread_options, compress_percentage),
9c42684e 4808 .maxval = 100,
e7f5de90 4809 .minval = 0,
9c42684e 4810 .help = "How compressible the buffer is (approximately)",
20eb06bd 4811 .interval = 5,
e8b0e958 4812 .category = FIO_OPT_C_IO,
3ceb458f 4813 .group = FIO_OPT_G_IO_BUF,
9c42684e 4814 },
f97a43a1
JA
4815 {
4816 .name = "buffer_compress_chunk",
e8b0e958 4817 .lname = "Buffer compression chunk size",
f97a43a1 4818 .type = FIO_OPT_INT,
a609f12a 4819 .off1 = offsetof(struct thread_options, compress_chunk),
207b18e4 4820 .parent = "buffer_compress_percentage",
d71c154c 4821 .hide = 1,
f97a43a1 4822 .help = "Size of compressible region in buffer",
1de80624 4823 .def = "512",
20eb06bd 4824 .interval = 256,
e8b0e958 4825 .category = FIO_OPT_C_IO,
3ceb458f 4826 .group = FIO_OPT_G_IO_BUF,
f97a43a1 4827 },
5c94b008
JA
4828 {
4829 .name = "dedupe_percentage",
4830 .lname = "Dedupe percentage",
4831 .type = FIO_OPT_INT,
4832 .cb = str_dedupe_cb,
a609f12a 4833 .off1 = offsetof(struct thread_options, dedupe_percentage),
5c94b008
JA
4834 .maxval = 100,
4835 .minval = 0,
4836 .help = "Percentage of buffers that are dedupable",
4837 .interval = 1,
4838 .category = FIO_OPT_C_IO,
4839 .group = FIO_OPT_G_IO_BUF,
4840 },
c49cfc76
BD
4841 {
4842 .name = "dedupe_global",
4843 .lname = "Global deduplication",
4844 .type = FIO_OPT_BOOL,
4845 .off1 = offsetof(struct thread_options, dedupe_global),
4846 .help = "Share deduplication buffers across jobs",
4847 .def = "0",
4848 .category = FIO_OPT_C_IO,
4849 .group = FIO_OPT_G_IO_BUF,
4850 },
0d71aa98
BD
4851 {
4852 .name = "dedupe_mode",
4853 .lname = "Dedupe mode",
4854 .help = "Mode for the deduplication buffer generation",
4855 .type = FIO_OPT_STR,
4856 .off1 = offsetof(struct thread_options, dedupe_mode),
4857 .parent = "dedupe_percentage",
4858 .def = "repeat",
4859 .category = FIO_OPT_C_IO,
4860 .group = FIO_OPT_G_IO_BUF,
4861 .posval = {
4862 { .ival = "repeat",
4863 .oval = DEDUPE_MODE_REPEAT,
4864 .help = "repeat previous page",
4865 },
4866 { .ival = "working_set",
4867 .oval = DEDUPE_MODE_WORKING_SET,
4868 .help = "choose a page randomly from limited working set defined in dedupe_working_set_percentage",
4869 },
4870 },
4871 },
4872 {
4873 .name = "dedupe_working_set_percentage",
4874 .lname = "Dedupe working set percentage",
4875 .help = "Dedupe working set size in percentages from file or device size used to generate dedupe patterns from",
4876 .type = FIO_OPT_INT,
4877 .off1 = offsetof(struct thread_options, dedupe_working_set_percentage),
4878 .parent = "dedupe_percentage",
4879 .def = "5",
4880 .maxval = 100,
4881 .minval = 0,
4882 .category = FIO_OPT_C_IO,
4883 .group = FIO_OPT_G_IO_BUF,
4884 },
83349190
YH
4885 {
4886 .name = "clat_percentiles",
e8b0e958 4887 .lname = "Completion latency percentiles",
83349190 4888 .type = FIO_OPT_BOOL,
a609f12a 4889 .off1 = offsetof(struct thread_options, clat_percentiles),
83349190 4890 .help = "Enable the reporting of completion latency percentiles",
467b35ed 4891 .def = "1",
b599759b
JA
4892 .category = FIO_OPT_C_STAT,
4893 .group = FIO_OPT_G_INVALID,
4894 },
4895 {
4896 .name = "lat_percentiles",
4897 .lname = "IO latency percentiles",
4898 .type = FIO_OPT_BOOL,
4899 .off1 = offsetof(struct thread_options, lat_percentiles),
4900 .help = "Enable the reporting of IO latency percentiles",
4901 .def = "0",
56440e63
VF
4902 .category = FIO_OPT_C_STAT,
4903 .group = FIO_OPT_G_INVALID,
4904 },
4905 {
4906 .name = "slat_percentiles",
4907 .lname = "Submission latency percentiles",
4908 .type = FIO_OPT_BOOL,
4909 .off1 = offsetof(struct thread_options, slat_percentiles),
4910 .help = "Enable the reporting of submission latency percentiles",
4911 .def = "0",
e8b0e958
JA
4912 .category = FIO_OPT_C_STAT,
4913 .group = FIO_OPT_G_INVALID,
83349190
YH
4914 },
4915 {
4916 .name = "percentile_list",
66347cfa 4917 .lname = "Percentile list",
83349190 4918 .type = FIO_OPT_FLOAT_LIST,
a609f12a
JA
4919 .off1 = offsetof(struct thread_options, percentile_list),
4920 .off2 = offsetof(struct thread_options, percentile_precision),
66347cfa
DE
4921 .help = "Specify a custom list of percentiles to report for "
4922 "completion latency and block errors",
fd112d34 4923 .def = "1:5:10:20:30:40:50:60:70:80:90:95:99:99.5:99.9:99.95:99.99",
83349190
YH
4924 .maxlen = FIO_IO_U_LIST_MAX_LEN,
4925 .minfp = 0.0,
4926 .maxfp = 100.0,
e8b0e958
JA
4927 .category = FIO_OPT_C_STAT,
4928 .group = FIO_OPT_G_INVALID,
e883cb35
JF
4929 },
4930 {
4931 .name = "significant_figures",
4932 .lname = "Significant figures",
4933 .type = FIO_OPT_INT,
4934 .off1 = offsetof(struct thread_options, sig_figs),
4935 .maxval = 10,
4936 .minval = 1,
4937 .help = "Significant figures for output-format set to normal",
4938 .def = "4",
4939 .interval = 1,
4940 .category = FIO_OPT_C_STAT,
4941 .group = FIO_OPT_G_INVALID,
83349190
YH
4942 },
4943
0a839f30
JA
4944#ifdef FIO_HAVE_DISK_UTIL
4945 {
4946 .name = "disk_util",
e8b0e958 4947 .lname = "Disk utilization",
0a839f30 4948 .type = FIO_OPT_BOOL,
a609f12a 4949 .off1 = offsetof(struct thread_options, do_disk_util),
f66ab3c8 4950 .help = "Log disk utilization statistics",
0a839f30 4951 .def = "1",
e8b0e958
JA
4952 .category = FIO_OPT_C_STAT,
4953 .group = FIO_OPT_G_INVALID,
0a839f30 4954 },
a275c37a
JA
4955#else
4956 {
4957 .name = "disk_util",
4958 .lname = "Disk utilization",
4959 .type = FIO_OPT_UNSUPPORTED,
4960 .help = "Your platform does not support disk utilization",
4961 },
0a839f30 4962#endif
993bf48b
JA
4963 {
4964 .name = "gtod_reduce",
e8b0e958 4965 .lname = "Reduce gettimeofday() calls",
993bf48b
JA
4966 .type = FIO_OPT_BOOL,
4967 .help = "Greatly reduce number of gettimeofday() calls",
4968 .cb = str_gtod_reduce_cb,
4969 .def = "0",
a4ed77fe 4970 .hide_on_set = 1,
e8b0e958
JA
4971 .category = FIO_OPT_C_STAT,
4972 .group = FIO_OPT_G_INVALID,
993bf48b 4973 },
02af0988
JA
4974 {
4975 .name = "disable_lat",
e8b0e958 4976 .lname = "Disable all latency stats",
02af0988 4977 .type = FIO_OPT_BOOL,
a609f12a 4978 .off1 = offsetof(struct thread_options, disable_lat),
02af0988
JA
4979 .help = "Disable latency numbers",
4980 .parent = "gtod_reduce",
d71c154c 4981 .hide = 1,
02af0988 4982 .def = "0",
e8b0e958
JA
4983 .category = FIO_OPT_C_STAT,
4984 .group = FIO_OPT_G_INVALID,
02af0988 4985 },
9520ebb9
JA
4986 {
4987 .name = "disable_clat",
e8b0e958 4988 .lname = "Disable completion latency stats",
9520ebb9 4989 .type = FIO_OPT_BOOL,
a609f12a 4990 .off1 = offsetof(struct thread_options, disable_clat),
9520ebb9 4991 .help = "Disable completion latency numbers",
993bf48b 4992 .parent = "gtod_reduce",
d71c154c 4993 .hide = 1,
9520ebb9 4994 .def = "0",
e8b0e958
JA
4995 .category = FIO_OPT_C_STAT,
4996 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
4997 },
4998 {
4999 .name = "disable_slat",
e8b0e958 5000 .lname = "Disable submission latency stats",
9520ebb9 5001 .type = FIO_OPT_BOOL,
a609f12a 5002 .off1 = offsetof(struct thread_options, disable_slat),
03e20d68 5003 .help = "Disable submission latency numbers",
993bf48b 5004 .parent = "gtod_reduce",
d71c154c 5005 .hide = 1,
9520ebb9 5006 .def = "0",
e8b0e958
JA
5007 .category = FIO_OPT_C_STAT,
5008 .group = FIO_OPT_G_INVALID,
9520ebb9
JA
5009 },
5010 {
5011 .name = "disable_bw_measurement",
afd2ceff 5012 .alias = "disable_bw",
e8b0e958 5013 .lname = "Disable bandwidth stats",
9520ebb9 5014 .type = FIO_OPT_BOOL,
a609f12a 5015 .off1 = offsetof(struct thread_options, disable_bw),
9520ebb9 5016 .help = "Disable bandwidth logging",
993bf48b 5017 .parent = "gtod_reduce",
d71c154c 5018 .hide = 1,
9520ebb9 5019 .def = "0",
e8b0e958
JA
5020 .category = FIO_OPT_C_STAT,
5021 .group = FIO_OPT_G_INVALID,
9520ebb9 5022 },
be4ecfdf
JA
5023 {
5024 .name = "gtod_cpu",
e8b0e958 5025 .lname = "Dedicated gettimeofday() CPU",
be4ecfdf 5026 .type = FIO_OPT_INT,
a609f12a 5027 .off1 = offsetof(struct thread_options, gtod_cpu),
03e20d68 5028 .help = "Set up dedicated gettimeofday() thread on this CPU",
29d43ff9 5029 .verify = gtod_cpu_verify,
e8b0e958 5030 .category = FIO_OPT_C_GENERAL,
10860056 5031 .group = FIO_OPT_G_CLOCK,
be4ecfdf 5032 },
12d325ca 5033 {
5034 .name = "job_start_clock_id",
5035 .lname = "Job start clock_id",
5036 .type = FIO_OPT_INT,
5037 .off1 = offsetof(struct thread_options, job_start_clock_id),
5038 .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",
5039 .verify = gtod_cpu_verify,
5040 .category = FIO_OPT_C_GENERAL,
5041 .group = FIO_OPT_G_CLOCK,
5042 },
771e58be
JA
5043 {
5044 .name = "unified_rw_reporting",
cce2fdfe 5045 .lname = "Unified RW Reporting",
5cb8a8cd 5046 .type = FIO_OPT_STR,
a609f12a 5047 .off1 = offsetof(struct thread_options, unified_rw_rep),
771e58be 5048 .help = "Unify reporting across data direction",
5cb8a8cd 5049 .def = "none",
90b7a96d
JA
5050 .category = FIO_OPT_C_GENERAL,
5051 .group = FIO_OPT_G_INVALID,
5cb8a8cd
BP
5052 .posval = {
5053 { .ival = "none",
5054 .oval = UNIFIED_SPLIT,
5055 .help = "Normal statistics reporting",
5056 },
5057 { .ival = "mixed",
5058 .oval = UNIFIED_MIXED,
5059 .help = "Statistics are summed per data direction and reported together",
5060 },
5061 { .ival = "both",
5062 .oval = UNIFIED_BOTH,
5063 .help = "Statistics are reported normally, followed by the mixed statistics"
5064 },
5065 /* Compatibility with former boolean values */
5066 { .ival = "0",
5067 .oval = UNIFIED_SPLIT,
5068 .help = "Alias for 'none'",
5069 },
5070 { .ival = "1",
5071 .oval = UNIFIED_MIXED,
5072 .help = "Alias for 'mixed'",
5073 },
5074 { .ival = "2",
5075 .oval = UNIFIED_BOTH,
5076 .help = "Alias for 'both'",
5077 },
5078 },
771e58be 5079 },
f2bba182
RR
5080 {
5081 .name = "continue_on_error",
e8b0e958 5082 .lname = "Continue on error",
06842027 5083 .type = FIO_OPT_STR,
a609f12a 5084 .off1 = offsetof(struct thread_options, continue_on_error),
03e20d68 5085 .help = "Continue on non-fatal errors during IO",
06842027 5086 .def = "none",
e8b0e958 5087 .category = FIO_OPT_C_GENERAL,
bc3f552f 5088 .group = FIO_OPT_G_ERR,
06842027
SL
5089 .posval = {
5090 { .ival = "none",
5091 .oval = ERROR_TYPE_NONE,
5092 .help = "Exit when an error is encountered",
5093 },
5094 { .ival = "read",
5095 .oval = ERROR_TYPE_READ,
5096 .help = "Continue on read errors only",
5097 },
5098 { .ival = "write",
5099 .oval = ERROR_TYPE_WRITE,
5100 .help = "Continue on write errors only",
5101 },
5102 { .ival = "io",
5103 .oval = ERROR_TYPE_READ | ERROR_TYPE_WRITE,
5104 .help = "Continue on any IO errors",
5105 },
5106 { .ival = "verify",
5107 .oval = ERROR_TYPE_VERIFY,
5108 .help = "Continue on verify errors only",
5109 },
5110 { .ival = "all",
5111 .oval = ERROR_TYPE_ANY,
5112 .help = "Continue on all io and verify errors",
5113 },
5114 { .ival = "0",
5115 .oval = ERROR_TYPE_NONE,
5116 .help = "Alias for 'none'",
5117 },
5118 { .ival = "1",
5119 .oval = ERROR_TYPE_ANY,
5120 .help = "Alias for 'all'",
5121 },
5122 },
f2bba182 5123 },
8b28bd41
DM
5124 {
5125 .name = "ignore_error",
cce2fdfe 5126 .lname = "Ignore Error",
8b28bd41
DM
5127 .type = FIO_OPT_STR,
5128 .cb = str_ignore_error_cb,
a609f12a 5129 .off1 = offsetof(struct thread_options, ignore_error_nr),
8b28bd41
DM
5130 .help = "Set a specific list of errors to ignore",
5131 .parent = "rw",
a94eb99a 5132 .category = FIO_OPT_C_GENERAL,
bc3f552f 5133 .group = FIO_OPT_G_ERR,
8b28bd41
DM
5134 },
5135 {
5136 .name = "error_dump",
cce2fdfe 5137 .lname = "Error Dump",
8b28bd41 5138 .type = FIO_OPT_BOOL,
a609f12a 5139 .off1 = offsetof(struct thread_options, error_dump),
8b28bd41
DM
5140 .def = "0",
5141 .help = "Dump info on each error",
a94eb99a 5142 .category = FIO_OPT_C_GENERAL,
bc3f552f 5143 .group = FIO_OPT_G_ERR,
8b28bd41 5144 },
9ac8a797
JA
5145 {
5146 .name = "profile",
e8b0e958 5147 .lname = "Profile",
79d16311 5148 .type = FIO_OPT_STR_STORE,
a609f12a 5149 .off1 = offsetof(struct thread_options, profile),
9ac8a797 5150 .help = "Select a specific builtin performance test",
13fca827 5151 .category = FIO_OPT_C_PROFILE,
e8b0e958 5152 .group = FIO_OPT_G_INVALID,
9ac8a797 5153 },
a696fa2a
JA
5154 {
5155 .name = "cgroup",
e8b0e958 5156 .lname = "Cgroup",
a696fa2a 5157 .type = FIO_OPT_STR_STORE,
a609f12a 5158 .off1 = offsetof(struct thread_options, cgroup),
a696fa2a 5159 .help = "Add job to cgroup of this name",
e8b0e958 5160 .category = FIO_OPT_C_GENERAL,
a1f6afec
JA
5161 .group = FIO_OPT_G_CGROUP,
5162 },
5163 {
5164 .name = "cgroup_nodelete",
5165 .lname = "Cgroup no-delete",
5166 .type = FIO_OPT_BOOL,
a609f12a 5167 .off1 = offsetof(struct thread_options, cgroup_nodelete),
a1f6afec
JA
5168 .help = "Do not delete cgroups after job completion",
5169 .def = "0",
5170 .parent = "cgroup",
5171 .category = FIO_OPT_C_GENERAL,
5172 .group = FIO_OPT_G_CGROUP,
a696fa2a
JA
5173 },
5174 {
5175 .name = "cgroup_weight",
e8b0e958 5176 .lname = "Cgroup weight",
a696fa2a 5177 .type = FIO_OPT_INT,
a609f12a 5178 .off1 = offsetof(struct thread_options, cgroup_weight),
a696fa2a
JA
5179 .help = "Use given weight for cgroup",
5180 .minval = 100,
5181 .maxval = 1000,
a1f6afec 5182 .parent = "cgroup",
e8b0e958 5183 .category = FIO_OPT_C_GENERAL,
a1f6afec 5184 .group = FIO_OPT_G_CGROUP,
7de87099 5185 },
e0b0d892
JA
5186 {
5187 .name = "uid",
e8b0e958 5188 .lname = "User ID",
e0b0d892 5189 .type = FIO_OPT_INT,
a609f12a 5190 .off1 = offsetof(struct thread_options, uid),
e0b0d892 5191 .help = "Run job with this user ID",
e8b0e958 5192 .category = FIO_OPT_C_GENERAL,
10860056 5193 .group = FIO_OPT_G_CRED,
e0b0d892
JA
5194 },
5195 {
5196 .name = "gid",
e8b0e958 5197 .lname = "Group ID",
e0b0d892 5198 .type = FIO_OPT_INT,
a609f12a 5199 .off1 = offsetof(struct thread_options, gid),
e0b0d892 5200 .help = "Run job with this group ID",
e8b0e958 5201 .category = FIO_OPT_C_GENERAL,
10860056 5202 .group = FIO_OPT_G_CRED,
e0b0d892 5203 },
a1f6afec
JA
5204 {
5205 .name = "kb_base",
5206 .lname = "KB Base",
41dd12d6 5207 .type = FIO_OPT_STR,
a609f12a 5208 .off1 = offsetof(struct thread_options, kb_base),
a1f6afec
JA
5209 .prio = 1,
5210 .def = "1024",
ba9c7219
JA
5211 .posval = {
5212 { .ival = "1024",
5213 .oval = 1024,
d694a6a7 5214 .help = "Inputs invert IEC and SI prefixes (for compatibility); outputs prefer binary",
ba9c7219
JA
5215 },
5216 { .ival = "1000",
5217 .oval = 1000,
d694a6a7 5218 .help = "Inputs use IEC and SI prefixes; outputs prefer SI",
ba9c7219
JA
5219 },
5220 },
d694a6a7 5221 .help = "Unit prefix interpretation for quantities of data (IEC and SI)",
a1f6afec
JA
5222 .category = FIO_OPT_C_GENERAL,
5223 .group = FIO_OPT_G_INVALID,
5224 },
cf3a0518
JA
5225 {
5226 .name = "unit_base",
d694a6a7 5227 .lname = "Unit for quantities of data (Bits or Bytes)",
92a1a1d7 5228 .type = FIO_OPT_STR,
a609f12a 5229 .off1 = offsetof(struct thread_options, unit_base),
cf3a0518 5230 .prio = 1,
71a08258
JA
5231 .posval = {
5232 { .ival = "0",
41a87019 5233 .oval = N2S_NONE,
71a08258
JA
5234 .help = "Auto-detect",
5235 },
5236 { .ival = "8",
41a87019 5237 .oval = N2S_BYTEPERSEC,
71a08258
JA
5238 .help = "Normal (byte based)",
5239 },
5240 { .ival = "1",
41a87019 5241 .oval = N2S_BITPERSEC,
71a08258
JA
5242 .help = "Bit based",
5243 },
5244 },
cf3a0518
JA
5245 .help = "Bit multiple of result summary data (8 for byte, 1 for bit)",
5246 .category = FIO_OPT_C_GENERAL,
5247 .group = FIO_OPT_G_INVALID,
5248 },
3ceb458f
JA
5249 {
5250 .name = "hugepage-size",
5251 .lname = "Hugepage size",
5252 .type = FIO_OPT_INT,
a609f12a 5253 .off1 = offsetof(struct thread_options, hugepage_size),
3ceb458f
JA
5254 .help = "When using hugepages, specify size of each page",
5255 .def = __fio_stringify(FIO_HUGE_PAGE),
5256 .interval = 1024 * 1024,
5257 .category = FIO_OPT_C_GENERAL,
5258 .group = FIO_OPT_G_INVALID,
5259 },
9e684a49
DE
5260 {
5261 .name = "flow_id",
e8b0e958 5262 .lname = "I/O flow ID",
9e684a49 5263 .type = FIO_OPT_INT,
a609f12a 5264 .off1 = offsetof(struct thread_options, flow_id),
9e684a49
DE
5265 .help = "The flow index ID to use",
5266 .def = "0",
e8b0e958
JA
5267 .category = FIO_OPT_C_IO,
5268 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5269 },
5270 {
5271 .name = "flow",
e8b0e958 5272 .lname = "I/O flow weight",
20c7a244 5273 .type = FIO_OPT_INT,
a609f12a 5274 .off1 = offsetof(struct thread_options, flow),
9e684a49
DE
5275 .help = "Weight for flow control of this job",
5276 .parent = "flow_id",
d71c154c 5277 .hide = 1,
9e684a49 5278 .def = "0",
d4e74fda 5279 .maxval = FLOW_MAX_WEIGHT,
e8b0e958
JA
5280 .category = FIO_OPT_C_IO,
5281 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5282 },
5283 {
5284 .name = "flow_watermark",
e8b0e958 5285 .lname = "I/O flow watermark",
d4e74fda 5286 .type = FIO_OPT_SOFT_DEPRECATED,
e8b0e958
JA
5287 .category = FIO_OPT_C_IO,
5288 .group = FIO_OPT_G_IO_FLOW,
9e684a49
DE
5289 },
5290 {
5291 .name = "flow_sleep",
e8b0e958 5292 .lname = "I/O flow sleep",
9e684a49 5293 .type = FIO_OPT_INT,
a609f12a 5294 .off1 = offsetof(struct thread_options, flow_sleep),
9e684a49
DE
5295 .help = "How many microseconds to sleep after being held"
5296 " back by the flow control mechanism",
5297 .parent = "flow_id",
d71c154c 5298 .hide = 1,
9e684a49 5299 .def = "0",
e8b0e958
JA
5300 .category = FIO_OPT_C_IO,
5301 .group = FIO_OPT_G_IO_FLOW,
9e684a49 5302 },
16e56d25
VF
5303 {
5304 .name = "steadystate",
5305 .lname = "Steady state threshold",
5306 .alias = "ss",
5307 .type = FIO_OPT_STR,
2c5d94bc 5308 .off1 = offsetof(struct thread_options, ss_state),
16e56d25
VF
5309 .cb = str_steadystate_cb,
5310 .help = "Define the criterion and limit to judge when a job has reached steady state",
5311 .def = "iops_slope:0.01%",
5312 .posval = {
5313 { .ival = "iops",
f0c50c66 5314 .oval = FIO_SS_IOPS,
16e56d25
VF
5315 .help = "maximum mean deviation of IOPS measurements",
5316 },
5317 { .ival = "iops_slope",
f0c50c66 5318 .oval = FIO_SS_IOPS_SLOPE,
16e56d25
VF
5319 .help = "slope calculated from IOPS measurements",
5320 },
5321 { .ival = "bw",
f0c50c66 5322 .oval = FIO_SS_BW,
16e56d25
VF
5323 .help = "maximum mean deviation of bandwidth measurements",
5324 },
5325 {
5326 .ival = "bw_slope",
f0c50c66 5327 .oval = FIO_SS_BW_SLOPE,
16e56d25
VF
5328 .help = "slope calculated from bandwidth measurements",
5329 },
5330 },
5331 .category = FIO_OPT_C_GENERAL,
5332 .group = FIO_OPT_G_RUNTIME,
5333 },
5334 {
5335 .name = "steadystate_duration",
5336 .lname = "Steady state duration",
5337 .alias = "ss_dur",
915ca980 5338 .parent = "steadystate",
16e56d25
VF
5339 .type = FIO_OPT_STR_VAL_TIME,
5340 .off1 = offsetof(struct thread_options, ss_dur),
5341 .help = "Stop workload upon attaining steady state for specified duration",
5342 .def = "0",
5343 .is_seconds = 1,
5344 .is_time = 1,
5345 .category = FIO_OPT_C_GENERAL,
5346 .group = FIO_OPT_G_RUNTIME,
5347 },
5348 {
5349 .name = "steadystate_ramp_time",
5350 .lname = "Steady state ramp time",
5351 .alias = "ss_ramp",
915ca980 5352 .parent = "steadystate",
16e56d25
VF
5353 .type = FIO_OPT_STR_VAL_TIME,
5354 .off1 = offsetof(struct thread_options, ss_ramp_time),
5355 .help = "Delay before initiation of data collection for steady state job termination testing",
5356 .def = "0",
5357 .is_seconds = 1,
5358 .is_time = 1,
5359 .category = FIO_OPT_C_GENERAL,
5360 .group = FIO_OPT_G_RUNTIME,
5361 },
90e678ba
CL
5362 {
5363 .name = "steadystate_check_interval",
5364 .lname = "Steady state check interval",
5365 .alias = "ss_interval",
5366 .parent = "steadystate",
5367 .type = FIO_OPT_STR_VAL_TIME,
5368 .off1 = offsetof(struct thread_options, ss_check_interval),
5369 .help = "Polling interval for the steady state check (too low means steadystate will not converge)",
5370 .def = "1",
5371 .is_seconds = 1,
5372 .is_time = 1,
5373 .category = FIO_OPT_C_GENERAL,
5374 .group = FIO_OPT_G_RUNTIME,
5375 },
214e1eca
JA
5376 {
5377 .name = NULL,
5378 },
5379};
5380
17af15d4 5381static void add_to_lopt(struct option *lopt, struct fio_option *o,
de890a1e 5382 const char *name, int val)
9f81736c 5383{
17af15d4 5384 lopt->name = (char *) name;
de890a1e 5385 lopt->val = val;
9f81736c 5386 if (o->type == FIO_OPT_STR_SET)
ff52be3d 5387 lopt->has_arg = optional_argument;
9f81736c
JA
5388 else
5389 lopt->has_arg = required_argument;
5390}
5391
de890a1e
SL
5392static void options_to_lopts(struct fio_option *opts,
5393 struct option *long_options,
5394 int i, int option_type)
214e1eca 5395{
de890a1e 5396 struct fio_option *o = &opts[0];
214e1eca 5397 while (o->name) {
de890a1e 5398 add_to_lopt(&long_options[i], o, o->name, option_type);
17af15d4
JA
5399 if (o->alias) {
5400 i++;
de890a1e 5401 add_to_lopt(&long_options[i], o, o->alias, option_type);
17af15d4 5402 }
214e1eca
JA
5403
5404 i++;
5405 o++;
5406 assert(i < FIO_NR_OPTIONS);
5407 }
5408}
5409
de890a1e
SL
5410void fio_options_set_ioengine_opts(struct option *long_options,
5411 struct thread_data *td)
5412{
5413 unsigned int i;
5414
5415 i = 0;
5416 while (long_options[i].name) {
5417 if (long_options[i].val == FIO_GETOPT_IOENGINE) {
5418 memset(&long_options[i], 0, sizeof(*long_options));
5419 break;
5420 }
5421 i++;
5422 }
5423
5424 /*
5425 * Just clear out the prior ioengine options.
5426 */
5427 if (!td || !td->eo)
5428 return;
5429
5430 options_to_lopts(td->io_ops->options, long_options, i,
5431 FIO_GETOPT_IOENGINE);
5432}
5433
5434void fio_options_dup_and_init(struct option *long_options)
5435{
5436 unsigned int i;
5437
9af4a244 5438 options_init(fio_options);
de890a1e
SL
5439
5440 i = 0;
5441 while (long_options[i].name)
5442 i++;
5443
9af4a244 5444 options_to_lopts(fio_options, long_options, i, FIO_GETOPT_JOB);
de890a1e
SL
5445}
5446
74929ac2
JA
5447struct fio_keyword {
5448 const char *word;
5449 const char *desc;
5450 char *replace;
5451};
5452
5453static struct fio_keyword fio_keywords[] = {
5454 {
5455 .word = "$pagesize",
5456 .desc = "Page size in the system",
5457 },
5458 {
5459 .word = "$mb_memory",
5460 .desc = "Megabytes of memory online",
5461 },
5462 {
5463 .word = "$ncpus",
5464 .desc = "Number of CPUs online in the system",
5465 },
5466 {
5467 .word = NULL,
5468 },
5469};
5470
af1dc266
JA
5471void fio_keywords_exit(void)
5472{
5473 struct fio_keyword *kw;
5474
5475 kw = &fio_keywords[0];
5476 while (kw->word) {
5477 free(kw->replace);
5478 kw->replace = NULL;
5479 kw++;
5480 }
5481}
5482
74929ac2
JA
5483void fio_keywords_init(void)
5484{
3b2e1464 5485 unsigned long long mb_memory;
74929ac2
JA
5486 char buf[128];
5487 long l;
5488
a4cfc477 5489 sprintf(buf, "%lu", (unsigned long) page_size);
74929ac2
JA
5490 fio_keywords[0].replace = strdup(buf);
5491
8eb016d3 5492 mb_memory = os_phys_mem() / (1024 * 1024);
3b2e1464 5493 sprintf(buf, "%llu", mb_memory);
74929ac2
JA
5494 fio_keywords[1].replace = strdup(buf);
5495
40f61ec7 5496 l = cpus_configured();
74929ac2
JA
5497 sprintf(buf, "%lu", l);
5498 fio_keywords[2].replace = strdup(buf);
5499}
5500
892a6ffc
JA
5501#define BC_APP "bc"
5502
5503static char *bc_calc(char *str)
5504{
d0c814ec 5505 char buf[128], *tmp;
892a6ffc
JA
5506 FILE *f;
5507 int ret;
5508
5509 /*
5510 * No math, just return string
5511 */
d0c814ec
SL
5512 if ((!strchr(str, '+') && !strchr(str, '-') && !strchr(str, '*') &&
5513 !strchr(str, '/')) || strchr(str, '\''))
892a6ffc
JA
5514 return str;
5515
5516 /*
5517 * Split option from value, we only need to calculate the value
5518 */
5519 tmp = strchr(str, '=');
5520 if (!tmp)
5521 return str;
5522
5523 tmp++;
892a6ffc 5524
d0c814ec
SL
5525 /*
5526 * Prevent buffer overflows; such a case isn't reasonable anyway
5527 */
5528 if (strlen(str) >= 128 || strlen(tmp) > 100)
5529 return str;
892a6ffc
JA
5530
5531 sprintf(buf, "which %s > /dev/null", BC_APP);
5532 if (system(buf)) {
5533 log_err("fio: bc is needed for performing math\n");
892a6ffc
JA
5534 return NULL;
5535 }
5536
d0c814ec 5537 sprintf(buf, "echo '%s' | %s", tmp, BC_APP);
892a6ffc 5538 f = popen(buf, "r");
3c3ed070 5539 if (!f)
892a6ffc 5540 return NULL;
892a6ffc 5541
d0c814ec 5542 ret = fread(&buf[tmp - str], 1, 128 - (tmp - str), f);
1d824f37
JA
5543 if (ret <= 0) {
5544 pclose(f);
892a6ffc 5545 return NULL;
1d824f37 5546 }
892a6ffc 5547
892a6ffc 5548 pclose(f);
d0c814ec
SL
5549 buf[(tmp - str) + ret - 1] = '\0';
5550 memcpy(buf, str, tmp - str);
892a6ffc 5551 free(str);
d0c814ec
SL
5552 return strdup(buf);
5553}
5554
5555/*
5556 * Return a copy of the input string with substrings of the form ${VARNAME}
5557 * substituted with the value of the environment variable VARNAME. The
5558 * substitution always occurs, even if VARNAME is empty or the corresponding
5559 * environment variable undefined.
5560 */
b4f5e72f 5561char *fio_option_dup_subs(const char *opt)
d0c814ec
SL
5562{
5563 char out[OPT_LEN_MAX+1];
5564 char in[OPT_LEN_MAX+1];
5565 char *outptr = out;
5566 char *inptr = in;
5567 char *ch1, *ch2, *env;
5568 ssize_t nchr = OPT_LEN_MAX;
5569 size_t envlen;
5570
5571 if (strlen(opt) + 1 > OPT_LEN_MAX) {
5572 log_err("OPT_LEN_MAX (%d) is too small\n", OPT_LEN_MAX);
5573 return NULL;
5574 }
5575
36833fb0 5576 snprintf(in, sizeof(in), "%s", opt);
d0c814ec
SL
5577
5578 while (*inptr && nchr > 0) {
5579 if (inptr[0] == '$' && inptr[1] == '{') {
5580 ch2 = strchr(inptr, '}');
5581 if (ch2 && inptr+1 < ch2) {
5582 ch1 = inptr+2;
5583 inptr = ch2+1;
5584 *ch2 = '\0';
5585
5586 env = getenv(ch1);
5587 if (env) {
5588 envlen = strlen(env);
5589 if (envlen <= nchr) {
5590 memcpy(outptr, env, envlen);
5591 outptr += envlen;
5592 nchr -= envlen;
5593 }
5594 }
5595
5596 continue;
5597 }
5598 }
5599
5600 *outptr++ = *inptr++;
5601 --nchr;
5602 }
5603
5604 *outptr = '\0';
5605 return strdup(out);
892a6ffc
JA
5606}
5607
74929ac2
JA
5608/*
5609 * Look for reserved variable names and replace them with real values
5610 */
5611static char *fio_keyword_replace(char *opt)
5612{
5613 char *s;
5614 int i;
d0c814ec 5615 int docalc = 0;
74929ac2
JA
5616
5617 for (i = 0; fio_keywords[i].word != NULL; i++) {
5618 struct fio_keyword *kw = &fio_keywords[i];
5619
5620 while ((s = strstr(opt, kw->word)) != NULL) {
33153428 5621 char *new = calloc(strlen(opt) + 1, 1);
74929ac2
JA
5622 char *o_org = opt;
5623 int olen = s - opt;
5624 int len;
5625
5626 /*
5627 * Copy part of the string before the keyword and
5628 * sprintf() the replacement after it.
5629 */
5630 memcpy(new, opt, olen);
5631 len = sprintf(new + olen, "%s", kw->replace);
5632
5633 /*
5634 * If there's more in the original string, copy that
5635 * in too
5636 */
85b9ee7e 5637 opt += olen + strlen(kw->word);
33153428 5638 /* keeps final zero thanks to calloc */
74929ac2 5639 if (strlen(opt))
85b9ee7e 5640 memcpy(new + olen + len, opt, strlen(opt));
74929ac2
JA
5641
5642 /*
5643 * replace opt and free the old opt
5644 */
5645 opt = new;
d0c814ec 5646 free(o_org);
7a958bd5 5647
d0c814ec 5648 docalc = 1;
74929ac2
JA
5649 }
5650 }
5651
d0c814ec
SL
5652 /*
5653 * Check for potential math and invoke bc, if possible
5654 */
5655 if (docalc)
5656 opt = bc_calc(opt);
5657
7a958bd5 5658 return opt;
74929ac2
JA
5659}
5660
d0c814ec
SL
5661static char **dup_and_sub_options(char **opts, int num_opts)
5662{
5663 int i;
5664 char **opts_copy = malloc(num_opts * sizeof(*opts));
5665 for (i = 0; i < num_opts; i++) {
b4f5e72f 5666 opts_copy[i] = fio_option_dup_subs(opts[i]);
d0c814ec
SL
5667 if (!opts_copy[i])
5668 continue;
5669 opts_copy[i] = fio_keyword_replace(opts_copy[i]);
5670 }
5671 return opts_copy;
5672}
5673
e15b023b 5674static void show_closest_option(const char *opt)
a2d027b9
JA
5675{
5676 int best_option, best_distance;
5677 int i, distance;
e15b023b
JA
5678 char *name;
5679
5680 if (!strlen(opt))
5681 return;
5682
5683 name = strdup(opt);
5684 i = 0;
5685 while (name[i] != '\0' && name[i] != '=')
5686 i++;
5687 name[i] = '\0';
a2d027b9
JA
5688
5689 best_option = -1;
5690 best_distance = INT_MAX;
5691 i = 0;
5692 while (fio_options[i].name) {
5693 distance = string_distance(name, fio_options[i].name);
5694 if (distance < best_distance) {
5695 best_distance = distance;
5696 best_option = i;
5697 }
5698 i++;
5699 }
5700
75e6bcba
JA
5701 if (best_option != -1 && string_distance_ok(name, best_distance) &&
5702 fio_options[best_option].type != FIO_OPT_UNSUPPORTED)
a2d027b9 5703 log_err("Did you mean %s?\n", fio_options[best_option].name);
e15b023b
JA
5704
5705 free(name);
a2d027b9
JA
5706}
5707
c2292325 5708int fio_options_parse(struct thread_data *td, char **opts, int num_opts)
214e1eca 5709{
de890a1e 5710 int i, ret, unknown;
d0c814ec 5711 char **opts_copy;
3b8b7135 5712
9af4a244 5713 sort_options(opts, fio_options, num_opts);
d0c814ec 5714 opts_copy = dup_and_sub_options(opts, num_opts);
3b8b7135 5715
de890a1e 5716 for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
9109883a 5717 const struct fio_option *o;
9af4a244 5718 int newret = parse_option(opts_copy[i], opts[i], fio_options,
a609f12a 5719 &o, &td->o, &td->opt_list);
d0c814ec 5720
a8523a6a
JA
5721 if (!newret && o)
5722 fio_option_mark_set(&td->o, o);
5723
de890a1e
SL
5724 if (opts_copy[i]) {
5725 if (newret && !o) {
5726 unknown++;
5727 continue;
5728 }
d0c814ec 5729 free(opts_copy[i]);
de890a1e
SL
5730 opts_copy[i] = NULL;
5731 }
5732
5733 ret |= newret;
5734 }
5735
5736 if (unknown) {
5737 ret |= ioengine_load(td);
5738 if (td->eo) {
5739 sort_options(opts_copy, td->io_ops->options, num_opts);
5740 opts = opts_copy;
5741 }
5742 for (i = 0; i < num_opts; i++) {
9109883a 5743 const struct fio_option *o = NULL;
de890a1e 5744 int newret = 1;
a2d027b9 5745
de890a1e
SL
5746 if (!opts_copy[i])
5747 continue;
5748
5749 if (td->eo)
5750 newret = parse_option(opts_copy[i], opts[i],
5751 td->io_ops->options, &o,
66e19a38 5752 td->eo, &td->opt_list);
de890a1e
SL
5753
5754 ret |= newret;
a2d027b9 5755 if (!o) {
de890a1e 5756 log_err("Bad option <%s>\n", opts[i]);
a2d027b9
JA
5757 show_closest_option(opts[i]);
5758 }
de890a1e
SL
5759 free(opts_copy[i]);
5760 opts_copy[i] = NULL;
5761 }
74929ac2 5762 }
3b8b7135 5763
d0c814ec 5764 free(opts_copy);
3b8b7135 5765 return ret;
214e1eca
JA
5766}
5767
5768int fio_cmd_option_parse(struct thread_data *td, const char *opt, char *val)
5769{
a8523a6a
JA
5770 int ret;
5771
a609f12a 5772 ret = parse_cmd_option(opt, val, fio_options, &td->o, &td->opt_list);
a8523a6a 5773 if (!ret) {
9109883a 5774 const struct fio_option *o;
a8523a6a 5775
9109883a 5776 o = find_option_c(fio_options, opt);
a8523a6a
JA
5777 if (o)
5778 fio_option_mark_set(&td->o, o);
5779 }
5780
5781 return ret;
214e1eca
JA
5782}
5783
de890a1e
SL
5784int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
5785 char *val)
5786{
d8b4f395
JA
5787 return parse_cmd_option(opt, val, td->io_ops->options, td->eo,
5788 &td->opt_list);
de890a1e
SL
5789}
5790
214e1eca
JA
5791void fio_fill_default_options(struct thread_data *td)
5792{
cb1402d6 5793 td->o.magic = OPT_MAGIC;
a609f12a 5794 fill_default_options(&td->o, fio_options);
214e1eca
JA
5795}
5796
5797int fio_show_option_help(const char *opt)
5798{
9af4a244 5799 return show_cmd_help(fio_options, opt);
214e1eca 5800}
d23bb327 5801
de890a1e
SL
5802/*
5803 * dupe FIO_OPT_STR_STORE options
5804 */
5805void fio_options_mem_dupe(struct thread_data *td)
5806{
53b5693d 5807 options_mem_dupe(fio_options, &td->o);
1647f592
JA
5808
5809 if (td->eo && td->io_ops) {
de890a1e 5810 void *oldeo = td->eo;
1647f592 5811
de890a1e
SL
5812 td->eo = malloc(td->io_ops->option_struct_size);
5813 memcpy(td->eo, oldeo, td->io_ops->option_struct_size);
53b5693d 5814 options_mem_dupe(td->io_ops->options, td->eo);
de890a1e
SL
5815 }
5816}
5817
d6978a32
JA
5818unsigned int fio_get_kb_base(void *data)
5819{
a609f12a
JA
5820 struct thread_data *td = cb_data_to_td(data);
5821 struct thread_options *o = &td->o;
d6978a32
JA
5822 unsigned int kb_base = 0;
5823
cb1402d6
JA
5824 /*
5825 * This is a hack... For private options, *data is not holding
5826 * a pointer to the thread_options, but to private data. This means
5827 * we can't safely dereference it, but magic is first so mem wise
5828 * it is valid. But this also means that if the job first sets
5829 * kb_base and expects that to be honored by private options,
5830 * it will be disappointed. We will return the global default
5831 * for this.
5832 */
5833 if (o && o->magic == OPT_MAGIC)
83ea422a 5834 kb_base = o->kb_base;
d6978a32
JA
5835 if (!kb_base)
5836 kb_base = 1024;
5837
5838 return kb_base;
5839}
9f988e2e 5840
9109883a 5841int add_option(const struct fio_option *o)
9f988e2e 5842{
07b3232d
JA
5843 struct fio_option *__o;
5844 int opt_index = 0;
5845
9af4a244 5846 __o = fio_options;
07b3232d
JA
5847 while (__o->name) {
5848 opt_index++;
5849 __o++;
5850 }
5851
7b504edd
JA
5852 if (opt_index + 1 == FIO_MAX_OPTS) {
5853 log_err("fio: FIO_MAX_OPTS is too small\n");
5854 return 1;
5855 }
5856
9af4a244 5857 memcpy(&fio_options[opt_index], o, sizeof(*o));
7b504edd 5858 fio_options[opt_index + 1].name = NULL;
07b3232d 5859 return 0;
9f988e2e 5860}
e2de69da 5861
07b3232d 5862void invalidate_profile_options(const char *prof_name)
e2de69da 5863{
07b3232d 5864 struct fio_option *o;
e2de69da 5865
9af4a244 5866 o = fio_options;
07b3232d
JA
5867 while (o->name) {
5868 if (o->prof_name && !strcmp(o->prof_name, prof_name)) {
5869 o->type = FIO_OPT_INVALID;
5870 o->prof_name = NULL;
5871 }
5872 o++;
e2de69da
JA
5873 }
5874}
f5b6bb85
JA
5875
5876void add_opt_posval(const char *optname, const char *ival, const char *help)
5877{
5878 struct fio_option *o;
5879 unsigned int i;
5880
9af4a244 5881 o = find_option(fio_options, optname);
f5b6bb85
JA
5882 if (!o)
5883 return;
5884
5885 for (i = 0; i < PARSE_MAX_VP; i++) {
5886 if (o->posval[i].ival)
5887 continue;
5888
5889 o->posval[i].ival = ival;
5890 o->posval[i].help = help;
5891 break;
5892 }
5893}
5894
5895void del_opt_posval(const char *optname, const char *ival)
5896{
5897 struct fio_option *o;
5898 unsigned int i;
5899
9af4a244 5900 o = find_option(fio_options, optname);
f5b6bb85
JA
5901 if (!o)
5902 return;
5903
5904 for (i = 0; i < PARSE_MAX_VP; i++) {
5905 if (!o->posval[i].ival)
5906 continue;
5907 if (strcmp(o->posval[i].ival, ival))
5908 continue;
5909
5910 o->posval[i].ival = NULL;
5911 o->posval[i].help = NULL;
5912 }
5913}
7e356b2d
JA
5914
5915void fio_options_free(struct thread_data *td)
5916{
ca6336a8 5917 options_free(fio_options, &td->o);
de890a1e
SL
5918 if (td->eo && td->io_ops && td->io_ops->options) {
5919 options_free(td->io_ops->options, td->eo);
824912be
JA
5920 free(td->eo);
5921 td->eo = NULL;
de890a1e 5922 }
7e356b2d 5923}
c504ee55 5924
8009f543
NC
5925void fio_dump_options_free(struct thread_data *td)
5926{
5927 while (!flist_empty(&td->opt_list)) {
5928 struct print_option *p;
5929
5930 p = flist_first_entry(&td->opt_list, struct print_option, list);
5931 flist_del_init(&p->list);
5932 free(p->name);
5933 free(p->value);
5934 free(p);
5935 }
5936}
5937
c504ee55
JA
5938struct fio_option *fio_option_find(const char *name)
5939{
5940 return find_option(fio_options, name);
5941}
5942
517c9c72 5943static struct fio_option *find_next_opt(struct fio_option *from,
f0e7f45a 5944 unsigned int off1)
a8523a6a 5945{
f0e7f45a 5946 struct fio_option *opt;
a8523a6a 5947
f0e7f45a
JA
5948 if (!from)
5949 from = &fio_options[0];
5950 else
5951 from++;
5952
5953 opt = NULL;
5954 do {
5955 if (off1 == from->off1) {
5956 opt = from;
a8523a6a
JA
5957 break;
5958 }
f0e7f45a
JA
5959 from++;
5960 } while (from->name);
a8523a6a 5961
f0e7f45a
JA
5962 return opt;
5963}
5964
5965static int opt_is_set(struct thread_options *o, struct fio_option *opt)
5966{
5967 unsigned int opt_off, index, offset;
a8523a6a
JA
5968
5969 opt_off = opt - &fio_options[0];
5970 index = opt_off / (8 * sizeof(uint64_t));
5971 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 5972 return (o->set_options[index] & ((uint64_t)1 << offset)) != 0;
a8523a6a
JA
5973}
5974
72f39748 5975bool __fio_option_is_set(struct thread_options *o, unsigned int off1)
f0e7f45a
JA
5976{
5977 struct fio_option *opt, *next;
5978
5979 next = NULL;
517c9c72 5980 while ((opt = find_next_opt(next, off1)) != NULL) {
f0e7f45a 5981 if (opt_is_set(o, opt))
72f39748 5982 return true;
f0e7f45a
JA
5983
5984 next = opt;
5985 }
5986
72f39748 5987 return false;
f0e7f45a
JA
5988}
5989
9109883a 5990void fio_option_mark_set(struct thread_options *o, const struct fio_option *opt)
a8523a6a
JA
5991{
5992 unsigned int opt_off, index, offset;
5993
5994 opt_off = opt - &fio_options[0];
5995 index = opt_off / (8 * sizeof(uint64_t));
5996 offset = opt_off & ((8 * sizeof(uint64_t)) - 1);
e9d686d6 5997 o->set_options[index] |= (uint64_t)1 << offset;
a8523a6a 5998}