Correct check to o->numjobs > 1 for verify warning
[fio.git] / init.c
CommitLineData
906c8d75 1/*
cb2c86fd 2 * This file contains job initialization and setup functions.
906c8d75 3 */
ebac4655
JA
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <fcntl.h>
8#include <ctype.h>
9#include <string.h>
10#include <errno.h>
11#include <sys/ipc.h>
12#include <sys/shm.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15
16#include "fio.h"
cb2c86fd 17#include "parse.h"
2e5cdb11 18#include "smalloc.h"
380065aa 19#include "filehash.h"
4f5af7b2 20#include "verify.h"
79d16311 21#include "profile.h"
ebac4655 22
bf2e821a
CC
23#include "lib/getopt.h"
24
964f5b9b 25static char fio_version_string[] = "fio 1.50-rc3";
214e1eca 26
ee738499 27#define FIO_RANDSEED (0xb1899bedUL)
ebac4655 28
214e1eca
JA
29static char **ini_file;
30static int max_jobs = MAX_JOBS;
cca73aa7 31static int dump_cmdline;
e1f36503 32
be4ecfdf 33static struct thread_data def_thread;
214e1eca 34struct thread_data *threads = NULL;
e1f36503 35
214e1eca
JA
36int exitall_on_terminate = 0;
37int terse_output = 0;
e592a06b 38int eta_print;
214e1eca
JA
39unsigned long long mlock_size = 0;
40FILE *f_out = NULL;
41FILE *f_err = NULL;
01f06b63 42char *job_section = NULL;
07b3232d 43char *exec_profile = NULL;
a9523c6f 44int warnings_fatal = 0;
ee738499 45
214e1eca 46int write_bw_log = 0;
4241ea8f 47int read_only = 0;
214e1eca 48
5ec10eaa
JA
49static int def_timeout;
50static int write_lat_log;
e1f36503 51
214e1eca 52static int prev_group_jobs;
b4692828 53
ee56ad50 54unsigned long fio_debug = 0;
5e1d306e
JA
55unsigned int fio_debug_jobno = -1;
56unsigned int *fio_debug_jobp = NULL;
ee56ad50 57
b4692828
JA
58/*
59 * Command line options. These will contain the above, plus a few
60 * extra that only pertain to fio itself and not jobs.
61 */
5ec10eaa 62static struct option l_opts[FIO_NR_OPTIONS] = {
b4692828
JA
63 {
64 .name = "output",
65 .has_arg = required_argument,
66 .val = 'o',
67 },
68 {
69 .name = "timeout",
70 .has_arg = required_argument,
71 .val = 't',
72 },
73 {
74 .name = "latency-log",
75 .has_arg = required_argument,
76 .val = 'l',
77 },
78 {
79 .name = "bandwidth-log",
80 .has_arg = required_argument,
81 .val = 'b',
82 },
83 {
84 .name = "minimal",
85 .has_arg = optional_argument,
86 .val = 'm',
87 },
88 {
89 .name = "version",
90 .has_arg = no_argument,
91 .val = 'v',
92 },
fd28ca49
JA
93 {
94 .name = "help",
95 .has_arg = no_argument,
96 .val = 'h',
97 },
98 {
99 .name = "cmdhelp",
320beefe 100 .has_arg = optional_argument,
fd28ca49
JA
101 .val = 'c',
102 },
cca73aa7
JA
103 {
104 .name = "showcmd",
105 .has_arg = no_argument,
724e4435
JA
106 .val = 's',
107 },
108 {
109 .name = "readonly",
110 .has_arg = no_argument,
111 .val = 'r',
cca73aa7 112 },
e592a06b
AC
113 {
114 .name = "eta",
115 .has_arg = required_argument,
116 .val = 'e',
117 },
ee56ad50
JA
118 {
119 .name = "debug",
120 .has_arg = required_argument,
121 .val = 'd',
122 },
01f06b63
JA
123 {
124 .name = "section",
125 .has_arg = required_argument,
126 .val = 'x',
127 },
2b386d25
JA
128 {
129 .name = "alloc-size",
130 .has_arg = required_argument,
131 .val = 'a',
132 },
9ac8a797
JA
133 {
134 .name = "profile",
135 .has_arg = required_argument,
136 .val = 'p',
137 },
a9523c6f
JA
138 {
139 .name = "warnings-fatal",
140 .has_arg = no_argument,
141 .val = 'w',
142 },
b4692828
JA
143 {
144 .name = NULL,
145 },
146};
147
9728ce37
JB
148FILE *get_f_out()
149{
150 return f_out;
151}
152
153FILE *get_f_err()
154{
155 return f_err;
156}
157
906c8d75
JA
158/*
159 * Return a free job structure.
160 */
ebac4655
JA
161static struct thread_data *get_new_job(int global, struct thread_data *parent)
162{
163 struct thread_data *td;
164
165 if (global)
166 return &def_thread;
e61f1ec8
BC
167 if (thread_number >= max_jobs) {
168 log_err("error: maximum number of jobs (%d) reached.\n",
169 max_jobs);
ebac4655 170 return NULL;
e61f1ec8 171 }
ebac4655
JA
172
173 td = &threads[thread_number++];
ddaeaa5a 174 *td = *parent;
ebac4655 175
e0b0d892
JA
176 td->o.uid = td->o.gid = -1U;
177
cade3ef4 178 dup_files(td, parent);
d23bb327 179 options_mem_dupe(td);
cade3ef4 180
15dc1934
JA
181 profile_add_hooks(td);
182
ebac4655 183 td->thread_number = thread_number;
ebac4655
JA
184 return td;
185}
186
187static void put_job(struct thread_data *td)
188{
549577a7
JA
189 if (td == &def_thread)
190 return;
58c55ba0
JA
191
192 profile_td_exit(td);
549577a7 193
16edf25d 194 if (td->error)
6d86144d 195 log_info("fio: %s\n", td->verror);
16edf25d 196
ebac4655
JA
197 memset(&threads[td->thread_number - 1], 0, sizeof(*td));
198 thread_number--;
199}
200
581e7141 201static int __setup_rate(struct thread_data *td, enum fio_ddir ddir)
127f6865 202{
581e7141 203 unsigned int bs = td->o.min_bs[ddir];
ba3e4e0c 204 unsigned long long bytes_per_sec;
127f6865 205
ff58fced
JA
206 assert(ddir_rw(ddir));
207
ba3e4e0c
RR
208 if (td->o.rate[ddir])
209 bytes_per_sec = td->o.rate[ddir];
210 else
211 bytes_per_sec = td->o.rate_iops[ddir] * bs;
127f6865 212
ba3e4e0c 213 if (!bytes_per_sec) {
127f6865
JA
214 log_err("rate lower than supported\n");
215 return -1;
216 }
217
ba3e4e0c 218 td->rate_nsec_cycle[ddir] = 1000000000ULL / bytes_per_sec;
581e7141 219 td->rate_pending_usleep[ddir] = 0;
127f6865
JA
220 return 0;
221}
222
581e7141
JA
223static int setup_rate(struct thread_data *td)
224{
225 int ret = 0;
226
227 if (td->o.rate[DDIR_READ] || td->o.rate_iops[DDIR_READ])
228 ret = __setup_rate(td, DDIR_READ);
229 if (td->o.rate[DDIR_WRITE] || td->o.rate_iops[DDIR_WRITE])
230 ret |= __setup_rate(td, DDIR_WRITE);
231
232 return ret;
233}
234
8347239a
JA
235static int fixed_block_size(struct thread_options *o)
236{
237 return o->min_bs[DDIR_READ] == o->max_bs[DDIR_READ] &&
238 o->min_bs[DDIR_WRITE] == o->max_bs[DDIR_WRITE] &&
239 o->min_bs[DDIR_READ] == o->min_bs[DDIR_WRITE];
240}
241
dad915e3
JA
242/*
243 * Lazy way of fixing up options that depend on each other. We could also
244 * define option callback handlers, but this is easier.
245 */
4e991c23 246static int fixup_options(struct thread_data *td)
e1f36503 247{
2dc1bbeb 248 struct thread_options *o = &td->o;
a9523c6f 249 int ret;
dad915e3 250
f356d01d 251#ifndef FIO_HAVE_PSHARED_MUTEX
9bbf57cc 252 if (!o->use_thread) {
f356d01d
JA
253 log_info("fio: this platform does not support process shared"
254 " mutexes, forcing use of threads. Use the 'thread'"
255 " option to get rid of this warning.\n");
9bbf57cc 256 o->use_thread = 1;
a9523c6f 257 ret = warnings_fatal;
f356d01d
JA
258 }
259#endif
260
2dc1bbeb 261 if (o->write_iolog_file && o->read_iolog_file) {
076efc7c 262 log_err("fio: read iolog overrides write_iolog\n");
2dc1bbeb
JA
263 free(o->write_iolog_file);
264 o->write_iolog_file = NULL;
a9523c6f 265 ret = warnings_fatal;
076efc7c 266 }
16b462ae 267
16b462ae
JA
268 /*
269 * only really works for sequential io for now, and with 1 file
270 */
2dc1bbeb
JA
271 if (o->zone_size && td_random(td) && o->open_files == 1)
272 o->zone_size = 0;
16b462ae
JA
273
274 /*
275 * Reads can do overwrites, we always need to pre-create the file
276 */
277 if (td_read(td) || td_rw(td))
2dc1bbeb 278 o->overwrite = 1;
16b462ae 279
2dc1bbeb 280 if (!o->min_bs[DDIR_READ])
5ec10eaa 281 o->min_bs[DDIR_READ] = o->bs[DDIR_READ];
2dc1bbeb
JA
282 if (!o->max_bs[DDIR_READ])
283 o->max_bs[DDIR_READ] = o->bs[DDIR_READ];
284 if (!o->min_bs[DDIR_WRITE])
5ec10eaa 285 o->min_bs[DDIR_WRITE] = o->bs[DDIR_WRITE];
2dc1bbeb
JA
286 if (!o->max_bs[DDIR_WRITE])
287 o->max_bs[DDIR_WRITE] = o->bs[DDIR_WRITE];
a00735e6 288
2dc1bbeb 289 o->rw_min_bs = min(o->min_bs[DDIR_READ], o->min_bs[DDIR_WRITE]);
a00735e6 290
2b7a01d0
JA
291 /*
292 * For random IO, allow blockalign offset other than min_bs.
293 */
294 if (!o->ba[DDIR_READ] || !td_random(td))
295 o->ba[DDIR_READ] = o->min_bs[DDIR_READ];
296 if (!o->ba[DDIR_WRITE] || !td_random(td))
297 o->ba[DDIR_WRITE] = o->min_bs[DDIR_WRITE];
298
299 if ((o->ba[DDIR_READ] != o->min_bs[DDIR_READ] ||
300 o->ba[DDIR_WRITE] != o->min_bs[DDIR_WRITE]) &&
9bbf57cc 301 !o->norandommap) {
2b7a01d0 302 log_err("fio: Any use of blockalign= turns off randommap\n");
9bbf57cc 303 o->norandommap = 1;
a9523c6f 304 ret = warnings_fatal;
2b7a01d0
JA
305 }
306
2dc1bbeb
JA
307 if (!o->file_size_high)
308 o->file_size_high = o->file_size_low;
9c60ce64 309
8347239a
JA
310 if (o->norandommap && o->verify != VERIFY_NONE
311 && !fixed_block_size(o)) {
312 log_err("fio: norandommap given for variable block sizes, "
313 "verify disabled\n");
2dc1bbeb 314 o->verify = VERIFY_NONE;
a9523c6f 315 ret = warnings_fatal;
bb8895e0 316 }
2dc1bbeb 317 if (o->bs_unaligned && (o->odirect || td->io_ops->flags & FIO_RAWIO))
690adba3 318 log_err("fio: bs_unaligned may not work with raw io\n");
e0a22335 319
48097d5c
JA
320 /*
321 * thinktime_spin must be less than thinktime
322 */
2dc1bbeb
JA
323 if (o->thinktime_spin > o->thinktime)
324 o->thinktime_spin = o->thinktime;
e916b390
JA
325
326 /*
327 * The low water mark cannot be bigger than the iodepth
328 */
2dc1bbeb 329 if (o->iodepth_low > o->iodepth || !o->iodepth_low) {
9467b77c
JA
330 /*
331 * syslet work around - if the workload is sequential,
332 * we want to let the queue drain all the way down to
333 * avoid seeking between async threads
334 */
335 if (!strcmp(td->io_ops->name, "syslet-rw") && !td_random(td))
2dc1bbeb 336 o->iodepth_low = 1;
9467b77c 337 else
2dc1bbeb 338 o->iodepth_low = o->iodepth;
9467b77c 339 }
cb5ab512
JA
340
341 /*
342 * If batch number isn't set, default to the same as iodepth
343 */
2dc1bbeb
JA
344 if (o->iodepth_batch > o->iodepth || !o->iodepth_batch)
345 o->iodepth_batch = o->iodepth;
b5af8293 346
2dc1bbeb
JA
347 if (o->nr_files > td->files_index)
348 o->nr_files = td->files_index;
9f9214f2 349
2dc1bbeb
JA
350 if (o->open_files > o->nr_files || !o->open_files)
351 o->open_files = o->nr_files;
4e991c23 352
581e7141
JA
353 if (((o->rate[0] + o->rate[1]) && (o->rate_iops[0] + o->rate_iops[1]))||
354 ((o->ratemin[0] + o->ratemin[1]) && (o->rate_iops_min[0] +
355 o->rate_iops_min[1]))) {
4e991c23 356 log_err("fio: rate and rate_iops are mutually exclusive\n");
a9523c6f 357 ret = 1;
4e991c23 358 }
581e7141
JA
359 if ((o->rate[0] < o->ratemin[0]) || (o->rate[1] < o->ratemin[1]) ||
360 (o->rate_iops[0] < o->rate_iops_min[0]) ||
361 (o->rate_iops[1] < o->rate_iops_min[1])) {
4e991c23 362 log_err("fio: minimum rate exceeds rate\n");
a9523c6f 363 ret = 1;
4e991c23
JA
364 }
365
cf4464ca
JA
366 if (!o->timeout && o->time_based) {
367 log_err("fio: time_based requires a runtime/timeout setting\n");
368 o->time_based = 0;
a9523c6f 369 ret = warnings_fatal;
cf4464ca
JA
370 }
371
aa31f1f1 372 if (o->fill_device && !o->size)
5921e80c 373 o->size = -1ULL;
5ec10eaa 374
9bbf57cc 375 if (o->verify != VERIFY_NONE) {
a9523c6f
JA
376 if (td_rw(td)) {
377 log_info("fio: mixed read/write workload with verify. "
378 "May not work as expected, unless you "
379 "pre-populated the file\n");
380 ret = warnings_fatal;
381 }
a6294434 382 if (td_write(td) && o->numjobs > 1) {
a9523c6f
JA
383 log_info("Multiple writers may overwrite blocks that "
384 "belong to other jobs. This can cause "
385 "verification failures.\n");
386 ret = warnings_fatal;
387 }
388
9bbf57cc 389 o->refill_buffers = 1;
2f1b8e8b
JA
390 if (o->max_bs[DDIR_WRITE] != o->min_bs[DDIR_WRITE] &&
391 !o->verify_interval)
392 o->verify_interval = o->min_bs[DDIR_WRITE];
d990588e 393 }
41ccd845 394
9bbf57cc
JA
395 if (o->pre_read) {
396 o->invalidate_cache = 0;
a9523c6f 397 if (td->io_ops->flags & FIO_PIPEIO) {
9c0d2241
JA
398 log_info("fio: cannot pre-read files with an IO engine"
399 " that isn't seekable. Pre-read disabled.\n");
a9523c6f
JA
400 ret = warnings_fatal;
401 }
9c0d2241 402 }
34f1c044 403
e72fa4d4 404#ifndef FIO_HAVE_FDATASYNC
9bbf57cc 405 if (o->fdatasync_blocks) {
e72fa4d4
JA
406 log_info("fio: this platform does not support fdatasync()"
407 " falling back to using fsync(). Use the 'fsync'"
408 " option instead of 'fdatasync' to get rid of"
409 " this warning\n");
9bbf57cc
JA
410 o->fsync_blocks = o->fdatasync_blocks;
411 o->fdatasync_blocks = 0;
a9523c6f 412 ret = warnings_fatal;
e72fa4d4
JA
413 }
414#endif
415
a9523c6f 416 return ret;
e1f36503
JA
417}
418
f8977ee6
JA
419/*
420 * This function leaks the buffer
421 */
422static char *to_kmg(unsigned int val)
423{
424 char *buf = malloc(32);
f3502ba2 425 char post[] = { 0, 'K', 'M', 'G', 'P', 'E', 0 };
f8977ee6
JA
426 char *p = post;
427
245142ff 428 do {
f8977ee6
JA
429 if (val & 1023)
430 break;
431
432 val >>= 10;
433 p++;
245142ff 434 } while (*p);
f8977ee6
JA
435
436 snprintf(buf, 31, "%u%c", val, *p);
437 return buf;
438}
439
09629a90
JA
440/* External engines are specified by "external:name.o") */
441static const char *get_engine_name(const char *str)
442{
443 char *p = strstr(str, ":");
444
445 if (!p)
446 return str;
447
448 p++;
449 strip_blank_front(&p);
450 strip_blank_end(p);
451 return p;
452}
453
e132cbae
JA
454static int exists_and_not_file(const char *filename)
455{
456 struct stat sb;
457
458 if (lstat(filename, &sb) == -1)
459 return 0;
460
ecc314ba
BC
461 /* \\.\ is the device namespace in Windows, where every file
462 * is a device node */
463 if (S_ISREG(sb.st_mode) && strncmp(filename, "\\\\.\\", 4) != 0)
e132cbae
JA
464 return 0;
465
466 return 1;
467}
468
5bfc35d7
JA
469void td_fill_rand_seeds(struct thread_data *td)
470{
471 os_random_seed(td->rand_seeds[0], &td->bsrange_state);
472 os_random_seed(td->rand_seeds[1], &td->verify_state);
473 os_random_seed(td->rand_seeds[2], &td->rwmix_state);
474
475 if (td->o.file_service_type == FIO_FSERVICE_RANDOM)
476 os_random_seed(td->rand_seeds[3], &td->next_file_state);
477
478 os_random_seed(td->rand_seeds[5], &td->file_size_state);
0d29de83 479 os_random_seed(td->rand_seeds[6], &td->trim_state);
5bfc35d7
JA
480
481 if (!td_random(td))
482 return;
483
484 if (td->o.rand_repeatable)
485 td->rand_seeds[4] = FIO_RANDSEED * td->thread_number;
486
487 os_random_seed(td->rand_seeds[4], &td->random_state);
488}
489
9c60ce64
JA
490/*
491 * Initialize the various random states we need (random io, block size ranges,
492 * read/write mix, etc).
493 */
494static int init_random_state(struct thread_data *td)
495{
68727076 496 int fd;
9c60ce64
JA
497
498 fd = open("/dev/urandom", O_RDONLY);
499 if (fd == -1) {
500 td_verror(td, errno, "open");
501 return 1;
502 }
503
5bfc35d7
JA
504 if (read(fd, td->rand_seeds, sizeof(td->rand_seeds)) <
505 (int) sizeof(td->rand_seeds)) {
9c60ce64
JA
506 td_verror(td, EIO, "read");
507 close(fd);
508 return 1;
509 }
510
511 close(fd);
5bfc35d7 512 td_fill_rand_seeds(td);
9c60ce64
JA
513 return 0;
514}
515
906c8d75
JA
516/*
517 * Adds a job to the list of things todo. Sanitizes the various options
518 * to make sure we don't have conflicts, and initializes various
519 * members of td.
520 */
75154845 521static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
ebac4655 522{
413dd459
JA
523 const char *ddir_str[] = { NULL, "read", "write", "rw", NULL,
524 "randread", "randwrite", "randrw" };
af52b345 525 unsigned int i;
09629a90 526 const char *engine;
af52b345 527 char fname[PATH_MAX];
e132cbae 528 int numjobs, file_alloced;
ebac4655 529
ebac4655
JA
530 /*
531 * the def_thread is just for options, it's not a real job
532 */
533 if (td == &def_thread)
534 return 0;
535
cca73aa7
JA
536 /*
537 * if we are just dumping the output command line, don't add the job
538 */
539 if (dump_cmdline) {
540 put_job(td);
541 return 0;
542 }
543
58c55ba0
JA
544 if (profile_td_init(td))
545 return 1;
546
2dc1bbeb 547 engine = get_engine_name(td->o.ioengine);
09629a90
JA
548 td->io_ops = load_ioengine(td, engine);
549 if (!td->io_ops) {
550 log_err("fio: failed to load engine %s\n", engine);
205927a3 551 goto err;
09629a90 552 }
df64119d 553
2dc1bbeb 554 if (td->o.use_thread)
9cedf167
JA
555 nr_thread++;
556 else
557 nr_process++;
558
2dc1bbeb 559 if (td->o.odirect)
690adba3
JA
560 td->io_ops->flags |= FIO_RAWIO;
561
e132cbae 562 file_alloced = 0;
691c8fb0 563 if (!td->o.filename && !td->files_index && !td->o.read_iolog_file) {
e132cbae 564 file_alloced = 1;
80be24f4 565
2dc1bbeb 566 if (td->o.nr_files == 1 && exists_and_not_file(jobname))
e132cbae 567 add_file(td, jobname);
7b05a215 568 else {
2dc1bbeb 569 for (i = 0; i < td->o.nr_files; i++) {
5ec10eaa
JA
570 sprintf(fname, "%s.%d.%d", jobname,
571 td->thread_number, i);
7b05a215
JA
572 add_file(td, fname);
573 }
af52b345 574 }
0af7b542 575 }
ebac4655 576
4e991c23
JA
577 if (fixup_options(td))
578 goto err;
e0a22335 579
07eb79df
JA
580 if (td->io_ops->flags & FIO_DISKLESSIO) {
581 struct fio_file *f;
582
583 for_each_file(td, f, i)
584 f->real_file_size = -1ULL;
585 }
586
cdd18ad8 587 td->mutex = fio_mutex_init(0);
ebac4655 588
756867bd
JA
589 td->ts.clat_stat[0].min_val = td->ts.clat_stat[1].min_val = ULONG_MAX;
590 td->ts.slat_stat[0].min_val = td->ts.slat_stat[1].min_val = ULONG_MAX;
02af0988 591 td->ts.lat_stat[0].min_val = td->ts.lat_stat[1].min_val = ULONG_MAX;
756867bd 592 td->ts.bw_stat[0].min_val = td->ts.bw_stat[1].min_val = ULONG_MAX;
cdd5411e 593 td->ddir_seq_nr = td->o.ddir_seq_nr;
ebac4655 594
755c3189 595 if ((td->o.stonewall || td->o.new_group) && prev_group_jobs) {
3c5df6fa 596 prev_group_jobs = 0;
ebac4655 597 groupid++;
3c5df6fa 598 }
ebac4655
JA
599
600 td->groupid = groupid;
3c5df6fa 601 prev_group_jobs++;
ebac4655 602
9c60ce64
JA
603 if (init_random_state(td))
604 goto err;
605
ebac4655
JA
606 if (setup_rate(td))
607 goto err;
608
2dc1bbeb 609 if (td->o.write_lat_log) {
02af0988 610 setup_log(&td->ts.lat_log);
756867bd
JA
611 setup_log(&td->ts.slat_log);
612 setup_log(&td->ts.clat_log);
ebac4655 613 }
2dc1bbeb 614 if (td->o.write_bw_log)
756867bd 615 setup_log(&td->ts.bw_log);
ebac4655 616
2dc1bbeb
JA
617 if (!td->o.name)
618 td->o.name = strdup(jobname);
01452055 619
c6ae0a5b 620 if (!terse_output) {
b990b5c0 621 if (!job_add_num) {
5ec10eaa
JA
622 if (!strcmp(td->io_ops->name, "cpuio")) {
623 log_info("%s: ioengine=cpu, cpuload=%u,"
624 " cpucycle=%u\n", td->o.name,
625 td->o.cpuload,
626 td->o.cpucycle);
627 } else {
f8977ee6
JA
628 char *c1, *c2, *c3, *c4;
629
2dc1bbeb
JA
630 c1 = to_kmg(td->o.min_bs[DDIR_READ]);
631 c2 = to_kmg(td->o.max_bs[DDIR_READ]);
632 c3 = to_kmg(td->o.min_bs[DDIR_WRITE]);
633 c4 = to_kmg(td->o.max_bs[DDIR_WRITE]);
f8977ee6 634
5ec10eaa
JA
635 log_info("%s: (g=%d): rw=%s, bs=%s-%s/%s-%s,"
636 " ioengine=%s, iodepth=%u\n",
637 td->o.name, td->groupid,
638 ddir_str[td->o.td_ddir],
639 c1, c2, c3, c4,
640 td->io_ops->name,
641 td->o.iodepth);
f8977ee6
JA
642
643 free(c1);
644 free(c2);
645 free(c3);
646 free(c4);
647 }
b990b5c0 648 } else if (job_add_num == 1)
6d86144d 649 log_info("...\n");
c6ae0a5b 650 }
ebac4655
JA
651
652 /*
653 * recurse add identical jobs, clear numjobs and stonewall options
654 * as they don't apply to sub-jobs
655 */
2dc1bbeb 656 numjobs = td->o.numjobs;
ebac4655
JA
657 while (--numjobs) {
658 struct thread_data *td_new = get_new_job(0, td);
659
660 if (!td_new)
661 goto err;
662
2dc1bbeb
JA
663 td_new->o.numjobs = 1;
664 td_new->o.stonewall = 0;
92c1d41f 665 td_new->o.new_group = 0;
e132cbae
JA
666
667 if (file_alloced) {
2dc1bbeb 668 td_new->o.filename = NULL;
e132cbae 669 td_new->files_index = 0;
4e6ea2f1 670 td_new->files_size = 0;
e132cbae
JA
671 td_new->files = NULL;
672 }
673
75154845 674 job_add_num = numjobs - 1;
ebac4655 675
75154845 676 if (add_job(td_new, jobname, job_add_num))
ebac4655
JA
677 goto err;
678 }
3c5df6fa 679
ebac4655
JA
680 return 0;
681err:
682 put_job(td);
683 return -1;
684}
685
79d16311
JA
686/*
687 * Parse as if 'o' was a command line
688 */
689void add_job_opts(const char **o)
690{
691 struct thread_data *td, *td_parent;
692 int i, in_global = 1;
693 char jobname[32];
694
695 i = 0;
696 td_parent = td = NULL;
697 while (o[i]) {
698 if (!strncmp(o[i], "name", 4)) {
699 in_global = 0;
700 if (td)
701 add_job(td, jobname, 0);
702 td = NULL;
703 sprintf(jobname, "%s", o[i] + 5);
704 }
705 if (in_global && !td_parent)
706 td_parent = get_new_job(1, &def_thread);
707 else if (!in_global && !td) {
708 if (!td_parent)
709 td_parent = &def_thread;
710 td = get_new_job(0, td_parent);
711 }
712 if (in_global)
713 fio_options_parse(td_parent, (char **) &o[i], 1);
714 else
715 fio_options_parse(td, (char **) &o[i], 1);
716 i++;
717 }
718
719 if (td)
720 add_job(td, jobname, 0);
721}
722
01f06b63
JA
723static int skip_this_section(const char *name)
724{
725 if (!job_section)
726 return 0;
727 if (!strncmp(name, "global", 6))
728 return 0;
729
b36beb6e 730 return strcmp(job_section, name);
01f06b63
JA
731}
732
ebac4655
JA
733static int is_empty_or_comment(char *line)
734{
735 unsigned int i;
736
737 for (i = 0; i < strlen(line); i++) {
738 if (line[i] == ';')
739 return 1;
5cc2da30
IM
740 if (line[i] == '#')
741 return 1;
ebac4655
JA
742 if (!isspace(line[i]) && !iscntrl(line[i]))
743 return 0;
744 }
745
746 return 1;
747}
748
07261983
JA
749/*
750 * This is our [ini] type file parser.
751 */
1e97cce9 752static int parse_jobs_ini(char *file, int stonewall_flag)
ebac4655 753{
e1f36503 754 unsigned int global;
ebac4655 755 struct thread_data *td;
fee3bb48 756 char *string, *name;
ebac4655
JA
757 FILE *f;
758 char *p;
0c7e37a0 759 int ret = 0, stonewall;
097b2991 760 int first_sect = 1;
ccf8f127 761 int skip_fgets = 0;
01f06b63 762 int inside_skip = 0;
3b8b7135
JA
763 char **opts;
764 int i, alloc_opts, num_opts;
ebac4655 765
5a729cbe
AC
766 if (!strcmp(file, "-"))
767 f = stdin;
768 else
769 f = fopen(file, "r");
770
ebac4655 771 if (!f) {
aea47d44 772 perror("fopen job file");
ebac4655
JA
773 return 1;
774 }
775
776 string = malloc(4096);
7f7e6e59
JA
777
778 /*
779 * it's really 256 + small bit, 280 should suffice
780 */
781 name = malloc(280);
782 memset(name, 0, 280);
ebac4655 783
3b8b7135
JA
784 alloc_opts = 8;
785 opts = malloc(sizeof(char *) * alloc_opts);
b7c6302d 786 num_opts = 0;
3b8b7135 787
0c7e37a0 788 stonewall = stonewall_flag;
7c124ac1 789 do {
ccf8f127
JA
790 /*
791 * if skip_fgets is set, we already have loaded a line we
792 * haven't handled.
793 */
794 if (!skip_fgets) {
795 p = fgets(string, 4095, f);
796 if (!p)
797 break;
798 }
cdc7f193 799
ccf8f127 800 skip_fgets = 0;
cdc7f193 801 strip_blank_front(&p);
6c7c7da1 802 strip_blank_end(p);
cdc7f193 803
ebac4655
JA
804 if (is_empty_or_comment(p))
805 continue;
6c7c7da1 806 if (sscanf(p, "[%255s]", name) != 1) {
01f06b63
JA
807 if (inside_skip)
808 continue;
5ec10eaa
JA
809 log_err("fio: option <%s> outside of [] job section\n",
810 p);
088b4207 811 break;
6c7c7da1 812 }
ebac4655 813
7a4b80a1
JA
814 name[strlen(name) - 1] = '\0';
815
01f06b63
JA
816 if (skip_this_section(name)) {
817 inside_skip = 1;
818 continue;
819 } else
820 inside_skip = 0;
821
ebac4655
JA
822 global = !strncmp(name, "global", 6);
823
cca73aa7 824 if (dump_cmdline) {
097b2991
JA
825 if (first_sect)
826 log_info("fio ");
cca73aa7
JA
827 if (!global)
828 log_info("--name=%s ", name);
097b2991 829 first_sect = 0;
cca73aa7
JA
830 }
831
ebac4655 832 td = get_new_job(global, &def_thread);
45410acb
JA
833 if (!td) {
834 ret = 1;
835 break;
836 }
ebac4655 837
972cfd25
JA
838 /*
839 * Seperate multiple job files by a stonewall
840 */
f9481919 841 if (!global && stonewall) {
2dc1bbeb 842 td->o.stonewall = stonewall;
972cfd25
JA
843 stonewall = 0;
844 }
845
3b8b7135
JA
846 num_opts = 0;
847 memset(opts, 0, alloc_opts * sizeof(char *));
848
ebac4655
JA
849 while ((p = fgets(string, 4096, f)) != NULL) {
850 if (is_empty_or_comment(p))
851 continue;
e1f36503 852
b6754f9d 853 strip_blank_front(&p);
7c124ac1 854
ccf8f127
JA
855 /*
856 * new section, break out and make sure we don't
857 * fgets() a new line at the top.
858 */
859 if (p[0] == '[') {
860 skip_fgets = 1;
7c124ac1 861 break;
ccf8f127 862 }
7c124ac1 863
4ae3f763 864 strip_blank_end(p);
aea47d44 865
3b8b7135
JA
866 if (num_opts == alloc_opts) {
867 alloc_opts <<= 1;
868 opts = realloc(opts,
869 alloc_opts * sizeof(char *));
870 }
871
872 opts[num_opts] = strdup(p);
873 num_opts++;
ebac4655 874 }
ebac4655 875
3b8b7135
JA
876 ret = fio_options_parse(td, opts, num_opts);
877 if (!ret) {
878 if (dump_cmdline)
879 for (i = 0; i < num_opts; i++)
880 log_info("--%s ", opts[i]);
881
45410acb 882 ret = add_job(td, name, 0);
3b8b7135 883 } else {
b1508cf9
JA
884 log_err("fio: job %s dropped\n", name);
885 put_job(td);
45410acb 886 }
3b8b7135
JA
887
888 for (i = 0; i < num_opts; i++)
889 free(opts[i]);
890 num_opts = 0;
7c124ac1 891 } while (!ret);
ebac4655 892
cca73aa7
JA
893 if (dump_cmdline)
894 log_info("\n");
895
3b8b7135
JA
896 for (i = 0; i < num_opts; i++)
897 free(opts[i]);
898
ebac4655
JA
899 free(string);
900 free(name);
2577594d 901 free(opts);
5a729cbe
AC
902 if (f != stdin)
903 fclose(f);
45410acb 904 return ret;
ebac4655
JA
905}
906
907static int fill_def_thread(void)
908{
909 memset(&def_thread, 0, sizeof(def_thread));
910
375b2695 911 fio_getaffinity(getpid(), &def_thread.o.cpumask);
ebac4655
JA
912
913 /*
ee738499 914 * fill default options
ebac4655 915 */
214e1eca 916 fio_fill_default_options(&def_thread);
ee738499 917
2dc1bbeb 918 def_thread.o.timeout = def_timeout;
ebac4655
JA
919 return 0;
920}
921
214e1eca
JA
922static void free_shm(void)
923{
924 struct shmid_ds sbuf;
925
926 if (threads) {
5e1d306e
JA
927 void *tp = threads;
928
214e1eca 929 threads = NULL;
5e1d306e
JA
930 file_hash_exit();
931 fio_debug_jobp = NULL;
932 shmdt(tp);
214e1eca
JA
933 shmctl(shm_id, IPC_RMID, &sbuf);
934 }
2e5cdb11
JA
935
936 scleanup();
214e1eca
JA
937}
938
939/*
940 * The thread area is shared between the main process and the job
941 * threads/processes. So setup a shared memory segment that will hold
380065aa
JA
942 * all the job info. We use the end of the region for keeping track of
943 * open files across jobs, for file sharing.
214e1eca
JA
944 */
945static int setup_thread_area(void)
946{
380065aa
JA
947 void *hash;
948
214e1eca
JA
949 /*
950 * 1024 is too much on some machines, scale max_jobs if
951 * we get a failure that looks like too large a shm segment
952 */
953 do {
954 size_t size = max_jobs * sizeof(struct thread_data);
955
380065aa 956 size += file_hash_size;
5e1d306e 957 size += sizeof(unsigned int);
380065aa 958
214e1eca
JA
959 shm_id = shmget(0, size, IPC_CREAT | 0600);
960 if (shm_id != -1)
961 break;
962 if (errno != EINVAL) {
963 perror("shmget");
964 break;
965 }
966
967 max_jobs >>= 1;
968 } while (max_jobs);
969
970 if (shm_id == -1)
971 return 1;
972
973 threads = shmat(shm_id, NULL, 0);
974 if (threads == (void *) -1) {
975 perror("shmat");
976 return 1;
977 }
978
1f809d15 979 memset(threads, 0, max_jobs * sizeof(struct thread_data));
380065aa 980 hash = (void *) threads + max_jobs * sizeof(struct thread_data);
5e1d306e
JA
981 fio_debug_jobp = (void *) hash + file_hash_size;
982 *fio_debug_jobp = -1;
380065aa 983 file_hash_init(hash);
214e1eca
JA
984 atexit(free_shm);
985 return 0;
986}
987
45378b35 988static void usage(const char *name)
4785f995 989{
45378b35 990 printf("%s [options] [job options] <job file(s)>\n", name);
ee56ad50 991 printf("\t--debug=options\tEnable debug logging\n");
b4692828
JA
992 printf("\t--output\tWrite output to file\n");
993 printf("\t--timeout\tRuntime in seconds\n");
994 printf("\t--latency-log\tGenerate per-job latency logs\n");
995 printf("\t--bandwidth-log\tGenerate per-job bandwidth logs\n");
996 printf("\t--minimal\tMinimal (terse) output\n");
997 printf("\t--version\tPrint version info and exit\n");
fd28ca49 998 printf("\t--help\t\tPrint this page\n");
5ec10eaa
JA
999 printf("\t--cmdhelp=cmd\tPrint command help, \"all\" for all of"
1000 " them\n");
cca73aa7 1001 printf("\t--showcmd\tTurn a job file into command line options\n");
e592a06b
AC
1002 printf("\t--eta=when\tWhen ETA estimate should be printed\n");
1003 printf("\t \tMay be \"always\", \"never\" or \"auto\"\n");
5ec10eaa
JA
1004 printf("\t--readonly\tTurn on safety read-only checks, preventing"
1005 " writes\n");
01f06b63 1006 printf("\t--section=name\tOnly run specified section in job file\n");
2b386d25
JA
1007 printf("\t--alloc-size=kb\tSet smalloc pool to this size in kb"
1008 " (def 1024)\n");
a9523c6f 1009 printf("\t--warnings-fatal Fio parser warnings are fatal\n");
aa58d252
JA
1010 printf("\nFio was written by Jens Axboe <jens.axboe@oracle.com>");
1011 printf("\n Jens Axboe <jaxboe@fusionio.com>\n");
4785f995
JA
1012}
1013
79e48f72 1014#ifdef FIO_INC_DEBUG
ee56ad50 1015struct debug_level debug_levels[] = {
bd6f78b2
JA
1016 { .name = "process", .shift = FD_PROCESS, },
1017 { .name = "file", .shift = FD_FILE, },
1018 { .name = "io", .shift = FD_IO, },
1019 { .name = "mem", .shift = FD_MEM, },
1020 { .name = "blktrace", .shift = FD_BLKTRACE },
1021 { .name = "verify", .shift = FD_VERIFY },
84422acd 1022 { .name = "random", .shift = FD_RANDOM },
a3d741fa 1023 { .name = "parse", .shift = FD_PARSE },
cd991b9e 1024 { .name = "diskutil", .shift = FD_DISKUTIL },
5e1d306e 1025 { .name = "job", .shift = FD_JOB },
29adda3c 1026 { .name = "mutex", .shift = FD_MUTEX },
79d16311 1027 { .name = "profile", .shift = FD_PROFILE },
c223da83 1028 { .name = "time", .shift = FD_TIME },
02444ad1 1029 { .name = NULL, },
ee56ad50
JA
1030};
1031
c09823ab 1032static int set_debug(const char *string)
ee56ad50
JA
1033{
1034 struct debug_level *dl;
1035 char *p = (char *) string;
1036 char *opt;
1037 int i;
1038
1039 if (!strcmp(string, "?") || !strcmp(string, "help")) {
1040 int i;
1041
1042 log_info("fio: dumping debug options:");
1043 for (i = 0; debug_levels[i].name; i++) {
1044 dl = &debug_levels[i];
1045 log_info("%s,", dl->name);
1046 }
bd6f78b2 1047 log_info("all\n");
c09823ab 1048 return 1;
ee56ad50
JA
1049 }
1050
1051 while ((opt = strsep(&p, ",")) != NULL) {
1052 int found = 0;
1053
5e1d306e
JA
1054 if (!strncmp(opt, "all", 3)) {
1055 log_info("fio: set all debug options\n");
1056 fio_debug = ~0UL;
1057 continue;
1058 }
1059
ee56ad50
JA
1060 for (i = 0; debug_levels[i].name; i++) {
1061 dl = &debug_levels[i];
5e1d306e
JA
1062 found = !strncmp(opt, dl->name, strlen(dl->name));
1063 if (!found)
1064 continue;
1065
1066 if (dl->shift == FD_JOB) {
1067 opt = strchr(opt, ':');
1068 if (!opt) {
1069 log_err("fio: missing job number\n");
1070 break;
1071 }
1072 opt++;
1073 fio_debug_jobno = atoi(opt);
1074 log_info("fio: set debug jobno %d\n",
1075 fio_debug_jobno);
1076 } else {
ee56ad50 1077 log_info("fio: set debug option %s\n", opt);
bd6f78b2 1078 fio_debug |= (1UL << dl->shift);
ee56ad50 1079 }
5e1d306e 1080 break;
ee56ad50
JA
1081 }
1082
1083 if (!found)
1084 log_err("fio: debug mask %s not found\n", opt);
1085 }
c09823ab 1086 return 0;
ee56ad50 1087}
79e48f72 1088#else
69b98d4c 1089static int set_debug(const char *string)
79e48f72
JA
1090{
1091 log_err("fio: debug tracing not included in build\n");
c09823ab 1092 return 1;
79e48f72
JA
1093}
1094#endif
9ac8a797 1095
972cfd25 1096static int parse_cmd_line(int argc, char *argv[])
ebac4655 1097{
b4692828 1098 struct thread_data *td = NULL;
c09823ab 1099 int c, ini_idx = 0, lidx, ret = 0, do_exit = 0, exit_val = 0;
ebac4655 1100
5ec10eaa 1101 while ((c = getopt_long_only(argc, argv, "", l_opts, &lidx)) != -1) {
ebac4655 1102 switch (c) {
2b386d25
JA
1103 case 'a':
1104 smalloc_pool_size = atoi(optarg);
1105 break;
b4692828
JA
1106 case 't':
1107 def_timeout = atoi(optarg);
1108 break;
1109 case 'l':
1110 write_lat_log = 1;
1111 break;
3d73e5a9 1112 case 'b':
b4692828
JA
1113 write_bw_log = 1;
1114 break;
1115 case 'o':
1116 f_out = fopen(optarg, "w+");
1117 if (!f_out) {
1118 perror("fopen output");
1119 exit(1);
1120 }
1121 f_err = f_out;
1122 break;
1123 case 'm':
1124 terse_output = 1;
1125 break;
1126 case 'h':
45378b35 1127 usage(argv[0]);
b4692828 1128 exit(0);
fd28ca49 1129 case 'c':
214e1eca 1130 exit(fio_show_option_help(optarg));
cca73aa7
JA
1131 case 's':
1132 dump_cmdline = 1;
1133 break;
724e4435
JA
1134 case 'r':
1135 read_only = 1;
1136 break;
b4692828 1137 case 'v':
bce964a1 1138 /* already being printed, just quit */
b4692828 1139 exit(0);
e592a06b
AC
1140 case 'e':
1141 if (!strcmp("always", optarg))
1142 eta_print = FIO_ETA_ALWAYS;
1143 else if (!strcmp("never", optarg))
1144 eta_print = FIO_ETA_NEVER;
1145 break;
ee56ad50 1146 case 'd':
c09823ab
JA
1147 if (set_debug(optarg))
1148 do_exit++;
ee56ad50 1149 break;
01f06b63
JA
1150 case 'x':
1151 if (!strcmp(optarg, "global")) {
5ec10eaa
JA
1152 log_err("fio: can't use global as only "
1153 "section\n");
c09823ab
JA
1154 do_exit++;
1155 exit_val = 1;
01f06b63
JA
1156 break;
1157 }
1158 if (job_section)
1159 free(job_section);
1160 job_section = strdup(optarg);
1161 break;
9ac8a797 1162 case 'p':
07b3232d 1163 exec_profile = strdup(optarg);
9ac8a797 1164 break;
b4692828 1165 case FIO_GETOPT_JOB: {
5ec10eaa 1166 const char *opt = l_opts[lidx].name;
b4692828
JA
1167 char *val = optarg;
1168
c2b1e753 1169 if (!strncmp(opt, "name", 4) && td) {
2dc1bbeb 1170 ret = add_job(td, td->o.name ?: "fio", 0);
c2b1e753
JA
1171 if (ret) {
1172 put_job(td);
1173 return 0;
1174 }
1175 td = NULL;
1176 }
b4692828 1177 if (!td) {
01f06b63 1178 int is_section = !strncmp(opt, "name", 4);
3106f220
JA
1179 int global = 0;
1180
01f06b63 1181 if (!is_section || !strncmp(val, "global", 6))
3106f220 1182 global = 1;
c2b1e753 1183
01f06b63
JA
1184 if (is_section && skip_this_section(val))
1185 continue;
1186
c2b1e753 1187 td = get_new_job(global, &def_thread);
b4692828
JA
1188 if (!td)
1189 return 0;
1190 }
38d0adb0 1191
214e1eca 1192 ret = fio_cmd_option_parse(td, opt, val);
b4692828
JA
1193 break;
1194 }
a9523c6f
JA
1195 case 'w':
1196 warnings_fatal = 1;
1197 break;
b4692828 1198 default:
c09823ab
JA
1199 do_exit++;
1200 exit_val = 1;
b4692828 1201 break;
ebac4655
JA
1202 }
1203 }
c9fad893 1204
c09823ab
JA
1205 if (do_exit)
1206 exit(exit_val);
536582bf 1207
b4692828 1208 if (td) {
7d6a8904 1209 if (!ret)
2dc1bbeb 1210 ret = add_job(td, td->o.name ?: "fio", 0);
7d6a8904
JA
1211 if (ret)
1212 put_job(td);
972cfd25 1213 }
774a6177 1214
b4692828
JA
1215 while (optind < argc) {
1216 ini_idx++;
1217 ini_file = realloc(ini_file, ini_idx * sizeof(char *));
1218 ini_file[ini_idx - 1] = strdup(argv[optind]);
1219 optind++;
eb8bbf48 1220 }
972cfd25
JA
1221
1222 return ini_idx;
ebac4655
JA
1223}
1224
ebac4655
JA
1225int parse_options(int argc, char *argv[])
1226{
972cfd25
JA
1227 int job_files, i;
1228
b4692828
JA
1229 f_out = stdout;
1230 f_err = stderr;
1231
2d7760d1
JA
1232 log_info("%s\n", fio_version_string);
1233
5ec10eaa 1234 fio_options_dup_and_init(l_opts);
b4692828 1235
ebac4655
JA
1236 if (setup_thread_area())
1237 return 1;
1238 if (fill_def_thread())
1239 return 1;
1240
972cfd25 1241 job_files = parse_cmd_line(argc, argv);
ebac4655 1242
972cfd25
JA
1243 for (i = 0; i < job_files; i++) {
1244 if (fill_def_thread())
1245 return 1;
0c7e37a0 1246 if (parse_jobs_ini(ini_file[i], i))
972cfd25 1247 return 1;
88c6ed80 1248 free(ini_file[i]);
972cfd25 1249 }
ebac4655 1250
88c6ed80 1251 free(ini_file);
d23bb327 1252 options_mem_free(&def_thread);
b4692828
JA
1253
1254 if (!thread_number) {
cca73aa7
JA
1255 if (dump_cmdline)
1256 return 0;
07b3232d
JA
1257 if (exec_profile)
1258 return 0;
cca73aa7 1259
03e20d68 1260 log_err("No jobs(s) defined\n\n");
45378b35 1261 usage(argv[0]);
b4692828
JA
1262 return 1;
1263 }
1264
be4ecfdf
JA
1265 if (def_thread.o.gtod_offload) {
1266 fio_gtod_init();
1267 fio_gtod_offload = 1;
1268 fio_gtod_cpu = def_thread.o.gtod_cpu;
1269 }
1270
ebac4655
JA
1271 return 0;
1272}