Start the process of making options more gfio friendly

We either need to eliminate the option callbacks, or ensure that
they don't have side effects outside of touching td->o. We will
need to use &td->o as the data passed in for the callbacks, not
the full td.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/backend.c b/backend.c
index 319bd25..4c784e8 100644
--- a/backend.c
+++ b/backend.c
@@ -1080,6 +1080,8 @@
 			goto err;
 	}
 
+	fio_verify_init(td);
+
 	fio_gettime(&td->epoch, NULL);
 	getrusage(RUSAGE_SELF, &td->ru_start);
 
diff --git a/cconv.c b/cconv.c
index 502cf82..8edfde0 100644
--- a/cconv.c
+++ b/cconv.c
@@ -29,6 +29,7 @@
 	string_to_cpu(&o->filename, top->filename);
 	string_to_cpu(&o->opendir, top->opendir);
 	string_to_cpu(&o->ioengine, top->ioengine);
+	string_to_cpu(&o->mmapfile, top->mmapfile);
 	string_to_cpu(&o->read_iolog_file, top->read_iolog_file);
 	string_to_cpu(&o->write_iolog_file, top->write_iolog_file);
 	string_to_cpu(&o->bw_log_file, top->bw_log_file);
@@ -207,6 +208,7 @@
 	string_to_net(top->filename, o->filename);
 	string_to_net(top->opendir, o->opendir);
 	string_to_net(top->ioengine, o->ioengine);
+	string_to_net(top->mmapfile, o->mmapfile);
 	string_to_net(top->read_iolog_file, o->read_iolog_file);
 	string_to_net(top->write_iolog_file, o->write_iolog_file);
 	string_to_net(top->bw_log_file, o->bw_log_file);
diff --git a/fio.h b/fio.h
index 6a7bd03..0aa24a5 100644
--- a/fio.h
+++ b/fio.h
@@ -110,7 +110,6 @@
 	unsigned int last_was_sync;
 	enum fio_ddir last_ddir;
 
-	char *mmapfile;
 	int mmapfd;
 
 	void *iolog_buf;
diff --git a/goptions.c b/goptions.c
index 28df693..b78accd 100644
--- a/goptions.c
+++ b/goptions.c
@@ -523,7 +523,7 @@
 	else if (o->def) {
 		long long val;
 
-		check_str_bytes(o->def, &val, NULL);
+		check_str_bytes(o->def, &val, o);
 		defval = val;
 	}
 
@@ -730,7 +730,7 @@
 	if (o->def) {
 		long long val;
 
-		check_str_bytes(o->def, &val, NULL);
+		check_str_bytes(o->def, &val, o);
 		for (i = 0; i < GOPT_RANGE_SPIN; i++)
 			defvals[i] = val;
 	}
diff --git a/memory.c b/memory.c
index 82a79bd..0135abb 100644
--- a/memory.c
+++ b/memory.c
@@ -121,8 +121,8 @@
 
 	td->mmapfd = 1;
 
-	if (td->mmapfile) {
-		td->mmapfd = open(td->mmapfile, O_RDWR|O_CREAT, 0644);
+	if (td->o.mmapfile) {
+		td->mmapfd = open(td->o.mmapfile, O_RDWR|O_CREAT, 0644);
 
 		if (td->mmapfd < 0) {
 			td_verror(td, errno, "open mmap file");
@@ -146,7 +146,7 @@
 		td->orig_buffer = NULL;
 		if (td->mmapfd) {
 			close(td->mmapfd);
-			unlink(td->mmapfile);
+			unlink(td->o.mmapfile);
 		}
 
 		return 1;
@@ -159,10 +159,10 @@
 {
 	dprint(FD_MEM, "munmap %u %p\n", total_mem, td->orig_buffer);
 	munmap(td->orig_buffer, td->orig_buffer_size);
-	if (td->mmapfile) {
+	if (td->o.mmapfile) {
 		close(td->mmapfd);
-		unlink(td->mmapfile);
-		free(td->mmapfile);
+		unlink(td->o.mmapfile);
+		free(td->o.mmapfile);
 	}
 }
 
diff --git a/options.c b/options.c
index d051da1..937a76e 100644
--- a/options.c
+++ b/options.c
@@ -61,7 +61,7 @@
 	return bsp1->perc < bsp2->perc;
 }
 
-static int bssplit_ddir(struct thread_data *td, int ddir, char *str)
+static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
 {
 	struct bssplit *bssplit;
 	unsigned int i, perc, perc_missing;
@@ -69,7 +69,7 @@
 	long long val;
 	char *fname;
 
-	td->o.bssplit_nr[ddir] = 4;
+	o->bssplit_nr[ddir] = 4;
 	bssplit = malloc(4 * sizeof(struct bssplit));
 
 	i = 0;
@@ -84,9 +84,9 @@
 		/*
 		 * grow struct buffer, if needed
 		 */
-		if (i == td->o.bssplit_nr[ddir]) {
-			td->o.bssplit_nr[ddir] <<= 1;
-			bssplit = realloc(bssplit, td->o.bssplit_nr[ddir]
+		if (i == o->bssplit_nr[ddir]) {
+			o->bssplit_nr[ddir] <<= 1;
+			bssplit = realloc(bssplit, o->bssplit_nr[ddir]
 						  * sizeof(struct bssplit));
 		}
 
@@ -102,9 +102,9 @@
 		} else
 			perc = -1;
 
-		if (str_to_decimal(fname, &val, 1, td)) {
+		if (str_to_decimal(fname, &val, 1, o)) {
 			log_err("fio: bssplit conversion failed\n");
-			free(td->o.bssplit);
+			free(o->bssplit);
 			return 1;
 		}
 
@@ -118,13 +118,13 @@
 		i++;
 	}
 
-	td->o.bssplit_nr[ddir] = i;
+	o->bssplit_nr[ddir] = i;
 
 	/*
 	 * Now check if the percentages add up, and how much is missing
 	 */
 	perc = perc_missing = 0;
-	for (i = 0; i < td->o.bssplit_nr[ddir]; i++) {
+	for (i = 0; i < o->bssplit_nr[ddir]; i++) {
 		struct bssplit *bsp = &bssplit[i];
 
 		if (bsp->perc == (unsigned char) -1)
@@ -143,7 +143,7 @@
 	 * them.
 	 */
 	if (perc_missing) {
-		for (i = 0; i < td->o.bssplit_nr[ddir]; i++) {
+		for (i = 0; i < o->bssplit_nr[ddir]; i++) {
 			struct bssplit *bsp = &bssplit[i];
 
 			if (bsp->perc == (unsigned char) -1)
@@ -151,14 +151,14 @@
 		}
 	}
 
-	td->o.min_bs[ddir] = min_bs;
-	td->o.max_bs[ddir] = max_bs;
+	o->min_bs[ddir] = min_bs;
+	o->max_bs[ddir] = max_bs;
 
 	/*
 	 * now sort based on percentages, for ease of lookup
 	 */
-	qsort(bssplit, td->o.bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
-	td->o.bssplit[ddir] = bssplit;
+	qsort(bssplit, o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
+	o->bssplit[ddir] = bssplit;
 	return 0;
 }
 
@@ -175,19 +175,19 @@
 
 	odir = strchr(str, ',');
 	if (odir) {
-		ret = bssplit_ddir(td, DDIR_WRITE, odir + 1);
+		ret = bssplit_ddir(&td->o, DDIR_WRITE, odir + 1);
 		if (!ret) {
 			*odir = '\0';
-			ret = bssplit_ddir(td, DDIR_READ, str);
+			ret = bssplit_ddir(&td->o, DDIR_READ, str);
 		}
 	} else {
 		char *op;
 
 		op = strdup(str);
 
-		ret = bssplit_ddir(td, DDIR_READ, str);
+		ret = bssplit_ddir(&td->o, DDIR_READ, str);
 		if (!ret)
-			ret = bssplit_ddir(td, DDIR_WRITE, op);
+			ret = bssplit_ddir(&td->o, DDIR_WRITE, op);
 
 		free(op);
 	}
@@ -199,26 +199,27 @@
 static int str_rw_cb(void *data, const char *str)
 {
 	struct thread_data *td = data;
+	struct thread_options *o = &td->o;
 	char *nr = get_opt_postfix(str);
 
-	td->o.ddir_seq_nr = 1;
-	td->o.ddir_seq_add = 0;
+	o->ddir_seq_nr = 1;
+	o->ddir_seq_add = 0;
 
 	if (!nr)
 		return 0;
 
 	if (td_random(td))
-		td->o.ddir_seq_nr = atoi(nr);
+		o->ddir_seq_nr = atoi(nr);
 	else {
 		long long val;
 
-		if (str_to_decimal(nr, &val, 1, td)) {
+		if (str_to_decimal(nr, &val, 1, o)) {
 			log_err("fio: rw postfix parsing failed\n");
 			free(nr);
 			return 1;
 		}
 
-		td->o.ddir_seq_add = val;
+		o->ddir_seq_add = val;
 	}
 
 	free(nr);
@@ -228,10 +229,11 @@
 static int str_mem_cb(void *data, const char *mem)
 {
 	struct thread_data *td = data;
+	struct thread_options *o = &td->o;
 
-	if (td->o.mem_type == MEM_MMAPHUGE || td->o.mem_type == MEM_MMAP) {
-		td->mmapfile = get_opt_postfix(mem);
-		if (td->o.mem_type == MEM_MMAPHUGE && !td->mmapfile) {
+	if (o->mem_type == MEM_MMAPHUGE || o->mem_type == MEM_MMAP) {
+		o->mmapfile = get_opt_postfix(mem);
+		if (o->mem_type == MEM_MMAPHUGE && !o->mmapfile) {
 			log_err("fio: mmaphuge:/path/to/file\n");
 			return 1;
 		}
@@ -240,18 +242,6 @@
 	return 0;
 }
 
-static int str_verify_cb(void *data, const char *mem)
-{
-	struct thread_data *td = data;
-
-	if (td->o.verify == VERIFY_CRC32C_INTEL ||
-	    td->o.verify == VERIFY_CRC32C) {
-		crc32c_intel_probe();
-	}
-
-	return 0;
-}
-
 static int fio_clock_source_cb(void *data, const char *str)
 {
 	struct thread_data *td = data;
@@ -1784,7 +1774,6 @@
 		.type	= FIO_OPT_STR,
 		.off1	= td_var_offset(verify),
 		.help	= "Verify data written",
-		.cb	= str_verify_cb,
 		.def	= "0",
 		.category = FIO_OPT_C_IO,
 		.group	= FIO_OPT_G_VERIFY,
@@ -3256,11 +3245,11 @@
 
 unsigned int fio_get_kb_base(void *data)
 {
-	struct thread_data *td = data;
+	struct thread_options *o = data;
 	unsigned int kb_base = 0;
 
-	if (td)
-		kb_base = td->o.kb_base;
+	if (o)
+		kb_base = o->kb_base;
 	if (!kb_base)
 		kb_base = 1024;
 
diff --git a/thread_options.h b/thread_options.h
index 61f4f57..e9c67ee 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -43,6 +43,7 @@
 	char *filename;
 	char *opendir;
 	char *ioengine;
+	char *mmapfile;
 	enum td_ddir td_ddir;
 	unsigned int rw_seq;
 	unsigned int kb_base;
@@ -226,6 +227,7 @@
 	uint8_t filename[FIO_TOP_STR_MAX];
 	uint8_t opendir[FIO_TOP_STR_MAX];
 	uint8_t ioengine[FIO_TOP_STR_MAX];
+	uint8_t mmapfile[FIO_TOP_STR_MAX];
 	uint32_t td_ddir;
 	uint32_t rw_seq;
 	uint32_t kb_base;
diff --git a/verify.c b/verify.c
index f25eab9..0846d39 100644
--- a/verify.c
+++ b/verify.c
@@ -1004,6 +1004,14 @@
 	return 1;
 }
 
+void fio_verify_init(struct thread_data *td)
+{
+	if (td->o.verify == VERIFY_CRC32C_INTEL ||
+	    td->o.verify == VERIFY_CRC32C) {
+		crc32c_intel_probe();
+	}
+}
+
 static void *verify_async_thread(void *data)
 {
 	struct thread_data *td = data;
diff --git a/verify.h b/verify.h
index 7c238c8..6a81e9b 100644
--- a/verify.h
+++ b/verify.h
@@ -75,6 +75,7 @@
 extern int __must_check verify_io_u(struct thread_data *, struct io_u *);
 extern int verify_io_u_async(struct thread_data *, struct io_u *);
 extern void fill_pattern(struct thread_data *td, void *p, unsigned int len, struct io_u *io_u, unsigned long seed, int use_seed);
+extern void fio_verify_init(struct thread_data *td);
 
 /*
  * Async verify offload