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