From patchwork Fri Jan 21 22:19:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunqiang Tang X-Patchwork-Id: 79952 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2E1C8B70EE for ; Sat, 22 Jan 2011 09:21:22 +1100 (EST) Received: from localhost ([127.0.0.1]:39614 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PgPIL-0000Zy-PV for incoming@patchwork.ozlabs.org; Fri, 21 Jan 2011 17:17:25 -0500 Received: from [140.186.70.92] (port=42161 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PgPGM-0008Ac-Li for qemu-devel@nongnu.org; Fri, 21 Jan 2011 17:16:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PgPFv-0002VB-Vl for qemu-devel@nongnu.org; Fri, 21 Jan 2011 17:14:57 -0500 Received: from e37.co.us.ibm.com ([32.97.110.158]:42276) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PgPFv-0002U6-Js for qemu-devel@nongnu.org; Fri, 21 Jan 2011 17:14:55 -0500 Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com [9.17.195.106]) by e37.co.us.ibm.com (8.14.4/8.13.1) with ESMTP id p0LMCEuW028831 for ; Fri, 21 Jan 2011 15:12:14 -0700 Received: from d03av05.boulder.ibm.com (d03av05.boulder.ibm.com [9.17.195.85]) by d03relay04.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p0LMEgCe087096 for ; Fri, 21 Jan 2011 15:14:42 -0700 Received: from d03av05.boulder.ibm.com (loopback [127.0.0.1]) by d03av05.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p0LMEg5T008678 for ; Fri, 21 Jan 2011 15:14:42 -0700 Received: from localhost.localdomain ([9.59.229.24]) by d03av05.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p0LMEfnZ008633; Fri, 21 Jan 2011 15:14:42 -0700 From: Chunqiang Tang To: qemu-devel@nongnu.org Date: Fri, 21 Jan 2011 17:19:15 -0500 Message-Id: <1295648355-17359-3-git-send-email-ctang@us.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1295648355-17359-1-git-send-email-ctang@us.ibm.com> References: <1295648355-17359-1-git-send-email-ctang@us.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: Chunqiang Tang Subject: [Qemu-devel] [PATCH 3/3] FVD: Made qemu-io working with simulation (blksim) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch is part of the Fast Virtual Disk (FVD) proposal. See the related discussions at http://lists.gnu.org/archive/html/qemu-devel/2011-01/msg00426.html. This patch adds the 'sim' command to qemu-io, which works with the blksim driver. With this extension, now a developer can use qemu-io to precisely control the order of disk I/Os, the order of callbacks, and the return code of every I/O operation. The purpose is to comprehensively test a block device driver under failures and race conditions. Bugs found by blksim under rare race conditions are guaranteed to be precisely reproducible, with no dependency on thread timing etc., which makes debugging much easier. Signed-off-by: Chunqiang Tang --- qemu-io-sim.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-io.c | 38 +++++++++++++++----- 2 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 qemu-io-sim.c 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 + * + * 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 ] [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(); /*