lib/tst_mkfs.c: fix a bug when calling tst_mkfs() with extra mkfs options

When we use tst_mkfs() to build a file system with extra mkfs options:

    tst_mkfs(NULL, device, "ext4", "-b 1024"); /* device is /dev/loop0 */

It will output some error message:

    TINFO  :  Formatting /dev/loop0 with ext4 extra opts='-b 1024'
    mke2fs 1.42.7 (21-Jan-2013)
    mkfs.ext4: invalid blocks '/dev/loop0' on device 'ext4'

In tst_mkfs()'s implementations argv is defined as below statments:
       const char *argv[] = {"mkfs", "-t", fs_type, NULL, NULL, NULL, NULL};

So in the above mkfs case, the argv's value will be:
	{"mkfs", "-t", "ext4", "-b 1024", "/dev/loop0", NULL};

Then when finally calling execvp(argv[0], (char *const *)argv), the
number of arguments is 5. It's like that we call (mkfs -t ext4 "-b 1024"
/dev/loop0) in shell, but the right command shoule be (mkfs -t ext4 -b
1024 /dev/loop0 # 6 args).  Of course, the true reason is that we didn't
assign correct arguments to argv array towards extra mkfs options.

With this patch, if user wants to pass extra mkfs options, he should do:
	const char *const opts[] = { "-b", "1024", NULL };
	tst_mkfs(NULL, device, "ext4", opts);

Signed-off-by: Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index 9c3ea2a..6e79d1a 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -705,6 +705,23 @@
 }
 -------------------------------------------------------------------------------
 
+2.2.13 Formatting a device with a filesystem
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+[source,c]
+-------------------------------------------------------------------------------
+#include "test.h"
+
+void tst_mkfs(void (cleanup_fn)(void), const char *dev,
+              const char *fs_type, const char *const fs_opts[]);
+-------------------------------------------------------------------------------
+
+This function takes a path to a device, filesystem type and an array of extra
+options passed to mkfs.
+
+The extra options 'fs_opts' should either be 'NULL' if there are none or a
+'NULL' terminated array of strings such as '{"-b", "1024", NULL}'.
+
 2.3 Writing a testcase in shell
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/include/test.h b/include/test.h
index 32b9680..baa3ef6 100644
--- a/include/test.h
+++ b/include/test.h
@@ -266,10 +266,10 @@
  *
  * @dev: path to a device
  * @fs_type: filesystem type
- * @fs_opts: extra mkfs options
+ * @fs_opts: NULL or NULL terminated array of extra mkfs options
  */
 void tst_mkfs(void (cleanup_fn)(void), const char *dev,
-              const char *fs_type, const char *fs_opts);
+	      const char *fs_type, const char *const fs_opts[]);
 
 /* lib/tst_fill_file.c
  *
diff --git a/lib/tst_mkfs.c b/lib/tst_mkfs.c
index cee04dd..7357cd9 100644
--- a/lib/tst_mkfs.c
+++ b/lib/tst_mkfs.c
@@ -18,18 +18,18 @@
 
 #include "test.h"
 
+#define OPTS_MAX 32u
+
 void tst_mkfs(void (cleanup_fn)(void), const char *dev,
-              const char *fs_type, const char *fs_opts)
+	      const char *fs_type, const char *const fs_opts[])
 {
-	tst_resm(TINFO, "Formatting %s with %s extra opts='%s'",
-	        dev, fs_type, fs_opts ? fs_opts : "");
+	int i, pos = 3;
+	const char *argv[OPTS_MAX] = {"mkfs", "-t", fs_type};
+	char fs_opts_str[1024] = "";
 
 	if (!fs_type)
 		tst_brkm(TBROK, cleanup_fn, "No fs_type specified");
 
-	const char *argv[] = {"mkfs", "-t", fs_type, NULL, NULL, NULL, NULL};
-	int pos = 3;
-
 	/*
 	 * mkfs.xfs and mkfs.btrfs aborts if it finds a filesystem
 	 * superblock on the device, which is the case here as we
@@ -40,10 +40,25 @@
 		argv[pos++] = "-f";
 	}
 
-	if (fs_opts)
-		argv[pos++] = fs_opts;
+	if (fs_opts) {
+		for (i = 0; fs_opts[i]; i++) {
+			argv[pos++] = fs_opts[i];
 
-	argv[pos] = dev;
+			if (pos + 2 > OPTS_MAX) {
+				tst_brkm(TBROK, cleanup_fn,
+				         "Too much mkfs options");
+			}
 
+			if (i)
+				strcat(fs_opts_str, " ");
+			strcat(fs_opts_str, fs_opts[i]);
+		}
+	}
+
+	argv[pos++] = dev;
+	argv[pos] = NULL;
+
+	tst_resm(TINFO, "Formatting %s with %s extra opts='%s'",
+		 dev, fs_type, fs_opts_str);
 	tst_run_cmd(cleanup_fn, argv, "/dev/null", NULL);
 }