qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/26] Block patches
@ 2010-04-23 15:30 Kevin Wolf
  0 siblings, 0 replies; 47+ messages in thread
From: Kevin Wolf @ 2010-04-23 15:30 UTC (permalink / raw)
  To: aliguori; +Cc: kwolf, qemu-devel

Hi Anthony,

this is the first part of the block patches that accumulated in my block branch
during your absence. I consider these patches ready to be merged into master.
I've not included another 13 patches that might still need discussion/review or
depend on such patches. I'm going to send another pull request for them some
time next week.

Kevin

The following changes since commit 6c557ab975fc8e5edb4167a241266c7c4657054a:
  Serge Ziryukin (1):
        audio/sdlaudio: remove unused variable

are available in the git repository at:

  git://repo.or.cz/qemu/kevin.git for-anthony

Bruce Rogers (1):
      Remove un-needed code

Christoph Hellwig (3):
      block: get rid of the BDRV_O_FILE flag
      block: split raw_getlength
      cleanup block driver option handling in vl.c

Kevin Wolf (14):
      qemu-config: qemu_read_config_file() reads the normal config file
      qemu-config: Make qemu_config_parse more generic
      blkdebug: Basic request passthrough
      blkdebug: Inject errors
      Make qemu-config available for tools
      blkdebug: Add events and rules
      qcow2: Trigger blkdebug events
      qcow2: Fix creation of large images
      Replace calls of old bdrv_open
      qcow2: Return 0/-errno in write_l2_entries
      qcow2: Fix error return code in qcow2_alloc_cluster_link_l2
      qcow2: Return 0/-errno in write_l1_entry
      qcow2: Return 0/-errno in l2_allocate
      block.h: bdrv_create2 doesn't exist any more

Stefan Hajnoczi (8):
      block: Do not export bdrv_first
      block: Convert bdrv_first to QTAILQ
      block: Convert first_drv to QLIST
      qemu-img: Eliminate bdrv_new_open() code duplication
      qemu-img: Fix BRDV_O_FLAGS typo
      linux-aio: Fix typo in read() EINTR check
      qcow2: Use QLIST_FOREACH_SAFE macro
      block: Free iovec arrays allocated by multiwrite_merge()

 Makefile.objs          |    6 +-
 block-migration.c      |   63 ++++---
 block.c                |  119 +++++++------
 block.h                |   66 ++++++-
 block/blkdebug.c       |  475 ++++++++++++++++++++++++++++++++++++++++++++++++
 block/qcow2-cluster.c  |   78 +++++---
 block/qcow2-refcount.c |   18 ++
 block/qcow2.c          |   63 +++++--
 block/raw-posix.c      |   65 +++++---
 block/vmdk.c           |    2 +-
 block/vvfat.c          |    5 +-
 block_int.h            |    9 +-
 hw/qdev-properties.c   |   19 ++-
 hw/qdev.h              |    1 -
 hw/virtio-blk.c        |    1 -
 hw/xen_disk.c          |    2 +-
 linux-aio.c            |    2 +-
 monitor.c              |    2 +-
 qemu-config.c          |   48 +++---
 qemu-config.h          |    4 +-
 qemu-img.c             |   93 ++--------
 qemu-io.c              |   28 ++--
 qemu-nbd.c             |    2 +-
 vl.c                   |   82 +++------
 24 files changed, 902 insertions(+), 351 deletions(-)
 create mode 100644 block/blkdebug.c

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 00/26] Block patches
@ 2012-11-14 18:47 Kevin Wolf
  2012-11-19  9:12 ` Kevin Wolf
  0 siblings, 1 reply; 47+ messages in thread
From: Kevin Wolf @ 2012-11-14 18:47 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit ce34cf72fe508b27a78f83c184142e8d1e6a048a:

  Merge remote-tracking branch 'awilliam/tags/vfio-pci-for-qemu-1.3.0-rc0' into staging (2012-11-14 08:53:40 -0600)

are available in the git repository at:

  git://repo.or.cz/qemu/kevin.git for-anthony

Bharata B Rao (1):
      qemu: Document GlusterFS block driver usage

Gerhard Wiesinger (1):
      vmdk: Fix data corruption bug in WRITE and READ handling

Hervé Poussineau (12):
      fdc-test: split test_media_change() test, so insert part can be reused
      fdc-test: insert media before fuzzing registers
      fdc-test: add tests for non-DMA READ command
      fdc: use status0 field instead of a local variable
      fdc: fix FD_SR0_SEEK for non-DMA transfers and multi sectors transfers
      fdc: fix FD_SR0_SEEK for initial seek on DMA transfers
      fdc: fix false FD_SR0_SEEK
      fdc: implement VERIFY command
      fdc-tests: add tests for VERIFY command
      fdc: remove double affectation of FD_MSR_CMDBUSY flag
      fdc: fix typo in zero constant
      fdc: remove last usage of FD_STATE_SEEK

Kevin Wolf (6):
      qcow2: Fix refcount table size calculation
      qemu-iotests: qcow2: Test growing large refcount table
      fdc: Remove status0 parameter from fdctrl_set_fifo()
      fdc-test: Check READ ID
      megasas: Use bdrv_drain_all instead of qemu_aio_flush
      qemu-io: Use bdrv_drain_all instead of qemu_aio_flush

Nick Thomas (1):
      tests: allow qemu-iotests to be run against nbd backend

Stefan Hajnoczi (4):
      MAINTAINERS: add Stefan Hajnoczi as block and virtio-blk co-maintainer
      aio: switch aiocb_size type int -> size_t
      aio: use g_slice_alloc() for AIOCB pooling
      aio: rename AIOPool to AIOCBInfo

Stefan Weil (1):
      block: Workaround for older versions of MinGW gcc

 MAINTAINERS                      |    2 +
 block.c                          |   31 +++----
 block/blkdebug.c                 |    4 +-
 block/blkverify.c                |    4 +-
 block/curl.c                     |    4 +-
 block/gluster.c                  |    6 +-
 block/iscsi.c                    |   12 +-
 block/linux-aio.c                |    4 +-
 block/qcow2-refcount.c           |    3 +-
 block/qed.c                      |    4 +-
 block/rbd.c                      |    4 +-
 block/sheepdog.c                 |    4 +-
 block/vmdk.c                     |   10 ++-
 block/win32-aio.c                |   14 ++--
 dma-helpers.c                    |    4 +-
 hw/fdc.c                         |  121 +++++++++++++-----------
 hw/ide/core.c                    |    4 +-
 hw/megasas.c                     |    2 +-
 qemu-aio.h                       |   12 +--
 qemu-doc.texi                    |   49 ++++++++++
 qemu-io.c                        |    2 +-
 qemu-options.hx                  |   17 ++++
 tests/fdc-test.c                 |  192 +++++++++++++++++++++++++++++++++++++-
 tests/qemu-iotests/044           |  117 +++++++++++++++++++++++
 tests/qemu-iotests/044.out       |    6 +
 tests/qemu-iotests/common        |   13 ++-
 tests/qemu-iotests/common.config |   10 +-
 tests/qemu-iotests/common.rc     |   23 +++++-
 tests/qemu-iotests/group         |    1 +
 tests/qemu-iotests/iotests.py    |    6 +-
 tests/qemu-iotests/qcow2.py      |    9 +-
 thread-pool.c                    |    4 +-
 32 files changed, 556 insertions(+), 142 deletions(-)
 create mode 100755 tests/qemu-iotests/044
 create mode 100644 tests/qemu-iotests/044.out

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2012-11-14 18:47 Kevin Wolf
@ 2012-11-19  9:12 ` Kevin Wolf
  0 siblings, 0 replies; 47+ messages in thread
From: Kevin Wolf @ 2012-11-19  9:12 UTC (permalink / raw)
  To: anthony; +Cc: Kevin Wolf, qemu-devel

Am 14.11.2012 19:47, schrieb Kevin Wolf:
> The following changes since commit ce34cf72fe508b27a78f83c184142e8d1e6a048a:
> 
>   Merge remote-tracking branch 'awilliam/tags/vfio-pci-for-qemu-1.3.0-rc0' into staging (2012-11-14 08:53:40 -0600)
> 
> are available in the git repository at:
> 
>   git://repo.or.cz/qemu/kevin.git for-anthony
> 
> Bharata B Rao (1):
>       qemu: Document GlusterFS block driver usage
> 
> Gerhard Wiesinger (1):
>       vmdk: Fix data corruption bug in WRITE and READ handling
> 
> Hervé Poussineau (12):
>       fdc-test: split test_media_change() test, so insert part can be reused
>       fdc-test: insert media before fuzzing registers
>       fdc-test: add tests for non-DMA READ command
>       fdc: use status0 field instead of a local variable
>       fdc: fix FD_SR0_SEEK for non-DMA transfers and multi sectors transfers
>       fdc: fix FD_SR0_SEEK for initial seek on DMA transfers
>       fdc: fix false FD_SR0_SEEK
>       fdc: implement VERIFY command
>       fdc-tests: add tests for VERIFY command
>       fdc: remove double affectation of FD_MSR_CMDBUSY flag
>       fdc: fix typo in zero constant
>       fdc: remove last usage of FD_STATE_SEEK
> 
> Kevin Wolf (6):
>       qcow2: Fix refcount table size calculation
>       qemu-iotests: qcow2: Test growing large refcount table
>       fdc: Remove status0 parameter from fdctrl_set_fifo()
>       fdc-test: Check READ ID
>       megasas: Use bdrv_drain_all instead of qemu_aio_flush
>       qemu-io: Use bdrv_drain_all instead of qemu_aio_flush
> 
> Nick Thomas (1):
>       tests: allow qemu-iotests to be run against nbd backend
> 
> Stefan Hajnoczi (4):
>       MAINTAINERS: add Stefan Hajnoczi as block and virtio-blk co-maintainer
>       aio: switch aiocb_size type int -> size_t
>       aio: use g_slice_alloc() for AIOCB pooling
>       aio: rename AIOPool to AIOCBInfo
> 
> Stefan Weil (1):
>       block: Workaround for older versions of MinGW gcc
> 
>  MAINTAINERS                      |    2 +
>  block.c                          |   31 +++----
>  block/blkdebug.c                 |    4 +-
>  block/blkverify.c                |    4 +-
>  block/curl.c                     |    4 +-
>  block/gluster.c                  |    6 +-
>  block/iscsi.c                    |   12 +-
>  block/linux-aio.c                |    4 +-
>  block/qcow2-refcount.c           |    3 +-
>  block/qed.c                      |    4 +-
>  block/rbd.c                      |    4 +-
>  block/sheepdog.c                 |    4 +-
>  block/vmdk.c                     |   10 ++-
>  block/win32-aio.c                |   14 ++--
>  dma-helpers.c                    |    4 +-
>  hw/fdc.c                         |  121 +++++++++++++-----------
>  hw/ide/core.c                    |    4 +-
>  hw/megasas.c                     |    2 +-
>  qemu-aio.h                       |   12 +--
>  qemu-doc.texi                    |   49 ++++++++++
>  qemu-io.c                        |    2 +-
>  qemu-options.hx                  |   17 ++++
>  tests/fdc-test.c                 |  192 +++++++++++++++++++++++++++++++++++++-
>  tests/qemu-iotests/044           |  117 +++++++++++++++++++++++
>  tests/qemu-iotests/044.out       |    6 +
>  tests/qemu-iotests/common        |   13 ++-
>  tests/qemu-iotests/common.config |   10 +-
>  tests/qemu-iotests/common.rc     |   23 +++++-
>  tests/qemu-iotests/group         |    1 +
>  tests/qemu-iotests/iotests.py    |    6 +-
>  tests/qemu-iotests/qcow2.py      |    9 +-
>  thread-pool.c                    |    4 +-
>  32 files changed, 556 insertions(+), 142 deletions(-)
>  create mode 100755 tests/qemu-iotests/044
>  create mode 100644 tests/qemu-iotests/044.out

Ping?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 00/26] Block patches
@ 2013-06-07 11:58 Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 01/26] blockdev: reset werror/rerror on drive_del Stefan Hajnoczi
                   ` (26 more replies)
  0 siblings, 27 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Stefan Hajnoczi

The following changes since commit 8819c10b5d55d537d59a0ffd5d623f348fc36c47:

  Merge remote-tracking branch 'sstabellini/xen_fixes_20130603' into staging (2013-06-04 14:58:58 -0500)

are available in the git repository at:


  git://github.com/stefanha/qemu.git block

for you to fetch changes up to e73fe2b46c38776288415ce7bc8ba3fcd23721c4:

  hmp: add parameters device and -v for info block (2013-06-07 13:45:01 +0200)

----------------------------------------------------------------
Andreas Färber (1):
      ide: Set BSY bit during FLUSH

Kevin Wolf (19):
      qemu-io: Remove unused args_command
      cutils: Support 'P' and 'E' suffixes in strtosz()
      qemu-io: Make cvtnum() a wrapper around strtosz_suffix()
      qemu-io: Handle cvtnum() errors in 'alloc'
      qemu-io: Don't use global bs in command implementations
      qemu-io: Split off commands to qemu-io-cmds.c
      qemu-io: Factor out qemuio_command
      qemu-io: Move 'help' function
      qemu-io: Move 'quit' function
      qemu-io: Move qemu_strsep() to cutils.c
      qemu-io: Move functions for registering and running commands
      qemu-io: Move command_loop() and friends
      qemu-io: Move remaining helpers from cmd.c
      qemu-io: Interface cleanup
      qemu-io: Use the qemu version for -V
      Make qemu-io commands available in HMP
      blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events
      ide-test: Add enum value for DEV
      ide-test: Add FLUSH CACHE test case

Stefan Hajnoczi (1):
      blockdev: reset werror/rerror on drive_del

Wenchao Xia (5):
      block: add snapshot info query function bdrv_query_snapshot_info_list()
      block: add image info query function bdrv_query_image_info()
      qmp: add ImageInfo in BlockDeviceInfo used by query-block
      hmp: show ImageInfo in 'info block'
      hmp: add parameters device and -v for info block

 Makefile                   |    2 +-
 Makefile.objs              |    1 +
 block.c                    |    8 +-
 block/blkdebug.c           |    3 +
 block/qapi.c               |  148 +++-
 blockdev.c                 |    4 +
 cmd.c                      |  612 -------------
 cmd.h                      |   79 --
 hmp-commands.hx            |   18 +
 hmp.c                      |   39 +
 hmp.h                      |    1 +
 hw/ide/core.c              |    1 +
 include/block/block.h      |    3 +
 include/block/qapi.h       |   14 +-
 include/qemu-common.h      |    3 +
 include/qemu-io.h          |   46 +
 monitor.c                  |   15 +-
 qapi-schema.json           |   10 +-
 qemu-img.c                 |   20 +-
 qemu-io-cmds.c             | 2118 ++++++++++++++++++++++++++++++++++++++++++++
 qemu-io.c                  | 1990 ++++-------------------------------------
 qmp-commands.hx            |   69 +-
 tests/ide-test.c           |   43 +-
 tests/qemu-iotests/049.out |    8 +-
 util/cutils.c              |   25 +
 25 files changed, 2717 insertions(+), 2563 deletions(-)
 delete mode 100644 cmd.c
 delete mode 100644 cmd.h
 create mode 100644 include/qemu-io.h
 create mode 100644 qemu-io-cmds.c

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 01/26] blockdev: reset werror/rerror on drive_del
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 02/26] qemu-io: Remove unused args_command Stefan Hajnoczi
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Stefan Hajnoczi

Paolo Bonzini <pbonzini@redhat.com> suggested the following test case:

1. Launch a guest and wait at the GRUB boot menu:

  qemu-system-x86_64 -enable-kvm -m 1024 \
   -drive if=none,cache=none,file=test.img,id=foo,werror=stop,rerror=stop
   -device virtio-blk-pci,drive=foo,id=virtio0,addr=4

2. Hot unplug the device:

  (qemu) drive_del foo

3. Select the first boot menu entry

Without this patch the guest pauses due to ENOMEDIUM.  The guest is
stuck in a continuous pause loop since the I/O request is retried and
fails immediately again when the guest is resumed.

With this patch the error is reported to the guest.

Note that this scenario actually happens sometimes during libvirt disk
hot unplug, where device_del is followed by drive_del.  I/O may still be
submitted to the drive after drive_del if the guest does not process the
PCI hot unplug notification.

Reported-by: Dafna Ron <dron@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 blockdev.c      | 4 ++++
 hmp-commands.hx | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index b9b2d10..9937311 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1180,6 +1180,10 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
      */
     if (bdrv_get_attached_dev(bs)) {
         bdrv_make_anon(bs);
+
+        /* Further I/O must not pause the guest */
+        bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
+                          BLOCKDEV_ON_ERROR_REPORT);
     } else {
         drive_uninit(drive_get_by_blockdev(bs));
     }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9cea415..4f5a3fd 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -185,6 +185,8 @@ Remove host block device.  The result is that guest generated IO is no longer
 submitted against the host device underlying the disk.  Once a drive has
 been deleted, the QEMU Block layer returns -EIO which results in IO
 errors in the guest for applications that are reading/writing to the device.
+These errors are always reported to the guest, regardless of the drive's error
+actions (drive options rerror, werror).
 ETEXI
 
     {
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 02/26] qemu-io: Remove unused args_command
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 01/26] blockdev: reset werror/rerror on drive_del Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 03/26] cutils: Support 'P' and 'E' suffixes in strtosz() Stefan Hajnoczi
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

The original intention seems to be something with handling multiple
images at once, but this has never been implemented and the only
function ever registered is implemented to make everything behave like a
"global" command. Just do that unconditionally now.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c     | 28 ++--------------------------
 cmd.h     |  2 --
 qemu-io.c | 10 ----------
 3 files changed, 2 insertions(+), 38 deletions(-)

diff --git a/cmd.c b/cmd.c
index 10a8688..4e7579b 100644
--- a/cmd.c
+++ b/cmd.c
@@ -34,7 +34,6 @@
 cmdinfo_t	*cmdtab;
 int		ncmds;
 
-static argsfunc_t	args_func;
 static checkfunc_t	check_func;
 static int		ncmdline;
 static char		**cmdline;
@@ -127,22 +126,6 @@ void add_user_command(char *optarg)
     cmdline[ncmdline-1] = optarg;
 }
 
-static int
-args_command(
-	int	index)
-{
-	if (args_func)
-		return args_func(index);
-	return 0;
-}
-
-void
-add_args_command(
-	argsfunc_t	af)
-{
-	args_func = af;
-}
-
 static void prep_fetchline(void *opaque)
 {
     int *fetchable = opaque;
@@ -155,7 +138,7 @@ static char *get_prompt(void);
 
 void command_loop(void)
 {
-    int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
+    int c, i, done = 0, fetchable = 0, prompted = 0;
     char *input;
     char **v;
     const cmdinfo_t *ct;
@@ -171,14 +154,7 @@ void command_loop(void)
         if (c) {
             ct = find_command(v[0]);
             if (ct) {
-                if (ct->flags & CMD_FLAG_GLOBAL) {
-                    done = command(ct, c, v);
-                } else {
-                    j = 0;
-                    while (!done && (j = args_command(j))) {
-                        done = command(ct, c, v);
-                    }
-                }
+                done = command(ct, c, v);
             } else {
                 fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
             }
diff --git a/cmd.h b/cmd.h
index b763b19..8e6f753 100644
--- a/cmd.h
+++ b/cmd.h
@@ -41,12 +41,10 @@ extern int		ncmds;
 void help_init(void);
 void quit_init(void);
 
-typedef int (*argsfunc_t)(int index);
 typedef int (*checkfunc_t)(const cmdinfo_t *ci);
 
 void add_command(const cmdinfo_t *ci);
 void add_user_command(char *optarg);
-void add_args_command(argsfunc_t af);
 void add_check_command(checkfunc_t cf);
 
 const cmdinfo_t *find_command(const char *cmd);
diff --git a/qemu-io.c b/qemu-io.c
index 5e6680b..4288b8c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1888,15 +1888,6 @@ static int open_f(int argc, char **argv)
     return openfile(argv[optind], flags, growable);
 }
 
-static int init_args_command(int index)
-{
-    /* only one device allowed so far */
-    if (index >= 1) {
-        return 0;
-    }
-    return ++index;
-}
-
 static int init_check_command(const cmdinfo_t *ct)
 {
     if (ct->flags & CMD_FLAG_GLOBAL) {
@@ -2043,7 +2034,6 @@ int main(int argc, char **argv)
     add_command(&wait_break_cmd);
     add_command(&abort_cmd);
 
-    add_args_command(init_args_command);
     add_check_command(init_check_command);
 
     /* open the device */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 03/26] cutils: Support 'P' and 'E' suffixes in strtosz()
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 01/26] blockdev: reset werror/rerror on drive_del Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 02/26] qemu-io: Remove unused args_command Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 04/26] qemu-io: Make cvtnum() a wrapper around strtosz_suffix() Stefan Hajnoczi
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/qemu-common.h      |  2 ++
 monitor.c                  |  8 ++++----
 qemu-img.c                 | 10 ++++++----
 tests/qemu-iotests/049.out |  8 ++++----
 util/cutils.c              |  4 ++++
 5 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/include/qemu-common.h b/include/qemu-common.h
index cb82ef3..d95ea1e 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -191,6 +191,8 @@ int parse_uint_full(const char *s, unsigned long long *value, int base);
  * A-Z, as strtosz() will use qemu_toupper() on the given argument
  * prior to comparison.
  */
+#define STRTOSZ_DEFSUFFIX_EB	'E'
+#define STRTOSZ_DEFSUFFIX_PB	'P'
 #define STRTOSZ_DEFSUFFIX_TB	'T'
 #define STRTOSZ_DEFSUFFIX_GB	'G'
 #define STRTOSZ_DEFSUFFIX_MB	'M'
diff --git a/monitor.c b/monitor.c
index eefc7f0..9d279b8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -93,10 +93,10 @@
  * 'M'          Non-negative target long (32 or 64 bit), in user mode the
  *              value is multiplied by 2^20 (think Mebibyte)
  * 'o'          octets (aka bytes)
- *              user mode accepts an optional T, t, G, g, M, m, K, k
- *              suffix, which multiplies the value by 2^40 for
- *              suffixes T and t, 2^30 for suffixes G and g, 2^20 for
- *              M and m, 2^10 for K and k
+ *              user mode accepts an optional E, e, P, p, T, t, G, g, M, m,
+ *              K, k suffix, which multiplies the value by 2^60 for suffixes E
+ *              and e, 2^50 for suffixes P and p, 2^40 for suffixes T and t,
+ *              2^30 for suffixes G and g, 2^20 for M and m, 2^10 for K and k
  * 'T'          double
  *              user mode accepts an optional ms, us, ns suffix,
  *              which divides the value by 1e3, 1e6, 1e9, respectively
diff --git a/qemu-img.c b/qemu-img.c
index 82c7977..e089c78 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -85,8 +85,9 @@ static void help(void)
            "    options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
            "    'directsync' and 'unsafe' (default for convert)\n"
            "  'size' is the disk image size in bytes. Optional suffixes\n"
-           "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
-           "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
+           "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
+           "    'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P)  are\n"
+           "    supported. 'b' is ignored.\n"
            "  'output_filename' is the destination disk image filename\n"
            "  'output_fmt' is the destination format\n"
            "  'options' is a comma separated list of format specific options in a\n"
@@ -387,8 +388,9 @@ static int img_create(int argc, char **argv)
                 error_report("Image size must be less than 8 EiB!");
             } else {
                 error_report("Invalid image size specified! You may use k, M, "
-                      "G or T suffixes for ");
-                error_report("kilobytes, megabytes, gigabytes and terabytes.");
+                      "G, T, P or E suffixes for ");
+                error_report("kilobytes, megabytes, gigabytes, terabytes, "
+                             "petabytes and exabytes.");
             }
             return 1;
         }
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index 72db13f..d2f0efe 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -108,15 +108,15 @@ qemu-img: Formatting or formatting option not supported for file format 'qcow2'
 Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off 
 
 qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
-qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for 
-qemu-img: kilobytes, megabytes, gigabytes and terabytes.
+qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for 
+qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
 
 qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2
 Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off 
 
 qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar
-qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for 
-qemu-img: kilobytes, megabytes, gigabytes and terabytes.
+qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for 
+qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
 
 qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
 qemu-img: Parameter 'size' expects a size
diff --git a/util/cutils.c b/util/cutils.c
index a165819..8f28896 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -267,6 +267,10 @@ static int64_t suffix_mul(char suffix, int64_t unit)
         return unit * unit * unit;
     case STRTOSZ_DEFSUFFIX_TB:
         return unit * unit * unit * unit;
+    case STRTOSZ_DEFSUFFIX_PB:
+        return unit * unit * unit * unit * unit;
+    case STRTOSZ_DEFSUFFIX_EB:
+        return unit * unit * unit * unit * unit * unit;
     }
     return -1;
 }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 04/26] qemu-io: Make cvtnum() a wrapper around strtosz_suffix()
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (2 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 03/26] cutils: Support 'P' and 'E' suffixes in strtosz() Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 05/26] qemu-io: Handle cvtnum() errors in 'alloc' Stefan Hajnoczi
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

No reason to implement the same thing multiple times. A nice side effect
is that fractional numbers like 0.5M can be used in qemu-io now.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c     | 37 -------------------------------------
 cmd.h     |  1 -
 qemu-io.c |  6 ++++++
 3 files changed, 6 insertions(+), 38 deletions(-)

diff --git a/cmd.c b/cmd.c
index 4e7579b..214c6f7 100644
--- a/cmd.c
+++ b/cmd.c
@@ -344,43 +344,6 @@ doneline(
 #define MEGABYTES(x)	((long long)(x) << 20)
 #define KILOBYTES(x)	((long long)(x) << 10)
 
-long long
-cvtnum(
-	char		*s)
-{
-	long long	i;
-	char		*sp;
-	int		c;
-
-	i = strtoll(s, &sp, 0);
-	if (i == 0 && sp == s)
-		return -1LL;
-	if (*sp == '\0')
-		return i;
-
-	if (sp[1] != '\0')
-		return -1LL;
-
-	c = qemu_tolower(*sp);
-	switch (c) {
-	default:
-		return i;
-	case 'k':
-		return KILOBYTES(i);
-	case 'm':
-		return MEGABYTES(i);
-	case 'g':
-		return GIGABYTES(i);
-	case 't':
-		return TERABYTES(i);
-	case 'p':
-		return PETABYTES(i);
-	case 'e':
-		return  EXABYTES(i);
-	}
-	return -1LL;
-}
-
 #define TO_EXABYTES(x)	((x) / EXABYTES(1))
 #define TO_PETABYTES(x)	((x) / PETABYTES(1))
 #define TO_TERABYTES(x)	((x) / TERABYTES(1))
diff --git a/cmd.h b/cmd.h
index 8e6f753..4dcfe88 100644
--- a/cmd.h
+++ b/cmd.h
@@ -58,7 +58,6 @@ char **breakline(char *input, int *count);
 void doneline(char *input, char **vec);
 char *fetchline(void);
 
-long long cvtnum(char *s);
 void cvtstr(double value, char *str, size_t sz);
 
 struct timeval tsub(struct timeval t1, struct timeval t2);
diff --git a/qemu-io.c b/qemu-io.c
index 4288b8c..8a719a8 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -29,6 +29,12 @@ static BlockDriverState *bs;
 
 static int misalign;
 
+static int64_t cvtnum(const char *s)
+{
+    char *end;
+    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
+}
+
 /*
  * Parse the pattern argument to various sub-commands.
  *
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 05/26] qemu-io: Handle cvtnum() errors in 'alloc'
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (3 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 04/26] qemu-io: Make cvtnum() a wrapper around strtosz_suffix() Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 06/26] qemu-io: Don't use global bs in command implementations Stefan Hajnoczi
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 qemu-io.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/qemu-io.c b/qemu-io.c
index 8a719a8..b4f56fc 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1596,7 +1596,10 @@ static int alloc_f(int argc, char **argv)
     int ret;
 
     offset = cvtnum(argv[1]);
-    if (offset & 0x1ff) {
+    if (offset < 0) {
+        printf("non-numeric offset argument -- %s\n", argv[1]);
+        return 0;
+    } else if (offset & 0x1ff) {
         printf("offset %" PRId64 " is not sector aligned\n",
                offset);
         return 0;
@@ -1604,6 +1607,10 @@ static int alloc_f(int argc, char **argv)
 
     if (argc == 3) {
         nb_sectors = cvtnum(argv[2]);
+        if (nb_sectors < 0) {
+            printf("non-numeric length argument -- %s\n", argv[2]);
+            return 0;
+        }
     } else {
         nb_sectors = 1;
     }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 06/26] qemu-io: Don't use global bs in command implementations
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (4 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 05/26] qemu-io: Handle cvtnum() errors in 'alloc' Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 07/26] qemu-io: Split off commands to qemu-io-cmds.c Stefan Hajnoczi
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Pass in the BlockDriverState to the command handlers instead of using
the global variable. This is an important step to make the commands
usable outside of qemu-io.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c     |   6 ++-
 cmd.h     |   8 ++-
 qemu-io.c | 167 ++++++++++++++++++++++++++++++++++----------------------------
 3 files changed, 101 insertions(+), 80 deletions(-)

diff --git a/cmd.c b/cmd.c
index 214c6f7..d501aab 100644
--- a/cmd.c
+++ b/cmd.c
@@ -57,7 +57,7 @@ check_command(
 	const cmdinfo_t	*ci)
 {
 	if (check_func)
-		return check_func(ci);
+		return check_func(qemuio_bs, ci);
 	return 1;
 }
 
@@ -103,7 +103,7 @@ command(
 		return 0;
 	}
 	optind = 0;
-	return ct->cfunc(argc, argv);
+	return ct->cfunc(qemuio_bs, argc, argv);
 }
 
 const cmdinfo_t *
@@ -452,6 +452,7 @@ static cmdinfo_t quit_cmd;
 /* ARGSUSED */
 static int
 quit_f(
+    BlockDriverState *bs,
 	int	argc,
 	char	**argv)
 {
@@ -490,6 +491,7 @@ help_all(void)
 
 static int
 help_f(
+    BlockDriverState *bs,
 	int		argc,
 	char		**argv)
 {
diff --git a/cmd.h b/cmd.h
index 4dcfe88..ccf6336 100644
--- a/cmd.h
+++ b/cmd.h
@@ -17,9 +17,13 @@
 #ifndef __COMMAND_H__
 #define __COMMAND_H__
 
+#include "qemu-common.h"
+
 #define CMD_FLAG_GLOBAL	((int)0x80000000)	/* don't iterate "args" */
 
-typedef int (*cfunc_t)(int argc, char **argv);
+extern BlockDriverState *qemuio_bs;
+
+typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
 typedef void (*helpfunc_t)(void);
 
 typedef struct cmdinfo {
@@ -41,7 +45,7 @@ extern int		ncmds;
 void help_init(void);
 void quit_init(void);
 
-typedef int (*checkfunc_t)(const cmdinfo_t *ci);
+typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
 
 void add_command(const cmdinfo_t *ci);
 void add_user_command(char *optarg);
diff --git a/qemu-io.c b/qemu-io.c
index b4f56fc..39d7063 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -25,8 +25,8 @@
 #define CMD_NOFILE_OK   0x01
 
 char *progname;
-static BlockDriverState *bs;
 
+BlockDriverState *qemuio_bs;
 static int misalign;
 
 static int64_t cvtnum(const char *s)
@@ -63,7 +63,7 @@ static int parse_pattern(const char *arg)
  */
 
 #define MISALIGN_OFFSET     16
-static void *qemu_io_alloc(size_t len, int pattern)
+static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
 {
     void *buf;
 
@@ -136,7 +136,8 @@ static void print_report(const char *op, struct timeval *t, int64_t offset,
  * vector matching it.
  */
 static void *
-create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
+create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
+             int pattern)
 {
     size_t *sizes = g_new0(size_t, nr_iov);
     size_t count = 0;
@@ -172,7 +173,7 @@ create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
 
     qemu_iovec_init(qiov, nr_iov);
 
-    buf = p = qemu_io_alloc(count, pattern);
+    buf = p = qemu_io_alloc(bs, count, pattern);
 
     for (i = 0; i < nr_iov; i++) {
         qemu_iovec_add(qiov, p, sizes[i]);
@@ -184,7 +185,8 @@ fail:
     return buf;
 }
 
-static int do_read(char *buf, int64_t offset, int count, int *total)
+static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                   int *total)
 {
     int ret;
 
@@ -196,7 +198,8 @@ static int do_read(char *buf, int64_t offset, int count, int *total)
     return 1;
 }
 
-static int do_write(char *buf, int64_t offset, int count, int *total)
+static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                    int *total)
 {
     int ret;
 
@@ -208,7 +211,8 @@ static int do_write(char *buf, int64_t offset, int count, int *total)
     return 1;
 }
 
-static int do_pread(char *buf, int64_t offset, int count, int *total)
+static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                    int *total)
 {
     *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
     if (*total < 0) {
@@ -217,7 +221,8 @@ static int do_pread(char *buf, int64_t offset, int count, int *total)
     return 1;
 }
 
-static int do_pwrite(char *buf, int64_t offset, int count, int *total)
+static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                     int *total)
 {
     *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
     if (*total < 0) {
@@ -227,6 +232,7 @@ static int do_pwrite(char *buf, int64_t offset, int count, int *total)
 }
 
 typedef struct {
+    BlockDriverState *bs;
     int64_t offset;
     int count;
     int *total;
@@ -238,7 +244,7 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
 {
     CoWriteZeroes *data = opaque;
 
-    data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
+    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
                                      data->count / BDRV_SECTOR_SIZE);
     data->done = true;
     if (data->ret < 0) {
@@ -249,10 +255,12 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
     *data->total = data->count;
 }
 
-static int do_co_write_zeroes(int64_t offset, int count, int *total)
+static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+                              int *total)
 {
     Coroutine *co;
     CoWriteZeroes data = {
+        .bs     = bs,
         .offset = offset,
         .count  = count,
         .total  = total,
@@ -271,7 +279,8 @@ static int do_co_write_zeroes(int64_t offset, int count, int *total)
     }
 }
 
-static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
+static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
+                               int count, int *total)
 {
     int ret;
 
@@ -283,7 +292,8 @@ static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
     return 1;
 }
 
-static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
+static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+                           int count, int *total)
 {
     *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
     if (*total < 0) {
@@ -292,7 +302,8 @@ static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
     return 1;
 }
 
-static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
+static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+                           int count, int *total)
 {
     *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
     if (*total < 0) {
@@ -307,7 +318,8 @@ static void aio_rw_done(void *opaque, int ret)
     *(int *)opaque = ret;
 }
 
-static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
+static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
+                        int64_t offset, int *total)
 {
     int async_ret = NOT_DONE;
 
@@ -321,7 +333,8 @@ static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
     return async_ret < 0 ? async_ret : 1;
 }
 
-static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
+static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
+                         int64_t offset, int *total)
 {
     int async_ret = NOT_DONE;
 
@@ -350,7 +363,8 @@ static void multiwrite_cb(void *opaque, int ret)
     }
 }
 
-static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
+static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
+                             int num_reqs, int *total)
 {
     int i, ret;
     struct multiwrite_async_ret async_ret = {
@@ -399,7 +413,7 @@ static void read_help(void)
 "\n");
 }
 
-static int read_f(int argc, char **argv);
+static int read_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t read_cmd = {
     .name       = "read",
@@ -412,7 +426,7 @@ static const cmdinfo_t read_cmd = {
     .help       = read_help,
 };
 
-static int read_f(int argc, char **argv)
+static int read_f(BlockDriverState *bs, int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
@@ -518,15 +532,15 @@ static int read_f(int argc, char **argv)
         }
     }
 
-    buf = qemu_io_alloc(count, 0xab);
+    buf = qemu_io_alloc(bs, count, 0xab);
 
     gettimeofday(&t1, NULL);
     if (pflag) {
-        cnt = do_pread(buf, offset, count, &total);
+        cnt = do_pread(bs, buf, offset, count, &total);
     } else if (bflag) {
-        cnt = do_load_vmstate(buf, offset, count, &total);
+        cnt = do_load_vmstate(bs, buf, offset, count, &total);
     } else {
-        cnt = do_read(buf, offset, count, &total);
+        cnt = do_read(bs, buf, offset, count, &total);
     }
     gettimeofday(&t2, NULL);
 
@@ -583,7 +597,7 @@ static void readv_help(void)
 "\n");
 }
 
-static int readv_f(int argc, char **argv);
+static int readv_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t readv_cmd = {
     .name       = "readv",
@@ -595,7 +609,7 @@ static const cmdinfo_t readv_cmd = {
     .help       = readv_help,
 };
 
-static int readv_f(int argc, char **argv)
+static int readv_f(BlockDriverState *bs, int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, qflag = 0, vflag = 0;
@@ -651,13 +665,13 @@ static int readv_f(int argc, char **argv)
     }
 
     nr_iov = argc - optind;
-    buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
+    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
     if (buf == NULL) {
         return 0;
     }
 
     gettimeofday(&t1, NULL);
-    cnt = do_aio_readv(&qiov, offset, &total);
+    cnt = do_aio_readv(bs, &qiov, offset, &total);
     gettimeofday(&t2, NULL);
 
     if (cnt < 0) {
@@ -714,7 +728,7 @@ static void write_help(void)
 "\n");
 }
 
-static int write_f(int argc, char **argv);
+static int write_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t write_cmd = {
     .name       = "write",
@@ -727,7 +741,7 @@ static const cmdinfo_t write_cmd = {
     .help       = write_help,
 };
 
-static int write_f(int argc, char **argv)
+static int write_f(BlockDriverState *bs, int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
@@ -814,20 +828,20 @@ static int write_f(int argc, char **argv)
     }
 
     if (!zflag) {
-        buf = qemu_io_alloc(count, pattern);
+        buf = qemu_io_alloc(bs, count, pattern);
     }
 
     gettimeofday(&t1, NULL);
     if (pflag) {
-        cnt = do_pwrite(buf, offset, count, &total);
+        cnt = do_pwrite(bs, buf, offset, count, &total);
     } else if (bflag) {
-        cnt = do_save_vmstate(buf, offset, count, &total);
+        cnt = do_save_vmstate(bs, buf, offset, count, &total);
     } else if (zflag) {
-        cnt = do_co_write_zeroes(offset, count, &total);
+        cnt = do_co_write_zeroes(bs, offset, count, &total);
     } else if (cflag) {
-        cnt = do_write_compressed(buf, offset, count, &total);
+        cnt = do_write_compressed(bs, buf, offset, count, &total);
     } else {
-        cnt = do_write(buf, offset, count, &total);
+        cnt = do_write(bs, buf, offset, count, &total);
     }
     gettimeofday(&t2, NULL);
 
@@ -870,7 +884,7 @@ writev_help(void)
 "\n");
 }
 
-static int writev_f(int argc, char **argv);
+static int writev_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t writev_cmd = {
     .name       = "writev",
@@ -882,7 +896,7 @@ static const cmdinfo_t writev_cmd = {
     .help       = writev_help,
 };
 
-static int writev_f(int argc, char **argv)
+static int writev_f(BlockDriverState *bs, int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, qflag = 0;
@@ -932,13 +946,13 @@ static int writev_f(int argc, char **argv)
     }
 
     nr_iov = argc - optind;
-    buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
+    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
     if (buf == NULL) {
         return 0;
     }
 
     gettimeofday(&t1, NULL);
-    cnt = do_aio_writev(&qiov, offset, &total);
+    cnt = do_aio_writev(bs, &qiov, offset, &total);
     gettimeofday(&t2, NULL);
 
     if (cnt < 0) {
@@ -979,7 +993,7 @@ static void multiwrite_help(void)
 "\n");
 }
 
-static int multiwrite_f(int argc, char **argv);
+static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t multiwrite_cmd = {
     .name       = "multiwrite",
@@ -991,7 +1005,7 @@ static const cmdinfo_t multiwrite_cmd = {
     .help       = multiwrite_help,
 };
 
-static int multiwrite_f(int argc, char **argv)
+static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, qflag = 0;
@@ -1072,7 +1086,7 @@ static int multiwrite_f(int argc, char **argv)
         nr_iov = j - optind;
 
         /* Build request */
-        buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
+        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
         if (buf[i] == NULL) {
             goto out;
         }
@@ -1090,7 +1104,7 @@ static int multiwrite_f(int argc, char **argv)
     nr_reqs = i;
 
     gettimeofday(&t1, NULL);
-    cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
+    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
     gettimeofday(&t2, NULL);
 
     if (cnt < 0) {
@@ -1218,7 +1232,7 @@ static void aio_read_help(void)
 "\n");
 }
 
-static int aio_read_f(int argc, char **argv);
+static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t aio_read_cmd = {
     .name       = "aio_read",
@@ -1230,7 +1244,7 @@ static const cmdinfo_t aio_read_cmd = {
     .help       = aio_read_help,
 };
 
-static int aio_read_f(int argc, char **argv)
+static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
 {
     int nr_iov, c;
     struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
@@ -1281,7 +1295,7 @@ static int aio_read_f(int argc, char **argv)
     }
 
     nr_iov = argc - optind;
-    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
+    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
     if (ctx->buf == NULL) {
         g_free(ctx);
         return 0;
@@ -1313,7 +1327,7 @@ static void aio_write_help(void)
 "\n");
 }
 
-static int aio_write_f(int argc, char **argv);
+static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t aio_write_cmd = {
     .name       = "aio_write",
@@ -1325,7 +1339,7 @@ static const cmdinfo_t aio_write_cmd = {
     .help       = aio_write_help,
 };
 
-static int aio_write_f(int argc, char **argv)
+static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
 {
     int nr_iov, c;
     int pattern = 0xcd;
@@ -1373,7 +1387,7 @@ static int aio_write_f(int argc, char **argv)
     }
 
     nr_iov = argc - optind;
-    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
+    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
     if (ctx->buf == NULL) {
         g_free(ctx);
         return 0;
@@ -1385,7 +1399,7 @@ static int aio_write_f(int argc, char **argv)
     return 0;
 }
 
-static int aio_flush_f(int argc, char **argv)
+static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_drain_all();
     return 0;
@@ -1397,7 +1411,7 @@ static const cmdinfo_t aio_flush_cmd = {
     .oneline    = "completes all outstanding aio requests"
 };
 
-static int flush_f(int argc, char **argv)
+static int flush_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_flush(bs);
     return 0;
@@ -1410,7 +1424,7 @@ static const cmdinfo_t flush_cmd = {
     .oneline    = "flush all in-core file state to disk",
 };
 
-static int truncate_f(int argc, char **argv)
+static int truncate_f(BlockDriverState *bs, int argc, char **argv)
 {
     int64_t offset;
     int ret;
@@ -1440,7 +1454,7 @@ static const cmdinfo_t truncate_cmd = {
     .oneline    = "truncates the current file at the given offset",
 };
 
-static int length_f(int argc, char **argv)
+static int length_f(BlockDriverState *bs, int argc, char **argv)
 {
     int64_t size;
     char s1[64];
@@ -1465,7 +1479,7 @@ static const cmdinfo_t length_cmd = {
 };
 
 
-static int info_f(int argc, char **argv)
+static int info_f(BlockDriverState *bs, int argc, char **argv)
 {
     BlockDriverInfo bdi;
     char s1[64], s2[64];
@@ -1516,7 +1530,7 @@ static void discard_help(void)
 "\n");
 }
 
-static int discard_f(int argc, char **argv);
+static int discard_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t discard_cmd = {
     .name       = "discard",
@@ -1529,7 +1543,7 @@ static const cmdinfo_t discard_cmd = {
     .help       = discard_help,
 };
 
-static int discard_f(int argc, char **argv)
+static int discard_f(BlockDriverState *bs, int argc, char **argv)
 {
     struct timeval t1, t2;
     int Cflag = 0, qflag = 0;
@@ -1587,7 +1601,7 @@ out:
     return 0;
 }
 
-static int alloc_f(int argc, char **argv)
+static int alloc_f(BlockDriverState *bs, int argc, char **argv)
 {
     int64_t offset, sector_num;
     int nb_sectors, remaining;
@@ -1649,7 +1663,8 @@ static const cmdinfo_t alloc_cmd = {
 };
 
 
-static int map_is_allocated(int64_t sector_num, int64_t nb_sectors, int64_t *pnum)
+static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
+                            int64_t nb_sectors, int64_t *pnum)
 {
     int num, num_checked;
     int ret, firstret;
@@ -1679,7 +1694,7 @@ static int map_is_allocated(int64_t sector_num, int64_t nb_sectors, int64_t *pnu
     return firstret;
 }
 
-static int map_f(int argc, char **argv)
+static int map_f(BlockDriverState *bs, int argc, char **argv)
 {
     int64_t offset;
     int64_t nb_sectors;
@@ -1692,7 +1707,7 @@ static int map_f(int argc, char **argv)
     nb_sectors = bs->total_sectors;
 
     do {
-        ret = map_is_allocated(offset, nb_sectors, &num);
+        ret = map_is_allocated(bs, offset, nb_sectors, &num);
         if (ret < 0) {
             error_report("Failed to get allocation status: %s", strerror(-ret));
             return 0;
@@ -1720,7 +1735,7 @@ static const cmdinfo_t map_cmd = {
        .oneline        = "prints the allocated areas of a file",
 };
 
-static int break_f(int argc, char **argv)
+static int break_f(BlockDriverState *bs, int argc, char **argv)
 {
     int ret;
 
@@ -1742,7 +1757,7 @@ static const cmdinfo_t break_cmd = {
                          "request as tag",
 };
 
-static int resume_f(int argc, char **argv)
+static int resume_f(BlockDriverState *bs, int argc, char **argv)
 {
     int ret;
 
@@ -1763,7 +1778,7 @@ static const cmdinfo_t resume_cmd = {
        .oneline        = "resumes the request tagged as tag",
 };
 
-static int wait_break_f(int argc, char **argv)
+static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
 {
     while (!bdrv_debug_is_suspended(bs, argv[1])) {
         qemu_aio_wait();
@@ -1781,7 +1796,7 @@ static const cmdinfo_t wait_break_cmd = {
        .oneline        = "waits for the suspension of a request",
 };
 
-static int abort_f(int argc, char **argv)
+static int abort_f(BlockDriverState *bs, int argc, char **argv)
 {
     abort();
 }
@@ -1793,10 +1808,10 @@ static const cmdinfo_t abort_cmd = {
        .oneline        = "simulate a program crash using abort(3)",
 };
 
-static int close_f(int argc, char **argv)
+static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_delete(bs);
-    bs = NULL;
+    qemuio_bs = NULL;
     return 0;
 }
 
@@ -1809,23 +1824,23 @@ static const cmdinfo_t close_cmd = {
 
 static int openfile(char *name, int flags, int growable)
 {
-    if (bs) {
+    if (qemuio_bs) {
         fprintf(stderr, "file open already, try 'help close'\n");
         return 1;
     }
 
     if (growable) {
-        if (bdrv_file_open(&bs, name, NULL, flags)) {
+        if (bdrv_file_open(&qemuio_bs, name, NULL, flags)) {
             fprintf(stderr, "%s: can't open device %s\n", progname, name);
             return 1;
         }
     } else {
-        bs = bdrv_new("hda");
+        qemuio_bs = bdrv_new("hda");
 
-        if (bdrv_open(bs, name, NULL, flags, NULL) < 0) {
+        if (bdrv_open(qemuio_bs, name, NULL, flags, NULL) < 0) {
             fprintf(stderr, "%s: can't open device %s\n", progname, name);
-            bdrv_delete(bs);
-            bs = NULL;
+            bdrv_delete(qemuio_bs);
+            qemuio_bs = NULL;
             return 1;
         }
     }
@@ -1850,7 +1865,7 @@ static void open_help(void)
 "\n");
 }
 
-static int open_f(int argc, char **argv);
+static int open_f(BlockDriverState *bs, int argc, char **argv);
 
 static const cmdinfo_t open_cmd = {
     .name       = "open",
@@ -1864,7 +1879,7 @@ static const cmdinfo_t open_cmd = {
     .help       = open_help,
 };
 
-static int open_f(int argc, char **argv)
+static int open_f(BlockDriverState *bs, int argc, char **argv)
 {
     int flags = 0;
     int readonly = 0;
@@ -1901,7 +1916,7 @@ static int open_f(int argc, char **argv)
     return openfile(argv[optind], flags, growable);
 }
 
-static int init_check_command(const cmdinfo_t *ct)
+static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
 {
     if (ct->flags & CMD_FLAG_GLOBAL) {
         return 1;
@@ -2064,8 +2079,8 @@ int main(int argc, char **argv)
      */
     bdrv_drain_all();
 
-    if (bs) {
-        bdrv_delete(bs);
+    if (qemuio_bs) {
+        bdrv_delete(qemuio_bs);
     }
     return 0;
 }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 07/26] qemu-io: Split off commands to qemu-io-cmds.c
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (5 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 06/26] qemu-io: Don't use global bs in command implementations Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 08/26] qemu-io: Factor out qemuio_command Stefan Hajnoczi
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

This is the implementation of all qemu-io commands that make sense to be
called from the qemu monitor, i.e. everything except open, close and
quit.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 Makefile       |    2 +-
 qemu-io-cmds.c | 1835 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-io.c      | 1817 +------------------------------------------------------
 3 files changed, 1838 insertions(+), 1816 deletions(-)
 create mode 100644 qemu-io-cmds.c

diff --git a/Makefile b/Makefile
index a96736b..cf932eb 100644
--- a/Makefile
+++ b/Makefile
@@ -186,7 +186,7 @@ qemu-img.o: qemu-img-cmds.h
 
 qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
 qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
+qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
new file mode 100644
index 0000000..0a3817a
--- /dev/null
+++ b/qemu-io-cmds.c
@@ -0,0 +1,1835 @@
+/*
+ * Command line utility to exercise the QEMU I/O path.
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "block/block_int.h"
+#include "cmd.h"
+
+#define CMD_NOFILE_OK   0x01
+
+int qemuio_misalign;
+
+static int64_t cvtnum(const char *s)
+{
+    char *end;
+    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
+}
+
+/*
+ * Parse the pattern argument to various sub-commands.
+ *
+ * Because the pattern is used as an argument to memset it must evaluate
+ * to an unsigned integer that fits into a single byte.
+ */
+static int parse_pattern(const char *arg)
+{
+    char *endptr = NULL;
+    long pattern;
+
+    pattern = strtol(arg, &endptr, 0);
+    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
+        printf("%s is not a valid pattern byte\n", arg);
+        return -1;
+    }
+
+    return pattern;
+}
+
+/*
+ * Memory allocation helpers.
+ *
+ * Make sure memory is aligned by default, or purposefully misaligned if
+ * that is specified on the command line.
+ */
+
+#define MISALIGN_OFFSET     16
+static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
+{
+    void *buf;
+
+    if (qemuio_misalign) {
+        len += MISALIGN_OFFSET;
+    }
+    buf = qemu_blockalign(bs, len);
+    memset(buf, pattern, len);
+    if (qemuio_misalign) {
+        buf += MISALIGN_OFFSET;
+    }
+    return buf;
+}
+
+static void qemu_io_free(void *p)
+{
+    if (qemuio_misalign) {
+        p -= MISALIGN_OFFSET;
+    }
+    qemu_vfree(p);
+}
+
+static void dump_buffer(const void *buffer, int64_t offset, int len)
+{
+    int i, j;
+    const uint8_t *p;
+
+    for (i = 0, p = buffer; i < len; i += 16) {
+        const uint8_t *s = p;
+
+        printf("%08" PRIx64 ":  ", offset + i);
+        for (j = 0; j < 16 && i + j < len; j++, p++) {
+            printf("%02x ", *p);
+        }
+        printf(" ");
+        for (j = 0; j < 16 && i + j < len; j++, s++) {
+            if (isalnum(*s)) {
+                printf("%c", *s);
+            } else {
+                printf(".");
+            }
+        }
+        printf("\n");
+    }
+}
+
+static void print_report(const char *op, struct timeval *t, int64_t offset,
+                         int count, int total, int cnt, int Cflag)
+{
+    char s1[64], s2[64], ts[64];
+
+    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
+    if (!Cflag) {
+        cvtstr((double)total, s1, sizeof(s1));
+        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
+        printf("%s %d/%d bytes at offset %" PRId64 "\n",
+               op, total, count, offset);
+        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
+               s1, cnt, ts, s2, tdiv((double)cnt, *t));
+    } else {/* bytes,ops,time,bytes/sec,ops/sec */
+        printf("%d,%d,%s,%.3f,%.3f\n",
+            total, cnt, ts,
+            tdiv((double)total, *t),
+            tdiv((double)cnt, *t));
+    }
+}
+
+/*
+ * Parse multiple length statements for vectored I/O, and construct an I/O
+ * vector matching it.
+ */
+static void *
+create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
+             int pattern)
+{
+    size_t *sizes = g_new0(size_t, nr_iov);
+    size_t count = 0;
+    void *buf = NULL;
+    void *p;
+    int i;
+
+    for (i = 0; i < nr_iov; i++) {
+        char *arg = argv[i];
+        int64_t len;
+
+        len = cvtnum(arg);
+        if (len < 0) {
+            printf("non-numeric length argument -- %s\n", arg);
+            goto fail;
+        }
+
+        /* should be SIZE_T_MAX, but that doesn't exist */
+        if (len > INT_MAX) {
+            printf("too large length argument -- %s\n", arg);
+            goto fail;
+        }
+
+        if (len & 0x1ff) {
+            printf("length argument %" PRId64
+                   " is not sector aligned\n", len);
+            goto fail;
+        }
+
+        sizes[i] = len;
+        count += len;
+    }
+
+    qemu_iovec_init(qiov, nr_iov);
+
+    buf = p = qemu_io_alloc(bs, count, pattern);
+
+    for (i = 0; i < nr_iov; i++) {
+        qemu_iovec_add(qiov, p, sizes[i]);
+        p += sizes[i];
+    }
+
+fail:
+    g_free(sizes);
+    return buf;
+}
+
+static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                   int *total)
+{
+    int ret;
+
+    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+    if (ret < 0) {
+        return ret;
+    }
+    *total = count;
+    return 1;
+}
+
+static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                    int *total)
+{
+    int ret;
+
+    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+    if (ret < 0) {
+        return ret;
+    }
+    *total = count;
+    return 1;
+}
+
+static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                    int *total)
+{
+    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
+}
+
+static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
+                     int *total)
+{
+    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
+}
+
+typedef struct {
+    BlockDriverState *bs;
+    int64_t offset;
+    int count;
+    int *total;
+    int ret;
+    bool done;
+} CoWriteZeroes;
+
+static void coroutine_fn co_write_zeroes_entry(void *opaque)
+{
+    CoWriteZeroes *data = opaque;
+
+    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
+                                     data->count / BDRV_SECTOR_SIZE);
+    data->done = true;
+    if (data->ret < 0) {
+        *data->total = data->ret;
+        return;
+    }
+
+    *data->total = data->count;
+}
+
+static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+                              int *total)
+{
+    Coroutine *co;
+    CoWriteZeroes data = {
+        .bs     = bs,
+        .offset = offset,
+        .count  = count,
+        .total  = total,
+        .done   = false,
+    };
+
+    co = qemu_coroutine_create(co_write_zeroes_entry);
+    qemu_coroutine_enter(co, &data);
+    while (!data.done) {
+        qemu_aio_wait();
+    }
+    if (data.ret < 0) {
+        return data.ret;
+    } else {
+        return 1;
+    }
+}
+
+static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
+                               int count, int *total)
+{
+    int ret;
+
+    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+    if (ret < 0) {
+        return ret;
+    }
+    *total = count;
+    return 1;
+}
+
+static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+                           int count, int *total)
+{
+    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
+}
+
+static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+                           int count, int *total)
+{
+    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
+    if (*total < 0) {
+        return *total;
+    }
+    return 1;
+}
+
+#define NOT_DONE 0x7fffffff
+static void aio_rw_done(void *opaque, int ret)
+{
+    *(int *)opaque = ret;
+}
+
+static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
+                        int64_t offset, int *total)
+{
+    int async_ret = NOT_DONE;
+
+    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
+                   aio_rw_done, &async_ret);
+    while (async_ret == NOT_DONE) {
+        main_loop_wait(false);
+    }
+
+    *total = qiov->size;
+    return async_ret < 0 ? async_ret : 1;
+}
+
+static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
+                         int64_t offset, int *total)
+{
+    int async_ret = NOT_DONE;
+
+    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
+                    aio_rw_done, &async_ret);
+    while (async_ret == NOT_DONE) {
+        main_loop_wait(false);
+    }
+
+    *total = qiov->size;
+    return async_ret < 0 ? async_ret : 1;
+}
+
+struct multiwrite_async_ret {
+    int num_done;
+    int error;
+};
+
+static void multiwrite_cb(void *opaque, int ret)
+{
+    struct multiwrite_async_ret *async_ret = opaque;
+
+    async_ret->num_done++;
+    if (ret < 0) {
+        async_ret->error = ret;
+    }
+}
+
+static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
+                             int num_reqs, int *total)
+{
+    int i, ret;
+    struct multiwrite_async_ret async_ret = {
+        .num_done = 0,
+        .error = 0,
+    };
+
+    *total = 0;
+    for (i = 0; i < num_reqs; i++) {
+        reqs[i].cb = multiwrite_cb;
+        reqs[i].opaque = &async_ret;
+        *total += reqs[i].qiov->size;
+    }
+
+    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
+    if (ret < 0) {
+        return ret;
+    }
+
+    while (async_ret.num_done < num_reqs) {
+        main_loop_wait(false);
+    }
+
+    return async_ret.error < 0 ? async_ret.error : 1;
+}
+
+static void read_help(void)
+{
+    printf(
+"\n"
+" reads a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" -b, -- read from the VM state rather than the virtual disk\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -l, -- length for pattern verification (only with -P)\n"
+" -p, -- use bdrv_pread to read the file\n"
+" -P, -- use a pattern to verify read data\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+" -s, -- start offset for pattern verification (only with -P)\n"
+" -v, -- dump buffer to standard output\n"
+"\n");
+}
+
+static int read_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t read_cmd = {
+    .name       = "read",
+    .altname    = "r",
+    .cfunc      = read_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
+    .oneline    = "reads a number of bytes at a specified offset",
+    .help       = read_help,
+};
+
+static int read_f(BlockDriverState *bs, int argc, char **argv)
+{
+    struct timeval t1, t2;
+    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
+    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    int count;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int pattern = 0, pattern_offset = 0, pattern_count = 0;
+
+    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
+        switch (c) {
+        case 'b':
+            bflag = 1;
+            break;
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'l':
+            lflag = 1;
+            pattern_count = cvtnum(optarg);
+            if (pattern_count < 0) {
+                printf("non-numeric length argument -- %s\n", optarg);
+                return 0;
+            }
+            break;
+        case 'p':
+            pflag = 1;
+            break;
+        case 'P':
+            Pflag = 1;
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 's':
+            sflag = 1;
+            pattern_offset = cvtnum(optarg);
+            if (pattern_offset < 0) {
+                printf("non-numeric length argument -- %s\n", optarg);
+                return 0;
+            }
+            break;
+        case 'v':
+            vflag = 1;
+            break;
+        default:
+            return command_usage(&read_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return command_usage(&read_cmd);
+    }
+
+    if (bflag && pflag) {
+        printf("-b and -p cannot be specified at the same time\n");
+        return 0;
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    optind++;
+    count = cvtnum(argv[optind]);
+    if (count < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    if (!Pflag && (lflag || sflag)) {
+        return command_usage(&read_cmd);
+    }
+
+    if (!lflag) {
+        pattern_count = count - pattern_offset;
+    }
+
+    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
+        printf("pattern verification range exceeds end of read data\n");
+        return 0;
+    }
+
+    if (!pflag) {
+        if (offset & 0x1ff) {
+            printf("offset %" PRId64 " is not sector aligned\n",
+                   offset);
+            return 0;
+        }
+        if (count & 0x1ff) {
+            printf("count %d is not sector aligned\n",
+                   count);
+            return 0;
+        }
+    }
+
+    buf = qemu_io_alloc(bs, count, 0xab);
+
+    gettimeofday(&t1, NULL);
+    if (pflag) {
+        cnt = do_pread(bs, buf, offset, count, &total);
+    } else if (bflag) {
+        cnt = do_load_vmstate(bs, buf, offset, count, &total);
+    } else {
+        cnt = do_read(bs, buf, offset, count, &total);
+    }
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("read failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (Pflag) {
+        void *cmp_buf = g_malloc(pattern_count);
+        memset(cmp_buf, pattern, pattern_count);
+        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
+            printf("Pattern verification failed at offset %"
+                   PRId64 ", %d bytes\n",
+                   offset + pattern_offset, pattern_count);
+        }
+        g_free(cmp_buf);
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    if (vflag) {
+        dump_buffer(buf, offset, count);
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("read", &t2, offset, count, total, cnt, Cflag);
+
+out:
+    qemu_io_free(buf);
+
+    return 0;
+}
+
+static void readv_help(void)
+{
+    printf(
+"\n"
+" reads a range of bytes from the given offset into multiple buffers\n"
+"\n"
+" Example:\n"
+" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" Uses multiple iovec buffers if more than one byte range is specified.\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -P, -- use a pattern to verify read data\n"
+" -v, -- dump buffer to standard output\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int readv_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t readv_cmd = {
+    .name       = "readv",
+    .cfunc      = readv_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cqv] [-P pattern ] off len [len..]",
+    .oneline    = "reads a number of bytes at a specified offset",
+    .help       = readv_help,
+};
+
+static int readv_f(BlockDriverState *bs, int argc, char **argv)
+{
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0, vflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int nr_iov;
+    QEMUIOVector qiov;
+    int pattern = 0;
+    int Pflag = 0;
+
+    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'P':
+            Pflag = 1;
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'v':
+            vflag = 1;
+            break;
+        default:
+            return command_usage(&readv_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return command_usage(&readv_cmd);
+    }
+
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+    optind++;
+
+    if (offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               offset);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
+    if (buf == NULL) {
+        return 0;
+    }
+
+    gettimeofday(&t1, NULL);
+    cnt = do_aio_readv(bs, &qiov, offset, &total);
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("readv failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (Pflag) {
+        void *cmp_buf = g_malloc(qiov.size);
+        memset(cmp_buf, pattern, qiov.size);
+        if (memcmp(buf, cmp_buf, qiov.size)) {
+            printf("Pattern verification failed at offset %"
+                   PRId64 ", %zd bytes\n", offset, qiov.size);
+        }
+        g_free(cmp_buf);
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    if (vflag) {
+        dump_buffer(buf, offset, qiov.size);
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
+
+out:
+    qemu_iovec_destroy(&qiov);
+    qemu_io_free(buf);
+    return 0;
+}
+
+static void write_help(void)
+{
+    printf(
+"\n"
+" writes a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd).\n"
+" -b, -- write to the VM state rather than the virtual disk\n"
+" -c, -- write compressed data with bdrv_write_compressed\n"
+" -p, -- use bdrv_pwrite to write the file\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+" -z, -- write zeroes using bdrv_co_write_zeroes\n"
+"\n");
+}
+
+static int write_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t write_cmd = {
+    .name       = "write",
+    .altname    = "w",
+    .cfunc      = write_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-bcCpqz] [-P pattern ] off len",
+    .oneline    = "writes a number of bytes at a specified offset",
+    .help       = write_help,
+};
+
+static int write_f(BlockDriverState *bs, int argc, char **argv)
+{
+    struct timeval t1, t2;
+    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
+    int cflag = 0;
+    int c, cnt;
+    char *buf = NULL;
+    int64_t offset;
+    int count;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int pattern = 0xcd;
+
+    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
+        switch (c) {
+        case 'b':
+            bflag = 1;
+            break;
+        case 'c':
+            cflag = 1;
+            break;
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'p':
+            pflag = 1;
+            break;
+        case 'P':
+            Pflag = 1;
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'z':
+            zflag = 1;
+            break;
+        default:
+            return command_usage(&write_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return command_usage(&write_cmd);
+    }
+
+    if (bflag + pflag + zflag > 1) {
+        printf("-b, -p, or -z cannot be specified at the same time\n");
+        return 0;
+    }
+
+    if (zflag && Pflag) {
+        printf("-z and -P cannot be specified at the same time\n");
+        return 0;
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    optind++;
+    count = cvtnum(argv[optind]);
+    if (count < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    if (!pflag) {
+        if (offset & 0x1ff) {
+            printf("offset %" PRId64 " is not sector aligned\n",
+                   offset);
+            return 0;
+        }
+
+        if (count & 0x1ff) {
+            printf("count %d is not sector aligned\n",
+                   count);
+            return 0;
+        }
+    }
+
+    if (!zflag) {
+        buf = qemu_io_alloc(bs, count, pattern);
+    }
+
+    gettimeofday(&t1, NULL);
+    if (pflag) {
+        cnt = do_pwrite(bs, buf, offset, count, &total);
+    } else if (bflag) {
+        cnt = do_save_vmstate(bs, buf, offset, count, &total);
+    } else if (zflag) {
+        cnt = do_co_write_zeroes(bs, offset, count, &total);
+    } else if (cflag) {
+        cnt = do_write_compressed(bs, buf, offset, count, &total);
+    } else {
+        cnt = do_write(bs, buf, offset, count, &total);
+    }
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("write failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
+
+out:
+    if (!zflag) {
+        qemu_io_free(buf);
+    }
+
+    return 0;
+}
+
+static void
+writev_help(void)
+{
+    printf(
+"\n"
+" writes a range of bytes from the given offset source from multiple buffers\n"
+"\n"
+" Example:\n"
+" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd).\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int writev_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t writev_cmd = {
+    .name       = "writev",
+    .cfunc      = writev_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] [-P pattern ] off len [len..]",
+    .oneline    = "writes a number of bytes at a specified offset",
+    .help       = writev_help,
+};
+
+static int writev_f(BlockDriverState *bs, int argc, char **argv)
+{
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0;
+    int c, cnt;
+    char *buf;
+    int64_t offset;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int nr_iov;
+    int pattern = 0xcd;
+    QEMUIOVector qiov;
+
+    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        default:
+            return command_usage(&writev_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return command_usage(&writev_cmd);
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+    optind++;
+
+    if (offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               offset);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
+    if (buf == NULL) {
+        return 0;
+    }
+
+    gettimeofday(&t1, NULL);
+    cnt = do_aio_writev(bs, &qiov, offset, &total);
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("writev failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
+out:
+    qemu_iovec_destroy(&qiov);
+    qemu_io_free(buf);
+    return 0;
+}
+
+static void multiwrite_help(void)
+{
+    printf(
+"\n"
+" writes a range of bytes from the given offset source from multiple buffers,\n"
+" in a batch of requests that may be merged by qemu\n"
+"\n"
+" Example:\n"
+" 'multiwrite 512 1k 1k ; 4k 1k'\n"
+"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
+" by one for each request contained in the multiwrite command.\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t multiwrite_cmd = {
+    .name       = "multiwrite",
+    .cfunc      = multiwrite_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
+    .oneline    = "issues multiple write requests at once",
+    .help       = multiwrite_help,
+};
+
+static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
+{
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0;
+    int c, cnt;
+    char **buf;
+    int64_t offset, first_offset = 0;
+    /* Some compilers get confused and warn if this is not initialized.  */
+    int total = 0;
+    int nr_iov;
+    int nr_reqs;
+    int pattern = 0xcd;
+    QEMUIOVector *qiovs;
+    int i;
+    BlockRequest *reqs;
+
+    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                return 0;
+            }
+            break;
+        default:
+            return command_usage(&writev_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return command_usage(&writev_cmd);
+    }
+
+    nr_reqs = 1;
+    for (i = optind; i < argc; i++) {
+        if (!strcmp(argv[i], ";")) {
+            nr_reqs++;
+        }
+    }
+
+    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
+    buf = g_malloc0(nr_reqs * sizeof(*buf));
+    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
+
+    for (i = 0; i < nr_reqs && optind < argc; i++) {
+        int j;
+
+        /* Read the offset of the request */
+        offset = cvtnum(argv[optind]);
+        if (offset < 0) {
+            printf("non-numeric offset argument -- %s\n", argv[optind]);
+            goto out;
+        }
+        optind++;
+
+        if (offset & 0x1ff) {
+            printf("offset %lld is not sector aligned\n",
+                   (long long)offset);
+            goto out;
+        }
+
+        if (i == 0) {
+            first_offset = offset;
+        }
+
+        /* Read lengths for qiov entries */
+        for (j = optind; j < argc; j++) {
+            if (!strcmp(argv[j], ";")) {
+                break;
+            }
+        }
+
+        nr_iov = j - optind;
+
+        /* Build request */
+        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
+        if (buf[i] == NULL) {
+            goto out;
+        }
+
+        reqs[i].qiov = &qiovs[i];
+        reqs[i].sector = offset >> 9;
+        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
+
+        optind = j + 1;
+
+        pattern++;
+    }
+
+    /* If there were empty requests at the end, ignore them */
+    nr_reqs = i;
+
+    gettimeofday(&t1, NULL);
+    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
+    gettimeofday(&t2, NULL);
+
+    if (cnt < 0) {
+        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
+        goto out;
+    }
+
+    if (qflag) {
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, t1);
+    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
+out:
+    for (i = 0; i < nr_reqs; i++) {
+        qemu_io_free(buf[i]);
+        if (reqs[i].qiov != NULL) {
+            qemu_iovec_destroy(&qiovs[i]);
+        }
+    }
+    g_free(buf);
+    g_free(reqs);
+    g_free(qiovs);
+    return 0;
+}
+
+struct aio_ctx {
+    QEMUIOVector qiov;
+    int64_t offset;
+    char *buf;
+    int qflag;
+    int vflag;
+    int Cflag;
+    int Pflag;
+    int pattern;
+    struct timeval t1;
+};
+
+static void aio_write_done(void *opaque, int ret)
+{
+    struct aio_ctx *ctx = opaque;
+    struct timeval t2;
+
+    gettimeofday(&t2, NULL);
+
+
+    if (ret < 0) {
+        printf("aio_write failed: %s\n", strerror(-ret));
+        goto out;
+    }
+
+    if (ctx->qflag) {
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, ctx->t1);
+    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
+                 ctx->qiov.size, 1, ctx->Cflag);
+out:
+    qemu_io_free(ctx->buf);
+    qemu_iovec_destroy(&ctx->qiov);
+    g_free(ctx);
+}
+
+static void aio_read_done(void *opaque, int ret)
+{
+    struct aio_ctx *ctx = opaque;
+    struct timeval t2;
+
+    gettimeofday(&t2, NULL);
+
+    if (ret < 0) {
+        printf("readv failed: %s\n", strerror(-ret));
+        goto out;
+    }
+
+    if (ctx->Pflag) {
+        void *cmp_buf = g_malloc(ctx->qiov.size);
+
+        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
+        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
+            printf("Pattern verification failed at offset %"
+                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
+        }
+        g_free(cmp_buf);
+    }
+
+    if (ctx->qflag) {
+        goto out;
+    }
+
+    if (ctx->vflag) {
+        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    t2 = tsub(t2, ctx->t1);
+    print_report("read", &t2, ctx->offset, ctx->qiov.size,
+                 ctx->qiov.size, 1, ctx->Cflag);
+out:
+    qemu_io_free(ctx->buf);
+    qemu_iovec_destroy(&ctx->qiov);
+    g_free(ctx);
+}
+
+static void aio_read_help(void)
+{
+    printf(
+"\n"
+" asynchronously reads a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" The read is performed asynchronously and the aio_flush command must be\n"
+" used to ensure all outstanding aio requests have been completed.\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -P, -- use a pattern to verify read data\n"
+" -v, -- dump buffer to standard output\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t aio_read_cmd = {
+    .name       = "aio_read",
+    .cfunc      = aio_read_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cqv] [-P pattern ] off len [len..]",
+    .oneline    = "asynchronously reads a number of bytes",
+    .help       = aio_read_help,
+};
+
+static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int nr_iov, c;
+    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+
+    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+        switch (c) {
+        case 'C':
+            ctx->Cflag = 1;
+            break;
+        case 'P':
+            ctx->Pflag = 1;
+            ctx->pattern = parse_pattern(optarg);
+            if (ctx->pattern < 0) {
+                g_free(ctx);
+                return 0;
+            }
+            break;
+        case 'q':
+            ctx->qflag = 1;
+            break;
+        case 'v':
+            ctx->vflag = 1;
+            break;
+        default:
+            g_free(ctx);
+            return command_usage(&aio_read_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        g_free(ctx);
+        return command_usage(&aio_read_cmd);
+    }
+
+    ctx->offset = cvtnum(argv[optind]);
+    if (ctx->offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        g_free(ctx);
+        return 0;
+    }
+    optind++;
+
+    if (ctx->offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               ctx->offset);
+        g_free(ctx);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
+    if (ctx->buf == NULL) {
+        g_free(ctx);
+        return 0;
+    }
+
+    gettimeofday(&ctx->t1, NULL);
+    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
+                   ctx->qiov.size >> 9, aio_read_done, ctx);
+    return 0;
+}
+
+static void aio_write_help(void)
+{
+    printf(
+"\n"
+" asynchronously writes a range of bytes from the given offset source\n"
+" from multiple buffers\n"
+"\n"
+" Example:\n"
+" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd).\n"
+" The write is performed asynchronously and the aio_flush command must be\n"
+" used to ensure all outstanding aio requests have been completed.\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t aio_write_cmd = {
+    .name       = "aio_write",
+    .cfunc      = aio_write_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] [-P pattern ] off len [len..]",
+    .oneline    = "asynchronously writes a number of bytes",
+    .help       = aio_write_help,
+};
+
+static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int nr_iov, c;
+    int pattern = 0xcd;
+    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+
+    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+        switch (c) {
+        case 'C':
+            ctx->Cflag = 1;
+            break;
+        case 'q':
+            ctx->qflag = 1;
+            break;
+        case 'P':
+            pattern = parse_pattern(optarg);
+            if (pattern < 0) {
+                g_free(ctx);
+                return 0;
+            }
+            break;
+        default:
+            g_free(ctx);
+            return command_usage(&aio_write_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        g_free(ctx);
+        return command_usage(&aio_write_cmd);
+    }
+
+    ctx->offset = cvtnum(argv[optind]);
+    if (ctx->offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        g_free(ctx);
+        return 0;
+    }
+    optind++;
+
+    if (ctx->offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               ctx->offset);
+        g_free(ctx);
+        return 0;
+    }
+
+    nr_iov = argc - optind;
+    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
+    if (ctx->buf == NULL) {
+        g_free(ctx);
+        return 0;
+    }
+
+    gettimeofday(&ctx->t1, NULL);
+    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
+                    ctx->qiov.size >> 9, aio_write_done, ctx);
+    return 0;
+}
+
+static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
+{
+    bdrv_drain_all();
+    return 0;
+}
+
+static const cmdinfo_t aio_flush_cmd = {
+    .name       = "aio_flush",
+    .cfunc      = aio_flush_f,
+    .oneline    = "completes all outstanding aio requests"
+};
+
+static int flush_f(BlockDriverState *bs, int argc, char **argv)
+{
+    bdrv_flush(bs);
+    return 0;
+}
+
+static const cmdinfo_t flush_cmd = {
+    .name       = "flush",
+    .altname    = "f",
+    .cfunc      = flush_f,
+    .oneline    = "flush all in-core file state to disk",
+};
+
+static int truncate_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int64_t offset;
+    int ret;
+
+    offset = cvtnum(argv[1]);
+    if (offset < 0) {
+        printf("non-numeric truncate argument -- %s\n", argv[1]);
+        return 0;
+    }
+
+    ret = bdrv_truncate(bs, offset);
+    if (ret < 0) {
+        printf("truncate: %s\n", strerror(-ret));
+        return 0;
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t truncate_cmd = {
+    .name       = "truncate",
+    .altname    = "t",
+    .cfunc      = truncate_f,
+    .argmin     = 1,
+    .argmax     = 1,
+    .args       = "off",
+    .oneline    = "truncates the current file at the given offset",
+};
+
+static int length_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int64_t size;
+    char s1[64];
+
+    size = bdrv_getlength(bs);
+    if (size < 0) {
+        printf("getlength: %s\n", strerror(-size));
+        return 0;
+    }
+
+    cvtstr(size, s1, sizeof(s1));
+    printf("%s\n", s1);
+    return 0;
+}
+
+
+static const cmdinfo_t length_cmd = {
+    .name   = "length",
+    .altname    = "l",
+    .cfunc      = length_f,
+    .oneline    = "gets the length of the current file",
+};
+
+
+static int info_f(BlockDriverState *bs, int argc, char **argv)
+{
+    BlockDriverInfo bdi;
+    char s1[64], s2[64];
+    int ret;
+
+    if (bs->drv && bs->drv->format_name) {
+        printf("format name: %s\n", bs->drv->format_name);
+    }
+    if (bs->drv && bs->drv->protocol_name) {
+        printf("format name: %s\n", bs->drv->protocol_name);
+    }
+
+    ret = bdrv_get_info(bs, &bdi);
+    if (ret) {
+        return 0;
+    }
+
+    cvtstr(bdi.cluster_size, s1, sizeof(s1));
+    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
+
+    printf("cluster size: %s\n", s1);
+    printf("vm state offset: %s\n", s2);
+
+    return 0;
+}
+
+
+
+static const cmdinfo_t info_cmd = {
+    .name       = "info",
+    .altname    = "i",
+    .cfunc      = info_f,
+    .oneline    = "prints information about the current file",
+};
+
+static void discard_help(void)
+{
+    printf(
+"\n"
+" discards a range of bytes from the given offset\n"
+"\n"
+" Example:\n"
+" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
+"\n"
+" Discards a segment of the currently open file.\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int discard_f(BlockDriverState *bs, int argc, char **argv);
+
+static const cmdinfo_t discard_cmd = {
+    .name       = "discard",
+    .altname    = "d",
+    .cfunc      = discard_f,
+    .argmin     = 2,
+    .argmax     = -1,
+    .args       = "[-Cq] off len",
+    .oneline    = "discards a number of bytes at a specified offset",
+    .help       = discard_help,
+};
+
+static int discard_f(BlockDriverState *bs, int argc, char **argv)
+{
+    struct timeval t1, t2;
+    int Cflag = 0, qflag = 0;
+    int c, ret;
+    int64_t offset;
+    int count;
+
+    while ((c = getopt(argc, argv, "Cq")) != EOF) {
+        switch (c) {
+        case 'C':
+            Cflag = 1;
+            break;
+        case 'q':
+            qflag = 1;
+            break;
+        default:
+            return command_usage(&discard_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return command_usage(&discard_cmd);
+    }
+
+    offset = cvtnum(argv[optind]);
+    if (offset < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    optind++;
+    count = cvtnum(argv[optind]);
+    if (count < 0) {
+        printf("non-numeric length argument -- %s\n", argv[optind]);
+        return 0;
+    }
+
+    gettimeofday(&t1, NULL);
+    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
+                       count >> BDRV_SECTOR_BITS);
+    gettimeofday(&t2, NULL);
+
+    if (ret < 0) {
+        printf("discard failed: %s\n", strerror(-ret));
+        goto out;
+    }
+
+    /* Finally, report back -- -C gives a parsable format */
+    if (!qflag) {
+        t2 = tsub(t2, t1);
+        print_report("discard", &t2, offset, count, count, 1, Cflag);
+    }
+
+out:
+    return 0;
+}
+
+static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int64_t offset, sector_num;
+    int nb_sectors, remaining;
+    char s1[64];
+    int num, sum_alloc;
+    int ret;
+
+    offset = cvtnum(argv[1]);
+    if (offset < 0) {
+        printf("non-numeric offset argument -- %s\n", argv[1]);
+        return 0;
+    } else if (offset & 0x1ff) {
+        printf("offset %" PRId64 " is not sector aligned\n",
+               offset);
+        return 0;
+    }
+
+    if (argc == 3) {
+        nb_sectors = cvtnum(argv[2]);
+        if (nb_sectors < 0) {
+            printf("non-numeric length argument -- %s\n", argv[2]);
+            return 0;
+        }
+    } else {
+        nb_sectors = 1;
+    }
+
+    remaining = nb_sectors;
+    sum_alloc = 0;
+    sector_num = offset >> 9;
+    while (remaining) {
+        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
+        sector_num += num;
+        remaining -= num;
+        if (ret) {
+            sum_alloc += num;
+        }
+        if (num == 0) {
+            nb_sectors -= remaining;
+            remaining = 0;
+        }
+    }
+
+    cvtstr(offset, s1, sizeof(s1));
+
+    printf("%d/%d sectors allocated at offset %s\n",
+           sum_alloc, nb_sectors, s1);
+    return 0;
+}
+
+static const cmdinfo_t alloc_cmd = {
+    .name       = "alloc",
+    .altname    = "a",
+    .argmin     = 1,
+    .argmax     = 2,
+    .cfunc      = alloc_f,
+    .args       = "off [sectors]",
+    .oneline    = "checks if a sector is present in the file",
+};
+
+
+static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
+                            int64_t nb_sectors, int64_t *pnum)
+{
+    int num, num_checked;
+    int ret, firstret;
+
+    num_checked = MIN(nb_sectors, INT_MAX);
+    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+    if (ret < 0) {
+        return ret;
+    }
+
+    firstret = ret;
+    *pnum = num;
+
+    while (nb_sectors > 0 && ret == firstret) {
+        sector_num += num;
+        nb_sectors -= num;
+
+        num_checked = MIN(nb_sectors, INT_MAX);
+        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+        if (ret == firstret) {
+            *pnum += num;
+        } else {
+            break;
+        }
+    }
+
+    return firstret;
+}
+
+static int map_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int64_t offset;
+    int64_t nb_sectors;
+    char s1[64];
+    int64_t num;
+    int ret;
+    const char *retstr;
+
+    offset = 0;
+    nb_sectors = bs->total_sectors;
+
+    do {
+        ret = map_is_allocated(bs, offset, nb_sectors, &num);
+        if (ret < 0) {
+            error_report("Failed to get allocation status: %s", strerror(-ret));
+            return 0;
+        }
+
+        retstr = ret ? "    allocated" : "not allocated";
+        cvtstr(offset << 9ULL, s1, sizeof(s1));
+        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
+               "at offset %s (%d)\n",
+               offset << 9ULL, num, nb_sectors, retstr, s1, ret);
+
+        offset += num;
+        nb_sectors -= num;
+    } while (offset < bs->total_sectors);
+
+    return 0;
+}
+
+static const cmdinfo_t map_cmd = {
+       .name           = "map",
+       .argmin         = 0,
+       .argmax         = 0,
+       .cfunc          = map_f,
+       .args           = "",
+       .oneline        = "prints the allocated areas of a file",
+};
+
+static int break_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int ret;
+
+    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
+    if (ret < 0) {
+        printf("Could not set breakpoint: %s\n", strerror(-ret));
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t break_cmd = {
+       .name           = "break",
+       .argmin         = 2,
+       .argmax         = 2,
+       .cfunc          = break_f,
+       .args           = "event tag",
+       .oneline        = "sets a breakpoint on event and tags the stopped "
+                         "request as tag",
+};
+
+static int resume_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int ret;
+
+    ret = bdrv_debug_resume(bs, argv[1]);
+    if (ret < 0) {
+        printf("Could not resume request: %s\n", strerror(-ret));
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t resume_cmd = {
+       .name           = "resume",
+       .argmin         = 1,
+       .argmax         = 1,
+       .cfunc          = resume_f,
+       .args           = "tag",
+       .oneline        = "resumes the request tagged as tag",
+};
+
+static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
+{
+    while (!bdrv_debug_is_suspended(bs, argv[1])) {
+        qemu_aio_wait();
+    }
+
+    return 0;
+}
+
+static const cmdinfo_t wait_break_cmd = {
+       .name           = "wait_break",
+       .argmin         = 1,
+       .argmax         = 1,
+       .cfunc          = wait_break_f,
+       .args           = "tag",
+       .oneline        = "waits for the suspension of a request",
+};
+
+static int abort_f(BlockDriverState *bs, int argc, char **argv)
+{
+    abort();
+}
+
+static const cmdinfo_t abort_cmd = {
+       .name           = "abort",
+       .cfunc          = abort_f,
+       .flags          = CMD_NOFILE_OK,
+       .oneline        = "simulate a program crash using abort(3)",
+};
+
+static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+{
+    if (ct->flags & CMD_FLAG_GLOBAL) {
+        return 1;
+    }
+    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
+        fprintf(stderr, "no file open, try 'help open'\n");
+        return 0;
+    }
+    return 1;
+}
+
+static void __attribute((constructor)) init_qemuio_commands(void)
+{
+    /* initialize commands */
+    help_init();
+    add_command(&read_cmd);
+    add_command(&readv_cmd);
+    add_command(&write_cmd);
+    add_command(&writev_cmd);
+    add_command(&multiwrite_cmd);
+    add_command(&aio_read_cmd);
+    add_command(&aio_write_cmd);
+    add_command(&aio_flush_cmd);
+    add_command(&flush_cmd);
+    add_command(&truncate_cmd);
+    add_command(&length_cmd);
+    add_command(&info_cmd);
+    add_command(&discard_cmd);
+    add_command(&alloc_cmd);
+    add_command(&map_cmd);
+    add_command(&break_cmd);
+    add_command(&resume_cmd);
+    add_command(&wait_break_cmd);
+    add_command(&abort_cmd);
+
+    add_check_command(init_check_command);
+}
diff --git a/qemu-io.c b/qemu-io.c
index 39d7063..14eef2c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -27,1786 +27,7 @@
 char *progname;
 
 BlockDriverState *qemuio_bs;
-static int misalign;
-
-static int64_t cvtnum(const char *s)
-{
-    char *end;
-    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
-}
-
-/*
- * Parse the pattern argument to various sub-commands.
- *
- * Because the pattern is used as an argument to memset it must evaluate
- * to an unsigned integer that fits into a single byte.
- */
-static int parse_pattern(const char *arg)
-{
-    char *endptr = NULL;
-    long pattern;
-
-    pattern = strtol(arg, &endptr, 0);
-    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
-        printf("%s is not a valid pattern byte\n", arg);
-        return -1;
-    }
-
-    return pattern;
-}
-
-/*
- * Memory allocation helpers.
- *
- * Make sure memory is aligned by default, or purposefully misaligned if
- * that is specified on the command line.
- */
-
-#define MISALIGN_OFFSET     16
-static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
-{
-    void *buf;
-
-    if (misalign) {
-        len += MISALIGN_OFFSET;
-    }
-    buf = qemu_blockalign(bs, len);
-    memset(buf, pattern, len);
-    if (misalign) {
-        buf += MISALIGN_OFFSET;
-    }
-    return buf;
-}
-
-static void qemu_io_free(void *p)
-{
-    if (misalign) {
-        p -= MISALIGN_OFFSET;
-    }
-    qemu_vfree(p);
-}
-
-static void dump_buffer(const void *buffer, int64_t offset, int len)
-{
-    int i, j;
-    const uint8_t *p;
-
-    for (i = 0, p = buffer; i < len; i += 16) {
-        const uint8_t *s = p;
-
-        printf("%08" PRIx64 ":  ", offset + i);
-        for (j = 0; j < 16 && i + j < len; j++, p++) {
-            printf("%02x ", *p);
-        }
-        printf(" ");
-        for (j = 0; j < 16 && i + j < len; j++, s++) {
-            if (isalnum(*s)) {
-                printf("%c", *s);
-            } else {
-                printf(".");
-            }
-        }
-        printf("\n");
-    }
-}
-
-static void print_report(const char *op, struct timeval *t, int64_t offset,
-                         int count, int total, int cnt, int Cflag)
-{
-    char s1[64], s2[64], ts[64];
-
-    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
-    if (!Cflag) {
-        cvtstr((double)total, s1, sizeof(s1));
-        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
-        printf("%s %d/%d bytes at offset %" PRId64 "\n",
-               op, total, count, offset);
-        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
-               s1, cnt, ts, s2, tdiv((double)cnt, *t));
-    } else {/* bytes,ops,time,bytes/sec,ops/sec */
-        printf("%d,%d,%s,%.3f,%.3f\n",
-            total, cnt, ts,
-            tdiv((double)total, *t),
-            tdiv((double)cnt, *t));
-    }
-}
-
-/*
- * Parse multiple length statements for vectored I/O, and construct an I/O
- * vector matching it.
- */
-static void *
-create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
-             int pattern)
-{
-    size_t *sizes = g_new0(size_t, nr_iov);
-    size_t count = 0;
-    void *buf = NULL;
-    void *p;
-    int i;
-
-    for (i = 0; i < nr_iov; i++) {
-        char *arg = argv[i];
-        int64_t len;
-
-        len = cvtnum(arg);
-        if (len < 0) {
-            printf("non-numeric length argument -- %s\n", arg);
-            goto fail;
-        }
-
-        /* should be SIZE_T_MAX, but that doesn't exist */
-        if (len > INT_MAX) {
-            printf("too large length argument -- %s\n", arg);
-            goto fail;
-        }
-
-        if (len & 0x1ff) {
-            printf("length argument %" PRId64
-                   " is not sector aligned\n", len);
-            goto fail;
-        }
-
-        sizes[i] = len;
-        count += len;
-    }
-
-    qemu_iovec_init(qiov, nr_iov);
-
-    buf = p = qemu_io_alloc(bs, count, pattern);
-
-    for (i = 0; i < nr_iov; i++) {
-        qemu_iovec_add(qiov, p, sizes[i]);
-        p += sizes[i];
-    }
-
-fail:
-    g_free(sizes);
-    return buf;
-}
-
-static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
-                   int *total)
-{
-    int ret;
-
-    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
-    if (ret < 0) {
-        return ret;
-    }
-    *total = count;
-    return 1;
-}
-
-static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
-                    int *total)
-{
-    int ret;
-
-    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
-    if (ret < 0) {
-        return ret;
-    }
-    *total = count;
-    return 1;
-}
-
-static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
-                    int *total)
-{
-    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
-    if (*total < 0) {
-        return *total;
-    }
-    return 1;
-}
-
-static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
-                     int *total)
-{
-    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
-    if (*total < 0) {
-        return *total;
-    }
-    return 1;
-}
-
-typedef struct {
-    BlockDriverState *bs;
-    int64_t offset;
-    int count;
-    int *total;
-    int ret;
-    bool done;
-} CoWriteZeroes;
-
-static void coroutine_fn co_write_zeroes_entry(void *opaque)
-{
-    CoWriteZeroes *data = opaque;
-
-    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
-                                     data->count / BDRV_SECTOR_SIZE);
-    data->done = true;
-    if (data->ret < 0) {
-        *data->total = data->ret;
-        return;
-    }
-
-    *data->total = data->count;
-}
-
-static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
-                              int *total)
-{
-    Coroutine *co;
-    CoWriteZeroes data = {
-        .bs     = bs,
-        .offset = offset,
-        .count  = count,
-        .total  = total,
-        .done   = false,
-    };
-
-    co = qemu_coroutine_create(co_write_zeroes_entry);
-    qemu_coroutine_enter(co, &data);
-    while (!data.done) {
-        qemu_aio_wait();
-    }
-    if (data.ret < 0) {
-        return data.ret;
-    } else {
-        return 1;
-    }
-}
-
-static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
-                               int count, int *total)
-{
-    int ret;
-
-    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
-    if (ret < 0) {
-        return ret;
-    }
-    *total = count;
-    return 1;
-}
-
-static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
-                           int count, int *total)
-{
-    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
-    if (*total < 0) {
-        return *total;
-    }
-    return 1;
-}
-
-static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
-                           int count, int *total)
-{
-    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
-    if (*total < 0) {
-        return *total;
-    }
-    return 1;
-}
-
-#define NOT_DONE 0x7fffffff
-static void aio_rw_done(void *opaque, int ret)
-{
-    *(int *)opaque = ret;
-}
-
-static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
-                        int64_t offset, int *total)
-{
-    int async_ret = NOT_DONE;
-
-    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
-                   aio_rw_done, &async_ret);
-    while (async_ret == NOT_DONE) {
-        main_loop_wait(false);
-    }
-
-    *total = qiov->size;
-    return async_ret < 0 ? async_ret : 1;
-}
-
-static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
-                         int64_t offset, int *total)
-{
-    int async_ret = NOT_DONE;
-
-    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
-                    aio_rw_done, &async_ret);
-    while (async_ret == NOT_DONE) {
-        main_loop_wait(false);
-    }
-
-    *total = qiov->size;
-    return async_ret < 0 ? async_ret : 1;
-}
-
-struct multiwrite_async_ret {
-    int num_done;
-    int error;
-};
-
-static void multiwrite_cb(void *opaque, int ret)
-{
-    struct multiwrite_async_ret *async_ret = opaque;
-
-    async_ret->num_done++;
-    if (ret < 0) {
-        async_ret->error = ret;
-    }
-}
-
-static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
-                             int num_reqs, int *total)
-{
-    int i, ret;
-    struct multiwrite_async_ret async_ret = {
-        .num_done = 0,
-        .error = 0,
-    };
-
-    *total = 0;
-    for (i = 0; i < num_reqs; i++) {
-        reqs[i].cb = multiwrite_cb;
-        reqs[i].opaque = &async_ret;
-        *total += reqs[i].qiov->size;
-    }
-
-    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
-    if (ret < 0) {
-        return ret;
-    }
-
-    while (async_ret.num_done < num_reqs) {
-        main_loop_wait(false);
-    }
-
-    return async_ret.error < 0 ? async_ret.error : 1;
-}
-
-static void read_help(void)
-{
-    printf(
-"\n"
-" reads a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
-"\n"
-" Reads a segment of the currently open file, optionally dumping it to the\n"
-" standard output stream (with -v option) for subsequent inspection.\n"
-" -b, -- read from the VM state rather than the virtual disk\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -l, -- length for pattern verification (only with -P)\n"
-" -p, -- use bdrv_pread to read the file\n"
-" -P, -- use a pattern to verify read data\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-" -s, -- start offset for pattern verification (only with -P)\n"
-" -v, -- dump buffer to standard output\n"
-"\n");
-}
-
-static int read_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t read_cmd = {
-    .name       = "read",
-    .altname    = "r",
-    .cfunc      = read_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
-    .oneline    = "reads a number of bytes at a specified offset",
-    .help       = read_help,
-};
-
-static int read_f(BlockDriverState *bs, int argc, char **argv)
-{
-    struct timeval t1, t2;
-    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
-    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
-    int c, cnt;
-    char *buf;
-    int64_t offset;
-    int count;
-    /* Some compilers get confused and warn if this is not initialized.  */
-    int total = 0;
-    int pattern = 0, pattern_offset = 0, pattern_count = 0;
-
-    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
-        switch (c) {
-        case 'b':
-            bflag = 1;
-            break;
-        case 'C':
-            Cflag = 1;
-            break;
-        case 'l':
-            lflag = 1;
-            pattern_count = cvtnum(optarg);
-            if (pattern_count < 0) {
-                printf("non-numeric length argument -- %s\n", optarg);
-                return 0;
-            }
-            break;
-        case 'p':
-            pflag = 1;
-            break;
-        case 'P':
-            Pflag = 1;
-            pattern = parse_pattern(optarg);
-            if (pattern < 0) {
-                return 0;
-            }
-            break;
-        case 'q':
-            qflag = 1;
-            break;
-        case 's':
-            sflag = 1;
-            pattern_offset = cvtnum(optarg);
-            if (pattern_offset < 0) {
-                printf("non-numeric length argument -- %s\n", optarg);
-                return 0;
-            }
-            break;
-        case 'v':
-            vflag = 1;
-            break;
-        default:
-            return command_usage(&read_cmd);
-        }
-    }
-
-    if (optind != argc - 2) {
-        return command_usage(&read_cmd);
-    }
-
-    if (bflag && pflag) {
-        printf("-b and -p cannot be specified at the same time\n");
-        return 0;
-    }
-
-    offset = cvtnum(argv[optind]);
-    if (offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-
-    optind++;
-    count = cvtnum(argv[optind]);
-    if (count < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-
-    if (!Pflag && (lflag || sflag)) {
-        return command_usage(&read_cmd);
-    }
-
-    if (!lflag) {
-        pattern_count = count - pattern_offset;
-    }
-
-    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
-        printf("pattern verification range exceeds end of read data\n");
-        return 0;
-    }
-
-    if (!pflag) {
-        if (offset & 0x1ff) {
-            printf("offset %" PRId64 " is not sector aligned\n",
-                   offset);
-            return 0;
-        }
-        if (count & 0x1ff) {
-            printf("count %d is not sector aligned\n",
-                   count);
-            return 0;
-        }
-    }
-
-    buf = qemu_io_alloc(bs, count, 0xab);
-
-    gettimeofday(&t1, NULL);
-    if (pflag) {
-        cnt = do_pread(bs, buf, offset, count, &total);
-    } else if (bflag) {
-        cnt = do_load_vmstate(bs, buf, offset, count, &total);
-    } else {
-        cnt = do_read(bs, buf, offset, count, &total);
-    }
-    gettimeofday(&t2, NULL);
-
-    if (cnt < 0) {
-        printf("read failed: %s\n", strerror(-cnt));
-        goto out;
-    }
-
-    if (Pflag) {
-        void *cmp_buf = g_malloc(pattern_count);
-        memset(cmp_buf, pattern, pattern_count);
-        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
-            printf("Pattern verification failed at offset %"
-                   PRId64 ", %d bytes\n",
-                   offset + pattern_offset, pattern_count);
-        }
-        g_free(cmp_buf);
-    }
-
-    if (qflag) {
-        goto out;
-    }
-
-    if (vflag) {
-        dump_buffer(buf, offset, count);
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, t1);
-    print_report("read", &t2, offset, count, total, cnt, Cflag);
-
-out:
-    qemu_io_free(buf);
-
-    return 0;
-}
-
-static void readv_help(void)
-{
-    printf(
-"\n"
-" reads a range of bytes from the given offset into multiple buffers\n"
-"\n"
-" Example:\n"
-" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
-"\n"
-" Reads a segment of the currently open file, optionally dumping it to the\n"
-" standard output stream (with -v option) for subsequent inspection.\n"
-" Uses multiple iovec buffers if more than one byte range is specified.\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -P, -- use a pattern to verify read data\n"
-" -v, -- dump buffer to standard output\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int readv_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t readv_cmd = {
-    .name       = "readv",
-    .cfunc      = readv_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-Cqv] [-P pattern ] off len [len..]",
-    .oneline    = "reads a number of bytes at a specified offset",
-    .help       = readv_help,
-};
-
-static int readv_f(BlockDriverState *bs, int argc, char **argv)
-{
-    struct timeval t1, t2;
-    int Cflag = 0, qflag = 0, vflag = 0;
-    int c, cnt;
-    char *buf;
-    int64_t offset;
-    /* Some compilers get confused and warn if this is not initialized.  */
-    int total = 0;
-    int nr_iov;
-    QEMUIOVector qiov;
-    int pattern = 0;
-    int Pflag = 0;
-
-    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
-        switch (c) {
-        case 'C':
-            Cflag = 1;
-            break;
-        case 'P':
-            Pflag = 1;
-            pattern = parse_pattern(optarg);
-            if (pattern < 0) {
-                return 0;
-            }
-            break;
-        case 'q':
-            qflag = 1;
-            break;
-        case 'v':
-            vflag = 1;
-            break;
-        default:
-            return command_usage(&readv_cmd);
-        }
-    }
-
-    if (optind > argc - 2) {
-        return command_usage(&readv_cmd);
-    }
-
-
-    offset = cvtnum(argv[optind]);
-    if (offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-    optind++;
-
-    if (offset & 0x1ff) {
-        printf("offset %" PRId64 " is not sector aligned\n",
-               offset);
-        return 0;
-    }
-
-    nr_iov = argc - optind;
-    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
-    if (buf == NULL) {
-        return 0;
-    }
-
-    gettimeofday(&t1, NULL);
-    cnt = do_aio_readv(bs, &qiov, offset, &total);
-    gettimeofday(&t2, NULL);
-
-    if (cnt < 0) {
-        printf("readv failed: %s\n", strerror(-cnt));
-        goto out;
-    }
-
-    if (Pflag) {
-        void *cmp_buf = g_malloc(qiov.size);
-        memset(cmp_buf, pattern, qiov.size);
-        if (memcmp(buf, cmp_buf, qiov.size)) {
-            printf("Pattern verification failed at offset %"
-                   PRId64 ", %zd bytes\n", offset, qiov.size);
-        }
-        g_free(cmp_buf);
-    }
-
-    if (qflag) {
-        goto out;
-    }
-
-    if (vflag) {
-        dump_buffer(buf, offset, qiov.size);
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, t1);
-    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
-
-out:
-    qemu_iovec_destroy(&qiov);
-    qemu_io_free(buf);
-    return 0;
-}
-
-static void write_help(void)
-{
-    printf(
-"\n"
-" writes a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd).\n"
-" -b, -- write to the VM state rather than the virtual disk\n"
-" -c, -- write compressed data with bdrv_write_compressed\n"
-" -p, -- use bdrv_pwrite to write the file\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-" -z, -- write zeroes using bdrv_co_write_zeroes\n"
-"\n");
-}
-
-static int write_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t write_cmd = {
-    .name       = "write",
-    .altname    = "w",
-    .cfunc      = write_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-bcCpqz] [-P pattern ] off len",
-    .oneline    = "writes a number of bytes at a specified offset",
-    .help       = write_help,
-};
-
-static int write_f(BlockDriverState *bs, int argc, char **argv)
-{
-    struct timeval t1, t2;
-    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
-    int cflag = 0;
-    int c, cnt;
-    char *buf = NULL;
-    int64_t offset;
-    int count;
-    /* Some compilers get confused and warn if this is not initialized.  */
-    int total = 0;
-    int pattern = 0xcd;
-
-    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
-        switch (c) {
-        case 'b':
-            bflag = 1;
-            break;
-        case 'c':
-            cflag = 1;
-            break;
-        case 'C':
-            Cflag = 1;
-            break;
-        case 'p':
-            pflag = 1;
-            break;
-        case 'P':
-            Pflag = 1;
-            pattern = parse_pattern(optarg);
-            if (pattern < 0) {
-                return 0;
-            }
-            break;
-        case 'q':
-            qflag = 1;
-            break;
-        case 'z':
-            zflag = 1;
-            break;
-        default:
-            return command_usage(&write_cmd);
-        }
-    }
-
-    if (optind != argc - 2) {
-        return command_usage(&write_cmd);
-    }
-
-    if (bflag + pflag + zflag > 1) {
-        printf("-b, -p, or -z cannot be specified at the same time\n");
-        return 0;
-    }
-
-    if (zflag && Pflag) {
-        printf("-z and -P cannot be specified at the same time\n");
-        return 0;
-    }
-
-    offset = cvtnum(argv[optind]);
-    if (offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-
-    optind++;
-    count = cvtnum(argv[optind]);
-    if (count < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-
-    if (!pflag) {
-        if (offset & 0x1ff) {
-            printf("offset %" PRId64 " is not sector aligned\n",
-                   offset);
-            return 0;
-        }
-
-        if (count & 0x1ff) {
-            printf("count %d is not sector aligned\n",
-                   count);
-            return 0;
-        }
-    }
-
-    if (!zflag) {
-        buf = qemu_io_alloc(bs, count, pattern);
-    }
-
-    gettimeofday(&t1, NULL);
-    if (pflag) {
-        cnt = do_pwrite(bs, buf, offset, count, &total);
-    } else if (bflag) {
-        cnt = do_save_vmstate(bs, buf, offset, count, &total);
-    } else if (zflag) {
-        cnt = do_co_write_zeroes(bs, offset, count, &total);
-    } else if (cflag) {
-        cnt = do_write_compressed(bs, buf, offset, count, &total);
-    } else {
-        cnt = do_write(bs, buf, offset, count, &total);
-    }
-    gettimeofday(&t2, NULL);
-
-    if (cnt < 0) {
-        printf("write failed: %s\n", strerror(-cnt));
-        goto out;
-    }
-
-    if (qflag) {
-        goto out;
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, t1);
-    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
-
-out:
-    if (!zflag) {
-        qemu_io_free(buf);
-    }
-
-    return 0;
-}
-
-static void
-writev_help(void)
-{
-    printf(
-"\n"
-" writes a range of bytes from the given offset source from multiple buffers\n"
-"\n"
-" Example:\n"
-" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd).\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int writev_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t writev_cmd = {
-    .name       = "writev",
-    .cfunc      = writev_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-Cq] [-P pattern ] off len [len..]",
-    .oneline    = "writes a number of bytes at a specified offset",
-    .help       = writev_help,
-};
-
-static int writev_f(BlockDriverState *bs, int argc, char **argv)
-{
-    struct timeval t1, t2;
-    int Cflag = 0, qflag = 0;
-    int c, cnt;
-    char *buf;
-    int64_t offset;
-    /* Some compilers get confused and warn if this is not initialized.  */
-    int total = 0;
-    int nr_iov;
-    int pattern = 0xcd;
-    QEMUIOVector qiov;
-
-    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
-        switch (c) {
-        case 'C':
-            Cflag = 1;
-            break;
-        case 'q':
-            qflag = 1;
-            break;
-        case 'P':
-            pattern = parse_pattern(optarg);
-            if (pattern < 0) {
-                return 0;
-            }
-            break;
-        default:
-            return command_usage(&writev_cmd);
-        }
-    }
-
-    if (optind > argc - 2) {
-        return command_usage(&writev_cmd);
-    }
-
-    offset = cvtnum(argv[optind]);
-    if (offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-    optind++;
-
-    if (offset & 0x1ff) {
-        printf("offset %" PRId64 " is not sector aligned\n",
-               offset);
-        return 0;
-    }
-
-    nr_iov = argc - optind;
-    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
-    if (buf == NULL) {
-        return 0;
-    }
-
-    gettimeofday(&t1, NULL);
-    cnt = do_aio_writev(bs, &qiov, offset, &total);
-    gettimeofday(&t2, NULL);
-
-    if (cnt < 0) {
-        printf("writev failed: %s\n", strerror(-cnt));
-        goto out;
-    }
-
-    if (qflag) {
-        goto out;
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, t1);
-    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
-out:
-    qemu_iovec_destroy(&qiov);
-    qemu_io_free(buf);
-    return 0;
-}
-
-static void multiwrite_help(void)
-{
-    printf(
-"\n"
-" writes a range of bytes from the given offset source from multiple buffers,\n"
-" in a batch of requests that may be merged by qemu\n"
-"\n"
-" Example:\n"
-" 'multiwrite 512 1k 1k ; 4k 1k'\n"
-"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
-" by one for each request contained in the multiwrite command.\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t multiwrite_cmd = {
-    .name       = "multiwrite",
-    .cfunc      = multiwrite_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
-    .oneline    = "issues multiple write requests at once",
-    .help       = multiwrite_help,
-};
-
-static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
-{
-    struct timeval t1, t2;
-    int Cflag = 0, qflag = 0;
-    int c, cnt;
-    char **buf;
-    int64_t offset, first_offset = 0;
-    /* Some compilers get confused and warn if this is not initialized.  */
-    int total = 0;
-    int nr_iov;
-    int nr_reqs;
-    int pattern = 0xcd;
-    QEMUIOVector *qiovs;
-    int i;
-    BlockRequest *reqs;
-
-    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
-        switch (c) {
-        case 'C':
-            Cflag = 1;
-            break;
-        case 'q':
-            qflag = 1;
-            break;
-        case 'P':
-            pattern = parse_pattern(optarg);
-            if (pattern < 0) {
-                return 0;
-            }
-            break;
-        default:
-            return command_usage(&writev_cmd);
-        }
-    }
-
-    if (optind > argc - 2) {
-        return command_usage(&writev_cmd);
-    }
-
-    nr_reqs = 1;
-    for (i = optind; i < argc; i++) {
-        if (!strcmp(argv[i], ";")) {
-            nr_reqs++;
-        }
-    }
-
-    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
-    buf = g_malloc0(nr_reqs * sizeof(*buf));
-    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
-
-    for (i = 0; i < nr_reqs && optind < argc; i++) {
-        int j;
-
-        /* Read the offset of the request */
-        offset = cvtnum(argv[optind]);
-        if (offset < 0) {
-            printf("non-numeric offset argument -- %s\n", argv[optind]);
-            goto out;
-        }
-        optind++;
-
-        if (offset & 0x1ff) {
-            printf("offset %lld is not sector aligned\n",
-                   (long long)offset);
-            goto out;
-        }
-
-        if (i == 0) {
-            first_offset = offset;
-        }
-
-        /* Read lengths for qiov entries */
-        for (j = optind; j < argc; j++) {
-            if (!strcmp(argv[j], ";")) {
-                break;
-            }
-        }
-
-        nr_iov = j - optind;
-
-        /* Build request */
-        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
-        if (buf[i] == NULL) {
-            goto out;
-        }
-
-        reqs[i].qiov = &qiovs[i];
-        reqs[i].sector = offset >> 9;
-        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
-
-        optind = j + 1;
-
-        pattern++;
-    }
-
-    /* If there were empty requests at the end, ignore them */
-    nr_reqs = i;
-
-    gettimeofday(&t1, NULL);
-    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
-    gettimeofday(&t2, NULL);
-
-    if (cnt < 0) {
-        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
-        goto out;
-    }
-
-    if (qflag) {
-        goto out;
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, t1);
-    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
-out:
-    for (i = 0; i < nr_reqs; i++) {
-        qemu_io_free(buf[i]);
-        if (reqs[i].qiov != NULL) {
-            qemu_iovec_destroy(&qiovs[i]);
-        }
-    }
-    g_free(buf);
-    g_free(reqs);
-    g_free(qiovs);
-    return 0;
-}
-
-struct aio_ctx {
-    QEMUIOVector qiov;
-    int64_t offset;
-    char *buf;
-    int qflag;
-    int vflag;
-    int Cflag;
-    int Pflag;
-    int pattern;
-    struct timeval t1;
-};
-
-static void aio_write_done(void *opaque, int ret)
-{
-    struct aio_ctx *ctx = opaque;
-    struct timeval t2;
-
-    gettimeofday(&t2, NULL);
-
-
-    if (ret < 0) {
-        printf("aio_write failed: %s\n", strerror(-ret));
-        goto out;
-    }
-
-    if (ctx->qflag) {
-        goto out;
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, ctx->t1);
-    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
-                 ctx->qiov.size, 1, ctx->Cflag);
-out:
-    qemu_io_free(ctx->buf);
-    qemu_iovec_destroy(&ctx->qiov);
-    g_free(ctx);
-}
-
-static void aio_read_done(void *opaque, int ret)
-{
-    struct aio_ctx *ctx = opaque;
-    struct timeval t2;
-
-    gettimeofday(&t2, NULL);
-
-    if (ret < 0) {
-        printf("readv failed: %s\n", strerror(-ret));
-        goto out;
-    }
-
-    if (ctx->Pflag) {
-        void *cmp_buf = g_malloc(ctx->qiov.size);
-
-        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
-        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
-            printf("Pattern verification failed at offset %"
-                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
-        }
-        g_free(cmp_buf);
-    }
-
-    if (ctx->qflag) {
-        goto out;
-    }
-
-    if (ctx->vflag) {
-        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    t2 = tsub(t2, ctx->t1);
-    print_report("read", &t2, ctx->offset, ctx->qiov.size,
-                 ctx->qiov.size, 1, ctx->Cflag);
-out:
-    qemu_io_free(ctx->buf);
-    qemu_iovec_destroy(&ctx->qiov);
-    g_free(ctx);
-}
-
-static void aio_read_help(void)
-{
-    printf(
-"\n"
-" asynchronously reads a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
-"\n"
-" Reads a segment of the currently open file, optionally dumping it to the\n"
-" standard output stream (with -v option) for subsequent inspection.\n"
-" The read is performed asynchronously and the aio_flush command must be\n"
-" used to ensure all outstanding aio requests have been completed.\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -P, -- use a pattern to verify read data\n"
-" -v, -- dump buffer to standard output\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t aio_read_cmd = {
-    .name       = "aio_read",
-    .cfunc      = aio_read_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-Cqv] [-P pattern ] off len [len..]",
-    .oneline    = "asynchronously reads a number of bytes",
-    .help       = aio_read_help,
-};
-
-static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int nr_iov, c;
-    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
-
-    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
-        switch (c) {
-        case 'C':
-            ctx->Cflag = 1;
-            break;
-        case 'P':
-            ctx->Pflag = 1;
-            ctx->pattern = parse_pattern(optarg);
-            if (ctx->pattern < 0) {
-                g_free(ctx);
-                return 0;
-            }
-            break;
-        case 'q':
-            ctx->qflag = 1;
-            break;
-        case 'v':
-            ctx->vflag = 1;
-            break;
-        default:
-            g_free(ctx);
-            return command_usage(&aio_read_cmd);
-        }
-    }
-
-    if (optind > argc - 2) {
-        g_free(ctx);
-        return command_usage(&aio_read_cmd);
-    }
-
-    ctx->offset = cvtnum(argv[optind]);
-    if (ctx->offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        g_free(ctx);
-        return 0;
-    }
-    optind++;
-
-    if (ctx->offset & 0x1ff) {
-        printf("offset %" PRId64 " is not sector aligned\n",
-               ctx->offset);
-        g_free(ctx);
-        return 0;
-    }
-
-    nr_iov = argc - optind;
-    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
-    if (ctx->buf == NULL) {
-        g_free(ctx);
-        return 0;
-    }
-
-    gettimeofday(&ctx->t1, NULL);
-    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
-                   ctx->qiov.size >> 9, aio_read_done, ctx);
-    return 0;
-}
-
-static void aio_write_help(void)
-{
-    printf(
-"\n"
-" asynchronously writes a range of bytes from the given offset source\n"
-" from multiple buffers\n"
-"\n"
-" Example:\n"
-" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
-"\n"
-" Writes into a segment of the currently open file, using a buffer\n"
-" filled with a set pattern (0xcdcdcdcd).\n"
-" The write is performed asynchronously and the aio_flush command must be\n"
-" used to ensure all outstanding aio requests have been completed.\n"
-" -P, -- use different pattern to fill file\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t aio_write_cmd = {
-    .name       = "aio_write",
-    .cfunc      = aio_write_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-Cq] [-P pattern ] off len [len..]",
-    .oneline    = "asynchronously writes a number of bytes",
-    .help       = aio_write_help,
-};
-
-static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int nr_iov, c;
-    int pattern = 0xcd;
-    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
-
-    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
-        switch (c) {
-        case 'C':
-            ctx->Cflag = 1;
-            break;
-        case 'q':
-            ctx->qflag = 1;
-            break;
-        case 'P':
-            pattern = parse_pattern(optarg);
-            if (pattern < 0) {
-                g_free(ctx);
-                return 0;
-            }
-            break;
-        default:
-            g_free(ctx);
-            return command_usage(&aio_write_cmd);
-        }
-    }
-
-    if (optind > argc - 2) {
-        g_free(ctx);
-        return command_usage(&aio_write_cmd);
-    }
-
-    ctx->offset = cvtnum(argv[optind]);
-    if (ctx->offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        g_free(ctx);
-        return 0;
-    }
-    optind++;
-
-    if (ctx->offset & 0x1ff) {
-        printf("offset %" PRId64 " is not sector aligned\n",
-               ctx->offset);
-        g_free(ctx);
-        return 0;
-    }
-
-    nr_iov = argc - optind;
-    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
-    if (ctx->buf == NULL) {
-        g_free(ctx);
-        return 0;
-    }
-
-    gettimeofday(&ctx->t1, NULL);
-    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
-                    ctx->qiov.size >> 9, aio_write_done, ctx);
-    return 0;
-}
-
-static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
-{
-    bdrv_drain_all();
-    return 0;
-}
-
-static const cmdinfo_t aio_flush_cmd = {
-    .name       = "aio_flush",
-    .cfunc      = aio_flush_f,
-    .oneline    = "completes all outstanding aio requests"
-};
-
-static int flush_f(BlockDriverState *bs, int argc, char **argv)
-{
-    bdrv_flush(bs);
-    return 0;
-}
-
-static const cmdinfo_t flush_cmd = {
-    .name       = "flush",
-    .altname    = "f",
-    .cfunc      = flush_f,
-    .oneline    = "flush all in-core file state to disk",
-};
-
-static int truncate_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int64_t offset;
-    int ret;
-
-    offset = cvtnum(argv[1]);
-    if (offset < 0) {
-        printf("non-numeric truncate argument -- %s\n", argv[1]);
-        return 0;
-    }
-
-    ret = bdrv_truncate(bs, offset);
-    if (ret < 0) {
-        printf("truncate: %s\n", strerror(-ret));
-        return 0;
-    }
-
-    return 0;
-}
-
-static const cmdinfo_t truncate_cmd = {
-    .name       = "truncate",
-    .altname    = "t",
-    .cfunc      = truncate_f,
-    .argmin     = 1,
-    .argmax     = 1,
-    .args       = "off",
-    .oneline    = "truncates the current file at the given offset",
-};
-
-static int length_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int64_t size;
-    char s1[64];
-
-    size = bdrv_getlength(bs);
-    if (size < 0) {
-        printf("getlength: %s\n", strerror(-size));
-        return 0;
-    }
-
-    cvtstr(size, s1, sizeof(s1));
-    printf("%s\n", s1);
-    return 0;
-}
-
-
-static const cmdinfo_t length_cmd = {
-    .name   = "length",
-    .altname    = "l",
-    .cfunc      = length_f,
-    .oneline    = "gets the length of the current file",
-};
-
-
-static int info_f(BlockDriverState *bs, int argc, char **argv)
-{
-    BlockDriverInfo bdi;
-    char s1[64], s2[64];
-    int ret;
-
-    if (bs->drv && bs->drv->format_name) {
-        printf("format name: %s\n", bs->drv->format_name);
-    }
-    if (bs->drv && bs->drv->protocol_name) {
-        printf("format name: %s\n", bs->drv->protocol_name);
-    }
-
-    ret = bdrv_get_info(bs, &bdi);
-    if (ret) {
-        return 0;
-    }
-
-    cvtstr(bdi.cluster_size, s1, sizeof(s1));
-    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
-
-    printf("cluster size: %s\n", s1);
-    printf("vm state offset: %s\n", s2);
-
-    return 0;
-}
-
-
-
-static const cmdinfo_t info_cmd = {
-    .name       = "info",
-    .altname    = "i",
-    .cfunc      = info_f,
-    .oneline    = "prints information about the current file",
-};
-
-static void discard_help(void)
-{
-    printf(
-"\n"
-" discards a range of bytes from the given offset\n"
-"\n"
-" Example:\n"
-" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
-"\n"
-" Discards a segment of the currently open file.\n"
-" -C, -- report statistics in a machine parsable format\n"
-" -q, -- quiet mode, do not show I/O statistics\n"
-"\n");
-}
-
-static int discard_f(BlockDriverState *bs, int argc, char **argv);
-
-static const cmdinfo_t discard_cmd = {
-    .name       = "discard",
-    .altname    = "d",
-    .cfunc      = discard_f,
-    .argmin     = 2,
-    .argmax     = -1,
-    .args       = "[-Cq] off len",
-    .oneline    = "discards a number of bytes at a specified offset",
-    .help       = discard_help,
-};
-
-static int discard_f(BlockDriverState *bs, int argc, char **argv)
-{
-    struct timeval t1, t2;
-    int Cflag = 0, qflag = 0;
-    int c, ret;
-    int64_t offset;
-    int count;
-
-    while ((c = getopt(argc, argv, "Cq")) != EOF) {
-        switch (c) {
-        case 'C':
-            Cflag = 1;
-            break;
-        case 'q':
-            qflag = 1;
-            break;
-        default:
-            return command_usage(&discard_cmd);
-        }
-    }
-
-    if (optind != argc - 2) {
-        return command_usage(&discard_cmd);
-    }
-
-    offset = cvtnum(argv[optind]);
-    if (offset < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-
-    optind++;
-    count = cvtnum(argv[optind]);
-    if (count < 0) {
-        printf("non-numeric length argument -- %s\n", argv[optind]);
-        return 0;
-    }
-
-    gettimeofday(&t1, NULL);
-    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
-                       count >> BDRV_SECTOR_BITS);
-    gettimeofday(&t2, NULL);
-
-    if (ret < 0) {
-        printf("discard failed: %s\n", strerror(-ret));
-        goto out;
-    }
-
-    /* Finally, report back -- -C gives a parsable format */
-    if (!qflag) {
-        t2 = tsub(t2, t1);
-        print_report("discard", &t2, offset, count, count, 1, Cflag);
-    }
-
-out:
-    return 0;
-}
-
-static int alloc_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int64_t offset, sector_num;
-    int nb_sectors, remaining;
-    char s1[64];
-    int num, sum_alloc;
-    int ret;
-
-    offset = cvtnum(argv[1]);
-    if (offset < 0) {
-        printf("non-numeric offset argument -- %s\n", argv[1]);
-        return 0;
-    } else if (offset & 0x1ff) {
-        printf("offset %" PRId64 " is not sector aligned\n",
-               offset);
-        return 0;
-    }
-
-    if (argc == 3) {
-        nb_sectors = cvtnum(argv[2]);
-        if (nb_sectors < 0) {
-            printf("non-numeric length argument -- %s\n", argv[2]);
-            return 0;
-        }
-    } else {
-        nb_sectors = 1;
-    }
-
-    remaining = nb_sectors;
-    sum_alloc = 0;
-    sector_num = offset >> 9;
-    while (remaining) {
-        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
-        sector_num += num;
-        remaining -= num;
-        if (ret) {
-            sum_alloc += num;
-        }
-        if (num == 0) {
-            nb_sectors -= remaining;
-            remaining = 0;
-        }
-    }
-
-    cvtstr(offset, s1, sizeof(s1));
-
-    printf("%d/%d sectors allocated at offset %s\n",
-           sum_alloc, nb_sectors, s1);
-    return 0;
-}
-
-static const cmdinfo_t alloc_cmd = {
-    .name       = "alloc",
-    .altname    = "a",
-    .argmin     = 1,
-    .argmax     = 2,
-    .cfunc      = alloc_f,
-    .args       = "off [sectors]",
-    .oneline    = "checks if a sector is present in the file",
-};
-
-
-static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                            int64_t nb_sectors, int64_t *pnum)
-{
-    int num, num_checked;
-    int ret, firstret;
-
-    num_checked = MIN(nb_sectors, INT_MAX);
-    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
-    if (ret < 0) {
-        return ret;
-    }
-
-    firstret = ret;
-    *pnum = num;
-
-    while (nb_sectors > 0 && ret == firstret) {
-        sector_num += num;
-        nb_sectors -= num;
-
-        num_checked = MIN(nb_sectors, INT_MAX);
-        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
-        if (ret == firstret) {
-            *pnum += num;
-        } else {
-            break;
-        }
-    }
-
-    return firstret;
-}
-
-static int map_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int64_t offset;
-    int64_t nb_sectors;
-    char s1[64];
-    int64_t num;
-    int ret;
-    const char *retstr;
-
-    offset = 0;
-    nb_sectors = bs->total_sectors;
-
-    do {
-        ret = map_is_allocated(bs, offset, nb_sectors, &num);
-        if (ret < 0) {
-            error_report("Failed to get allocation status: %s", strerror(-ret));
-            return 0;
-        }
-
-        retstr = ret ? "    allocated" : "not allocated";
-        cvtstr(offset << 9ULL, s1, sizeof(s1));
-        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
-               "at offset %s (%d)\n",
-               offset << 9ULL, num, nb_sectors, retstr, s1, ret);
-
-        offset += num;
-        nb_sectors -= num;
-    } while (offset < bs->total_sectors);
-
-    return 0;
-}
-
-static const cmdinfo_t map_cmd = {
-       .name           = "map",
-       .argmin         = 0,
-       .argmax         = 0,
-       .cfunc          = map_f,
-       .args           = "",
-       .oneline        = "prints the allocated areas of a file",
-};
-
-static int break_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int ret;
-
-    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
-    if (ret < 0) {
-        printf("Could not set breakpoint: %s\n", strerror(-ret));
-    }
-
-    return 0;
-}
-
-static const cmdinfo_t break_cmd = {
-       .name           = "break",
-       .argmin         = 2,
-       .argmax         = 2,
-       .cfunc          = break_f,
-       .args           = "event tag",
-       .oneline        = "sets a breakpoint on event and tags the stopped "
-                         "request as tag",
-};
-
-static int resume_f(BlockDriverState *bs, int argc, char **argv)
-{
-    int ret;
-
-    ret = bdrv_debug_resume(bs, argv[1]);
-    if (ret < 0) {
-        printf("Could not resume request: %s\n", strerror(-ret));
-    }
-
-    return 0;
-}
-
-static const cmdinfo_t resume_cmd = {
-       .name           = "resume",
-       .argmin         = 1,
-       .argmax         = 1,
-       .cfunc          = resume_f,
-       .args           = "tag",
-       .oneline        = "resumes the request tagged as tag",
-};
-
-static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
-{
-    while (!bdrv_debug_is_suspended(bs, argv[1])) {
-        qemu_aio_wait();
-    }
-
-    return 0;
-}
-
-static const cmdinfo_t wait_break_cmd = {
-       .name           = "wait_break",
-       .argmin         = 1,
-       .argmax         = 1,
-       .cfunc          = wait_break_f,
-       .args           = "tag",
-       .oneline        = "waits for the suspension of a request",
-};
-
-static int abort_f(BlockDriverState *bs, int argc, char **argv)
-{
-    abort();
-}
-
-static const cmdinfo_t abort_cmd = {
-       .name           = "abort",
-       .cfunc          = abort_f,
-       .flags          = CMD_NOFILE_OK,
-       .oneline        = "simulate a program crash using abort(3)",
-};
+extern int qemuio_misalign;
 
 static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
@@ -1916,18 +137,6 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
     return openfile(argv[optind], flags, growable);
 }
 
-static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
-{
-    if (ct->flags & CMD_FLAG_GLOBAL) {
-        return 1;
-    }
-    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
-        fprintf(stderr, "no file open, try 'help open'\n");
-        return 0;
-    }
-    return 1;
-}
-
 static void usage(const char *name)
 {
     printf(
@@ -1998,7 +207,7 @@ int main(int argc, char **argv)
             readonly = 1;
             break;
         case 'm':
-            misalign = 1;
+            qemuio_misalign = 1;
             break;
         case 'g':
             growable = 1;
@@ -2039,30 +248,8 @@ int main(int argc, char **argv)
 
     /* initialize commands */
     quit_init();
-    help_init();
     add_command(&open_cmd);
     add_command(&close_cmd);
-    add_command(&read_cmd);
-    add_command(&readv_cmd);
-    add_command(&write_cmd);
-    add_command(&writev_cmd);
-    add_command(&multiwrite_cmd);
-    add_command(&aio_read_cmd);
-    add_command(&aio_write_cmd);
-    add_command(&aio_flush_cmd);
-    add_command(&flush_cmd);
-    add_command(&truncate_cmd);
-    add_command(&length_cmd);
-    add_command(&info_cmd);
-    add_command(&discard_cmd);
-    add_command(&alloc_cmd);
-    add_command(&map_cmd);
-    add_command(&break_cmd);
-    add_command(&resume_cmd);
-    add_command(&wait_break_cmd);
-    add_command(&abort_cmd);
-
-    add_check_command(init_check_command);
 
     /* open the device */
     if (!readonly) {
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 08/26] qemu-io: Factor out qemuio_command
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (6 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 07/26] qemu-io: Split off commands to qemu-io-cmds.c Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 09/26] qemu-io: Move 'help' function Stefan Hajnoczi
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

It's duplicated code. Move it to qemu-io-cmds.c because it's not
dependent on any static data of the qemu-io tool.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c          | 43 +++++--------------------------------------
 cmd.h          |  3 ++-
 qemu-io-cmds.c | 24 ++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 39 deletions(-)

diff --git a/cmd.c b/cmd.c
index d501aab..7ae978f 100644
--- a/cmd.c
+++ b/cmd.c
@@ -138,28 +138,11 @@ static char *get_prompt(void);
 
 void command_loop(void)
 {
-    int c, i, done = 0, fetchable = 0, prompted = 0;
+    int i, done = 0, fetchable = 0, prompted = 0;
     char *input;
-    char **v;
-    const cmdinfo_t *ct;
 
     for (i = 0; !done && i < ncmdline; i++) {
-        input = strdup(cmdline[i]);
-        if (!input) {
-            fprintf(stderr, _("cannot strdup command '%s': %s\n"),
-                    cmdline[i], strerror(errno));
-            exit(1);
-        }
-        v = breakline(input, &c);
-        if (c) {
-            ct = find_command(v[0]);
-            if (ct) {
-                done = command(ct, c, v);
-            } else {
-                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
-            }
-	}
-        doneline(input, v);
+        done = qemuio_command(cmdline[i]);
     }
     if (cmdline) {
         g_free(cmdline);
@@ -179,20 +162,13 @@ void command_loop(void)
         if (!fetchable) {
             continue;
         }
+
         input = fetchline();
         if (input == NULL) {
             break;
         }
-        v = breakline(input, &c);
-        if (c) {
-            ct = find_command(v[0]);
-            if (ct) {
-                done = command(ct, c, v);
-            } else {
-                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
-            }
-        }
-        doneline(input, v);
+        done = qemuio_command(input);
+        free(input);
 
         prompted = 0;
         fetchable = 0;
@@ -328,15 +304,6 @@ char **breakline(char *input, int *count)
     return rval;
 }
 
-void
-doneline(
-	char	*input,
-	char	**vec)
-{
-	free(input);
-	free(vec);
-}
-
 #define EXABYTES(x)	((long long)(x) << 60)
 #define PETABYTES(x)	((long long)(x) << 50)
 #define TERABYTES(x)	((long long)(x) << 40)
diff --git a/cmd.h b/cmd.h
index ccf6336..d676408 100644
--- a/cmd.h
+++ b/cmd.h
@@ -59,7 +59,6 @@ int command(const cmdinfo_t *ci, int argc, char **argv);
 
 /* from input.h */
 char **breakline(char *input, int *count);
-void doneline(char *input, char **vec);
 char *fetchline(void);
 
 void cvtstr(double value, char *str, size_t sz);
@@ -77,4 +76,6 @@ void timestr(struct timeval *tv, char *str, size_t sz, int flags);
 
 extern char *progname;
 
+bool qemuio_command(const char *cmd);
+
 #endif	/* __COMMAND_H__ */
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 0a3817a..8b12446 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1807,6 +1807,30 @@ static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
     return 1;
 }
 
+bool qemuio_command(const char *cmd)
+{
+    char *input;
+    const cmdinfo_t *ct;
+    char **v;
+    int c;
+    bool done = false;
+
+    input = g_strdup(cmd);
+    v = breakline(input, &c);
+    if (c) {
+        ct = find_command(v[0]);
+        if (ct) {
+            done = command(ct, c, v);
+        } else {
+            fprintf(stderr, "command \"%s\" not found\n", v[0]);
+        }
+    }
+    g_free(input);
+    g_free(v);
+
+    return done;
+}
+
 static void __attribute((constructor)) init_qemuio_commands(void)
 {
     /* initialize commands */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 09/26] qemu-io: Move 'help' function
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (7 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 08/26] qemu-io: Factor out qemuio_command Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 10/26] qemu-io: Move 'quit' function Stefan Hajnoczi
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

No reason to treat it different from other commands. Move it to
qemu-io-cmds.c, adapt the coding style and register it like any other
command.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c          | 79 ----------------------------------------------------------
 cmd.h          |  1 -
 qemu-io-cmds.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 66 insertions(+), 81 deletions(-)

diff --git a/cmd.c b/cmd.c
index 7ae978f..2941ad3 100644
--- a/cmd.c
+++ b/cmd.c
@@ -439,82 +439,3 @@ quit_init(void)
 
 	add_command(&quit_cmd);
 }
-
-/* from libxcmd/help.c */
-
-static cmdinfo_t help_cmd;
-static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
-static void help_oneline(const char *cmd, const cmdinfo_t *ct);
-
-static void
-help_all(void)
-{
-	const cmdinfo_t	*ct;
-
-	for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
-		help_oneline(ct->name, ct);
-	printf(_("\nUse 'help commandname' for extended help.\n"));
-}
-
-static int
-help_f(
-    BlockDriverState *bs,
-	int		argc,
-	char		**argv)
-{
-	const cmdinfo_t	*ct;
-
-	if (argc == 1) {
-		help_all();
-		return 0;
-	}
-	ct = find_command(argv[1]);
-	if (ct == NULL) {
-		printf(_("command %s not found\n"), argv[1]);
-		return 0;
-	}
-	help_onecmd(argv[1], ct);
-	return 0;
-}
-
-static void
-help_onecmd(
-	const char	*cmd,
-	const cmdinfo_t	*ct)
-{
-	help_oneline(cmd, ct);
-	if (ct->help)
-		ct->help();
-}
-
-static void
-help_oneline(
-	const char	*cmd,
-	const cmdinfo_t	*ct)
-{
-	if (cmd)
-		printf("%s ", cmd);
-	else {
-		printf("%s ", ct->name);
-		if (ct->altname)
-			printf("(or %s) ", ct->altname);
-	}
-	if (ct->args)
-		printf("%s ", ct->args);
-	printf("-- %s\n", ct->oneline);
-}
-
-void
-help_init(void)
-{
-	help_cmd.name = _("help");
-	help_cmd.altname = _("?");
-	help_cmd.cfunc = help_f;
-	help_cmd.argmin = 0;
-	help_cmd.argmax = 1;
-	help_cmd.flags = CMD_FLAG_GLOBAL;
-	help_cmd.args = _("[command]");
-	help_cmd.oneline = _("help for one or all commands");
-
-	add_command(&help_cmd);
-}
diff --git a/cmd.h b/cmd.h
index d676408..89e7c6e 100644
--- a/cmd.h
+++ b/cmd.h
@@ -42,7 +42,6 @@ typedef struct cmdinfo {
 extern cmdinfo_t	*cmdtab;
 extern int		ncmds;
 
-void help_init(void);
 void quit_init(void);
 
 typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 8b12446..fa8d9a0 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1795,6 +1795,71 @@ static const cmdinfo_t abort_cmd = {
        .oneline        = "simulate a program crash using abort(3)",
 };
 
+static void help_oneline(const char *cmd, const cmdinfo_t *ct)
+{
+    if (cmd) {
+        printf("%s ", cmd);
+    } else {
+        printf("%s ", ct->name);
+        if (ct->altname) {
+            printf("(or %s) ", ct->altname);
+        }
+    }
+
+    if (ct->args) {
+        printf("%s ", ct->args);
+    }
+    printf("-- %s\n", ct->oneline);
+}
+
+static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
+{
+    help_oneline(cmd, ct);
+    if (ct->help) {
+        ct->help();
+    }
+}
+
+static void help_all(void)
+{
+    const cmdinfo_t *ct;
+
+    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+        help_oneline(ct->name, ct);
+    }
+    printf("\nUse 'help commandname' for extended help.\n");
+}
+
+static int help_f(BlockDriverState *bs, int argc, char **argv)
+{
+    const cmdinfo_t *ct;
+
+    if (argc == 1) {
+        help_all();
+        return 0;
+    }
+
+    ct = find_command(argv[1]);
+    if (ct == NULL) {
+        printf("command %s not found\n", argv[1]);
+        return 0;
+    }
+
+    help_onecmd(argv[1], ct);
+    return 0;
+}
+
+static const cmdinfo_t help_cmd = {
+    .name       = "help",
+    .altname    = "?",
+    .cfunc      = help_f,
+    .argmin     = 0,
+    .argmax     = 1,
+    .flags      = CMD_FLAG_GLOBAL,
+    .args       = "[command]",
+    .oneline    = "help for one or all commands",
+};
+
 static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
 {
     if (ct->flags & CMD_FLAG_GLOBAL) {
@@ -1834,7 +1899,7 @@ bool qemuio_command(const char *cmd)
 static void __attribute((constructor)) init_qemuio_commands(void)
 {
     /* initialize commands */
-    help_init();
+    add_command(&help_cmd);
     add_command(&read_cmd);
     add_command(&readv_cmd);
     add_command(&write_cmd);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 10/26] qemu-io: Move 'quit' function
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (8 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 09/26] qemu-io: Move 'help' function Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 11/26] qemu-io: Move qemu_strsep() to cutils.c Stefan Hajnoczi
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

This one only makes sense in the context of the qemu-io tool, so move it
to qemu-io.c. Adapt coding style and register it like other commands.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c     | 29 -----------------------------
 cmd.h     |  2 --
 qemu-io.c | 17 ++++++++++++++++-
 3 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/cmd.c b/cmd.c
index 2941ad3..8496e74 100644
--- a/cmd.c
+++ b/cmd.c
@@ -410,32 +410,3 @@ timestr(
 		snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
 	}
 }
-
-
-/* from libxcmd/quit.c */
-
-static cmdinfo_t quit_cmd;
-
-/* ARGSUSED */
-static int
-quit_f(
-    BlockDriverState *bs,
-	int	argc,
-	char	**argv)
-{
-	return 1;
-}
-
-void
-quit_init(void)
-{
-	quit_cmd.name = _("quit");
-	quit_cmd.altname = _("q");
-	quit_cmd.cfunc = quit_f;
-	quit_cmd.argmin = -1;
-	quit_cmd.argmax = -1;
-	quit_cmd.flags = CMD_FLAG_GLOBAL;
-	quit_cmd.oneline = _("exit the program");
-
-	add_command(&quit_cmd);
-}
diff --git a/cmd.h b/cmd.h
index 89e7c6e..5b6f61b 100644
--- a/cmd.h
+++ b/cmd.h
@@ -42,8 +42,6 @@ typedef struct cmdinfo {
 extern cmdinfo_t	*cmdtab;
 extern int		ncmds;
 
-void quit_init(void);
-
 typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
 
 void add_command(const cmdinfo_t *ci);
diff --git a/qemu-io.c b/qemu-io.c
index 14eef2c..8f6c57e 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -137,6 +137,21 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
     return openfile(argv[optind], flags, growable);
 }
 
+static int quit_f(BlockDriverState *bs, int argc, char **argv)
+{
+    return 1;
+}
+
+static const cmdinfo_t quit_cmd = {
+    .name       = "quit",
+    .altname    = "q",
+    .cfunc      = quit_f,
+    .argmin     = -1,
+    .argmax     = -1,
+    .flags      = CMD_FLAG_GLOBAL,
+    .oneline    = "exit the program",
+};
+
 static void usage(const char *name)
 {
     printf(
@@ -247,7 +262,7 @@ int main(int argc, char **argv)
     bdrv_init();
 
     /* initialize commands */
-    quit_init();
+    add_command(&quit_cmd);
     add_command(&open_cmd);
     add_command(&close_cmd);
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 11/26] qemu-io: Move qemu_strsep() to cutils.c
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (9 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 10/26] qemu-io: Move 'quit' function Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 12/26] qemu-io: Move functions for registering and running commands Stefan Hajnoczi
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c                 | 21 ---------------------
 include/qemu-common.h |  1 +
 util/cutils.c         | 21 +++++++++++++++++++++
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/cmd.c b/cmd.c
index 8496e74..f6bf2c5 100644
--- a/cmd.c
+++ b/cmd.c
@@ -255,27 +255,6 @@ fetchline(void)
 }
 #endif
 
-static char *qemu_strsep(char **input, const char *delim)
-{
-    char *result = *input;
-    if (result != NULL) {
-        char *p;
-
-        for (p = result; *p != '\0'; p++) {
-            if (strchr(delim, *p)) {
-                break;
-            }
-        }
-        if (*p == '\0') {
-            *input = NULL;
-        } else {
-            *p = '\0';
-            *input = p + 1;
-        }
-    }
-    return result;
-}
-
 char **breakline(char *input, int *count)
 {
     int c = 0;
diff --git a/include/qemu-common.h b/include/qemu-common.h
index d95ea1e..ed8b6e2 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -174,6 +174,7 @@ char *pstrcat(char *buf, int buf_size, const char *s);
 int strstart(const char *str, const char *val, const char **ptr);
 int stristart(const char *str, const char *val, const char **ptr);
 int qemu_strnlen(const char *s, int max_len);
+char *qemu_strsep(char **input, const char *delim);
 time_t mktimegm(struct tm *tm);
 int qemu_fls(int i);
 int qemu_fdatasync(int fd);
diff --git a/util/cutils.c b/util/cutils.c
index 8f28896..0116fcd 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -107,6 +107,27 @@ int qemu_strnlen(const char *s, int max_len)
     return i;
 }
 
+char *qemu_strsep(char **input, const char *delim)
+{
+    char *result = *input;
+    if (result != NULL) {
+        char *p;
+
+        for (p = result; *p != '\0'; p++) {
+            if (strchr(delim, *p)) {
+                break;
+            }
+        }
+        if (*p == '\0') {
+            *input = NULL;
+        } else {
+            *p = '\0';
+            *input = p + 1;
+        }
+    }
+    return result;
+}
+
 time_t mktimegm(struct tm *tm)
 {
     time_t t;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 12/26] qemu-io: Move functions for registering and running commands
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (10 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 11/26] qemu-io: Move qemu_strsep() to cutils.c Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 13/26] qemu-io: Move command_loop() and friends Stefan Hajnoczi
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c          | 113 ---------------------------------
 cmd.h          |  11 +---
 qemu-io-cmds.c | 192 ++++++++++++++++++++++++++++++++++++++++++---------------
 qemu-io.c      |  10 +--
 4 files changed, 148 insertions(+), 178 deletions(-)

diff --git a/cmd.c b/cmd.c
index f6bf2c5..6616d61 100644
--- a/cmd.c
+++ b/cmd.c
@@ -31,94 +31,9 @@
 
 /* from libxcmd/command.c */
 
-cmdinfo_t	*cmdtab;
-int		ncmds;
-
-static checkfunc_t	check_func;
 static int		ncmdline;
 static char		**cmdline;
 
-static int
-compare(const void *a, const void *b)
-{
-	return strcmp(((const cmdinfo_t *)a)->name,
-		      ((const cmdinfo_t *)b)->name);
-}
-
-void add_command(const cmdinfo_t *ci)
-{
-    cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
-    cmdtab[ncmds - 1] = *ci;
-    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
-}
-
-static int
-check_command(
-	const cmdinfo_t	*ci)
-{
-	if (check_func)
-		return check_func(qemuio_bs, ci);
-	return 1;
-}
-
-void
-add_check_command(
-	checkfunc_t	cf)
-{
-	check_func = cf;
-}
-
-int
-command_usage(
-	const cmdinfo_t *ci)
-{
-	printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
-	return 0;
-}
-
-int
-command(
-	const cmdinfo_t	*ct,
-	int		argc,
-	char		**argv)
-{
-	char		*cmd = argv[0];
-
-	if (!check_command(ct))
-		return 0;
-
-	if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
-		if (ct->argmax == -1)
-			fprintf(stderr,
-	_("bad argument count %d to %s, expected at least %d arguments\n"),
-				argc-1, cmd, ct->argmin);
-		else if (ct->argmin == ct->argmax)
-			fprintf(stderr,
-	_("bad argument count %d to %s, expected %d arguments\n"),
-				argc-1, cmd, ct->argmin);
-		else
-			fprintf(stderr,
-	_("bad argument count %d to %s, expected between %d and %d arguments\n"),
-			argc-1, cmd, ct->argmin, ct->argmax);
-		return 0;
-	}
-	optind = 0;
-	return ct->cfunc(qemuio_bs, argc, argv);
-}
-
-const cmdinfo_t *
-find_command(
-	const char	*cmd)
-{
-	cmdinfo_t	*ct;
-
-	for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
-		if (strcmp(ct->name, cmd) == 0 ||
-		    (ct->altname && strcmp(ct->altname, cmd) == 0))
-			return (const cmdinfo_t *)ct;
-	}
-	return NULL;
-}
 
 void add_user_command(char *optarg)
 {
@@ -255,34 +170,6 @@ fetchline(void)
 }
 #endif
 
-char **breakline(char *input, int *count)
-{
-    int c = 0;
-    char *p;
-    char **rval = calloc(sizeof(char *), 1);
-    char **tmp;
-
-    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
-        if (!*p) {
-            continue;
-        }
-        c++;
-        tmp = realloc(rval, sizeof(*rval) * (c + 1));
-        if (!tmp) {
-            free(rval);
-            rval = NULL;
-            c = 0;
-            break;
-        } else {
-            rval = tmp;
-        }
-        rval[c - 1] = p;
-        rval[c] = NULL;
-    }
-    *count = c;
-    return rval;
-}
-
 #define EXABYTES(x)	((long long)(x) << 60)
 #define PETABYTES(x)	((long long)(x) << 50)
 #define TERABYTES(x)	((long long)(x) << 40)
diff --git a/cmd.h b/cmd.h
index 5b6f61b..0d01a33 100644
--- a/cmd.h
+++ b/cmd.h
@@ -39,23 +39,16 @@ typedef struct cmdinfo {
 	helpfunc_t      help;
 } cmdinfo_t;
 
-extern cmdinfo_t	*cmdtab;
-extern int		ncmds;
-
 typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
 
-void add_command(const cmdinfo_t *ci);
+void qemuio_add_command(const cmdinfo_t *ci);
 void add_user_command(char *optarg);
 void add_check_command(checkfunc_t cf);
 
-const cmdinfo_t *find_command(const char *cmd);
-
 void command_loop(void);
-int command_usage(const cmdinfo_t *ci);
-int command(const cmdinfo_t *ci, int argc, char **argv);
+int qemuio_command_usage(const cmdinfo_t *ci);
 
 /* from input.h */
-char **breakline(char *input, int *count);
 char *fetchline(void);
 
 void cvtstr(double value, char *str, size_t sz);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index fa8d9a0..8acc866 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -16,6 +16,110 @@
 
 int qemuio_misalign;
 
+static cmdinfo_t *cmdtab;
+static int ncmds;
+
+static int compare_cmdname(const void *a, const void *b)
+{
+    return strcmp(((const cmdinfo_t *)a)->name,
+                  ((const cmdinfo_t *)b)->name);
+}
+
+void qemuio_add_command(const cmdinfo_t *ci)
+{
+    cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
+    cmdtab[ncmds - 1] = *ci;
+    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
+}
+
+int qemuio_command_usage(const cmdinfo_t *ci)
+{
+    printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
+    return 0;
+}
+
+static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+{
+    if (ct->flags & CMD_FLAG_GLOBAL) {
+        return 1;
+    }
+    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
+        fprintf(stderr, "no file open, try 'help open'\n");
+        return 0;
+    }
+    return 1;
+}
+
+static int command(const cmdinfo_t *ct, int argc, char **argv)
+{
+    char *cmd = argv[0];
+
+    if (!init_check_command(qemuio_bs, ct)) {
+        return 0;
+    }
+
+    if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
+        if (ct->argmax == -1) {
+            fprintf(stderr,
+                    "bad argument count %d to %s, expected at least %d arguments\n",
+                    argc-1, cmd, ct->argmin);
+        } else if (ct->argmin == ct->argmax) {
+            fprintf(stderr,
+                    "bad argument count %d to %s, expected %d arguments\n",
+                    argc-1, cmd, ct->argmin);
+        } else {
+            fprintf(stderr,
+                    "bad argument count %d to %s, expected between %d and %d arguments\n",
+                    argc-1, cmd, ct->argmin, ct->argmax);
+        }
+        return 0;
+    }
+    optind = 0;
+    return ct->cfunc(qemuio_bs, argc, argv);
+}
+
+static const cmdinfo_t *find_command(const char *cmd)
+{
+    cmdinfo_t *ct;
+
+    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+        if (strcmp(ct->name, cmd) == 0 ||
+            (ct->altname && strcmp(ct->altname, cmd) == 0))
+        {
+            return (const cmdinfo_t *)ct;
+        }
+    }
+    return NULL;
+}
+
+static char **breakline(char *input, int *count)
+{
+    int c = 0;
+    char *p;
+    char **rval = g_malloc0(sizeof(char *));
+    char **tmp;
+
+    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
+        if (!*p) {
+            continue;
+        }
+        c++;
+        tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
+        if (!tmp) {
+            g_free(rval);
+            rval = NULL;
+            c = 0;
+            break;
+        } else {
+            rval = tmp;
+        }
+        rval[c - 1] = p;
+        rval[c] = NULL;
+    }
+    *count = c;
+    return rval;
+}
+
 static int64_t cvtnum(const char *s)
 {
     char *end;
@@ -467,12 +571,12 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
             vflag = 1;
             break;
         default:
-            return command_usage(&read_cmd);
+            return qemuio_command_usage(&read_cmd);
         }
     }
 
     if (optind != argc - 2) {
-        return command_usage(&read_cmd);
+        return qemuio_command_usage(&read_cmd);
     }
 
     if (bflag && pflag) {
@@ -494,7 +598,7 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
     }
 
     if (!Pflag && (lflag || sflag)) {
-        return command_usage(&read_cmd);
+        return qemuio_command_usage(&read_cmd);
     }
 
     if (!lflag) {
@@ -629,12 +733,12 @@ static int readv_f(BlockDriverState *bs, int argc, char **argv)
             vflag = 1;
             break;
         default:
-            return command_usage(&readv_cmd);
+            return qemuio_command_usage(&readv_cmd);
         }
     }
 
     if (optind > argc - 2) {
-        return command_usage(&readv_cmd);
+        return qemuio_command_usage(&readv_cmd);
     }
 
 
@@ -769,12 +873,12 @@ static int write_f(BlockDriverState *bs, int argc, char **argv)
             zflag = 1;
             break;
         default:
-            return command_usage(&write_cmd);
+            return qemuio_command_usage(&write_cmd);
         }
     }
 
     if (optind != argc - 2) {
-        return command_usage(&write_cmd);
+        return qemuio_command_usage(&write_cmd);
     }
 
     if (bflag + pflag + zflag > 1) {
@@ -911,12 +1015,12 @@ static int writev_f(BlockDriverState *bs, int argc, char **argv)
             }
             break;
         default:
-            return command_usage(&writev_cmd);
+            return qemuio_command_usage(&writev_cmd);
         }
     }
 
     if (optind > argc - 2) {
-        return command_usage(&writev_cmd);
+        return qemuio_command_usage(&writev_cmd);
     }
 
     offset = cvtnum(argv[optind]);
@@ -1023,12 +1127,12 @@ static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
             }
             break;
         default:
-            return command_usage(&writev_cmd);
+            return qemuio_command_usage(&writev_cmd);
         }
     }
 
     if (optind > argc - 2) {
-        return command_usage(&writev_cmd);
+        return qemuio_command_usage(&writev_cmd);
     }
 
     nr_reqs = 1;
@@ -1257,13 +1361,13 @@ static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
             break;
         default:
             g_free(ctx);
-            return command_usage(&aio_read_cmd);
+            return qemuio_command_usage(&aio_read_cmd);
         }
     }
 
     if (optind > argc - 2) {
         g_free(ctx);
-        return command_usage(&aio_read_cmd);
+        return qemuio_command_usage(&aio_read_cmd);
     }
 
     ctx->offset = cvtnum(argv[optind]);
@@ -1349,13 +1453,13 @@ static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
             break;
         default:
             g_free(ctx);
-            return command_usage(&aio_write_cmd);
+            return qemuio_command_usage(&aio_write_cmd);
         }
     }
 
     if (optind > argc - 2) {
         g_free(ctx);
-        return command_usage(&aio_write_cmd);
+        return qemuio_command_usage(&aio_write_cmd);
     }
 
     ctx->offset = cvtnum(argv[optind]);
@@ -1547,12 +1651,12 @@ static int discard_f(BlockDriverState *bs, int argc, char **argv)
             qflag = 1;
             break;
         default:
-            return command_usage(&discard_cmd);
+            return qemuio_command_usage(&discard_cmd);
         }
     }
 
     if (optind != argc - 2) {
-        return command_usage(&discard_cmd);
+        return qemuio_command_usage(&discard_cmd);
     }
 
     offset = cvtnum(argv[optind]);
@@ -1860,18 +1964,6 @@ static const cmdinfo_t help_cmd = {
     .oneline    = "help for one or all commands",
 };
 
-static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
-{
-    if (ct->flags & CMD_FLAG_GLOBAL) {
-        return 1;
-    }
-    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
-        fprintf(stderr, "no file open, try 'help open'\n");
-        return 0;
-    }
-    return 1;
-}
-
 bool qemuio_command(const char *cmd)
 {
     char *input;
@@ -1899,26 +1991,24 @@ bool qemuio_command(const char *cmd)
 static void __attribute((constructor)) init_qemuio_commands(void)
 {
     /* initialize commands */
-    add_command(&help_cmd);
-    add_command(&read_cmd);
-    add_command(&readv_cmd);
-    add_command(&write_cmd);
-    add_command(&writev_cmd);
-    add_command(&multiwrite_cmd);
-    add_command(&aio_read_cmd);
-    add_command(&aio_write_cmd);
-    add_command(&aio_flush_cmd);
-    add_command(&flush_cmd);
-    add_command(&truncate_cmd);
-    add_command(&length_cmd);
-    add_command(&info_cmd);
-    add_command(&discard_cmd);
-    add_command(&alloc_cmd);
-    add_command(&map_cmd);
-    add_command(&break_cmd);
-    add_command(&resume_cmd);
-    add_command(&wait_break_cmd);
-    add_command(&abort_cmd);
-
-    add_check_command(init_check_command);
+    qemuio_add_command(&help_cmd);
+    qemuio_add_command(&read_cmd);
+    qemuio_add_command(&readv_cmd);
+    qemuio_add_command(&write_cmd);
+    qemuio_add_command(&writev_cmd);
+    qemuio_add_command(&multiwrite_cmd);
+    qemuio_add_command(&aio_read_cmd);
+    qemuio_add_command(&aio_write_cmd);
+    qemuio_add_command(&aio_flush_cmd);
+    qemuio_add_command(&flush_cmd);
+    qemuio_add_command(&truncate_cmd);
+    qemuio_add_command(&length_cmd);
+    qemuio_add_command(&info_cmd);
+    qemuio_add_command(&discard_cmd);
+    qemuio_add_command(&alloc_cmd);
+    qemuio_add_command(&map_cmd);
+    qemuio_add_command(&break_cmd);
+    qemuio_add_command(&resume_cmd);
+    qemuio_add_command(&wait_break_cmd);
+    qemuio_add_command(&abort_cmd);
 }
diff --git a/qemu-io.c b/qemu-io.c
index 8f6c57e..3bf5aec 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -122,7 +122,7 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
             growable = 1;
             break;
         default:
-            return command_usage(&open_cmd);
+            return qemuio_command_usage(&open_cmd);
         }
     }
 
@@ -131,7 +131,7 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
     }
 
     if (optind != argc - 1) {
-        return command_usage(&open_cmd);
+        return qemuio_command_usage(&open_cmd);
     }
 
     return openfile(argv[optind], flags, growable);
@@ -262,9 +262,9 @@ int main(int argc, char **argv)
     bdrv_init();
 
     /* initialize commands */
-    add_command(&quit_cmd);
-    add_command(&open_cmd);
-    add_command(&close_cmd);
+    qemuio_add_command(&quit_cmd);
+    qemuio_add_command(&open_cmd);
+    qemuio_add_command(&close_cmd);
 
     /* open the device */
     if (!readonly) {
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 13/26] qemu-io: Move command_loop() and friends
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (11 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 12/26] qemu-io: Move functions for registering and running commands Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 14/26] qemu-io: Move remaining helpers from cmd.c Stefan Hajnoczi
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.c     | 139 --------------------------------------------------------------
 cmd.h     |   9 ----
 qemu-io.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 148 deletions(-)

diff --git a/cmd.c b/cmd.c
index 6616d61..26d38a8 100644
--- a/cmd.c
+++ b/cmd.c
@@ -31,145 +31,6 @@
 
 /* from libxcmd/command.c */
 
-static int		ncmdline;
-static char		**cmdline;
-
-
-void add_user_command(char *optarg)
-{
-    cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
-    cmdline[ncmdline-1] = optarg;
-}
-
-static void prep_fetchline(void *opaque)
-{
-    int *fetchable = opaque;
-
-    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
-    *fetchable= 1;
-}
-
-static char *get_prompt(void);
-
-void command_loop(void)
-{
-    int i, done = 0, fetchable = 0, prompted = 0;
-    char *input;
-
-    for (i = 0; !done && i < ncmdline; i++) {
-        done = qemuio_command(cmdline[i]);
-    }
-    if (cmdline) {
-        g_free(cmdline);
-        return;
-    }
-
-    while (!done) {
-        if (!prompted) {
-            printf("%s", get_prompt());
-            fflush(stdout);
-            qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
-            prompted = 1;
-        }
-
-        main_loop_wait(false);
-
-        if (!fetchable) {
-            continue;
-        }
-
-        input = fetchline();
-        if (input == NULL) {
-            break;
-        }
-        done = qemuio_command(input);
-        free(input);
-
-        prompted = 0;
-        fetchable = 0;
-    }
-    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
-}
-
-/* from libxcmd/input.c */
-
-#if defined(ENABLE_READLINE)
-# include <readline/history.h>
-# include <readline/readline.h>
-#elif defined(ENABLE_EDITLINE)
-# include <histedit.h>
-#endif
-
-static char *
-get_prompt(void)
-{
-	static char	prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
-
-	if (!prompt[0])
-		snprintf(prompt, sizeof(prompt), "%s> ", progname);
-	return prompt;
-}
-
-#if defined(ENABLE_READLINE)
-char *
-fetchline(void)
-{
-	char	*line;
-
-	line = readline(get_prompt());
-	if (line && *line)
-		add_history(line);
-	return line;
-}
-#elif defined(ENABLE_EDITLINE)
-static char *el_get_prompt(EditLine *e) { return get_prompt(); }
-char *
-fetchline(void)
-{
-	static EditLine	*el;
-	static History	*hist;
-	HistEvent	hevent;
-	char		*line;
-	int		count;
-
-	if (!el) {
-		hist = history_init();
-		history(hist, &hevent, H_SETSIZE, 100);
-		el = el_init(progname, stdin, stdout, stderr);
-		el_source(el, NULL);
-		el_set(el, EL_SIGNAL, 1);
-		el_set(el, EL_PROMPT, el_get_prompt);
-		el_set(el, EL_HIST, history, (const char *)hist);
-	}
-	line = strdup(el_gets(el, &count));
-	if (line) {
-		if (count > 0)
-			line[count-1] = '\0';
-		if (*line)
-			history(hist, &hevent, H_ENTER, line);
-	}
-	return line;
-}
-#else
-# define MAXREADLINESZ	1024
-char *
-fetchline(void)
-{
-	char	*p, *line = malloc(MAXREADLINESZ);
-
-	if (!line)
-		return NULL;
-	if (!fgets(line, MAXREADLINESZ, stdin)) {
-		free(line);
-		return NULL;
-	}
-	p = line + strlen(line);
-	if (p != line && p[-1] == '\n')
-		p[-1] = '\0';
-	return line;
-}
-#endif
-
 #define EXABYTES(x)	((long long)(x) << 60)
 #define PETABYTES(x)	((long long)(x) << 50)
 #define TERABYTES(x)	((long long)(x) << 40)
diff --git a/cmd.h b/cmd.h
index 0d01a33..da0c7cf 100644
--- a/cmd.h
+++ b/cmd.h
@@ -39,18 +39,11 @@ typedef struct cmdinfo {
 	helpfunc_t      help;
 } cmdinfo_t;
 
-typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
-
 void qemuio_add_command(const cmdinfo_t *ci);
-void add_user_command(char *optarg);
-void add_check_command(checkfunc_t cf);
 
-void command_loop(void);
 int qemuio_command_usage(const cmdinfo_t *ci);
 
 /* from input.h */
-char *fetchline(void);
-
 void cvtstr(double value, char *str, size_t sz);
 
 struct timeval tsub(struct timeval t1, struct timeval t2);
@@ -64,8 +57,6 @@ enum {
 
 void timestr(struct timeval *tv, char *str, size_t sz, int flags);
 
-extern char *progname;
-
 bool qemuio_command(const char *cmd);
 
 #endif	/* __COMMAND_H__ */
diff --git a/qemu-io.c b/qemu-io.c
index 3bf5aec..eec8cbc 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -29,6 +29,10 @@ char *progname;
 BlockDriverState *qemuio_bs;
 extern int qemuio_misalign;
 
+/* qemu-io commands passed using -c */
+static int ncmdline;
+static char **cmdline;
+
 static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_delete(bs);
@@ -174,6 +178,141 @@ static void usage(const char *name)
 }
 
 
+#if defined(ENABLE_READLINE)
+# include <readline/history.h>
+# include <readline/readline.h>
+#elif defined(ENABLE_EDITLINE)
+# include <histedit.h>
+#endif
+
+static char *get_prompt(void)
+{
+    static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
+
+    if (!prompt[0]) {
+        snprintf(prompt, sizeof(prompt), "%s> ", progname);
+    }
+
+    return prompt;
+}
+
+#if defined(ENABLE_READLINE)
+static char *fetchline(void)
+{
+    char *line = readline(get_prompt());
+    if (line && *line) {
+        add_history(line);
+    }
+    return line;
+}
+#elif defined(ENABLE_EDITLINE)
+static char *el_get_prompt(EditLine *e)
+{
+    return get_prompt();
+}
+
+static char *fetchline(void)
+{
+    static EditLine *el;
+    static History *hist;
+    HistEvent hevent;
+    char *line;
+    int count;
+
+    if (!el) {
+        hist = history_init();
+        history(hist, &hevent, H_SETSIZE, 100);
+        el = el_init(progname, stdin, stdout, stderr);
+        el_source(el, NULL);
+        el_set(el, EL_SIGNAL, 1);
+        el_set(el, EL_PROMPT, el_get_prompt);
+        el_set(el, EL_HIST, history, (const char *)hist);
+    }
+    line = strdup(el_gets(el, &count));
+    if (line) {
+        if (count > 0) {
+            line[count-1] = '\0';
+        }
+        if (*line) {
+            history(hist, &hevent, H_ENTER, line);
+        }
+    }
+    return line;
+}
+#else
+# define MAXREADLINESZ 1024
+static char *fetchline(void)
+{
+    char *p, *line = g_malloc(MAXREADLINESZ);
+
+    if (!fgets(line, MAXREADLINESZ, stdin)) {
+        g_free(line);
+        return NULL;
+    }
+
+    p = line + strlen(line);
+    if (p != line && p[-1] == '\n') {
+        p[-1] = '\0';
+    }
+
+    return line;
+}
+#endif
+
+static void prep_fetchline(void *opaque)
+{
+    int *fetchable = opaque;
+
+    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
+    *fetchable= 1;
+}
+
+static void command_loop(void)
+{
+    int i, done = 0, fetchable = 0, prompted = 0;
+    char *input;
+
+    for (i = 0; !done && i < ncmdline; i++) {
+        done = qemuio_command(cmdline[i]);
+    }
+    if (cmdline) {
+        g_free(cmdline);
+        return;
+    }
+
+    while (!done) {
+        if (!prompted) {
+            printf("%s", get_prompt());
+            fflush(stdout);
+            qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
+            prompted = 1;
+        }
+
+        main_loop_wait(false);
+
+        if (!fetchable) {
+            continue;
+        }
+
+        input = fetchline();
+        if (input == NULL) {
+            break;
+        }
+        done = qemuio_command(input);
+        g_free(input);
+
+        prompted = 0;
+        fetchable = 0;
+    }
+    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
+}
+
+static void add_user_command(char *optarg)
+{
+    cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
+    cmdline[ncmdline-1] = optarg;
+}
+
 int main(int argc, char **argv)
 {
     int readonly = 0;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 14/26] qemu-io: Move remaining helpers from cmd.c
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (12 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 13/26] qemu-io: Move command_loop() and friends Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 15/26] qemu-io: Interface cleanup Stefan Hajnoczi
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 Makefile       |   2 +-
 cmd.c          | 139 ---------------------------------------------------------
 cmd.h          |  14 ------
 qemu-io-cmds.c | 104 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 105 insertions(+), 154 deletions(-)
 delete mode 100644 cmd.c

diff --git a/Makefile b/Makefile
index cf932eb..87298e5 100644
--- a/Makefile
+++ b/Makefile
@@ -186,7 +186,7 @@ qemu-img.o: qemu-img-cmds.h
 
 qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
 qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
+qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o $(block-obj-y) libqemuutil.a libqemustub.a
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
diff --git a/cmd.c b/cmd.c
deleted file mode 100644
index 26d38a8..0000000
--- a/cmd.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2003-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <getopt.h>
-
-#include "cmd.h"
-#include "block/aio.h"
-#include "qemu/main-loop.h"
-
-#define _(x)	x	/* not gettext support yet */
-
-/* from libxcmd/command.c */
-
-#define EXABYTES(x)	((long long)(x) << 60)
-#define PETABYTES(x)	((long long)(x) << 50)
-#define TERABYTES(x)	((long long)(x) << 40)
-#define GIGABYTES(x)	((long long)(x) << 30)
-#define MEGABYTES(x)	((long long)(x) << 20)
-#define KILOBYTES(x)	((long long)(x) << 10)
-
-#define TO_EXABYTES(x)	((x) / EXABYTES(1))
-#define TO_PETABYTES(x)	((x) / PETABYTES(1))
-#define TO_TERABYTES(x)	((x) / TERABYTES(1))
-#define TO_GIGABYTES(x)	((x) / GIGABYTES(1))
-#define TO_MEGABYTES(x)	((x) / MEGABYTES(1))
-#define TO_KILOBYTES(x)	((x) / KILOBYTES(1))
-
-void
-cvtstr(
-	double		value,
-	char		*str,
-	size_t		size)
-{
-	char		*trim;
-	const char	*suffix;
-
-	if (value >= EXABYTES(1)) {
-		suffix = " EiB";
-		snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
-	} else if (value >= PETABYTES(1)) {
-		suffix = " PiB";
-		snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
-	} else if (value >= TERABYTES(1)) {
-		suffix = " TiB";
-		snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
-	} else if (value >= GIGABYTES(1)) {
-		suffix = " GiB";
-		snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
-	} else if (value >= MEGABYTES(1)) {
-		suffix = " MiB";
-		snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
-	} else if (value >= KILOBYTES(1)) {
-		suffix = " KiB";
-		snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
-	} else {
-		suffix = " bytes";
-		snprintf(str, size - 6, "%f", value);
-	}
-
-	trim = strstr(str, ".000");
-	if (trim) {
-		strcpy(trim, suffix);
-	} else {
-		strcat(str, suffix);
-	}
-}
-
-struct timeval
-tsub(struct timeval t1, struct timeval t2)
-{
-	t1.tv_usec -= t2.tv_usec;
-	if (t1.tv_usec < 0) {
-		t1.tv_usec += 1000000;
-		t1.tv_sec--;
-	}
-	t1.tv_sec -= t2.tv_sec;
-	return t1;
-}
-
-double
-tdiv(double value, struct timeval tv)
-{
-	return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
-}
-
-#define HOURS(sec)	((sec) / (60 * 60))
-#define MINUTES(sec)	(((sec) % (60 * 60)) / 60)
-#define SECONDS(sec)	((sec) % 60)
-
-void
-timestr(
-	struct timeval	*tv,
-	char		*ts,
-	size_t		size,
-	int		format)
-{
-	double		usec = (double)tv->tv_usec / 1000000.0;
-
-	if (format & TERSE_FIXED_TIME) {
-		if (!HOURS(tv->tv_sec)) {
-			snprintf(ts, size, "%u:%02u.%02u",
-				(unsigned int) MINUTES(tv->tv_sec),
-				(unsigned int) SECONDS(tv->tv_sec),
-				(unsigned int) (usec * 100));
-			return;
-		}
-		format |= VERBOSE_FIXED_TIME;	/* fallback if hours needed */
-	}
-
-	if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
-		snprintf(ts, size, "%u:%02u:%02u.%02u",
-			(unsigned int) HOURS(tv->tv_sec),
-			(unsigned int) MINUTES(tv->tv_sec),
-			(unsigned int) SECONDS(tv->tv_sec),
-			(unsigned int) (usec * 100));
-	} else {
-		snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
-	}
-}
diff --git a/cmd.h b/cmd.h
index da0c7cf..9907795 100644
--- a/cmd.h
+++ b/cmd.h
@@ -43,20 +43,6 @@ void qemuio_add_command(const cmdinfo_t *ci);
 
 int qemuio_command_usage(const cmdinfo_t *ci);
 
-/* from input.h */
-void cvtstr(double value, char *str, size_t sz);
-
-struct timeval tsub(struct timeval t1, struct timeval t2);
-double tdiv(double value, struct timeval tv);
-
-enum {
-	DEFAULT_TIME		= 0x0,
-	TERSE_FIXED_TIME	= 0x1,
-	VERBOSE_FIXED_TIME	= 0x2
-};
-
-void timestr(struct timeval *tv, char *str, size_t sz, int flags);
-
 bool qemuio_command(const char *cmd);
 
 #endif	/* __COMMAND_H__ */
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 8acc866..05ce342 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -126,6 +126,110 @@ static int64_t cvtnum(const char *s)
     return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
 }
 
+#define EXABYTES(x)     ((long long)(x) << 60)
+#define PETABYTES(x)    ((long long)(x) << 50)
+#define TERABYTES(x)    ((long long)(x) << 40)
+#define GIGABYTES(x)    ((long long)(x) << 30)
+#define MEGABYTES(x)    ((long long)(x) << 20)
+#define KILOBYTES(x)    ((long long)(x) << 10)
+
+#define TO_EXABYTES(x)  ((x) / EXABYTES(1))
+#define TO_PETABYTES(x) ((x) / PETABYTES(1))
+#define TO_TERABYTES(x) ((x) / TERABYTES(1))
+#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
+#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
+#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
+
+static void cvtstr(double value, char *str, size_t size)
+{
+    char *trim;
+    const char *suffix;
+
+    if (value >= EXABYTES(1)) {
+        suffix = " EiB";
+        snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
+    } else if (value >= PETABYTES(1)) {
+        suffix = " PiB";
+        snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
+    } else if (value >= TERABYTES(1)) {
+        suffix = " TiB";
+        snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
+    } else if (value >= GIGABYTES(1)) {
+        suffix = " GiB";
+        snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
+    } else if (value >= MEGABYTES(1)) {
+        suffix = " MiB";
+        snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
+    } else if (value >= KILOBYTES(1)) {
+        suffix = " KiB";
+        snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
+    } else {
+        suffix = " bytes";
+        snprintf(str, size - 6, "%f", value);
+    }
+
+    trim = strstr(str, ".000");
+    if (trim) {
+        strcpy(trim, suffix);
+    } else {
+        strcat(str, suffix);
+    }
+}
+
+
+
+static struct timeval tsub(struct timeval t1, struct timeval t2)
+{
+    t1.tv_usec -= t2.tv_usec;
+    if (t1.tv_usec < 0) {
+        t1.tv_usec += 1000000;
+        t1.tv_sec--;
+    }
+    t1.tv_sec -= t2.tv_sec;
+    return t1;
+}
+
+static double tdiv(double value, struct timeval tv)
+{
+    return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
+}
+
+#define HOURS(sec)      ((sec) / (60 * 60))
+#define MINUTES(sec)    (((sec) % (60 * 60)) / 60)
+#define SECONDS(sec)    ((sec) % 60)
+
+enum {
+    DEFAULT_TIME        = 0x0,
+    TERSE_FIXED_TIME    = 0x1,
+    VERBOSE_FIXED_TIME  = 0x2,
+};
+
+static void timestr(struct timeval *tv, char *ts, size_t size, int format)
+{
+    double usec = (double)tv->tv_usec / 1000000.0;
+
+    if (format & TERSE_FIXED_TIME) {
+        if (!HOURS(tv->tv_sec)) {
+            snprintf(ts, size, "%u:%02u.%02u",
+                    (unsigned int) MINUTES(tv->tv_sec),
+                    (unsigned int) SECONDS(tv->tv_sec),
+                    (unsigned int) (usec * 100));
+            return;
+        }
+        format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
+    }
+
+    if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
+        snprintf(ts, size, "%u:%02u:%02u.%02u",
+                (unsigned int) HOURS(tv->tv_sec),
+                (unsigned int) MINUTES(tv->tv_sec),
+                (unsigned int) SECONDS(tv->tv_sec),
+                (unsigned int) (usec * 100));
+    } else {
+        snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
+    }
+}
+
 /*
  * Parse the pattern argument to various sub-commands.
  *
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 15/26] qemu-io: Interface cleanup
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (13 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 14/26] qemu-io: Move remaining helpers from cmd.c Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 16/26] qemu-io: Use the qemu version for -V Stefan Hajnoczi
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 cmd.h             | 48 ------------------------------------------------
 include/qemu-io.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 qemu-io-cmds.c    | 14 +++++++-------
 qemu-io.c         |  7 +++----
 4 files changed, 56 insertions(+), 59 deletions(-)
 delete mode 100644 cmd.h
 create mode 100644 include/qemu-io.h

diff --git a/cmd.h b/cmd.h
deleted file mode 100644
index 9907795..0000000
--- a/cmd.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __COMMAND_H__
-#define __COMMAND_H__
-
-#include "qemu-common.h"
-
-#define CMD_FLAG_GLOBAL	((int)0x80000000)	/* don't iterate "args" */
-
-extern BlockDriverState *qemuio_bs;
-
-typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
-typedef void (*helpfunc_t)(void);
-
-typedef struct cmdinfo {
-	const char	*name;
-	const char	*altname;
-	cfunc_t		cfunc;
-	int		argmin;
-	int		argmax;
-	int		canpush;
-	int		flags;
-	const char	*args;
-	const char	*oneline;
-	helpfunc_t      help;
-} cmdinfo_t;
-
-void qemuio_add_command(const cmdinfo_t *ci);
-
-int qemuio_command_usage(const cmdinfo_t *ci);
-
-bool qemuio_command(const char *cmd);
-
-#endif	/* __COMMAND_H__ */
diff --git a/include/qemu-io.h b/include/qemu-io.h
new file mode 100644
index 0000000..a418b46
--- /dev/null
+++ b/include/qemu-io.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_IO_H
+#define QEMU_IO_H
+
+#include "qemu-common.h"
+
+#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
+
+typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
+typedef void (*helpfunc_t)(void);
+
+typedef struct cmdinfo {
+    const char* name;
+    const char* altname;
+    cfunc_t     cfunc;
+    int         argmin;
+    int         argmax;
+    int         canpush;
+    int         flags;
+    const char  *args;
+    const char  *oneline;
+    helpfunc_t  help;
+} cmdinfo_t;
+
+bool qemuio_command(BlockDriverState *bs, const char *cmd);
+
+void qemuio_add_command(const cmdinfo_t *ci);
+int qemuio_command_usage(const cmdinfo_t *ci);
+
+#endif /* QEMU_IO_H */
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 05ce342..ffbcf31 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -8,9 +8,8 @@
  * See the COPYING file in the top-level directory.
  */
 
-#include "qemu-common.h"
+#include "qemu-io.h"
 #include "block/block_int.h"
-#include "cmd.h"
 
 #define CMD_NOFILE_OK   0x01
 
@@ -50,11 +49,12 @@ static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
     return 1;
 }
 
-static int command(const cmdinfo_t *ct, int argc, char **argv)
+static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
+                   char **argv)
 {
     char *cmd = argv[0];
 
-    if (!init_check_command(qemuio_bs, ct)) {
+    if (!init_check_command(bs, ct)) {
         return 0;
     }
 
@@ -75,7 +75,7 @@ static int command(const cmdinfo_t *ct, int argc, char **argv)
         return 0;
     }
     optind = 0;
-    return ct->cfunc(qemuio_bs, argc, argv);
+    return ct->cfunc(bs, argc, argv);
 }
 
 static const cmdinfo_t *find_command(const char *cmd)
@@ -2068,7 +2068,7 @@ static const cmdinfo_t help_cmd = {
     .oneline    = "help for one or all commands",
 };
 
-bool qemuio_command(const char *cmd)
+bool qemuio_command(BlockDriverState *bs, const char *cmd)
 {
     char *input;
     const cmdinfo_t *ct;
@@ -2081,7 +2081,7 @@ bool qemuio_command(const char *cmd)
     if (c) {
         ct = find_command(v[0]);
         if (ct) {
-            done = command(ct, c, v);
+            done = command(bs, ct, c, v);
         } else {
             fprintf(stderr, "command \"%s\" not found\n", v[0]);
         }
diff --git a/qemu-io.c b/qemu-io.c
index eec8cbc..514edcb 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -14,10 +14,9 @@
 #include <getopt.h>
 #include <libgen.h>
 
-#include "qemu-common.h"
+#include "qemu-io.h"
 #include "qemu/main-loop.h"
 #include "block/block_int.h"
-#include "cmd.h"
 #include "trace/control.h"
 
 #define VERSION	"0.0.1"
@@ -273,7 +272,7 @@ static void command_loop(void)
     char *input;
 
     for (i = 0; !done && i < ncmdline; i++) {
-        done = qemuio_command(cmdline[i]);
+        done = qemuio_command(qemuio_bs, cmdline[i]);
     }
     if (cmdline) {
         g_free(cmdline);
@@ -298,7 +297,7 @@ static void command_loop(void)
         if (input == NULL) {
             break;
         }
-        done = qemuio_command(input);
+        done = qemuio_command(qemuio_bs, input);
         g_free(input);
 
         prompted = 0;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 16/26] qemu-io: Use the qemu version for -V
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (14 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 15/26] qemu-io: Interface cleanup Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 17/26] Make qemu-io commands available in HMP Stefan Hajnoczi
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Always printing 0.0.1 and never updating the version number wasn't very
useful. qemu-io is released with qemu, so using the same version number
makes most sense.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 qemu-io.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/qemu-io.c b/qemu-io.c
index 514edcb..cb9def5 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -19,8 +19,6 @@
 #include "block/block_int.h"
 #include "trace/control.h"
 
-#define VERSION	"0.0.1"
-
 #define CMD_NOFILE_OK   0x01
 
 char *progname;
@@ -380,7 +378,7 @@ int main(int argc, char **argv)
             }
             break;
         case 'V':
-            printf("%s version %s\n", progname, VERSION);
+            printf("%s version %s\n", progname, QEMU_VERSION);
             exit(0);
         case 'h':
             usage(progname);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 17/26] Make qemu-io commands available in HMP
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (15 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 16/26] qemu-io: Use the qemu version for -V Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 18/26] blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events Stefan Hajnoczi
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

It was decided to not make this command available in QMP in order to
make clear that this is not supposed to be a stable API and should be
used only for testing and debugging purposes.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 Makefile        |  2 +-
 Makefile.objs   |  1 +
 hmp-commands.hx | 16 ++++++++++++++++
 hmp.c           | 18 ++++++++++++++++++
 hmp.h           |  1 +
 5 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 87298e5..9a77ae0 100644
--- a/Makefile
+++ b/Makefile
@@ -186,7 +186,7 @@ qemu-img.o: qemu-img-cmds.h
 
 qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
 qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o $(block-obj-y) libqemuutil.a libqemustub.a
+qemu-io$(EXESUF): qemu-io.o $(block-obj-y) libqemuutil.a libqemustub.a
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
diff --git a/Makefile.objs b/Makefile.objs
index 286ce06..5b288ba 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,6 +13,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
 block-obj-$(CONFIG_WIN32) += aio-win32.o
 block-obj-y += block/
 block-obj-y += qapi-types.o qapi-visit.o
+block-obj-y += qemu-io-cmds.o
 
 block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
 block-obj-y += qemu-coroutine-sleep.o
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 4f5a3fd..396691a 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1553,6 +1553,22 @@ Removes the chardev @var{id}.
 ETEXI
 
     {
+        .name       = "qemu-io",
+        .args_type  = "device:B,command:s",
+        .params     = "[device] \"[command]\"",
+        .help       = "run a qemu-io command on a block device",
+        .mhandler.cmd = hmp_qemu_io,
+    },
+
+STEXI
+@item qemu-io @var{device} @var{command}
+@findex qemu-io
+
+Executes a qemu-io command on the given block device.
+
+ETEXI
+
+    {
         .name       = "info",
         .args_type  = "item:s?",
         .params     = "[subcommand]",
diff --git a/hmp.c b/hmp.c
index 4fb76ec..64e0baa 100644
--- a/hmp.c
+++ b/hmp.c
@@ -22,6 +22,7 @@
 #include "qemu/sockets.h"
 #include "monitor/monitor.h"
 #include "ui/console.h"
+#include "qemu-io.h"
 
 static void hmp_handle_error(Monitor *mon, Error **errp)
 {
@@ -1425,3 +1426,20 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
     qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
     hmp_handle_error(mon, &local_err);
 }
+
+void hmp_qemu_io(Monitor *mon, const QDict *qdict)
+{
+    BlockDriverState *bs;
+    const char* device = qdict_get_str(qdict, "device");
+    const char* command = qdict_get_str(qdict, "command");
+    Error *err = NULL;
+
+    bs = bdrv_find(device);
+    if (bs) {
+        qemuio_command(bs, command);
+    } else {
+        error_set(&err, QERR_DEVICE_NOT_FOUND, device);
+    }
+
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 95fe76e..56d2e92 100644
--- a/hmp.h
+++ b/hmp.h
@@ -85,5 +85,6 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
 void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
 void hmp_chardev_add(Monitor *mon, const QDict *qdict);
 void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
+void hmp_qemu_io(Monitor *mon, const QDict *qdict);
 
 #endif
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 18/26] blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (16 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 17/26] Make qemu-io commands available in HMP Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 19/26] ide-test: Add enum value for DEV Stefan Hajnoczi
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block.c               | 8 ++++----
 block/blkdebug.c      | 3 +++
 include/block/block.h | 3 +++
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/block.c b/block.c
index 3f616de..79ad33d 100644
--- a/block.c
+++ b/block.c
@@ -3186,13 +3186,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
 
 void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
 {
-    BlockDriver *drv = bs->drv;
-
-    if (!drv || !drv->bdrv_debug_event) {
+    if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
         return;
     }
 
-    drv->bdrv_debug_event(bs, event);
+    bs->drv->bdrv_debug_event(bs, event);
 }
 
 int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
@@ -4024,6 +4022,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
     }
 
     /* Write back cached data to the OS even with cache=unsafe */
+    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS);
     if (bs->drv->bdrv_co_flush_to_os) {
         ret = bs->drv->bdrv_co_flush_to_os(bs);
         if (ret < 0) {
@@ -4036,6 +4035,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
         goto flush_parent;
     }
 
+    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK);
     if (bs->drv->bdrv_co_flush_to_disk) {
         ret = bs->drv->bdrv_co_flush_to_disk(bs);
     } else if (bs->drv->bdrv_aio_flush) {
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 71f99e4..ccb627a 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -182,6 +182,9 @@ static const char *event_names[BLKDBG_EVENT_MAX] = {
     [BLKDBG_CLUSTER_ALLOC]                  = "cluster_alloc",
     [BLKDBG_CLUSTER_ALLOC_BYTES]            = "cluster_alloc_bytes",
     [BLKDBG_CLUSTER_FREE]                   = "cluster_free",
+
+    [BLKDBG_FLUSH_TO_OS]                    = "flush_to_os",
+    [BLKDBG_FLUSH_TO_DISK]                  = "flush_to_disk",
 };
 
 static int get_event_by_name(const char *name, BlkDebugEvent *event)
diff --git a/include/block/block.h b/include/block/block.h
index dc5b388..2307f67 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -424,6 +424,9 @@ typedef enum {
     BLKDBG_CLUSTER_ALLOC_BYTES,
     BLKDBG_CLUSTER_FREE,
 
+    BLKDBG_FLUSH_TO_OS,
+    BLKDBG_FLUSH_TO_DISK,
+
     BLKDBG_EVENT_MAX,
 } BlkDebugEvent;
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 19/26] ide-test: Add enum value for DEV
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (17 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 18/26] blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 20/26] ide: Set BSY bit during FLUSH Stefan Hajnoczi
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

Get rid of the magic number.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/ide-test.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/ide-test.c b/tests/ide-test.c
index 365e995..1c31a2e 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -64,6 +64,7 @@ enum {
 };
 
 enum {
+    DEV     = 0x10,
     LBA     = 0x40,
 };
 
@@ -394,7 +395,7 @@ static void test_identify(void)
 
     /* Read in the IDENTIFY buffer and check registers */
     data = inb(IDE_BASE + reg_device);
-    g_assert_cmpint(data & 0x10, ==, 0);
+    g_assert_cmpint(data & DEV, ==, 0);
 
     for (i = 0; i < 256; i++) {
         data = inb(IDE_BASE + reg_status);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 20/26] ide: Set BSY bit during FLUSH
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (18 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 19/26] ide-test: Add enum value for DEV Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 12:10   ` Paolo Bonzini
  2013-06-07 11:58 ` [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case Stefan Hajnoczi
                   ` (6 subsequent siblings)
  26 siblings, 1 reply; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Anthony Liguori, Andreas Färber, Stefan Hajnoczi

From: Andreas Färber <afaerber@suse.de>

The implementation of the ATA FLUSH command invokes a flush at the block
layer, which may on raw files on POSIX entail a synchronous fdatasync().
This may in some cases take so long that the SLES 11 SP1 guest driver
reports I/O errors and filesystems get corrupted or remounted read-only.

Avoid this by setting BUSY_STAT, so that the guest is made aware we are
in the middle of an operation and no ATA commands are attempted to be
processed concurrently.

Addresses BNC#637297.

Suggested-by: Gonglei (Arei) <arei.gonglei@huawei.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/ide/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index c7a8041..9926d92 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -814,6 +814,7 @@ void ide_flush_cache(IDEState *s)
         return;
     }
 
+    s->status |= BUSY_STAT;
     bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
     bdrv_aio_flush(s->bs, ide_flush_cb, s);
 }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (19 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 20/26] ide: Set BSY bit during FLUSH Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-14 17:54   ` Peter Maydell
  2013-06-07 11:58 ` [Qemu-devel] [PULL 22/26] block: add snapshot info query function bdrv_query_snapshot_info_list() Stefan Hajnoczi
                   ` (5 subsequent siblings)
  26 siblings, 1 reply; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi

From: Kevin Wolf <kwolf@redhat.com>

This checks in particular that BSY is set while the flush request is in
flight.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/ide-test.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/tests/ide-test.c b/tests/ide-test.c
index 1c31a2e..828e71a 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -77,6 +77,7 @@ enum {
 enum {
     CMD_READ_DMA    = 0xc8,
     CMD_WRITE_DMA   = 0xca,
+    CMD_FLUSH_CACHE = 0xe7,
     CMD_IDENTIFY    = 0xec,
 
     CMDF_ABORT      = 0x100,
@@ -424,6 +425,43 @@ static void test_identify(void)
     ide_test_quit();
 }
 
+static void test_flush(void)
+{
+    uint8_t data;
+
+    ide_test_start(
+        "-vnc none "
+        "-drive file=blkdebug::%s,if=ide,cache=writeback",
+        tmp_path);
+
+    /* Delay the completion of the flush request until we explicitly do it */
+    qmp("{'execute':'human-monitor-command', 'arguments': { "
+        "'command-line': 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
+
+    /* FLUSH CACHE command on device 0*/
+    outb(IDE_BASE + reg_device, 0);
+    outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE);
+
+    /* Check status while request is in flight*/
+    data = inb(IDE_BASE + reg_status);
+    assert_bit_set(data, BSY | DRDY);
+    assert_bit_clear(data, DF | ERR | DRQ);
+
+    /* Complete the command */
+    qmp("{'execute':'human-monitor-command', 'arguments': { "
+        "'command-line': 'qemu-io ide0-hd0 \"resume A\"'} }");
+
+    /* Check registers */
+    data = inb(IDE_BASE + reg_device);
+    g_assert_cmpint(data & DEV, ==, 0);
+
+    data = inb(IDE_BASE + reg_status);
+    assert_bit_set(data, DRDY);
+    assert_bit_clear(data, BSY | DF | ERR | DRQ);
+
+    ide_test_quit();
+}
+
 int main(int argc, char **argv)
 {
     const char *arch = qtest_get_arch();
@@ -454,6 +492,8 @@ int main(int argc, char **argv)
     qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt);
     qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown);
 
+    qtest_add_func("/ide/flush", test_flush);
+
     ret = g_test_run();
 
     /* Cleanup */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 22/26] block: add snapshot info query function bdrv_query_snapshot_info_list()
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (20 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 23/26] block: add image info query function bdrv_query_image_info() Stefan Hajnoczi
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Wenchao Xia, Stefan Hajnoczi

From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>

This patch adds function bdrv_query_snapshot_info_list(), which will
retrieve snapshot info of an image in qmp object format. The implementation
is based on the code moved from qemu-img.c with modification to fit more
for qmp based block layer API.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/qapi.c         | 55 +++++++++++++++++++++++++++++++++++++++-------------
 include/block/qapi.h |  4 +++-
 qemu-img.c           |  5 ++++-
 3 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index 794dbf8..1ed56da 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -26,29 +26,56 @@
 #include "block/block_int.h"
 #include "qmp-commands.h"
 
-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info)
+/*
+ * Returns 0 on success, with *p_list either set to describe snapshot
+ * information, or NULL because there are no snapshots.  Returns -errno on
+ * error, with *p_list untouched.
+ */
+int bdrv_query_snapshot_info_list(BlockDriverState *bs,
+                                  SnapshotInfoList **p_list,
+                                  Error **errp)
 {
     int i, sn_count;
     QEMUSnapshotInfo *sn_tab = NULL;
-    SnapshotInfoList *info_list, *cur_item = NULL;
+    SnapshotInfoList *info_list, *cur_item = NULL, *head = NULL;
+    SnapshotInfo *info;
+
     sn_count = bdrv_snapshot_list(bs, &sn_tab);
+    if (sn_count < 0) {
+        const char *dev = bdrv_get_device_name(bs);
+        switch (sn_count) {
+        case -ENOMEDIUM:
+            error_setg(errp, "Device '%s' is not inserted", dev);
+            break;
+        case -ENOTSUP:
+            error_setg(errp,
+                       "Device '%s' does not support internal snapshots",
+                       dev);
+            break;
+        default:
+            error_setg_errno(errp, -sn_count,
+                             "Can't list snapshots of device '%s'", dev);
+            break;
+        }
+        return sn_count;
+    }
 
     for (i = 0; i < sn_count; i++) {
-        info->has_snapshots = true;
-        info_list = g_new0(SnapshotInfoList, 1);
+        info = g_new0(SnapshotInfo, 1);
+        info->id            = g_strdup(sn_tab[i].id_str);
+        info->name          = g_strdup(sn_tab[i].name);
+        info->vm_state_size = sn_tab[i].vm_state_size;
+        info->date_sec      = sn_tab[i].date_sec;
+        info->date_nsec     = sn_tab[i].date_nsec;
+        info->vm_clock_sec  = sn_tab[i].vm_clock_nsec / 1000000000;
+        info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
 
-        info_list->value                = g_new0(SnapshotInfo, 1);
-        info_list->value->id            = g_strdup(sn_tab[i].id_str);
-        info_list->value->name          = g_strdup(sn_tab[i].name);
-        info_list->value->vm_state_size = sn_tab[i].vm_state_size;
-        info_list->value->date_sec      = sn_tab[i].date_sec;
-        info_list->value->date_nsec     = sn_tab[i].date_nsec;
-        info_list->value->vm_clock_sec  = sn_tab[i].vm_clock_nsec / 1000000000;
-        info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
+        info_list = g_new0(SnapshotInfoList, 1);
+        info_list->value = info;
 
         /* XXX: waiting for the qapi to support qemu-queue.h types */
         if (!cur_item) {
-            info->snapshots = cur_item = info_list;
+            head = cur_item = info_list;
         } else {
             cur_item->next = info_list;
             cur_item = info_list;
@@ -57,6 +84,8 @@ void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info)
     }
 
     g_free(sn_tab);
+    *p_list = head;
+    return 0;
 }
 
 void bdrv_collect_image_info(BlockDriverState *bs,
diff --git a/include/block/qapi.h b/include/block/qapi.h
index e6e568d..4f223d1 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -29,7 +29,9 @@
 #include "block/block.h"
 #include "block/snapshot.h"
 
-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info);
+int bdrv_query_snapshot_info_list(BlockDriverState *bs,
+                                  SnapshotInfoList **p_list,
+                                  Error **errp);
 void bdrv_collect_image_info(BlockDriverState *bs,
                              ImageInfo *info,
                              const char *filename);
diff --git a/qemu-img.c b/qemu-img.c
index e089c78..e3d8fe3 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1667,7 +1667,10 @@ static ImageInfoList *collect_image_info_list(const char *filename,
 
         info = g_new0(ImageInfo, 1);
         bdrv_collect_image_info(bs, info, filename);
-        bdrv_collect_snapshots(bs, info);
+        bdrv_query_snapshot_info_list(bs, &info->snapshots, NULL);
+        if (info->snapshots) {
+            info->has_snapshots = true;
+        }
 
         elem = g_new0(ImageInfoList, 1);
         elem->value = info;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 23/26] block: add image info query function bdrv_query_image_info()
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (21 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 22/26] block: add snapshot info query function bdrv_query_snapshot_info_list() Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 24/26] qmp: add ImageInfo in BlockDeviceInfo used by query-block Stefan Hajnoczi
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Wenchao Xia, Stefan Hajnoczi

From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>

This patch adds function bdrv_query_image_info(), which will
retrieve image info in qmp object format. The implementation is
based on the code moved from qemu-img.c, but uses block layer
function to get snapshot info.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/qapi.c         | 43 +++++++++++++++++++++++++++++++++++++------
 include/block/qapi.h |  6 +++---
 qemu-img.c           | 11 ++++++-----
 3 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index 1ed56da..e9d8b74 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -88,18 +88,29 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
     return 0;
 }
 
-void bdrv_collect_image_info(BlockDriverState *bs,
-                             ImageInfo *info,
-                             const char *filename)
+/**
+ * bdrv_query_image_info:
+ * @bs: block device to examine
+ * @p_info: location to store image information
+ * @errp: location to store error information
+ *
+ * @p_info will be set only on success. On error, store error in @errp.
+ */
+void bdrv_query_image_info(BlockDriverState *bs,
+                           ImageInfo **p_info,
+                           Error **errp)
 {
     uint64_t total_sectors;
-    char backing_filename[1024];
+    const char *backing_filename;
     char backing_filename2[1024];
     BlockDriverInfo bdi;
+    int ret;
+    Error *err = NULL;
+    ImageInfo *info = g_new0(ImageInfo, 1);
 
     bdrv_get_geometry(bs, &total_sectors);
 
-    info->filename        = g_strdup(filename);
+    info->filename        = g_strdup(bs->filename);
     info->format          = g_strdup(bdrv_get_format_name(bs));
     info->virtual_size    = total_sectors * 512;
     info->actual_size     = bdrv_get_allocated_file_size(bs);
@@ -116,7 +127,7 @@ void bdrv_collect_image_info(BlockDriverState *bs,
         info->dirty_flag = bdi.is_dirty;
         info->has_dirty_flag = true;
     }
-    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
+    backing_filename = bs->backing_file;
     if (backing_filename[0] != '\0') {
         info->backing_filename = g_strdup(backing_filename);
         info->has_backing_filename = true;
@@ -134,6 +145,26 @@ void bdrv_collect_image_info(BlockDriverState *bs,
             info->has_backing_filename_format = true;
         }
     }
+
+    ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err);
+    switch (ret) {
+    case 0:
+        if (info->snapshots) {
+            info->has_snapshots = true;
+        }
+        break;
+    /* recoverable error */
+    case -ENOMEDIUM:
+    case -ENOTSUP:
+        error_free(err);
+        break;
+    default:
+        error_propagate(errp, err);
+        qapi_free_ImageInfo(info);
+        return;
+    }
+
+    *p_info = info;
 }
 
 BlockInfo *bdrv_query_info(BlockDriverState *bs)
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 4f223d1..ab1f48f 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -32,9 +32,9 @@
 int bdrv_query_snapshot_info_list(BlockDriverState *bs,
                                   SnapshotInfoList **p_list,
                                   Error **errp);
-void bdrv_collect_image_info(BlockDriverState *bs,
-                             ImageInfo *info,
-                             const char *filename);
+void bdrv_query_image_info(BlockDriverState *bs,
+                           ImageInfo **p_info,
+                           Error **errp);
 BlockInfo *bdrv_query_info(BlockDriverState *s);
 BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 
diff --git a/qemu-img.c b/qemu-img.c
index e3d8fe3..809b4f1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1644,6 +1644,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
     ImageInfoList *head = NULL;
     ImageInfoList **last = &head;
     GHashTable *filenames;
+    Error *err = NULL;
 
     filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
 
@@ -1665,11 +1666,11 @@ static ImageInfoList *collect_image_info_list(const char *filename,
             goto err;
         }
 
-        info = g_new0(ImageInfo, 1);
-        bdrv_collect_image_info(bs, info, filename);
-        bdrv_query_snapshot_info_list(bs, &info->snapshots, NULL);
-        if (info->snapshots) {
-            info->has_snapshots = true;
+        bdrv_query_image_info(bs, &info, &err);
+        if (error_is_set(&err)) {
+            error_report("%s", error_get_pretty(err));
+            error_free(err);
+            goto err;
         }
 
         elem = g_new0(ImageInfoList, 1);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 24/26] qmp: add ImageInfo in BlockDeviceInfo used by query-block
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (22 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 23/26] block: add image info query function bdrv_query_image_info() Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 25/26] hmp: show ImageInfo in 'info block' Stefan Hajnoczi
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Wenchao Xia, Stefan Hajnoczi

From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>

Now image info will be retrieved as an embbed json object inside
BlockDeviceInfo, backing chain info and all related internal snapshot
info can be got in the enhanced recursive structure of ImageInfo. New
recursive member *backing-image is added to reflect the backing chain
status.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/qapi.c         | 50 ++++++++++++++++++++++++++++++++++---
 include/block/qapi.h |  4 ++-
 qapi-schema.json     | 10 ++++++--
 qmp-commands.hx      | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 125 insertions(+), 8 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index e9d8b74..a4bc411 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -94,6 +94,13 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
  * @p_info: location to store image information
  * @errp: location to store error information
  *
+ * Store "flat" image information in @p_info.
+ *
+ * "Flat" means it does *not* query backing image information,
+ * i.e. (*pinfo)->has_backing_image will be set to false and
+ * (*pinfo)->backing_image to NULL even when the image does in fact have
+ * a backing image.
+ *
  * @p_info will be set only on success. On error, store error in @errp.
  */
 void bdrv_query_image_info(BlockDriverState *bs,
@@ -167,9 +174,15 @@ void bdrv_query_image_info(BlockDriverState *bs,
     *p_info = info;
 }
 
-BlockInfo *bdrv_query_info(BlockDriverState *bs)
+/* @p_info will be set only on success. */
+void bdrv_query_info(BlockDriverState *bs,
+                     BlockInfo **p_info,
+                     Error **errp)
 {
     BlockInfo *info = g_malloc0(sizeof(*info));
+    BlockDriverState *bs0;
+    ImageInfo **p_image_info;
+    Error *local_err = NULL;
     info->device = g_strdup(bs->device_name);
     info->type = g_strdup("unknown");
     info->locked = bdrv_dev_is_medium_locked(bs);
@@ -223,8 +236,30 @@ BlockInfo *bdrv_query_info(BlockDriverState *bs)
             info->inserted->iops_wr =
                            bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
         }
+
+        bs0 = bs;
+        p_image_info = &info->inserted->image;
+        while (1) {
+            bdrv_query_image_info(bs0, p_image_info, &local_err);
+            if (error_is_set(&local_err)) {
+                error_propagate(errp, local_err);
+                goto err;
+            }
+            if (bs0->drv && bs0->backing_hd) {
+                bs0 = bs0->backing_hd;
+                (*p_image_info)->has_backing_image = true;
+                p_image_info = &((*p_image_info)->backing_image);
+            } else {
+                break;
+            }
+        }
     }
-    return info;
+
+    *p_info = info;
+    return;
+
+ err:
+    qapi_free_BlockInfo(info);
 }
 
 BlockStats *bdrv_query_stats(const BlockDriverState *bs)
@@ -261,16 +296,25 @@ BlockInfoList *qmp_query_block(Error **errp)
 {
     BlockInfoList *head = NULL, **p_next = &head;
     BlockDriverState *bs = NULL;
+    Error *local_err = NULL;
 
      while ((bs = bdrv_next(bs))) {
         BlockInfoList *info = g_malloc0(sizeof(*info));
-        info->value = bdrv_query_info(bs);
+        bdrv_query_info(bs, &info->value, &local_err);
+        if (error_is_set(&local_err)) {
+            error_propagate(errp, local_err);
+            goto err;
+        }
 
         *p_next = info;
         p_next = &info->next;
     }
 
     return head;
+
+ err:
+    qapi_free_BlockInfoList(head);
+    return NULL;
 }
 
 BlockStatsList *qmp_query_blockstats(Error **errp)
diff --git a/include/block/qapi.h b/include/block/qapi.h
index ab1f48f..0496cc9 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -35,7 +35,9 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
 void bdrv_query_image_info(BlockDriverState *bs,
                            ImageInfo **p_info,
                            Error **errp);
-BlockInfo *bdrv_query_info(BlockDriverState *s);
+void bdrv_query_info(BlockDriverState *bs,
+                     BlockInfo **p_info,
+                     Error **errp);
 BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 
 void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
diff --git a/qapi-schema.json b/qapi-schema.json
index ef1f657..5ad6894 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -236,6 +236,8 @@
 #
 # @snapshots: #optional list of VM snapshots
 #
+# @backing-image: #optional info of the backing image (since 1.6)
+#
 # Since: 1.3
 #
 ##
@@ -245,7 +247,8 @@
            '*actual-size': 'int', 'virtual-size': 'int',
            '*cluster-size': 'int', '*encrypted': 'bool',
            '*backing-filename': 'str', '*full-backing-filename': 'str',
-           '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }
+           '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
+           '*backing-image': 'ImageInfo' } }
 
 ##
 # @ImageCheck:
@@ -756,6 +759,8 @@
 #
 # @iops_wr: write I/O operations per second is specified
 #
+# @image: the info of image used (since: 1.6)
+#
 # Since: 0.14.0
 #
 # Notes: This interface is only found in @BlockInfo.
@@ -765,7 +770,8 @@
             '*backing_file': 'str', 'backing_file_depth': 'int',
             'encrypted': 'bool', 'encryption_key_missing': 'bool',
             'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
-            'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
+            'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+            'image': 'ImageInfo' } }
 
 ##
 # @BlockDeviceIoStatus:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130e..8cea5e5 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1704,6 +1704,47 @@ Each json-object contain the following:
          - "iops": limit total I/O operations per second (json-int)
          - "iops_rd": limit read operations per second (json-int)
          - "iops_wr": limit write operations per second (json-int)
+         - "image": the detail of the image, it is a json-object containing
+            the following:
+             - "filename": image file name (json-string)
+             - "format": image format (json-string)
+             - "virtual-size": image capacity in bytes (json-int)
+             - "dirty-flag": true if image is not cleanly closed, not present
+                             means clean (json-bool, optional)
+             - "actual-size": actual size on disk in bytes of the image, not
+                              present when image does not support thin
+                              provision (json-int, optional)
+             - "cluster-size": size of a cluster in bytes, not present if image
+                               format does not support it (json-int, optional)
+             - "encrypted": true if the image is encrypted, not present means
+                            false or the image format does not support
+                            encryption (json-bool, optional)
+             - "backing_file": backing file name, not present means no backing
+                               file is used or the image format does not
+                               support backing file chain
+                               (json-string, optional)
+             - "full-backing-filename": full path of the backing file, not
+                                        present if it equals backing_file or no
+                                        backing file is used
+                                        (json-string, optional)
+             - "backing-filename-format": the format of the backing file, not
+                                          present means unknown or no backing
+                                          file (json-string, optional)
+             - "snapshots": the internal snapshot info, it is an optional list
+                of json-object containing the following:
+                 - "id": unique snapshot id (json-string)
+                 - "name": snapshot name (json-string)
+                 - "vm-state-size": size of the VM state in bytes (json-int)
+                 - "date-sec": UTC date of the snapshot in seconds (json-int)
+                 - "date-nsec": fractional part in nanoseconds to be used with
+                                date-sec(json-int)
+                 - "vm-clock-sec": VM clock relative to boot in seconds
+                                   (json-int)
+                 - "vm-clock-nsec": fractional part in nanoseconds to be used
+                                    with vm-clock-sec (json-int)
+             - "backing-image": the detail of the backing image, it is an
+                                optional json-object only present when a
+                                backing image present for this image
 
 - "io-status": I/O operation status, only present if the device supports it
                and the VM is configured to stop on errors. It's always reset
@@ -1724,14 +1765,38 @@ Example:
                "ro":false,
                "drv":"qcow2",
                "encrypted":false,
-               "file":"disks/test.img",
-               "backing_file_depth":0,
+               "file":"disks/test.qcow2",
+               "backing_file_depth":1,
                "bps":1000000,
                "bps_rd":0,
                "bps_wr":0,
                "iops":1000000,
                "iops_rd":0,
                "iops_wr":0,
+               "image":{
+                  "filename":"disks/test.qcow2",
+                  "format":"qcow2",
+                  "virtual-size":2048000,
+                  "backing_file":"base.qcow2",
+                  "full-backing-filename":"disks/base.qcow2",
+                  "backing-filename-format:"qcow2",
+                  "snapshots":[
+                     {
+                        "id": "1",
+                        "name": "snapshot1",
+                        "vm-state-size": 0,
+                        "date-sec": 10000200,
+                        "date-nsec": 12,
+                        "vm-clock-sec": 206,
+                        "vm-clock-nsec": 30
+                     }
+                  ],
+                  "backing-image":{
+                      "filename":"disks/base.qcow2",
+                      "format":"qcow2",
+                      "virtual-size":2048000
+                  }
+               }
             },
             "type":"unknown"
          },
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 25/26] hmp: show ImageInfo in 'info block'
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (23 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 24/26] qmp: add ImageInfo in BlockDeviceInfo used by query-block Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-07 11:58 ` [Qemu-devel] [PULL 26/26] hmp: add parameters device and -v for info block Stefan Hajnoczi
  2013-06-17 21:17 ` [Qemu-devel] [PULL 00/26] Block patches Anthony Liguori
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Wenchao Xia, Stefan Hajnoczi

From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>

Now human monitor can show image details, include internal
snapshot and backing chain info for every block device.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hmp.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/hmp.c b/hmp.c
index 64e0baa..4fc3bfe 100644
--- a/hmp.c
+++ b/hmp.c
@@ -22,6 +22,7 @@
 #include "qemu/sockets.h"
 #include "monitor/monitor.h"
 #include "ui/console.h"
+#include "block/qapi.h"
 #include "qemu-io.h"
 
 static void hmp_handle_error(Monitor *mon, Error **errp)
@@ -278,6 +279,7 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
 void hmp_info_block(Monitor *mon, const QDict *qdict)
 {
     BlockInfoList *block_list, *info;
+    ImageInfo *image_info;
 
     block_list = qmp_query_block(NULL);
 
@@ -319,6 +321,18 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
                             info->value->inserted->iops,
                             info->value->inserted->iops_rd,
                             info->value->inserted->iops_wr);
+
+            monitor_printf(mon, " images:\n");
+            image_info = info->value->inserted->image;
+            while (1) {
+                bdrv_image_info_dump((fprintf_function)monitor_printf, mon,
+                                     image_info);
+                if (image_info->has_backing_image) {
+                    image_info = image_info->backing_image;
+                } else {
+                    break;
+                }
+            }
         } else {
             monitor_printf(mon, " [not inserted]");
         }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 26/26] hmp: add parameters device and -v for info block
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (24 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 25/26] hmp: show ImageInfo in 'info block' Stefan Hajnoczi
@ 2013-06-07 11:58 ` Stefan Hajnoczi
  2013-06-17 21:17 ` [Qemu-devel] [PULL 00/26] Block patches Anthony Liguori
  26 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-07 11:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Wenchao Xia, Stefan Hajnoczi

From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>

With these parameters, user can choose the information to be showed,
to avoid message flood in the monitor.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hmp.c     | 25 ++++++++++++++++---------
 monitor.c |  7 ++++---
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/hmp.c b/hmp.c
index 4fc3bfe..494a9aa 100644
--- a/hmp.c
+++ b/hmp.c
@@ -280,10 +280,15 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
 {
     BlockInfoList *block_list, *info;
     ImageInfo *image_info;
+    const char *device = qdict_get_try_str(qdict, "device");
+    bool verbose = qdict_get_try_bool(qdict, "verbose", 0);
 
     block_list = qmp_query_block(NULL);
 
     for (info = block_list; info; info = info->next) {
+        if (device && strcmp(device, info->value->device)) {
+            continue;
+        }
         monitor_printf(mon, "%s: removable=%d",
                        info->value->device, info->value->removable);
 
@@ -322,15 +327,17 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
                             info->value->inserted->iops_rd,
                             info->value->inserted->iops_wr);
 
-            monitor_printf(mon, " images:\n");
-            image_info = info->value->inserted->image;
-            while (1) {
-                bdrv_image_info_dump((fprintf_function)monitor_printf, mon,
-                                     image_info);
-                if (image_info->has_backing_image) {
-                    image_info = image_info->backing_image;
-                } else {
-                    break;
+            if (verbose) {
+                monitor_printf(mon, " images:\n");
+                image_info = info->value->inserted->image;
+                while (1) {
+                        bdrv_image_info_dump((fprintf_function)monitor_printf,
+                                             mon, image_info);
+                    if (image_info->has_backing_image) {
+                        image_info = image_info->backing_image;
+                    } else {
+                        break;
+                    }
                 }
             }
         } else {
diff --git a/monitor.c b/monitor.c
index 9d279b8..017411f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2472,9 +2472,10 @@ static mon_cmd_t info_cmds[] = {
     },
     {
         .name       = "block",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the block devices",
+        .args_type  = "verbose:-v,device:B?",
+        .params     = "[-v] [device]",
+        .help       = "show info of one block device or all block devices "
+                      "(and details of images with -v option)",
         .mhandler.cmd = hmp_info_block,
     },
     {
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 20/26] ide: Set BSY bit during FLUSH
  2013-06-07 11:58 ` [Qemu-devel] [PULL 20/26] ide: Set BSY bit during FLUSH Stefan Hajnoczi
@ 2013-06-07 12:10   ` Paolo Bonzini
  0 siblings, 0 replies; 47+ messages in thread
From: Paolo Bonzini @ 2013-06-07 12:10 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Kevin Wolf, Anthony Liguori, qemu-stable, qemu-devel,
	Andreas Färber

Il 07/06/2013 07:58, Stefan Hajnoczi ha scritto:
> From: Andreas Färber <afaerber@suse.de>
> 
> The implementation of the ATA FLUSH command invokes a flush at the block
> layer, which may on raw files on POSIX entail a synchronous fdatasync().
> This may in some cases take so long that the SLES 11 SP1 guest driver
> reports I/O errors and filesystems get corrupted or remounted read-only.
> 
> Avoid this by setting BUSY_STAT, so that the guest is made aware we are
> in the middle of an operation and no ATA commands are attempted to be
> processed concurrently.
> 
> Addresses BNC#637297.
> 
> Suggested-by: Gonglei (Arei) <arei.gonglei@huawei.com>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  hw/ide/core.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/ide/core.c b/hw/ide/core.c
> index c7a8041..9926d92 100644
> --- a/hw/ide/core.c
> +++ b/hw/ide/core.c
> @@ -814,6 +814,7 @@ void ide_flush_cache(IDEState *s)
>          return;
>      }
>  
> +    s->status |= BUSY_STAT;
>      bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
>      bdrv_aio_flush(s->bs, ide_flush_cb, s);
>  }
> 

Cc: qemu-stable@nongnu.org

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case
  2013-06-07 11:58 ` [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case Stefan Hajnoczi
@ 2013-06-14 17:54   ` Peter Maydell
  2013-06-14 18:11     ` Peter Maydell
  0 siblings, 1 reply; 47+ messages in thread
From: Peter Maydell @ 2013-06-14 17:54 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: Kevin Wolf, Anthony Liguori, qemu-devel

On 7 June 2013 12:58, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> From: Kevin Wolf <kwolf@redhat.com>
>
> This checks in particular that BSY is set while the flush request is in
> flight.

This test doesn't seem to pass. At commit bd07684aac
(where the test landed):

cam-vm-266:precise:qemu$ (cd build/x86;
QTEST_QEMU_BINARY=i386-softmmu/qemu-system-i386
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$((RANDOM % 255 + 1))} gtester -k
--verbose -m=quick tests/ide-test)
TEST: tests/ide-test... (pid=25118)
  /i386/ide/identify:                                                  OK
  /i386/ide/bmdma/setup:                                               OK
  /i386/ide/bmdma/simple_rw:                                           OK
  /i386/ide/bmdma/short_prdt:                                          OK
  /i386/ide/bmdma/long_prdt:                                           OK
  /i386/ide/bmdma/teardown:                                            OK
  /i386/ide/flush:
blkdebug: Suspended request 'A'
blkdebug: Resuming request 'A'
**
ERROR:/home/petmay01/linaro/qemu-from-laptop/qemu/tests/ide-test.c:460:test_flush:
assertion failed ((data) & (BSY | DF | ERR | DRQ) == 0): (0x00000080
== 0x00000000)
FAIL
GTester: last random seed: R02S67ac87128346f4ba02226525fc3ecccf
(pid=25136)
FAIL: tests/ide-test


thanks
-- PMM

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case
  2013-06-14 17:54   ` Peter Maydell
@ 2013-06-14 18:11     ` Peter Maydell
  2013-06-14 18:18       ` Anthony Liguori
  0 siblings, 1 reply; 47+ messages in thread
From: Peter Maydell @ 2013-06-14 18:11 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: Kevin Wolf, Anthony Liguori, qemu-devel

On 14 June 2013 18:54, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 7 June 2013 12:58, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>> From: Kevin Wolf <kwolf@redhat.com>
>>
>> This checks in particular that BSY is set while the flush request is in
>> flight.
>
> This test doesn't seem to pass.

> ERROR:/home/petmay01/linaro/qemu-from-laptop/qemu/tests/ide-test.c:460:test_flush:
> assertion failed ((data) & (BSY | DF | ERR | DRQ) == 0): (0x00000080
> == 0x00000000)

...fixed by http://patchwork.ozlabs.org/patch/250334/

thanks
-- PMM

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case
  2013-06-14 18:11     ` Peter Maydell
@ 2013-06-14 18:18       ` Anthony Liguori
  2013-06-17 12:45         ` Stefan Hajnoczi
  0 siblings, 1 reply; 47+ messages in thread
From: Anthony Liguori @ 2013-06-14 18:18 UTC (permalink / raw)
  To: Peter Maydell, Stefan Hajnoczi; +Cc: Kevin Wolf, qemu-devel

Peter Maydell <peter.maydell@linaro.org> writes:

> On 14 June 2013 18:54, Peter Maydell <peter.maydell@linaro.org> wrote:
>> On 7 June 2013 12:58, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>>> From: Kevin Wolf <kwolf@redhat.com>
>>>
>>> This checks in particular that BSY is set while the flush request is in
>>> flight.
>>
>> This test doesn't seem to pass.
>
>> ERROR:/home/petmay01/linaro/qemu-from-laptop/qemu/tests/ide-test.c:460:test_flush:
>> assertion failed ((data) & (BSY | DF | ERR | DRQ) == 0): (0x00000080
>> == 0x00000000)
>
> ...fixed by http://patchwork.ozlabs.org/patch/250334/

I'm testing it myself now.  Since it's already in the block tree, I'll
push it directly as it's blocking my queue.

Unless Kevin or Stefan are planning on sending a pull request today of
course.

Regards,

Anthony Liguori

>
> thanks
> -- PMM

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case
  2013-06-14 18:18       ` Anthony Liguori
@ 2013-06-17 12:45         ` Stefan Hajnoczi
  0 siblings, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2013-06-17 12:45 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Kevin Wolf, Peter Maydell, qemu-devel, Stefan Hajnoczi

On Fri, Jun 14, 2013 at 01:18:44PM -0500, Anthony Liguori wrote:
> Peter Maydell <peter.maydell@linaro.org> writes:
> 
> > On 14 June 2013 18:54, Peter Maydell <peter.maydell@linaro.org> wrote:
> >> On 7 June 2013 12:58, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> >>> From: Kevin Wolf <kwolf@redhat.com>
> >>>
> >>> This checks in particular that BSY is set while the flush request is in
> >>> flight.
> >>
> >> This test doesn't seem to pass.
> >
> >> ERROR:/home/petmay01/linaro/qemu-from-laptop/qemu/tests/ide-test.c:460:test_flush:
> >> assertion failed ((data) & (BSY | DF | ERR | DRQ) == 0): (0x00000080
> >> == 0x00000000)
> >
> > ...fixed by http://patchwork.ozlabs.org/patch/250334/
> 
> I'm testing it myself now.  Since it's already in the block tree, I'll
> push it directly as it's blocking my queue.
> 
> Unless Kevin or Stefan are planning on sending a pull request today of
> course.

Thanks for merging mdroth's fix!

Stefan

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
                   ` (25 preceding siblings ...)
  2013-06-07 11:58 ` [Qemu-devel] [PULL 26/26] hmp: add parameters device and -v for info block Stefan Hajnoczi
@ 2013-06-17 21:17 ` Anthony Liguori
  26 siblings, 0 replies; 47+ messages in thread
From: Anthony Liguori @ 2013-06-17 21:17 UTC (permalink / raw)
  To: Stefan Hajnoczi, qemu-devel; +Cc: Anthony Liguori

Pulled.  Thanks.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 00/26] Block patches
@ 2013-08-30 14:30 Kevin Wolf
  2013-08-30 17:14 ` Anthony Liguori
  0 siblings, 1 reply; 47+ messages in thread
From: Kevin Wolf @ 2013-08-30 14:30 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit b5d54bd42158b90b239bb6ce9c13072eb3a53fd2:

  Merge remote-tracking branch 'qemu-kvm/uq/master' into stable-1.5 (2013-08-29 17:21:51 -0500)

are available in the git repository at:


  git://repo.or.cz/qemu/kevin.git for-anthony

for you to fetch changes up to edcbf2869829001b60b15ad32609138ae784a588:

  qemu-iotests: Overlapping cluster allocations (2013-08-30 15:48:59 +0200)

----------------------------------------------------------------
Bharata B Rao (1):
      gluster: Abort on AIO completion failure

Kevin Wolf (6):
      qcow2: Change default for new images to compat=1.1
      block: Remove redundant assertion
      qapi-types.py: Split off generate_struct_fields()
      Revert "block: Disable driver-specific options for 1.6"
      qemu-iotests: Update reference output for 051
      block: Remove old raw driver

Laszlo Ersek (7):
      add skeleton for BSD licensed "raw" BlockDriver
      raw_bsd: emit debug events in bdrv_co_readv() and bdrv_co_writev()
      raw_bsd: add raw_create()
      raw_bsd: introduce "special members"
      raw_bsd: add raw_create_options
      raw_bsd: register bdrv_raw
      switch raw block driver from "raw.o" to "raw_bsd.o"

Max Reitz (11):
      option: Add assigned flag to QEMUOptionParameter
      qcow2-refcount: Snapshot update for zero clusters
      qemu-iotests: Snapshotting zero clusters
      qcow2: Add corrupt bit
      qcow2: Metadata overlap checks
      qcow2: Employ metadata overlap checks
      qcow2-refcount: Move OFLAG_COPIED checks
      qcow2-refcount: Repair OFLAG_COPIED errors
      qcow2-refcount: Repair shared refcount blocks
      qcow2_check: Mark image consistent
      qemu-iotests: Overlapping cluster allocations

Peter Maydell (1):
      block/qcow2.h: Avoid "1LL << 63" (shifts into sign bit)

 block.c                    |   1 -
 block/Makefile.objs        |   2 +-
 block/gluster.c            |  15 +-
 block/qcow2-cache.c        |  17 ++
 block/qcow2-cluster.c      |  25 ++-
 block/qcow2-refcount.c     | 533 ++++++++++++++++++++++++++++++++++++++++-----
 block/qcow2-snapshot.c     |  22 ++
 block/qcow2.c              |  83 ++++++-
 block/qcow2.h              |  53 ++++-
 block/{raw.c => raw_bsd.c} | 170 +++++++--------
 blockdev.c                 | 143 ------------
 docs/specs/qcow2.txt       |   7 +-
 include/block/block.h      |   1 +
 include/monitor/monitor.h  |   1 +
 include/qemu/option.h      |   1 +
 monitor.c                  |   1 +
 scripts/qapi-types.py      |  19 +-
 tests/qemu-iotests/031.out |  12 +-
 tests/qemu-iotests/036.out |   2 +-
 tests/qemu-iotests/051.out |   1 -
 tests/qemu-iotests/060     | 111 ++++++++++
 tests/qemu-iotests/060.out |  44 ++++
 tests/qemu-iotests/062     |  64 ++++++
 tests/qemu-iotests/062.out |   9 +
 tests/qemu-iotests/group   |   4 +-
 util/qemu-option.c         |   9 +
 26 files changed, 1028 insertions(+), 322 deletions(-)
 rename block/{raw.c => raw_bsd.c} (57%)
 create mode 100755 tests/qemu-iotests/060
 create mode 100644 tests/qemu-iotests/060.out
 create mode 100755 tests/qemu-iotests/062
 create mode 100644 tests/qemu-iotests/062.out

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2013-08-30 14:30 Kevin Wolf
@ 2013-08-30 17:14 ` Anthony Liguori
  2013-09-02  8:24   ` Kevin Wolf
  0 siblings, 1 reply; 47+ messages in thread
From: Anthony Liguori @ 2013-08-30 17:14 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

This pull request breaks make check, qemu-system-i386 segvs when
running qtest.  bisect blames the following commit.  I confirmed this
commit introduces the breakage too.

commit 19abade25242079f4b5582de17b2302fe185be2b
Author: Max Reitz <mreitz@redhat.com>
Date:   Fri Aug 30 14:34:29 2013 +0200

    qcow2-refcount: Repair shared refcount blocks

    If the refcount of a refcount block is greater than one, we can at least
    try to repair that problem by duplicating the affected block.

    Signed-off-by: Max Reitz <mreitz@redhat.com>
    Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Backtrace is:

Core was generated by `i386-softmmu/qemu-system-i386 -qtest
unix:/tmp/qtest-30888.sock,nowait -qtest-l'.
Program terminated with signal 11, Segmentation fault.
#0  __strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp.S:259
259    ../sysdeps/x86_64/multiarch/strcmp.S: No such file or directory.
    in ../sysdeps/x86_64/multiarch/strcmp.S
(gdb) bt
#0  __strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp.S:259
#1  0x00002abc7727c395 in get_event_by_name (event=<synthetic pointer>,
    name=0x2abc77e69a96 "flush_to_os")
    at /home/anthony/git/qemu/block/blkdebug.c:195
#2  blkdebug_debug_breakpoint (bs=<optimized out>,
    event=0x2abc77e69a96 "flush_to_os", tag=0x2abc77e69aa2 "A")
    at /home/anthony/git/qemu/block/blkdebug.c:572
#3  0x00002abc773bab84 in break_f (bs=<optimized out>, argc=<optimized out>,
    argv=<optimized out>) at /home/anthony/git/qemu/qemu-io-cmds.c:1938
#4  0x00002abc773be088 in command (argv=0x2abc77e69dc0, argc=3,
    ct=<optimized out>, bs=0x2abc77de35c0)
    at /home/anthony/git/qemu/qemu-io-cmds.c:79
#5  qemuio_command (bs=0x2abc77de35c0, cmd=<optimized out>)
    at /home/anthony/git/qemu/qemu-io-cmds.c:2085
#6  0x00002abc772b8f4d in hmp_qemu_io (mon=0x7fffa0de1110,
    qdict=<optimized out>) at /home/anthony/git/qemu/hmp.c:1510
#7  0x00002abc77469749 in handle_user_command (mon=0x7fffa0de1110,
    cmdline=<optimized out>) at /home/anthony/git/qemu/monitor.c:4005
#8  0x00002abc77469908 in qmp_human_monitor_command (
    command_line=0x2abc77e69a10 "qemu-io ide0-hd0 \"break flush_to_os A\"",
    has_cpu_index=false, cpu_index=<optimized out>, errp=0x7fffa0de11d0)
    at /home/anthony/git/qemu/monitor.c:710
#9  0x00002abc773c29a7 in qmp_marshal_input_human_monitor_command (
---Type <return> to continue, or q <return> to quit---
    mon=<optimized out>, qdict=<optimized out>, ret=0x7fffa0de1240)
    at qmp-marshal.c:1658
#10 0x00002abc774642a0 in qmp_call_cmd (params=0x2abc77e8a370,
    mon=0x2abc77dea430, cmd=<optimized out>)
    at /home/anthony/git/qemu/monitor.c:4506
#11 handle_qmp_command (parser=<optimized out>, tokens=<optimized out>)
    at /home/anthony/git/qemu/monitor.c:4572
#12 0x00002abc774fc2f1 in json_message_process_token (lexer=0x2abc77dea4e0,
    token=0x2abc77e69800, type=JSON_OPERATOR, x=143, y=0)
    at /home/anthony/git/qemu/qobject/json-streamer.c:87
#13 0x00002abc7750ea12 in json_lexer_feed_char (lexer=0x2abc77dea4e0,
    ch=125 '}', flush=false) at /home/anthony/git/qemu/qobject/json-lexer.c:303
#14 0x00002abc7750eba9 in json_lexer_feed (lexer=0x2abc77dea4e0,
    buffer=0x7fffa0de1440 "}nb 0x511\n 0x3\nn ioapic\nNt\"|\274*", size=1)
    at /home/anthony/git/qemu/qobject/json-lexer.c:356
#15 0x00002abc774626fb in monitor_control_read (opaque=<optimized out>,
    buf=<optimized out>, size=<optimized out>)
    at /home/anthony/git/qemu/monitor.c:4593
#16 0x00002abc773b6f87 in qemu_chr_be_write (len=<optimized out>,
    buf=0x7fffa0de1440 "}nb 0x511\n 0x3\nn ioapic\nNt\"|\274*",
    s=0x2abc77ddfbf0) at /home/anthony/git/qemu/qemu-char.c:165
#17 tcp_chr_read (chan=<optimized out>, cond=<optimized out>,
    opaque=0x2abc77ddfbf0) at /home/anthony/git/qemu/qemu-char.c:2509
#18 0x00002abc7840fa5d in g_main_context_dispatch ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#19 0x00002abc7738a671 in glib_pollfds_poll ()
    at /home/anthony/git/qemu/main-loop.c:189
#20 os_host_main_loop_wait (timeout=<optimized out>)
    at /home/anthony/git/qemu/main-loop.c:234
#21 main_loop_wait (nonblocking=<optimized out>)
    at /home/anthony/git/qemu/main-loop.c:484
#22 0x00002abc77260b9a in main_loop () at /home/anthony/git/qemu/vl.c:2090
#23 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>)
    at /home/anthony/git/qemu/vl.c:4435
(gdb)

Regards,

Anthony Liguori


On Fri, Aug 30, 2013 at 9:30 AM, Kevin Wolf <kwolf@redhat.com> wrote:
> The following changes since commit b5d54bd42158b90b239bb6ce9c13072eb3a53fd2:
>
>   Merge remote-tracking branch 'qemu-kvm/uq/master' into stable-1.5 (2013-08-29 17:21:51 -0500)
>
> are available in the git repository at:
>
>
>   git://repo.or.cz/qemu/kevin.git for-anthony
>
> for you to fetch changes up to edcbf2869829001b60b15ad32609138ae784a588:
>
>   qemu-iotests: Overlapping cluster allocations (2013-08-30 15:48:59 +0200)
>
> ----------------------------------------------------------------
> Bharata B Rao (1):
>       gluster: Abort on AIO completion failure
>
> Kevin Wolf (6):
>       qcow2: Change default for new images to compat=1.1
>       block: Remove redundant assertion
>       qapi-types.py: Split off generate_struct_fields()
>       Revert "block: Disable driver-specific options for 1.6"
>       qemu-iotests: Update reference output for 051
>       block: Remove old raw driver
>
> Laszlo Ersek (7):
>       add skeleton for BSD licensed "raw" BlockDriver
>       raw_bsd: emit debug events in bdrv_co_readv() and bdrv_co_writev()
>       raw_bsd: add raw_create()
>       raw_bsd: introduce "special members"
>       raw_bsd: add raw_create_options
>       raw_bsd: register bdrv_raw
>       switch raw block driver from "raw.o" to "raw_bsd.o"
>
> Max Reitz (11):
>       option: Add assigned flag to QEMUOptionParameter
>       qcow2-refcount: Snapshot update for zero clusters
>       qemu-iotests: Snapshotting zero clusters
>       qcow2: Add corrupt bit
>       qcow2: Metadata overlap checks
>       qcow2: Employ metadata overlap checks
>       qcow2-refcount: Move OFLAG_COPIED checks
>       qcow2-refcount: Repair OFLAG_COPIED errors
>       qcow2-refcount: Repair shared refcount blocks
>       qcow2_check: Mark image consistent
>       qemu-iotests: Overlapping cluster allocations
>
> Peter Maydell (1):
>       block/qcow2.h: Avoid "1LL << 63" (shifts into sign bit)
>
>  block.c                    |   1 -
>  block/Makefile.objs        |   2 +-
>  block/gluster.c            |  15 +-
>  block/qcow2-cache.c        |  17 ++
>  block/qcow2-cluster.c      |  25 ++-
>  block/qcow2-refcount.c     | 533 ++++++++++++++++++++++++++++++++++++++++-----
>  block/qcow2-snapshot.c     |  22 ++
>  block/qcow2.c              |  83 ++++++-
>  block/qcow2.h              |  53 ++++-
>  block/{raw.c => raw_bsd.c} | 170 +++++++--------
>  blockdev.c                 | 143 ------------
>  docs/specs/qcow2.txt       |   7 +-
>  include/block/block.h      |   1 +
>  include/monitor/monitor.h  |   1 +
>  include/qemu/option.h      |   1 +
>  monitor.c                  |   1 +
>  scripts/qapi-types.py      |  19 +-
>  tests/qemu-iotests/031.out |  12 +-
>  tests/qemu-iotests/036.out |   2 +-
>  tests/qemu-iotests/051.out |   1 -
>  tests/qemu-iotests/060     | 111 ++++++++++
>  tests/qemu-iotests/060.out |  44 ++++
>  tests/qemu-iotests/062     |  64 ++++++
>  tests/qemu-iotests/062.out |   9 +
>  tests/qemu-iotests/group   |   4 +-
>  util/qemu-option.c         |   9 +
>  26 files changed, 1028 insertions(+), 322 deletions(-)
>  rename block/{raw.c => raw_bsd.c} (57%)
>  create mode 100755 tests/qemu-iotests/060
>  create mode 100644 tests/qemu-iotests/060.out
>  create mode 100755 tests/qemu-iotests/062
>  create mode 100644 tests/qemu-iotests/062.out

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2013-08-30 17:14 ` Anthony Liguori
@ 2013-09-02  8:24   ` Kevin Wolf
  0 siblings, 0 replies; 47+ messages in thread
From: Kevin Wolf @ 2013-09-02  8:24 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

Am 30.08.2013 um 19:14 hat Anthony Liguori geschrieben:
> This pull request breaks make check, qemu-system-i386 segvs when
> running qtest.  bisect blames the following commit.  I confirmed this
> commit introduces the breakage too.
> 
> commit 19abade25242079f4b5582de17b2302fe185be2b
> Author: Max Reitz <mreitz@redhat.com>
> Date:   Fri Aug 30 14:34:29 2013 +0200
> 
>     qcow2-refcount: Repair shared refcount blocks
> 
>     If the refcount of a refcount block is greater than one, we can at least
>     try to repair that problem by duplicating the affected block.
> 
>     Signed-off-by: Max Reitz <mreitz@redhat.com>
>     Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Sorry, seems I messed up here. The shell history shows that I did
run 'make check', but somehow the failure must have escaped my
attention (it's not an assertion failure and we do have some noise
in successful runs, maybe that's why)

The other test case that could have caught it (qemu-iotests 026) has
been broken for ages, and we need to finally fix it.

Thanks for catching this, Anthony. I'll send a v2.

Kevin

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 00/26] Block patches
@ 2014-09-05 16:13 Stefan Hajnoczi
  2014-09-05 16:32 ` Peter Maydell
  0 siblings, 1 reply; 47+ messages in thread
From: Stefan Hajnoczi @ 2014-09-05 16:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Stefan Hajnoczi

The following changes since commit 30eaca3acdf17d7bcbd1213eb149c02037edfb0b:

  Merge remote-tracking branch 'remotes/spice/tags/pull-spice-20140902-1' into staging (2014-09-02 10:26:10 +0100)

are available in the git repository at:


  git://github.com/stefanha/qemu.git tags/block-pull-request

for you to fetch changes up to 804b985da5f781a2ff0a723c1aae520b9ea95f27:

  ide: Add resize callback to ide/core (2014-09-05 10:38:56 +0100)

----------------------------------------------------------------
Block pull request

----------------------------------------------------------------
Chrysostomos Nanakos (1):
      block/archipelago: Use QEMU atomic builtins

Fam Zheng (2):
      virtio: Import virtio_vring.h
      block: Always compile virtio-blk dataplane

John Snow (5):
      libqos: add a simple first-fit memory allocator
      qtest/ide: Uninitialize PC allocator
      ide: Add wwn support to IDE-ATAPI drive
      IDE: Fill the IDENTIFY request consistently
      ide: Add resize callback to ide/core

Laszlo Ersek (2):
      pflash_cfi01: fixup stale DPRINTF() calls
      pflash_cfi01: write flash contents to bdrv on incoming migration

Liu Yuan (1):
      block: kill tail whitespace in block.c

MORITA Kazutaka (1):
      MAINTAINERS: update sheepdog maintainer

Marc Marí (7):
      tests: Functions bus_foreach and device_find from libqos virtio API
      tests: Add virtio device initialization
      libqos: Added basic virtqueue support to virtio implementation
      libqos: Added indirect descriptor support to virtio implementation
      libqos: Added test case for configuration changes in virtio-blk test
      libqos: Added MSI-X support
      libqos: Added EVENT_IDX support

Peter Lieven (3):
      rename parse_enum_option to qapi_enum_parse and make it public
      qemu-nbd: add option to set detect-zeroes mode
      qemu-nbd: fix indentation and coding style

Stefan Hajnoczi (4):
      qemu-img: clarify src_cache option documentation
      qemu-img: fix rebase src_cache option documentation
      vmdk: fix vmdk_parse_extents() extent_file leaks
      vmdk: fix buf leak in vmdk_parse_extents()

 MAINTAINERS                         |   2 +-
 block.c                             |   2 +-
 block/archipelago.c                 |  76 ++---
 block/vmdk.c                        |   4 +-
 blockdev.c                          |  30 +-
 configure                           |  21 +-
 hw/block/Makefile.objs              |   2 +-
 hw/block/pflash_cfi01.c             |  18 +-
 hw/block/virtio-blk.c               |  20 +-
 hw/ide/core.c                       | 111 +++++--
 hw/net/vhost_net.c                  |   2 +-
 hw/virtio/Makefile.objs             |   2 +-
 include/hw/virtio/dataplane/vring.h |   2 +-
 include/hw/virtio/virtio-blk.h      |   2 -
 include/hw/virtio/virtio_ring.h     | 167 ++++++++++
 include/qapi/util.h                 |  17 +
 linux-headers/linux/vhost.h         |   2 +-
 qapi/Makefile.objs                  |   2 +-
 qapi/qapi-util.c                    |  34 ++
 qemu-img.c                          |   3 +-
 qemu-img.texi                       |   7 +-
 qemu-nbd.c                          | 100 ++++--
 tests/Makefile                      |   3 +-
 tests/ide-test.c                    |   2 +
 tests/libqos/malloc-pc.c            | 280 +++++++++++++++-
 tests/libqos/malloc-pc.h            |   9 +
 tests/libqos/pci.c                  | 111 ++++++-
 tests/libqos/pci.h                  |  10 +
 tests/libqos/virtio-pci.c           | 343 +++++++++++++++++++
 tests/libqos/virtio-pci.h           |  61 ++++
 tests/libqos/virtio.c               | 257 +++++++++++++++
 tests/libqos/virtio.h               | 182 ++++++++++
 tests/libqtest.c                    |  48 +++
 tests/libqtest.h                    |   7 +
 tests/virtio-blk-test.c             | 640 +++++++++++++++++++++++++++++++++++-
 35 files changed, 2368 insertions(+), 211 deletions(-)
 create mode 100644 include/hw/virtio/virtio_ring.h
 create mode 100644 include/qapi/util.h
 create mode 100644 qapi/qapi-util.c
 create mode 100644 tests/libqos/virtio-pci.c
 create mode 100644 tests/libqos/virtio-pci.h
 create mode 100644 tests/libqos/virtio.c
 create mode 100644 tests/libqos/virtio.h

-- 
1.9.3

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2014-09-05 16:13 Stefan Hajnoczi
@ 2014-09-05 16:32 ` Peter Maydell
  0 siblings, 0 replies; 47+ messages in thread
From: Peter Maydell @ 2014-09-05 16:32 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: QEMU Developers

On 5 September 2014 17:13, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> The following changes since commit 30eaca3acdf17d7bcbd1213eb149c02037edfb0b:
>
>   Merge remote-tracking branch 'remotes/spice/tags/pull-spice-20140902-1' into staging (2014-09-02 10:26:10 +0100)
>
> are available in the git repository at:
>
>
>   git://github.com/stefanha/qemu.git tags/block-pull-request
>
> for you to fetch changes up to 804b985da5f781a2ff0a723c1aae520b9ea95f27:
>
>   ide: Add resize callback to ide/core (2014-09-05 10:38:56 +0100)
>
> ----------------------------------------------------------------
> Block pull request

Hi. I'm afraid this doesn't build on win32:

/home/petmay01/linaro/qemu-for-merges/hw/virtio/dataplane/vring.c: In
function ‘get_desc’:
/home/petmay01/linaro/qemu-for-merges/hw/virtio/dataplane/vring.c:184:
error: ‘ENOBUFS’ undeclared (first use in this function)
/home/petmay01/linaro/qemu-for-merges/hw/virtio/dataplane/vring.c:184:
error: (Each undeclared identifier is reported only once
/home/petmay01/linaro/qemu-for-merges/hw/virtio/dataplane/vring.c:184:
error: for each function it appears in.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PULL 00/26] Block patches
@ 2015-01-09 10:16 Stefan Hajnoczi
  2015-01-10 19:05 ` Peter Maydell
  0 siblings, 1 reply; 47+ messages in thread
From: Stefan Hajnoczi @ 2015-01-09 10:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Stefan Hajnoczi

This pull request depends on the previous block pull request which has not been
merged yet.  It was sent on Monday, 5th of January (Message-id:
<1420458696-1885-1-git-send-email-stefanha@redhat.com>).

The following changes since commit 3bd54e576f40f1d5bf45b4828c7316efd76a4db6:

  migration/block: fix pending() return value (2015-01-05 11:34:52 +0000)

are available in the git repository at:

  git://github.com/stefanha/qemu.git tags/block-pull-request

for you to fetch changes up to 4cba4284918145de66e27959725559f8aaf764ef:

  NVMe: Set correct VS Value for 1.1 Compliant Controllers (2015-01-09 10:12:23 +0000)

----------------------------------------------------------------

----------------------------------------------------------------

Alex Friedman (1):
  nvme: Fix get/set number of queues feature

Anubhav Rakshit (1):
  NVMe: Set correct VS Value for 1.1 Compliant Controllers

Chrysostomos Nanakos (1):
  MAINTAINERS: Update email addresses for Chrysostomos Nanakos

Fam Zheng (7):
  .gitignore: Ignore generated "common.env"
  qemu-iotests: Replace "/bin/true" with "true"
  qemu-iotests: Add "_supported_os Linux" to 058
  tests/Makefile: Add check-block to make check on Linux
  qemu-iotests: Add supported os parameter for python tests
  block: Split BLOCK_OP_TYPE_COMMIT to BLOCK_OP_TYPE_COMMIT_{SOURCE,
    TARGET}
  MAINTAINERS: Add migration/block* to block subsystem

John Snow (1):
  ide: Implement VPD response for ATAPI

Marc Marí (6):
  libqos: Convert malloc-pc allocator to a generic allocator
  libqos: Change use of pointers to uint64_t in virtio
  tests: Prepare virtio-blk-test for multi-arch implementation
  libqos: Remove PCI assumptions in constants of virtio driver
  libqos: Add malloc generic
  libqos: Add virtio MMIO support

Paolo Bonzini (6):
  coroutine-ucontext: use __thread
  qemu-thread: add per-thread atexit functions
  test-coroutine: avoid overflow on 32-bit systems
  QSLIST: add lock-free operations
  coroutine: rewrite pool to avoid mutex
  coroutine: drop qemu_coroutine_adjust_pool_size

Peter Lieven (2):
  coroutine: try harder not to delete coroutines
  block: limited request size in write zeroes unsupported path

Programmingkid (1):
  block/raw-posix.c: Fixes raw_getlength() on Mac OS X so that it
    reports the correct length of a real CD

 .gitignore                       |   1 +
 MAINTAINERS                      |   2 +-
 block.c                          |  11 +-
 block/block-backend.c            |   4 -
 block/raw-posix.c                |  18 ++-
 blockdev.c                       |   6 +-
 configure                        |   2 +-
 coroutine-ucontext.c             |  69 +++-------
 hw/block/dataplane/virtio-blk.c  |   3 +-
 hw/block/nvme.c                  |   8 +-
 hw/ide/atapi.c                   | 111 ++++++++++++++--
 hw/ide/internal.h                |   1 +
 include/block/block.h            |   3 +-
 include/block/coroutine.h        |  10 --
 include/qemu/queue.h             |  15 ++-
 include/qemu/thread.h            |   4 +
 qemu-coroutine.c                 | 103 +++++++-------
 tests/Makefile                   |   9 +-
 tests/libqos/malloc-generic.c    |  50 +++++++
 tests/libqos/malloc-generic.h    |  21 +++
 tests/libqos/malloc-pc.c         | 280 +--------------------------------------
 tests/libqos/malloc-pc.h         |  11 +-
 tests/libqos/malloc.c            | 270 +++++++++++++++++++++++++++++++++++++
 tests/libqos/malloc.h            |  45 ++++---
 tests/libqos/virtio-mmio.c       | 190 ++++++++++++++++++++++++++
 tests/libqos/virtio-mmio.h       |  46 +++++++
 tests/libqos/virtio-pci.c        |  50 +++----
 tests/libqos/virtio-pci.h        |  24 ++--
 tests/libqos/virtio.c            |   8 +-
 tests/libqos/virtio.h            |  16 +--
 tests/qemu-iotests/058           |   1 +
 tests/qemu-iotests/common.config |   2 +-
 tests/qemu-iotests/common.filter |   2 +-
 tests/qemu-iotests/common.rc     |   2 +-
 tests/qemu-iotests/iotests.py    |   5 +-
 tests/test-coroutine.c           |   2 +-
 tests/virtio-blk-test.c          | 249 +++++++++++++++++++++++-----------
 util/qemu-thread-posix.c         |  37 ++++++
 util/qemu-thread-win32.c         |  48 +++++--
 39 files changed, 1154 insertions(+), 585 deletions(-)
 create mode 100644 tests/libqos/malloc-generic.c
 create mode 100644 tests/libqos/malloc-generic.h
 create mode 100644 tests/libqos/malloc.c
 create mode 100644 tests/libqos/virtio-mmio.c
 create mode 100644 tests/libqos/virtio-mmio.h

-- 
2.1.0

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2015-01-09 10:16 Stefan Hajnoczi
@ 2015-01-10 19:05 ` Peter Maydell
  2015-01-10 19:10   ` Peter Maydell
  2015-01-12 14:25   ` Stefan Hajnoczi
  0 siblings, 2 replies; 47+ messages in thread
From: Peter Maydell @ 2015-01-10 19:05 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: QEMU Developers

On 9 January 2015 at 10:16, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> This pull request depends on the previous block pull request which has not been
> merged yet.  It was sent on Monday, 5th of January (Message-id:
> <1420458696-1885-1-git-send-email-stefanha@redhat.com>).
>
> The following changes since commit 3bd54e576f40f1d5bf45b4828c7316efd76a4db6:
>
>   migration/block: fix pending() return value (2015-01-05 11:34:52 +0000)
>
> are available in the git repository at:
>
>   git://github.com/stefanha/qemu.git tags/block-pull-request
>
> for you to fetch changes up to 4cba4284918145de66e27959725559f8aaf764ef:
>
>   NVMe: Set correct VS Value for 1.1 Compliant Controllers (2015-01-09 10:12:23 +0000)

I'm confused. You say this pull depends on the other one, but
the emails give the same tag name for both, so I can't pull
the other one first. (In fact, if not for this one failing I
would have applied it under the assumption that it *was* the
previous pullreq...)

In any case, this one fails 'make check':

GTESTER check-qtest-arm
WARNING: Image format was not specified for '/tmp/qtest.ZDWVz0' and
probing guessed raw.
         Automatically detecting the format is dangerous for raw
images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
**
ERROR:/home/petmay01/linaro/qemu-for-merges/tests/libqos/virtio.c:91:qvirtio_wait_queue_isr:
assertion failed: (g_get_monotonic_time() - start_time <= timeout_us)
GTester: last random seed: R02Scf242b6e43396cc299f6f06431644f8f
make: *** [check-qtest-arm] Error 1
make: Leaving directory `/home/petmay01/linaro/qemu-for-merges/build/all'

thanks
-- PMM

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2015-01-10 19:05 ` Peter Maydell
@ 2015-01-10 19:10   ` Peter Maydell
  2015-01-12  9:52     ` Fam Zheng
  2015-01-12 14:25   ` Stefan Hajnoczi
  1 sibling, 1 reply; 47+ messages in thread
From: Peter Maydell @ 2015-01-10 19:10 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: QEMU Developers

On 10 January 2015 at 19:05, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 9 January 2015 at 10:16, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>> This pull request depends on the previous block pull request which has not been
>> merged yet.  It was sent on Monday, 5th of January (Message-id:
>> <1420458696-1885-1-git-send-email-stefanha@redhat.com>).
>>
>> The following changes since commit 3bd54e576f40f1d5bf45b4828c7316efd76a4db6:
>>
>>   migration/block: fix pending() return value (2015-01-05 11:34:52 +0000)
>>
>> are available in the git repository at:
>>
>>   git://github.com/stefanha/qemu.git tags/block-pull-request
>>
>> for you to fetch changes up to 4cba4284918145de66e27959725559f8aaf764ef:
>>
>>   NVMe: Set correct VS Value for 1.1 Compliant Controllers (2015-01-09 10:12:23 +0000)
>
> I'm confused. You say this pull depends on the other one, but
> the emails give the same tag name for both, so I can't pull
> the other one first. (In fact, if not for this one failing I
> would have applied it under the assumption that it *was* the
> previous pullreq...)
>
> In any case, this one fails 'make check':

Failed also and differently on my 32 bit ARM board, though that
may just be because I run this set with V=1; last part
of the log below. Looks like something is trying to run
qemu-system-arm without specifying a machine to use...

 === Testing plain filename for blkdebug ===

-blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT

 === Testing plain filename for blkdebug without configuration file ===

-blkdebug::TEST_DIR/t.IMGFMT
 *** done
100                [20:40:41] [20:40:45]
101                [20:40:45] [20:40:45] [not run]
        101 -- not suitable for this image format: qcow2
102                [20:40:45] [20:40:46] [failed, exit status 141] -
output mismatch (see 102.out.bad)
--- /root/qemu/tests/qemu-iotests/102.out       2014-11-03
18:34:23.000000000 +0000
+++ 102.out.bad 2015-01-09 20:40:46.000000000 +0000
@@ -15,7 +15,6 @@
 wrote 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 Image resized.
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qemu-io drv0 map
-[                       0]      128/     128 sectors     allocated at
offset 0 bytes (1)
-*** done
+No machine specified, and there is no default.
+Use -machine help to list supported machines!
+Timeout waiting for allocated on handle 0
103                [20:40:46] [20:40:47]
105                [20:40:47] [20:40:48]
107                [20:40:48] [20:40:49]
108                [20:40:49] [20:40:52]
110                [20:40:52] [20:40:53]
111                [20:40:53] [20:40:53]
113                [20:40:53] [20:40:53] [not run]
        113 -- not suitable for this image format: qcow2
114                [20:40:53] [20:40:54]
Not run: 016 045 059 064 065 070 075 077 078 081 084 088 092 101 113
Failures: 028 067 068 071 087 095 099 102
Failed 8 of 65 tests
make: *** [check-tests/qemu-iotests-quick.sh] Error 1


-- PMM

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2015-01-10 19:10   ` Peter Maydell
@ 2015-01-12  9:52     ` Fam Zheng
  2015-01-12 10:32       ` Paolo Bonzini
  0 siblings, 1 reply; 47+ messages in thread
From: Fam Zheng @ 2015-01-12  9:52 UTC (permalink / raw)
  To: Stefan Hajnoczi, Peter Maydell; +Cc: QEMU Developers

On Sat, 01/10 19:10, Peter Maydell wrote:
> On 10 January 2015 at 19:05, Peter Maydell <peter.maydell@linaro.org> wrote:
> > On 9 January 2015 at 10:16, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> >> This pull request depends on the previous block pull request which has not been
> >> merged yet.  It was sent on Monday, 5th of January (Message-id:
> >> <1420458696-1885-1-git-send-email-stefanha@redhat.com>).
> >>
> >> The following changes since commit 3bd54e576f40f1d5bf45b4828c7316efd76a4db6:
> >>
> >>   migration/block: fix pending() return value (2015-01-05 11:34:52 +0000)
> >>
> >> are available in the git repository at:
> >>
> >>   git://github.com/stefanha/qemu.git tags/block-pull-request
> >>
> >> for you to fetch changes up to 4cba4284918145de66e27959725559f8aaf764ef:
> >>
> >>   NVMe: Set correct VS Value for 1.1 Compliant Controllers (2015-01-09 10:12:23 +0000)
> >
> > I'm confused. You say this pull depends on the other one, but
> > the emails give the same tag name for both, so I can't pull
> > the other one first. (In fact, if not for this one failing I
> > would have applied it under the assumption that it *was* the
> > previous pullreq...)
> >
> > In any case, this one fails 'make check':
> 
> Failed also and differently on my 32 bit ARM board, though that
> may just be because I run this set with V=1; last part
> of the log below. Looks like something is trying to run
> qemu-system-arm without specifying a machine to use...
> 

Ouch! This is something that proves really hard to do.

Stefan, please drop the make check-block series in next revision.

Fam

>  === Testing plain filename for blkdebug ===
> 
> -blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT
> 
>  === Testing plain filename for blkdebug without configuration file ===
> 
> -blkdebug::TEST_DIR/t.IMGFMT
>  *** done
> 100                [20:40:41] [20:40:45]
> 101                [20:40:45] [20:40:45] [not run]
>         101 -- not suitable for this image format: qcow2
> 102                [20:40:45] [20:40:46] [failed, exit status 141] -
> output mismatch (see 102.out.bad)
> --- /root/qemu/tests/qemu-iotests/102.out       2014-11-03
> 18:34:23.000000000 +0000
> +++ 102.out.bad 2015-01-09 20:40:46.000000000 +0000
> @@ -15,7 +15,6 @@
>  wrote 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  Image resized.
> -QEMU X.Y.Z monitor - type 'help' for more information
> -(qemu) qemu-io drv0 map
> -[                       0]      128/     128 sectors     allocated at
> offset 0 bytes (1)
> -*** done
> +No machine specified, and there is no default.
> +Use -machine help to list supported machines!
> +Timeout waiting for allocated on handle 0
> 103                [20:40:46] [20:40:47]
> 105                [20:40:47] [20:40:48]
> 107                [20:40:48] [20:40:49]
> 108                [20:40:49] [20:40:52]
> 110                [20:40:52] [20:40:53]
> 111                [20:40:53] [20:40:53]
> 113                [20:40:53] [20:40:53] [not run]
>         113 -- not suitable for this image format: qcow2
> 114                [20:40:53] [20:40:54]
> Not run: 016 045 059 064 065 070 075 077 078 081 084 088 092 101 113
> Failures: 028 067 068 071 087 095 099 102
> Failed 8 of 65 tests
> make: *** [check-tests/qemu-iotests-quick.sh] Error 1
> 
> 
> -- PMM
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2015-01-12  9:52     ` Fam Zheng
@ 2015-01-12 10:32       ` Paolo Bonzini
  0 siblings, 0 replies; 47+ messages in thread
From: Paolo Bonzini @ 2015-01-12 10:32 UTC (permalink / raw)
  To: Fam Zheng, Stefan Hajnoczi, Peter Maydell; +Cc: QEMU Developers



On 12/01/2015 10:52, Fam Zheng wrote:
> On Sat, 01/10 19:10, Peter Maydell wrote:
>> On 10 January 2015 at 19:05, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> On 9 January 2015 at 10:16, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>>>> This pull request depends on the previous block pull request which has not been
>>>> merged yet.  It was sent on Monday, 5th of January (Message-id:
>>>> <1420458696-1885-1-git-send-email-stefanha@redhat.com>).
>>>>
>>>> The following changes since commit 3bd54e576f40f1d5bf45b4828c7316efd76a4db6:
>>>>
>>>>   migration/block: fix pending() return value (2015-01-05 11:34:52 +0000)
>>>>
>>>> are available in the git repository at:
>>>>
>>>>   git://github.com/stefanha/qemu.git tags/block-pull-request
>>>>
>>>> for you to fetch changes up to 4cba4284918145de66e27959725559f8aaf764ef:
>>>>
>>>>   NVMe: Set correct VS Value for 1.1 Compliant Controllers (2015-01-09 10:12:23 +0000)
>>>
>>> I'm confused. You say this pull depends on the other one, but
>>> the emails give the same tag name for both, so I can't pull
>>> the other one first. (In fact, if not for this one failing I
>>> would have applied it under the assumption that it *was* the
>>> previous pullreq...)
>>>
>>> In any case, this one fails 'make check':
>>
>> Failed also and differently on my 32 bit ARM board, though that
>> may just be because I run this set with V=1; last part
>> of the log below. Looks like something is trying to run
>> qemu-system-arm without specifying a machine to use...
>>
> 
> Ouch! This is something that proves really hard to do.
> 
> Stefan, please drop the make check-block series in next revision.

No need to drop the bug fixes.  One can just drop patch 11
("tests/Makefile: Add check-block to make check on Linux").

Paolo

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PULL 00/26] Block patches
  2015-01-10 19:05 ` Peter Maydell
  2015-01-10 19:10   ` Peter Maydell
@ 2015-01-12 14:25   ` Stefan Hajnoczi
  1 sibling, 0 replies; 47+ messages in thread
From: Stefan Hajnoczi @ 2015-01-12 14:25 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

[-- Attachment #1: Type: text/plain, Size: 1448 bytes --]

On Sat, Jan 10, 2015 at 07:05:47PM +0000, Peter Maydell wrote:
> On 9 January 2015 at 10:16, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> > This pull request depends on the previous block pull request which has not been
> > merged yet.  It was sent on Monday, 5th of January (Message-id:
> > <1420458696-1885-1-git-send-email-stefanha@redhat.com>).
> >
> > The following changes since commit 3bd54e576f40f1d5bf45b4828c7316efd76a4db6:
> >
> >   migration/block: fix pending() return value (2015-01-05 11:34:52 +0000)
> >
> > are available in the git repository at:
> >
> >   git://github.com/stefanha/qemu.git tags/block-pull-request
> >
> > for you to fetch changes up to 4cba4284918145de66e27959725559f8aaf764ef:
> >
> >   NVMe: Set correct VS Value for 1.1 Compliant Controllers (2015-01-09 10:12:23 +0000)
> 
> I'm confused. You say this pull depends on the other one, but
> the emails give the same tag name for both, so I can't pull
> the other one first. (In fact, if not for this one failing I
> would have applied it under the assumption that it *was* the
> previous pullreq...)

I used a script that overwrites the pull request tag.

Sorry for the confusion.  You can look at the "for you to fetch changes
up to 4cba4284918145de66e27959725559f8aaf764ef" lines to identify which
commits are part of each pull request.

I'm resending a new (combined) revision without the make check-block
commit.

Stefan

[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2015-01-12 14:25 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-07 11:58 [Qemu-devel] [PULL 00/26] Block patches Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 01/26] blockdev: reset werror/rerror on drive_del Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 02/26] qemu-io: Remove unused args_command Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 03/26] cutils: Support 'P' and 'E' suffixes in strtosz() Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 04/26] qemu-io: Make cvtnum() a wrapper around strtosz_suffix() Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 05/26] qemu-io: Handle cvtnum() errors in 'alloc' Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 06/26] qemu-io: Don't use global bs in command implementations Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 07/26] qemu-io: Split off commands to qemu-io-cmds.c Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 08/26] qemu-io: Factor out qemuio_command Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 09/26] qemu-io: Move 'help' function Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 10/26] qemu-io: Move 'quit' function Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 11/26] qemu-io: Move qemu_strsep() to cutils.c Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 12/26] qemu-io: Move functions for registering and running commands Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 13/26] qemu-io: Move command_loop() and friends Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 14/26] qemu-io: Move remaining helpers from cmd.c Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 15/26] qemu-io: Interface cleanup Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 16/26] qemu-io: Use the qemu version for -V Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 17/26] Make qemu-io commands available in HMP Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 18/26] blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 19/26] ide-test: Add enum value for DEV Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 20/26] ide: Set BSY bit during FLUSH Stefan Hajnoczi
2013-06-07 12:10   ` Paolo Bonzini
2013-06-07 11:58 ` [Qemu-devel] [PULL 21/26] ide-test: Add FLUSH CACHE test case Stefan Hajnoczi
2013-06-14 17:54   ` Peter Maydell
2013-06-14 18:11     ` Peter Maydell
2013-06-14 18:18       ` Anthony Liguori
2013-06-17 12:45         ` Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 22/26] block: add snapshot info query function bdrv_query_snapshot_info_list() Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 23/26] block: add image info query function bdrv_query_image_info() Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 24/26] qmp: add ImageInfo in BlockDeviceInfo used by query-block Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 25/26] hmp: show ImageInfo in 'info block' Stefan Hajnoczi
2013-06-07 11:58 ` [Qemu-devel] [PULL 26/26] hmp: add parameters device and -v for info block Stefan Hajnoczi
2013-06-17 21:17 ` [Qemu-devel] [PULL 00/26] Block patches Anthony Liguori
  -- strict thread matches above, loose matches on Subject: below --
2015-01-09 10:16 Stefan Hajnoczi
2015-01-10 19:05 ` Peter Maydell
2015-01-10 19:10   ` Peter Maydell
2015-01-12  9:52     ` Fam Zheng
2015-01-12 10:32       ` Paolo Bonzini
2015-01-12 14:25   ` Stefan Hajnoczi
2014-09-05 16:13 Stefan Hajnoczi
2014-09-05 16:32 ` Peter Maydell
2013-08-30 14:30 Kevin Wolf
2013-08-30 17:14 ` Anthony Liguori
2013-09-02  8:24   ` Kevin Wolf
2012-11-14 18:47 Kevin Wolf
2012-11-19  9:12 ` Kevin Wolf
2010-04-23 15:30 Kevin Wolf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).