diff --git a/qemu-io-sim.c b/qemu-io-sim.c
new file mode 100644
index 0000000..816f8ae
--- /dev/null
+++ b/qemu-io-sim.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010-2011 IBM
+ *
+ * Authors:
+ *         Chunqiang Tang <ctang@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*=============================================================================
+ * qemu-io-sim works with qemu-io to perform simulated testing. The 'sim'
+ * command allows the user to control the order of disk I/O and callback
+ * activities in order to test rare race conditions. See block/blksim.c
+ * Note that in the manual mode, qemu-io's 'sim' command can only work with
+ * qemu-io's 'aio_read' and 'aio_write' commands. The automated testing mode,
+ * 'qemu-io --auto', performs a much more comprehensive fully automated test
+ * (see qemu-io-auto.c). Below is one example of using qemu-io to perform
+ * manual testing in the simulation mode.
+ 
+$ qemu-img create -f qcow2 -obacking_fmt=blksim -b base.raw test.qcow2
+$ qemu-io -f qcow2 blksim:test.qcow2
+qemu-io> aio_read 0 512
+Added READ uuid=0  filename=base.raw  sector_num=0  nb_sectors=1
+qemu-io> aio_read 0 1024
+Added READ uuid=1  filename=base.raw  sector_num=0  nb_sectors=2
+qemu-io> sim list
+uuid=0  READ           file=base.raw  sector_num=0  nb_sectors=1
+uuid=1  READ           file=base.raw  sector_num=0  nb_sectors=2
+qemu-io> aio_write 512 1024
+Added WRITE uuid=2  filename=test.qcow2  sector_num=33297  nb_sectors=2
+qemu-io> sim list
+uuid=0  READ           file=base.raw  sector_num=0  nb_sectors=1
+uuid=1  READ           file=base.raw  sector_num=0  nb_sectors=2
+uuid=2  WRITE          file=test.qcow2  sector_num=33297  nb_sectors=2
+qemu-io> sim 2
+Added WRITE_CALLBACK uuid=3  filename=test.qcow2  sector_num=33297  nb_sectors=2
+qemu-io> sim list
+uuid=0  READ           file=base.raw  sector_num=0  nb_sectors=1
+uuid=1  READ           file=base.raw  sector_num=0  nb_sectors=2
+uuid=3  CALLBACK WRITE file=test.qcow2  sector_num=33297  nb_sectors=2
+qemu-io> sim 1
+Added READ_CALLBACK uuid=4  filename=base.raw  sector_num=0  nb_sectors=2
+qemu-io> sim list
+uuid=0  READ           file=base.raw  sector_num=0  nb_sectors=1
+uuid=3  CALLBACK WRITE file=test.qcow2  sector_num=33297  nb_sectors=2
+uuid=4  CALLBACK READ  file=base.raw  sector_num=0  nb_sectors=2
+qemu-io> sim 3
+Added WRITE uuid=5  filename=test.qcow2  sector_num=528  nb_sectors=1
+qemu-io> sim list
+uuid=0  READ           file=base.raw  sector_num=0  nb_sectors=1
+uuid=4  CALLBACK READ  file=base.raw  sector_num=0  nb_sectors=2
+uuid=5  WRITE          file=test.qcow2  sector_num=528  nb_sectors=1
+
+*=============================================================================*/
+
+#include "block/blksim.h"
+
+static void sim_help (void)
+{
+    printf ("\n"
+            " sim list\t\tlist all simulation tasks\n"
+            " sim <#task> [#ret]\trun a simulation task, optionally "
+                    "using #ret as the return value of a read/write operation\n"
+            " sim all [#ret]\t\trun all tasks, optionally using #ret as "
+                    "the return value of read/write tasks\n"
+            " sim prefetch\t\tstart prefetching\n");
+}
+
+static int sim_f (int argc, char **argv)
+{
+    int ret = 0;
+
+    if (argc == 3) {
+        ret = atoi (argv[2]);
+    }
+    else if (argc != 2) {
+        sim_help ();
+        return 0;
+    }
+
+    if (strcmp (argv[1], "list") == 0) {
+        blksim_list_tasks ();
+    }
+    else if (strcmp (argv[1], "all") == 0) {
+        blksim_set_disk_io_return_code (ret);
+        int n = blksim_run_all_tasks ();
+        blksim_set_disk_io_return_code (0);
+        printf ("Executed %d tasks.\n", n);
+    }
+    else {
+        blksim_set_disk_io_return_code (ret);
+        blksim_run_task_by_uuid (atoll (argv[1]));
+        blksim_set_disk_io_return_code (0);
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t sim_cmd = {
+    .name = "sim",
+    .altname = "s",
+    .cfunc = sim_f,
+    .argmin = 1,
+    .argmax = 2,
+    .args = "",
+    .oneline = "use simulation to control the order of disk I/Os and callbacks",
+    .help = sim_help,
+};
diff --git a/qemu-io.c b/qemu-io.c
index 5b24c5e..9144a6a 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1584,7 +1584,7 @@ static const cmdinfo_t close_cmd = {
 	.oneline	= "close the current open file",
 };
 
-static int openfile(char *name, int flags, int growable)
+static int openfile(char *name, const char *fmt, int flags, int growable)
 {
 	if (bs) {
 		fprintf(stderr, "file open already, try 'help close'\n");
@@ -1597,9 +1597,17 @@ static int openfile(char *name, int flags, int growable)
 			return 1;
 		}
 	} else {
+                BlockDriver *drv = NULL;
+                if (fmt && !(drv = bdrv_find_format (fmt))) {
+                        fprintf(stderr, "%s: can't find driver for format "
+                                "%s \n", progname, fmt);
+                        bs = NULL;
+                        return 1;
+                }
+
 		bs = bdrv_new("hda");
 
-		if (bdrv_open(bs, name, flags, NULL) < 0) {
+		if (bdrv_open(bs, name, flags, drv) < 0) {
 			fprintf(stderr, "%s: can't open device %s\n", progname, name);
 			bs = NULL;
 			return 1;
@@ -1636,7 +1644,7 @@ static const cmdinfo_t open_cmd = {
 	.argmin		= 1,
 	.argmax		= -1,
 	.flags		= CMD_NOFILE_OK,
-	.args		= "[-Crsn] [path]",
+	.args		= "[-Crsn] [-f <format>] [path]",
 	.oneline	= "open the file specified by path",
 	.help		= open_help,
 };
@@ -1648,8 +1656,9 @@ open_f(int argc, char **argv)
 	int readonly = 0;
 	int growable = 0;
 	int c;
+        const char *fmt = NULL;
 
-	while ((c = getopt(argc, argv, "snrg")) != EOF) {
+	while ((c = getopt(argc, argv, "snrgf:")) != EOF) {
 		switch (c) {
 		case 's':
 			flags |= BDRV_O_SNAPSHOT;
@@ -1663,6 +1672,9 @@ open_f(int argc, char **argv)
 		case 'g':
 			growable = 1;
 			break;
+		case 'f':
+                        fmt = optarg;
+			break;
 		default:
 			return command_usage(&open_cmd);
 		}
@@ -1675,7 +1687,7 @@ open_f(int argc, char **argv)
 	if (optind != argc - 1)
 		return command_usage(&open_cmd);
 
-	return openfile(argv[optind], flags, growable);
+	return openfile(argv[optind], fmt, flags, growable);
 }
 
 static int
@@ -1701,10 +1713,12 @@ init_check_command(
 	return 1;
 }
 
+#include "qemu-io-sim.c"
+
 static void usage(const char *name)
 {
 	printf(
-"Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
+"Usage: %s [-h] [-a] [-V] [-rsnm] [-c cmd] ... [file]\n"
 "QEMU Disk exerciser\n"
 "\n"
 "  -c, --cmd            command to execute\n"
@@ -1714,18 +1728,18 @@ static void usage(const char *name)
 "  -g, --growable       allow file to grow (only applies to protocols)\n"
 "  -m, --misalign       misalign allocations for O_DIRECT\n"
 "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
+"  -f, --format         image format of the file\n"
 "  -h, --help           display this help and exit\n"
 "  -V, --version        output version information and exit\n"
 "\n",
 	name);
 }
 
-
 int main(int argc, char **argv)
 {
 	int readonly = 0;
 	int growable = 0;
-	const char *sopt = "hVc:rsnmgk";
+	const char *sopt = "hVc:rsnmgkaf:";
         const struct option lopt[] = {
 		{ "help", 0, NULL, 'h' },
 		{ "version", 0, NULL, 'V' },
@@ -1737,11 +1751,13 @@ int main(int argc, char **argv)
 		{ "misalign", 0, NULL, 'm' },
 		{ "growable", 0, NULL, 'g' },
 		{ "native-aio", 0, NULL, 'k' },
+		{ "format", 1, NULL, 'f' },
 		{ NULL, 0, NULL, 0 }
 	};
 	int c;
 	int opt_index = 0;
 	int flags = 0;
+        const char *fmt = NULL;
 
 	progname = basename(argv[0]);
 
@@ -1768,6 +1784,9 @@ int main(int argc, char **argv)
 		case 'k':
 			flags |= BDRV_O_NATIVE_AIO;
 			break;
+		case 'f':
+                        fmt = optarg;
+                        break;
 		case 'V':
 			printf("%s version %s\n", progname, VERSION);
 			exit(0);
@@ -1807,6 +1826,7 @@ int main(int argc, char **argv)
 	add_command(&discard_cmd);
 	add_command(&alloc_cmd);
 	add_command(&map_cmd);
+        add_command(&sim_cmd);
 
 	add_args_command(init_args_command);
 	add_check_command(init_check_command);
@@ -1817,7 +1837,7 @@ int main(int argc, char **argv)
         }
 
 	if ((argc - optind) == 1)
-		openfile(argv[optind], flags, growable);
+		openfile(argv[optind], fmt, flags, growable);
 	command_loop();
 
 	/*
