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