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