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