Add parent link to options

Then we can nest display for --cmdhelp=all, to tie options
together.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/options.c b/options.c
index 9ba9ca5..7f4ed2d 100644
--- a/options.c
+++ b/options.c
@@ -390,12 +390,14 @@
 		.type	= FIO_OPT_INT,
 		.off1	= td_var_offset(iodepth_batch),
 		.help	= "Number of IO to submit in one go",
+		.parent	= "iodepth",
 	},
 	{
 		.name	= "iodepth_low",
 		.type	= FIO_OPT_INT,
 		.off1	= td_var_offset(iodepth_low),
 		.help	= "Low water mark for queuing depth",
+		.parent	= "iodepth",
 	},
 	{
 		.name	= "size",
@@ -649,6 +651,7 @@
 		.off1   = td_var_offset(verify_interval),
 		.minval	= 2 * sizeof(struct verify_header),
 		.help   = "Store verify buffer header every N bytes",
+		.parent	= "verify",
 	},
 	{
 		.name	= "verify_offset",
@@ -656,12 +659,14 @@
 		.help	= "Offset verify header location by N bytes",
 		.def	= "0",
 		.cb	= str_verify_offset_cb,	
+		.parent	= "verify",
 	},
 	{
 		.name	= "verify_pattern",
 		.type	= FIO_OPT_INT,
 		.cb	= str_verify_pattern_cb,
 		.help	= "Fill pattern for IO buffers",
+		.parent	= "verify",
 	},
 	{
 		.name	= "write_iolog",
@@ -717,13 +722,6 @@
 		.def	= "0",
 	},
 	{
-		.name	= "rwmixcycle",
-		.type	= FIO_OPT_INT,
-		.off1	= td_var_offset(rwmixcycle),
-		.help	= "Cycle period for mixed read/write workloads (msec)",
-		.def	= "500",
-	},
-	{
 		.name	= "rwmixread",
 		.type	= FIO_OPT_INT,
 		.off1	= td_var_offset(rwmix[DDIR_READ]),
@@ -740,6 +738,14 @@
 		.def	= "50",
 	},
 	{
+		.name	= "rwmixcycle",
+		.type	= FIO_OPT_INT,
+		.off1	= td_var_offset(rwmixcycle),
+		.help	= "Cycle period for mixed read/write workloads (msec)",
+		.def	= "500",
+		.parent	= "rwmixread",
+	},
+	{
 		.name	= "nice",
 		.type	= FIO_OPT_INT,
 		.off1	= td_var_offset(nice),
@@ -779,6 +785,7 @@
 		.off1	= td_var_offset(thinktime_spin),
 		.help	= "Start think time by spinning this amount (usec)",
 		.def	= "0",
+		.parent	= "thinktime",
 	},
 	{
 		.name	= "thinktime_blocks",
@@ -786,6 +793,7 @@
 		.off1	= td_var_offset(thinktime_blocks),
 		.help	= "IO buffer period between 'thinktime'",
 		.def	= "1",
+		.parent	= "thinktime",
 	},
 	{
 		.name	= "rate",
@@ -798,6 +806,7 @@
 		.type	= FIO_OPT_INT,
 		.off1	= td_var_offset(ratemin),
 		.help	= "Job must meet this rate or it will be shutdown",
+		.parent	= "rate",
 	},
 	{
 		.name	= "rate_iops",
@@ -810,6 +819,7 @@
 		.type	= FIO_OPT_INT,
 		.off1	= td_var_offset(rate_iops_min),
 		.help	= "Job must meet this rate or it will be shutdown",
+		.parent	= "rate_iops",
 	},
 	{
 		.name	= "ratecycle",
@@ -817,6 +827,7 @@
 		.off1	= td_var_offset(ratecycle),
 		.help	= "Window average for rate limits (msec)",
 		.def	= "1000",
+		.parent = "rate",
 	},
 	{
 		.name	= "invalidate",
diff --git a/parse.c b/parse.c
index 6fd617c..962538c 100644
--- a/parse.c
+++ b/parse.c
@@ -561,6 +561,37 @@
 	show_option_values(o);
 }
 
+static struct fio_option *find_child(struct fio_option *options,
+				     struct fio_option *o)
+{
+	struct fio_option *__o;
+
+	for (__o = &options[0]; __o->name; __o++)
+		if (__o->parent && !strcmp(__o->parent, o->name))
+			return __o;
+
+	return NULL;
+}
+
+static void print_option(struct fio_option *options, struct fio_option *o,
+			 int level)
+{
+	char name[256], *p;
+	int i;
+
+	if (!o)
+		return;
+	
+	p = name;
+	for (i = 0; i < level; i++)
+		p += sprintf(p, "%s", "    ");
+
+	sprintf(p, "%s", o->name);
+
+	printf("%-24s: %s\n", name, o->help);
+	print_option(options, find_child(options, o), level + 1);
+}
+
 int show_cmd_help(struct fio_option *options, const char *name)
 {
 	struct fio_option *o, *closest;
@@ -594,9 +625,10 @@
 		if (show_all || match) {
 			found = 1;
 			if (match)
-				printf("%20s: %s\n", o->name, o->help);
+				printf("%24s: %s\n", o->name, o->help);
 			if (show_all) {
-				printf("%-20s: %s\n", o->name, o->help);
+				if (!o->parent)
+					print_option(options, o, 0);
 				continue;
 			}
 		}
diff --git a/parse.h b/parse.h
index 752da34..c3b66d7 100644
--- a/parse.h
+++ b/parse.h
@@ -45,6 +45,7 @@
 	const char *help;		/* help text for option */
 	const char *def;		/* default setting */
 	const struct value_pair posval[PARSE_MAX_VP];/* possible values */
+	const char *parent;		/* parent option */
 };
 
 typedef int (str_cb_fn)(void *, char *);