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