Free/alloc every FIO_OPT_STR_STORE string

Makes ownership clear, though the freeing is a bit anal.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/fio.c b/fio.c
index 9fabbe9..f6c3fc8 100644
--- a/fio.c
+++ b/fio.c
@@ -878,6 +878,7 @@
 	close_files(td);
 	close_ioengine(td);
 	cleanup_io_u(td);
+	options_mem_free(td);
 	td_set_runstate(td, TD_EXITED);
 	return (void *) (unsigned long) td->error;
 err_sem:
diff --git a/fio.h b/fio.h
index 8a79289..736fefb 100644
--- a/fio.h
+++ b/fio.h
@@ -691,6 +691,8 @@
 extern void fio_fill_default_options(struct thread_data *);
 extern int fio_show_option_help(const char *);
 extern void fio_options_dup_and_init(struct option *);
+extern void options_mem_dupe(struct thread_data *);
+extern void options_mem_free(struct thread_data *);
 #define FIO_GETOPT_JOB		0x89988998
 #define FIO_NR_OPTIONS		128
 
diff --git a/init.c b/init.c
index e5d776c..c1f774d 100644
--- a/init.c
+++ b/init.c
@@ -116,6 +116,7 @@
 	*td = *parent;
 
 	dup_files(td, parent);
+	options_mem_dupe(td);
 
 	td->thread_number = thread_number;
 	return td;
@@ -801,6 +802,7 @@
 	}
 
 	free(ini_file);
+	options_mem_free(&def_thread);
 
 	if (!thread_number) {
 		log_err("No jobs defined(s)\n");
diff --git a/options.c b/options.c
index 4f30f2c..7d4396e 100644
--- a/options.c
+++ b/options.c
@@ -864,3 +864,39 @@
 {
 	return show_cmd_help(options, opt);
 }
+
+static void __options_mem(struct thread_data *td, int alloc)
+{
+	struct thread_options *o = &td->o;
+	struct fio_option *opt;
+	char **ptr;
+	int i;
+
+	for (i = 0, opt = &options[0]; opt->name; i++, opt = &options[i]) {
+		if (opt->type != FIO_OPT_STR_STORE)
+			continue;
+
+		ptr = (void *) o + opt->off1;
+		if (*ptr) {
+			if (alloc)
+				*ptr = strdup(*ptr);
+			else {
+				free(*ptr);
+				*ptr = NULL;
+			}
+		}
+	}
+}
+
+/*
+ * dupe FIO_OPT_STR_STORE options
+ */
+void options_mem_dupe(struct thread_data *td)
+{
+	__options_mem(td, 1);
+}
+
+void options_mem_free(struct thread_data *td)
+{
+	__options_mem(td, 0);
+}