init.c revision 9c1f7434526606fc8a4296190a2dea5de2651266
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 <assert.h>
13#include <sys/ipc.h>
14#include <sys/shm.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17
18#include "fio.h"
19#include "parse.h"
20
21/*
22 * The default options
23 */
24#define DEF_BS			(4096)
25#define DEF_TIMEOUT		(0)
26#define DEF_RATE_CYCLE		(1000)
27#define DEF_ODIRECT		(1)
28#define DEF_IO_ENGINE		(FIO_SYNCIO)
29#define DEF_IO_ENGINE_NAME	"sync"
30#define DEF_SEQUENTIAL		(1)
31#define DEF_RAND_REPEAT		(1)
32#define DEF_OVERWRITE		(0)
33#define DEF_INVALIDATE		(1)
34#define DEF_SYNCIO		(0)
35#define DEF_RANDSEED		(0xb1899bedUL)
36#define DEF_BWAVGTIME		(500)
37#define DEF_CREATE_SER		(1)
38#define DEF_CREATE_FSYNC	(1)
39#define DEF_LOOPS		(1)
40#define DEF_VERIFY		(0)
41#define DEF_STONEWALL		(0)
42#define DEF_NUMJOBS		(1)
43#define DEF_USE_THREAD		(0)
44#define DEF_FILE_SIZE		(1024 * 1024 * 1024UL)
45#define DEF_ZONE_SIZE		(0)
46#define DEF_ZONE_SKIP		(0)
47#define DEF_RWMIX_CYCLE		(500)
48#define DEF_RWMIX_READ		(50)
49#define DEF_NICE		(0)
50#define DEF_NR_FILES		(1)
51#define DEF_UNLINK		(1)
52#define DEF_WRITE_BW_LOG	(0)
53#define DEF_WRITE_LAT_LOG	(0)
54#define DEF_NO_RAND_MAP		(0)
55#define DEF_HUGEPAGE_SIZE	FIO_HUGE_PAGE
56#define DEF_THINKTIME_BLOCKS	(1)
57
58#define td_var_offset(var)	((size_t) &((struct thread_data *)0)->var)
59
60static int str_rw_cb(void *, const char *);
61static int str_ioengine_cb(void *, const char *);
62static int str_mem_cb(void *, const char *);
63static int str_verify_cb(void *, const char *);
64static int str_lockmem_cb(void *, unsigned long *);
65#ifdef FIO_HAVE_IOPRIO
66static int str_prio_cb(void *, unsigned int *);
67static int str_prioclass_cb(void *, unsigned int *);
68#endif
69static int str_exitall_cb(void);
70static int str_cpumask_cb(void *, unsigned int *);
71
72/*
73 * Map of job/command line options
74 */
75static struct fio_option options[] = {
76	{
77		.name	= "name",
78		.type	= FIO_OPT_STR_STORE,
79		.off1	= td_var_offset(name),
80	},
81	{
82		.name	= "directory",
83		.type	= FIO_OPT_STR_STORE,
84		.off1	= td_var_offset(directory),
85	},
86	{
87		.name	= "filename",
88		.type	= FIO_OPT_STR_STORE,
89		.off1	= td_var_offset(filename),
90	},
91	{
92		.name	= "rw",
93		.type	= FIO_OPT_STR,
94		.cb	= str_rw_cb,
95	},
96	{
97		.name	= "ioengine",
98		.type	= FIO_OPT_STR,
99		.cb	= str_ioengine_cb,
100	},
101	{
102		.name	= "mem",
103		.type	= FIO_OPT_STR,
104		.cb	= str_mem_cb,
105	},
106	{
107		.name	= "verify",
108		.type	= FIO_OPT_STR,
109		.cb	= str_verify_cb,
110	},
111	{
112		.name	= "write_iolog",
113		.type	= FIO_OPT_STR_STORE,
114		.off1	= td_var_offset(write_iolog_file),
115	},
116	{
117		.name	= "read_iolog",
118		.type	= FIO_OPT_STR_STORE,
119		.off1	= td_var_offset(read_iolog_file),
120	},
121	{
122		.name	= "exec_prerun",
123		.type	= FIO_OPT_STR_STORE,
124		.off1	= td_var_offset(exec_prerun),
125	},
126	{
127		.name	= "exec_postrun",
128		.type	= FIO_OPT_STR_STORE,
129		.off1	= td_var_offset(exec_postrun),
130	},
131#ifdef FIO_HAVE_IOSCHED_SWITCH
132	{
133		.name	= "ioscheduler",
134		.type	= FIO_OPT_STR_STORE,
135		.off1	= td_var_offset(ioscheduler),
136	},
137#endif
138	{
139		.name	= "size",
140		.type	= FIO_OPT_STR_VAL,
141		.off1	= td_var_offset(total_file_size),
142	},
143	{
144		.name	= "bs",
145		.type	= FIO_OPT_STR_VAL_INT,
146		.off1	= td_var_offset(bs[DDIR_READ]),
147		.off2	= td_var_offset(bs[DDIR_WRITE]),
148	},
149	{
150		.name	= "offset",
151		.type	= FIO_OPT_STR_VAL,
152		.off1	= td_var_offset(start_offset),
153	},
154	{
155		.name	= "zonesize",
156		.type	= FIO_OPT_STR_VAL,
157		.off1	= td_var_offset(zone_size),
158	},
159	{
160		.name	= "zoneskip",
161		.type	= FIO_OPT_STR_VAL,
162		.off1	= td_var_offset(zone_skip),
163	},
164	{
165		.name	= "lockmem",
166		.type	= FIO_OPT_STR_VAL,
167		.cb	= str_lockmem_cb,
168	},
169	{
170		.name	= "bsrange",
171		.type	= FIO_OPT_RANGE,
172		.off1	= td_var_offset(min_bs[DDIR_READ]),
173		.off2	= td_var_offset(max_bs[DDIR_READ]),
174		.off3	= td_var_offset(min_bs[DDIR_WRITE]),
175		.off4	= td_var_offset(max_bs[DDIR_WRITE]),
176	},
177	{
178		.name	= "nrfiles",
179		.type	= FIO_OPT_INT,
180		.off1	= td_var_offset(nr_files),
181	},
182	{
183		.name	= "iodepth",
184		.type	= FIO_OPT_INT,
185		.off1	= td_var_offset(iodepth),
186	},
187	{
188		.name	= "fsync",
189		.type	= FIO_OPT_INT,
190		.off1	= td_var_offset(fsync_blocks),
191	},
192	{
193		.name	= "rwmixcycle",
194		.type	= FIO_OPT_INT,
195		.off1	= td_var_offset(rwmixcycle),
196	},
197	{
198		.name	= "rwmixread",
199		.type	= FIO_OPT_INT,
200		.off1	= td_var_offset(rwmixread),
201		.max_val= 100,
202	},
203	{
204		.name	= "rwmixwrite",
205		.type	= FIO_OPT_INT,
206		.off1	= td_var_offset(rwmixwrite),
207		.max_val= 100,
208	},
209	{
210		.name	= "nice",
211		.type	= FIO_OPT_INT,
212		.off1	= td_var_offset(nice),
213	},
214#ifdef FIO_HAVE_IOPRIO
215	{
216		.name	= "prio",
217		.type	= FIO_OPT_INT,
218		.cb	= str_prio_cb,
219	},
220	{
221		.name	= "prioclass",
222		.type	= FIO_OPT_INT,
223		.cb	= str_prioclass_cb,
224	},
225#endif
226	{
227		.name	= "thinktime",
228		.type	= FIO_OPT_INT,
229		.off1	= td_var_offset(thinktime)
230	},
231	{
232		.name	= "thinktime_blocks",
233		.type	= FIO_OPT_INT,
234		.off1	= td_var_offset(thinktime_blocks)
235	},
236	{
237		.name	= "rate",
238		.type	= FIO_OPT_INT,
239		.off1	= td_var_offset(rate)
240	},
241	{
242		.name	= "ratemin",
243		.type	= FIO_OPT_INT,
244		.off1	= td_var_offset(ratemin)
245	},
246	{
247		.name	= "ratecycle",
248		.type	= FIO_OPT_INT,
249		.off1	= td_var_offset(ratecycle)
250	},
251	{
252		.name	= "startdelay",
253		.type	= FIO_OPT_INT,
254		.off1	= td_var_offset(start_delay)
255	},
256	{
257		.name	= "timeout",
258		.type	= FIO_OPT_STR_VAL_TIME,
259		.off1	= td_var_offset(timeout)
260	},
261	{
262		.name	= "invalidate",
263		.type	= FIO_OPT_INT,
264		.off1	= td_var_offset(invalidate_cache)
265	},
266	{
267		.name	= "sync",
268		.type	= FIO_OPT_INT,
269		.off1	= td_var_offset(sync_io)
270	},
271	{
272		.name	= "bwavgtime",
273		.type	= FIO_OPT_INT,
274		.off1	= td_var_offset(bw_avg_time)
275	},
276	{
277		.name	= "create_serialize",
278		.type	= FIO_OPT_INT,
279		.off1	= td_var_offset(create_serialize)
280	},
281	{
282		.name	= "create_fsync",
283		.type	= FIO_OPT_INT,
284		.off1	= td_var_offset(create_fsync)
285	},
286	{
287		.name	= "loops",
288		.type	= FIO_OPT_INT,
289		.off1	= td_var_offset(loops)
290	},
291	{
292		.name	= "numjobs",
293		.type	= FIO_OPT_INT,
294		.off1	= td_var_offset(numjobs)
295	},
296	{
297		.name	= "cpuload",
298		.type	= FIO_OPT_INT,
299		.off1	= td_var_offset(cpuload)
300	},
301	{
302		.name	= "cpuchunks",
303		.type	= FIO_OPT_INT,
304		.off1	= td_var_offset(cpucycle)
305	},
306	{
307		.name	= "direct",
308		.type	= FIO_OPT_INT,
309		.off1	= td_var_offset(odirect)
310	},
311	{
312		.name	= "overwrite",
313		.type	= FIO_OPT_INT,
314		.off1	= td_var_offset(overwrite)
315	},
316#ifdef FIO_HAVE_CPU_AFFINITY
317	{
318		.name	= "cpumask",
319		.type	= FIO_OPT_INT,
320		.cb	= str_cpumask_cb,
321	},
322#endif
323	{
324		.name	= "end_fsync",
325		.type	= FIO_OPT_INT,
326		.off1	= td_var_offset(end_fsync)
327	},
328	{
329		.name	= "unlink",
330		.type	= FIO_OPT_STR_SET,
331		.off1	= td_var_offset(unlink),
332	},
333	{
334		.name	= "exitall",
335		.type	= FIO_OPT_STR_SET,
336		.cb	= str_exitall_cb,
337	},
338	{
339		.name	= "stonewall",
340		.type	= FIO_OPT_STR_SET,
341		.off1	= td_var_offset(stonewall),
342	},
343	{
344		.name	= "thread",
345		.type	= FIO_OPT_STR_SET,
346		.off1	= td_var_offset(thread),
347	},
348	{
349		.name	= "write_bw_log",
350		.type	= FIO_OPT_STR_SET,
351		.off1	= td_var_offset(write_bw_log),
352	},
353	{
354		.name	= "write_lat_log",
355		.type	= FIO_OPT_STR_SET,
356		.off1	= td_var_offset(write_lat_log),
357	},
358	{
359		.name	= "norandommap",
360		.type	= FIO_OPT_STR_SET,
361		.off1	= td_var_offset(norandommap),
362	},
363	{
364		.name	= "bs_unaligned",
365		.type	= FIO_OPT_STR_SET,
366		.off1	= td_var_offset(bs_unaligned),
367	},
368	{
369		.name	= "hugepage-size",
370		.type	= FIO_OPT_STR_VAL,
371		.off1	= td_var_offset(hugepage_size),
372	},
373	{
374		.name = NULL,
375	},
376};
377
378#define FIO_JOB_OPTS	(sizeof(options) / sizeof(struct fio_option))
379#define FIO_CMD_OPTS	(16)
380#define FIO_GETOPT_JOB	(0x89988998)
381
382/*
383 * Command line options. These will contain the above, plus a few
384 * extra that only pertain to fio itself and not jobs.
385 */
386static struct option long_options[FIO_JOB_OPTS + FIO_CMD_OPTS] = {
387	{
388		.name		= "output",
389		.has_arg	= required_argument,
390		.val		= 'o',
391	},
392	{
393		.name		= "timeout",
394		.has_arg	= required_argument,
395		.val		= 't',
396	},
397	{
398		.name		= "latency-log",
399		.has_arg	= required_argument,
400		.val		= 'l',
401	},
402	{
403		.name		= "bandwidth-log",
404		.has_arg	= required_argument,
405		.val		= 'b',
406	},
407	{
408		.name		= "minimal",
409		.has_arg	= optional_argument,
410		.val		= 'm',
411	},
412	{
413		.name		= "version",
414		.has_arg	= no_argument,
415		.val		= 'v',
416	},
417	{
418		.name		= NULL,
419	},
420};
421
422static int def_timeout = DEF_TIMEOUT;
423
424static char fio_version_string[] = "fio 1.10";
425
426static char **ini_file;
427static int max_jobs = MAX_JOBS;
428
429struct thread_data def_thread;
430struct thread_data *threads = NULL;
431
432int exitall_on_terminate = 0;
433int terse_output = 0;
434unsigned long long mlock_size = 0;
435FILE *f_out = NULL;
436FILE *f_err = NULL;
437
438static int write_lat_log = DEF_WRITE_LAT_LOG;
439static int write_bw_log = DEF_WRITE_BW_LOG;
440
441/*
442 * Return a free job structure.
443 */
444static struct thread_data *get_new_job(int global, struct thread_data *parent)
445{
446	struct thread_data *td;
447
448	if (global)
449		return &def_thread;
450	if (thread_number >= max_jobs)
451		return NULL;
452
453	td = &threads[thread_number++];
454	*td = *parent;
455
456	td->thread_number = thread_number;
457	return td;
458}
459
460static void put_job(struct thread_data *td)
461{
462	if (td == &def_thread)
463		return;
464
465	memset(&threads[td->thread_number - 1], 0, sizeof(*td));
466	thread_number--;
467}
468
469/*
470 * Lazy way of fixing up options that depend on each other. We could also
471 * define option callback handlers, but this is easier.
472 */
473static void fixup_options(struct thread_data *td)
474{
475	if (!td->rwmixread && td->rwmixwrite)
476		td->rwmixread = 100 - td->rwmixwrite;
477
478	if (td->write_iolog_file && td->read_iolog_file) {
479		log_err("fio: read iolog overrides write_iolog\n");
480		free(td->write_iolog_file);
481		td->write_iolog_file = NULL;
482	}
483
484	if (td->io_ops->flags & FIO_SYNCIO)
485		td->iodepth = 1;
486	else {
487		if (!td->iodepth)
488			td->iodepth = td->nr_files;
489	}
490
491	/*
492	 * only really works for sequential io for now, and with 1 file
493	 */
494	if (td->zone_size && !td->sequential && td->nr_files == 1)
495		td->zone_size = 0;
496
497	/*
498	 * Reads can do overwrites, we always need to pre-create the file
499	 */
500	if (td_read(td) || td_rw(td))
501		td->overwrite = 1;
502
503	if (!td->min_bs[DDIR_READ])
504		td->min_bs[DDIR_READ]= td->bs[DDIR_READ];
505	if (!td->max_bs[DDIR_READ])
506		td->max_bs[DDIR_READ] = td->bs[DDIR_READ];
507	if (!td->min_bs[DDIR_WRITE])
508		td->min_bs[DDIR_WRITE]= td->bs[DDIR_WRITE];
509	if (!td->max_bs[DDIR_WRITE])
510		td->max_bs[DDIR_WRITE] = td->bs[DDIR_WRITE];
511
512	td->rw_min_bs = min(td->min_bs[DDIR_READ], td->min_bs[DDIR_WRITE]);
513
514	if (td_read(td) && !td_rw(td))
515		td->verify = 0;
516
517	if (td->norandommap && td->verify != VERIFY_NONE) {
518		log_err("fio: norandommap given, verify disabled\n");
519		td->verify = VERIFY_NONE;
520	}
521	if (td->bs_unaligned && (td->odirect || td->io_ops->flags & FIO_RAWIO))
522		log_err("fio: bs_unaligned may not work with raw io\n");
523
524	/*
525	 * O_DIRECT and char doesn't mix, clear that flag if necessary.
526	 */
527	if (td->filetype == FIO_TYPE_CHAR && td->odirect)
528		td->odirect = 0;
529}
530
531/*
532 * This function leaks the buffer
533 */
534static char *to_kmg(unsigned int val)
535{
536	char *buf = malloc(32);
537	char post[] = { 0, 'K', 'M', 'G', 'P', 0 };
538	char *p = post;
539
540	do {
541		if (val & 1023)
542			break;
543
544		val >>= 10;
545		p++;
546	} while (*p);
547
548	snprintf(buf, 31, "%u%c", val, *p);
549	return buf;
550}
551
552/*
553 * Adds a job to the list of things todo. Sanitizes the various options
554 * to make sure we don't have conflicts, and initializes various
555 * members of td.
556 */
557static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
558{
559	const char *ddir_str[] = { "read", "write", "randread", "randwrite",
560				   "rw", NULL, "randrw" };
561	struct stat sb;
562	int numjobs, ddir, i;
563	struct fio_file *f;
564
565	/*
566	 * the def_thread is just for options, it's not a real job
567	 */
568	if (td == &def_thread)
569		return 0;
570
571	/*
572	 * Set default io engine, if none set
573	 */
574	if (!td->io_ops) {
575		td->io_ops = load_ioengine(td, DEF_IO_ENGINE_NAME);
576		if (!td->io_ops) {
577			log_err("default engine %s not there?\n", DEF_IO_ENGINE_NAME);
578			return 1;
579		}
580	}
581
582	if (td->odirect)
583		td->io_ops->flags |= FIO_RAWIO;
584
585	td->filetype = FIO_TYPE_FILE;
586	if (!stat(jobname, &sb)) {
587		if (S_ISBLK(sb.st_mode))
588			td->filetype = FIO_TYPE_BD;
589		else if (S_ISCHR(sb.st_mode))
590			td->filetype = FIO_TYPE_CHAR;
591	}
592
593	fixup_options(td);
594
595	if (td->filename)
596		td->nr_uniq_files = 1;
597	else
598		td->nr_uniq_files = td->nr_files;
599
600	if (td->filetype == FIO_TYPE_FILE || td->filename) {
601		char tmp[PATH_MAX];
602		int len = 0;
603
604		if (td->directory && td->directory[0] != '\0')
605			sprintf(tmp, "%s/", td->directory);
606
607		td->files = malloc(sizeof(struct fio_file) * td->nr_files);
608
609		for_each_file(td, f, i) {
610			memset(f, 0, sizeof(*f));
611			f->fd = -1;
612
613			if (td->filename)
614				sprintf(tmp + len, "%s", td->filename);
615			else
616				sprintf(tmp + len, "%s.%d.%d", jobname, td->thread_number, i);
617			f->file_name = strdup(tmp);
618		}
619	} else {
620		td->nr_files = 1;
621		td->files = malloc(sizeof(struct fio_file));
622		f = &td->files[0];
623
624		memset(f, 0, sizeof(*f));
625		f->fd = -1;
626		f->file_name = strdup(jobname);
627	}
628
629	for_each_file(td, f, i) {
630		f->file_size = td->total_file_size / td->nr_files;
631		f->file_offset = td->start_offset;
632	}
633
634	fio_sem_init(&td->mutex, 0);
635
636	td->clat_stat[0].min_val = td->clat_stat[1].min_val = ULONG_MAX;
637	td->slat_stat[0].min_val = td->slat_stat[1].min_val = ULONG_MAX;
638	td->bw_stat[0].min_val = td->bw_stat[1].min_val = ULONG_MAX;
639
640	if (td->stonewall && td->thread_number > 1)
641		groupid++;
642
643	td->groupid = groupid;
644
645	if (setup_rate(td))
646		goto err;
647
648	if (td->write_lat_log) {
649		setup_log(&td->slat_log);
650		setup_log(&td->clat_log);
651	}
652	if (td->write_bw_log)
653		setup_log(&td->bw_log);
654
655	if (!td->name)
656		td->name = strdup(jobname);
657
658	ddir = td->ddir + (!td->sequential << 1) + (td->iomix << 2);
659
660	if (!terse_output) {
661		if (!job_add_num) {
662			if (td->io_ops->flags & FIO_CPUIO)
663				fprintf(f_out, "%s: ioengine=cpu, cpuload=%u, cpucycle=%u\n", td->name, td->cpuload, td->cpucycle);
664			else {
665				char *c1, *c2, *c3, *c4;
666
667				c1 = to_kmg(td->min_bs[DDIR_READ]);
668				c2 = to_kmg(td->max_bs[DDIR_READ]);
669				c3 = to_kmg(td->min_bs[DDIR_WRITE]);
670				c4 = to_kmg(td->max_bs[DDIR_WRITE]);
671
672				fprintf(f_out, "%s: (g=%d): rw=%s, odir=%u, bs=%s-%s/%s-%s, rate=%u, ioengine=%s, iodepth=%u\n", td->name, td->groupid, ddir_str[ddir], td->odirect, c1, c2, c3, c4, td->rate, td->io_ops->name, td->iodepth);
673
674				free(c1);
675				free(c2);
676				free(c3);
677				free(c4);
678			}
679		} else if (job_add_num == 1)
680			fprintf(f_out, "...\n");
681	}
682
683	/*
684	 * recurse add identical jobs, clear numjobs and stonewall options
685	 * as they don't apply to sub-jobs
686	 */
687	numjobs = td->numjobs;
688	while (--numjobs) {
689		struct thread_data *td_new = get_new_job(0, td);
690
691		if (!td_new)
692			goto err;
693
694		td_new->numjobs = 1;
695		td_new->stonewall = 0;
696		job_add_num = numjobs - 1;
697
698		if (add_job(td_new, jobname, job_add_num))
699			goto err;
700	}
701	return 0;
702err:
703	put_job(td);
704	return -1;
705}
706
707/*
708 * Initialize the various random states we need (random io, block size ranges,
709 * read/write mix, etc).
710 */
711int init_random_state(struct thread_data *td)
712{
713	unsigned long seeds[4];
714	int fd, num_maps, blocks, i;
715	struct fio_file *f;
716
717	if (td->io_ops->flags & FIO_CPUIO)
718		return 0;
719
720	fd = open("/dev/urandom", O_RDONLY);
721	if (fd == -1) {
722		td_verror(td, errno);
723		return 1;
724	}
725
726	if (read(fd, seeds, sizeof(seeds)) < (int) sizeof(seeds)) {
727		td_verror(td, EIO);
728		close(fd);
729		return 1;
730	}
731
732	close(fd);
733
734	os_random_seed(seeds[0], &td->bsrange_state);
735	os_random_seed(seeds[1], &td->verify_state);
736	os_random_seed(seeds[2], &td->rwmix_state);
737
738	if (td->sequential)
739		return 0;
740
741	if (td->rand_repeatable)
742		seeds[3] = DEF_RANDSEED;
743
744	if (!td->norandommap) {
745		for_each_file(td, f, i) {
746			blocks = (f->file_size + td->rw_min_bs - 1) / td->rw_min_bs;
747			num_maps = (blocks + BLOCKS_PER_MAP-1)/ BLOCKS_PER_MAP;
748			f->file_map = malloc(num_maps * sizeof(long));
749			f->num_maps = num_maps;
750			memset(f->file_map, 0, num_maps * sizeof(long));
751		}
752	}
753
754	os_random_seed(seeds[3], &td->random_state);
755	return 0;
756}
757
758static void fill_cpu_mask(os_cpu_mask_t cpumask, int cpu)
759{
760#ifdef FIO_HAVE_CPU_AFFINITY
761	unsigned int i;
762
763	CPU_ZERO(&cpumask);
764
765	for (i = 0; i < sizeof(int) * 8; i++) {
766		if ((1 << i) & cpu)
767			CPU_SET(i, &cpumask);
768	}
769#endif
770}
771
772static int is_empty_or_comment(char *line)
773{
774	unsigned int i;
775
776	for (i = 0; i < strlen(line); i++) {
777		if (line[i] == ';')
778			return 1;
779		if (!isspace(line[i]) && !iscntrl(line[i]))
780			return 0;
781	}
782
783	return 1;
784}
785
786static int str_rw_cb(void *data, const char *mem)
787{
788	struct thread_data *td = data;
789
790	if (!strncmp(mem, "read", 4) || !strncmp(mem, "0", 1)) {
791		td->ddir = DDIR_READ;
792		td->sequential = 1;
793		return 0;
794	} else if (!strncmp(mem, "randread", 8)) {
795		td->ddir = DDIR_READ;
796		td->sequential = 0;
797		return 0;
798	} else if (!strncmp(mem, "write", 5) || !strncmp(mem, "1", 1)) {
799		td->ddir = DDIR_WRITE;
800		td->sequential = 1;
801		return 0;
802	} else if (!strncmp(mem, "randwrite", 9)) {
803		td->ddir = DDIR_WRITE;
804		td->sequential = 0;
805		return 0;
806	} else if (!strncmp(mem, "rw", 2)) {
807		td->ddir = DDIR_READ;
808		td->iomix = 1;
809		td->sequential = 1;
810		return 0;
811	} else if (!strncmp(mem, "randrw", 6)) {
812		td->ddir = DDIR_READ;
813		td->iomix = 1;
814		td->sequential = 0;
815		return 0;
816	}
817
818	log_err("fio: data direction: read, write, randread, randwrite, rw, randrw\n");
819	return 1;
820}
821
822static int str_verify_cb(void *data, const char *mem)
823{
824	struct thread_data *td = data;
825
826	if (!strncmp(mem, "0", 1)) {
827		td->verify = VERIFY_NONE;
828		return 0;
829	} else if (!strncmp(mem, "md5", 3) || !strncmp(mem, "1", 1)) {
830		td->verify = VERIFY_MD5;
831		return 0;
832	} else if (!strncmp(mem, "crc32", 5)) {
833		td->verify = VERIFY_CRC32;
834		return 0;
835	}
836
837	log_err("fio: verify types: md5, crc32\n");
838	return 1;
839}
840
841/*
842 * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
843 */
844static char *get_mmap_file(const char *str)
845{
846	char *p = strstr(str, ":");
847
848	if (!p)
849		return NULL;
850
851	p++;
852	strip_blank_front(&p);
853	strip_blank_end(p);
854	return strdup(p);
855}
856
857static int str_mem_cb(void *data, const char *mem)
858{
859	struct thread_data *td = data;
860
861	if (!strncmp(mem, "malloc", 6)) {
862		td->mem_type = MEM_MALLOC;
863		return 0;
864	} else if (!strncmp(mem, "mmaphuge", 8)) {
865#ifdef FIO_HAVE_HUGETLB
866		/*
867		 * mmaphuge must be appended with the actual file
868		 */
869		td->mmapfile = get_mmap_file(mem);
870		if (!td->mmapfile) {
871			log_err("fio: mmaphuge:/path/to/file\n");
872			return 1;
873		}
874
875		td->mem_type = MEM_MMAPHUGE;
876		return 0;
877#else
878		log_err("fio: mmaphuge not available\n");
879		return 1;
880#endif
881	} else if (!strncmp(mem, "mmap", 4)) {
882		/*
883		 * Check if the user wants file backed memory. It's ok
884		 * if there's no file given, we'll just use anon mamp then.
885		 */
886		td->mmapfile = get_mmap_file(mem);
887		td->mem_type = MEM_MMAP;
888		return 0;
889	} else if (!strncmp(mem, "shmhuge", 7)) {
890#ifdef FIO_HAVE_HUGETLB
891		td->mem_type = MEM_SHMHUGE;
892		return 0;
893#else
894		log_err("fio: shmhuge not available\n");
895		return 1;
896#endif
897	} else if (!strncmp(mem, "shm", 3)) {
898		td->mem_type = MEM_SHM;
899		return 0;
900	}
901
902	log_err("fio: mem type: malloc, shm, shmhuge, mmap, mmaphuge\n");
903	return 1;
904}
905
906static int str_ioengine_cb(void *data, const char *str)
907{
908	struct thread_data *td = data;
909
910	td->io_ops = load_ioengine(td, str);
911	if (td->io_ops)
912		return 0;
913
914	log_err("fio: ioengine= libaio, posixaio, sync, mmap, sgio, splice, cpu, null\n");
915	log_err("fio: or specify path to dynamic ioengine module\n");
916	return 1;
917}
918
919static int str_lockmem_cb(void fio_unused *data, unsigned long *val)
920{
921	mlock_size = *val;
922	return 0;
923}
924
925#ifdef FIO_HAVE_IOPRIO
926static int str_prioclass_cb(void *data, unsigned int *val)
927{
928	struct thread_data *td = data;
929
930	td->ioprio |= *val << IOPRIO_CLASS_SHIFT;
931	return 0;
932}
933
934static int str_prio_cb(void *data, unsigned int *val)
935{
936	struct thread_data *td = data;
937
938	td->ioprio |= *val;
939	return 0;
940}
941#endif
942
943static int str_exitall_cb(void)
944{
945	exitall_on_terminate = 1;
946	return 0;
947}
948
949static int str_cpumask_cb(void *data, unsigned int *val)
950{
951	struct thread_data *td = data;
952
953	fill_cpu_mask(td->cpumask, *val);
954	return 0;
955}
956
957/*
958 * This is our [ini] type file parser.
959 */
960static int parse_jobs_ini(char *file, int stonewall_flag)
961{
962	unsigned int global;
963	struct thread_data *td;
964	char *string, *name;
965	fpos_t off;
966	FILE *f;
967	char *p;
968	int ret = 0, stonewall;
969
970	f = fopen(file, "r");
971	if (!f) {
972		perror("fopen job file");
973		return 1;
974	}
975
976	string = malloc(4096);
977	name = malloc(256);
978	memset(name, 0, 256);
979
980	stonewall = stonewall_flag;
981	do {
982		p = fgets(string, 4095, f);
983		if (!p)
984			break;
985		if (is_empty_or_comment(p))
986			continue;
987		if (sscanf(p, "[%255s]", name) != 1)
988			continue;
989
990		global = !strncmp(name, "global", 6);
991
992		name[strlen(name) - 1] = '\0';
993
994		td = get_new_job(global, &def_thread);
995		if (!td) {
996			ret = 1;
997			break;
998		}
999
1000		/*
1001		 * Seperate multiple job files by a stonewall
1002		 */
1003		if (!global && stonewall) {
1004			td->stonewall = stonewall;
1005			stonewall = 0;
1006		}
1007
1008		fgetpos(f, &off);
1009		while ((p = fgets(string, 4096, f)) != NULL) {
1010			if (is_empty_or_comment(p))
1011				continue;
1012
1013			strip_blank_front(&p);
1014
1015			if (p[0] == '[')
1016				break;
1017
1018			strip_blank_end(p);
1019
1020			fgetpos(f, &off);
1021
1022			/*
1023			 * Don't break here, continue parsing options so we
1024			 * dump all the bad ones. Makes trial/error fixups
1025			 * easier on the user.
1026			 */
1027			ret |= parse_option(p, options, td);
1028		}
1029
1030		if (!ret) {
1031			fsetpos(f, &off);
1032			ret = add_job(td, name, 0);
1033		} else {
1034			log_err("fio: job %s dropped\n", name);
1035			put_job(td);
1036		}
1037	} while (!ret);
1038
1039	free(string);
1040	free(name);
1041	fclose(f);
1042	return ret;
1043}
1044
1045static int fill_def_thread(void)
1046{
1047	memset(&def_thread, 0, sizeof(def_thread));
1048
1049	if (fio_getaffinity(getpid(), &def_thread.cpumask) == -1) {
1050		perror("sched_getaffinity");
1051		return 1;
1052	}
1053
1054	/*
1055	 * fill globals
1056	 */
1057	def_thread.ddir = DDIR_READ;
1058	def_thread.iomix = 0;
1059	def_thread.bs[DDIR_READ] = DEF_BS;
1060	def_thread.bs[DDIR_WRITE] = DEF_BS;
1061	def_thread.min_bs[DDIR_READ] = def_thread.min_bs[DDIR_WRITE] = 0;
1062	def_thread.max_bs[DDIR_READ] = def_thread.max_bs[DDIR_WRITE] = 0;
1063	def_thread.odirect = DEF_ODIRECT;
1064	def_thread.ratecycle = DEF_RATE_CYCLE;
1065	def_thread.sequential = DEF_SEQUENTIAL;
1066	def_thread.timeout = def_timeout;
1067	def_thread.overwrite = DEF_OVERWRITE;
1068	def_thread.invalidate_cache = DEF_INVALIDATE;
1069	def_thread.sync_io = DEF_SYNCIO;
1070	def_thread.mem_type = MEM_MALLOC;
1071	def_thread.bw_avg_time = DEF_BWAVGTIME;
1072	def_thread.create_serialize = DEF_CREATE_SER;
1073	def_thread.create_fsync = DEF_CREATE_FSYNC;
1074	def_thread.loops = DEF_LOOPS;
1075	def_thread.verify = DEF_VERIFY;
1076	def_thread.stonewall = DEF_STONEWALL;
1077	def_thread.numjobs = DEF_NUMJOBS;
1078	def_thread.use_thread = DEF_USE_THREAD;
1079	def_thread.rwmixcycle = DEF_RWMIX_CYCLE;
1080	def_thread.rwmixread = DEF_RWMIX_READ;
1081	def_thread.nice = DEF_NICE;
1082	def_thread.rand_repeatable = DEF_RAND_REPEAT;
1083	def_thread.nr_files = DEF_NR_FILES;
1084	def_thread.unlink = DEF_UNLINK;
1085	def_thread.write_bw_log = write_bw_log;
1086	def_thread.write_lat_log = write_lat_log;
1087	def_thread.norandommap = DEF_NO_RAND_MAP;
1088	def_thread.hugepage_size = DEF_HUGEPAGE_SIZE;
1089	def_thread.thinktime_blocks = DEF_THINKTIME_BLOCKS;
1090#ifdef FIO_HAVE_DISK_UTIL
1091	def_thread.do_disk_util = 1;
1092#endif
1093
1094	return 0;
1095}
1096
1097static void usage(void)
1098{
1099	printf("%s\n", fio_version_string);
1100	printf("\t--output\tWrite output to file\n");
1101	printf("\t--timeout\tRuntime in seconds\n");
1102	printf("\t--latency-log\tGenerate per-job latency logs\n");
1103	printf("\t--bandwidth-log\tGenerate per-job bandwidth logs\n");
1104	printf("\t--minimal\tMinimal (terse) output\n");
1105	printf("\t--version\tPrint version info and exit\n");
1106}
1107
1108static int parse_cmd_line(int argc, char *argv[])
1109{
1110	struct thread_data *td = NULL;
1111	int c, ini_idx = 0, lidx, ret;
1112
1113	while ((c = getopt_long(argc, argv, "", long_options, &lidx)) != -1) {
1114		switch (c) {
1115		case 't':
1116			def_timeout = atoi(optarg);
1117			break;
1118		case 'l':
1119			write_lat_log = 1;
1120			break;
1121		case 'w':
1122			write_bw_log = 1;
1123			break;
1124		case 'o':
1125			f_out = fopen(optarg, "w+");
1126			if (!f_out) {
1127				perror("fopen output");
1128				exit(1);
1129			}
1130			f_err = f_out;
1131			break;
1132		case 'm':
1133			terse_output = 1;
1134			break;
1135		case 'h':
1136			usage();
1137			exit(0);
1138		case 'v':
1139			printf("%s\n", fio_version_string);
1140			exit(0);
1141		case FIO_GETOPT_JOB: {
1142			const char *opt = long_options[lidx].name;
1143			char *val = optarg;
1144
1145			if (!strncmp(opt, "name", 4) && td) {
1146				ret = add_job(td, td->name ?: "fio", 0);
1147				if (ret) {
1148					put_job(td);
1149					return 0;
1150				}
1151				td = NULL;
1152			}
1153			if (!td) {
1154				int global = !strncmp(val, "global", 6);
1155
1156				td = get_new_job(global, &def_thread);
1157				if (!td)
1158					return 0;
1159			}
1160
1161			ret = parse_cmd_option(opt, val, options, td);
1162			if (ret) {
1163				log_err("fio: job dropped\n");
1164				put_job(td);
1165				td = NULL;
1166			}
1167			break;
1168		}
1169		default:
1170			break;
1171		}
1172	}
1173
1174	if (td) {
1175		ret = add_job(td, td->name ?: "fio", 0);
1176		if (ret)
1177			put_job(td);
1178	}
1179
1180	while (optind < argc) {
1181		ini_idx++;
1182		ini_file = realloc(ini_file, ini_idx * sizeof(char *));
1183		ini_file[ini_idx - 1] = strdup(argv[optind]);
1184		optind++;
1185	}
1186
1187	return ini_idx;
1188}
1189
1190static void free_shm(void)
1191{
1192	struct shmid_ds sbuf;
1193
1194	if (threads) {
1195		shmdt((void *) threads);
1196		threads = NULL;
1197		shmctl(shm_id, IPC_RMID, &sbuf);
1198	}
1199}
1200
1201/*
1202 * The thread area is shared between the main process and the job
1203 * threads/processes. So setup a shared memory segment that will hold
1204 * all the job info.
1205 */
1206static int setup_thread_area(void)
1207{
1208	/*
1209	 * 1024 is too much on some machines, scale max_jobs if
1210	 * we get a failure that looks like too large a shm segment
1211	 */
1212	do {
1213		size_t size = max_jobs * sizeof(struct thread_data);
1214
1215		shm_id = shmget(0, size, IPC_CREAT | 0600);
1216		if (shm_id != -1)
1217			break;
1218		if (errno != EINVAL) {
1219			perror("shmget");
1220			break;
1221		}
1222
1223		max_jobs >>= 1;
1224	} while (max_jobs);
1225
1226	if (shm_id == -1)
1227		return 1;
1228
1229	threads = shmat(shm_id, NULL, 0);
1230	if (threads == (void *) -1) {
1231		perror("shmat");
1232		return 1;
1233	}
1234
1235	atexit(free_shm);
1236	return 0;
1237}
1238
1239/*
1240 * Copy the fio options into the long options map, so we mirror
1241 * job and cmd line options.
1242 */
1243static void dupe_job_options(void)
1244{
1245	struct fio_option *o;
1246	unsigned int i;
1247
1248	i = 0;
1249	while (long_options[i].name)
1250		i++;
1251
1252	o = &options[0];
1253	while (o->name) {
1254		long_options[i].name = o->name;
1255		long_options[i].val = FIO_GETOPT_JOB;
1256		if (o->type == FIO_OPT_STR_SET)
1257			long_options[i].has_arg = no_argument;
1258		else
1259			long_options[i].has_arg = required_argument;
1260
1261		i++;
1262		o++;
1263		assert(i < FIO_JOB_OPTS + FIO_CMD_OPTS);
1264	}
1265}
1266
1267int parse_options(int argc, char *argv[])
1268{
1269	int job_files, i;
1270
1271	f_out = stdout;
1272	f_err = stderr;
1273
1274	dupe_job_options();
1275
1276	if (setup_thread_area())
1277		return 1;
1278	if (fill_def_thread())
1279		return 1;
1280
1281	job_files = parse_cmd_line(argc, argv);
1282
1283	for (i = 0; i < job_files; i++) {
1284		if (fill_def_thread())
1285			return 1;
1286		if (parse_jobs_ini(ini_file[i], i))
1287			return 1;
1288		free(ini_file[i]);
1289	}
1290
1291	free(ini_file);
1292
1293	if (!thread_number) {
1294		log_err("No jobs defined(s)\n");
1295		return 1;
1296	}
1297
1298	return 0;
1299}
1300