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