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