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