qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/10] Block patches
@ 2010-08-30 16:32 Kevin Wolf
  2010-09-06 15:07 ` Kevin Wolf
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Wolf @ 2010-08-30 16:32 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 02a89b219039621c940863aa5a9da4fec81a1546:

  isapc: fix segfault. (2010-08-28 08:50:40 +0000)

are available in the git repository at:
  git://repo.or.cz/qemu/kevin.git for-anthony

Andrew de Quincey (1):
      posix-aio-compat: Fix async_conmtext for ioctl

Izumi Tsutsui (1):
      sheepdog: remove unnecessary includes

Kevin Wolf (4):
      virtio: Factor virtqueue_map_sg out
      virtio-blk: Fix migration of queued requests
      block: Fix image re-open in bdrv_commit
      qemu-img rebase: Open new backing file read-only

Laurent Vivier (1):
      nbd: Introduce NBD named exports.

Loïc Minier (1):
      vvfat: fat_chksum(): fix access above array bounds

Miguel Di Ciurcio Filho (2):
      monitor: make 'info snapshots' show only fully available snapshots
      savevm: Generate a name when run without one

 block.c            |   13 ++++--
 block/nbd.c        |   68 +++++++++++++++++++++--------
 block/sheepdog.c   |   10 ----
 block/vvfat.c      |    2 +-
 hw/virtio-blk.c    |    5 ++
 hw/virtio.c        |   38 +++++++++++------
 hw/virtio.h        |    3 +
 nbd.c              |  118 ++++++++++++++++++++++++++++++++++++++++++++++-----
 nbd.h              |    5 ++-
 posix-aio-compat.c |    1 +
 qemu-doc.texi      |    7 +++
 qemu-img.c         |    2 +-
 qemu-nbd.c         |    4 +-
 savevm.c           |   88 ++++++++++++++++++++++++++++-----------
 14 files changed, 276 insertions(+), 88 deletions(-)

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

* Re: [Qemu-devel] [PULL 00/10] Block patches
  2010-08-30 16:32 Kevin Wolf
@ 2010-09-06 15:07 ` Kevin Wolf
  0 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2010-09-06 15:07 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

Am 30.08.2010 18:32, schrieb Kevin Wolf:
> The following changes since commit 02a89b219039621c940863aa5a9da4fec81a1546:
> 
>   isapc: fix segfault. (2010-08-28 08:50:40 +0000)
> 
> are available in the git repository at:
>   git://repo.or.cz/qemu/kevin.git for-anthony
> 
> Andrew de Quincey (1):
>       posix-aio-compat: Fix async_conmtext for ioctl
> 
> Izumi Tsutsui (1):
>       sheepdog: remove unnecessary includes
> 
> Kevin Wolf (4):
>       virtio: Factor virtqueue_map_sg out
>       virtio-blk: Fix migration of queued requests
>       block: Fix image re-open in bdrv_commit
>       qemu-img rebase: Open new backing file read-only
> 
> Laurent Vivier (1):
>       nbd: Introduce NBD named exports.
> 
> Loïc Minier (1):
>       vvfat: fat_chksum(): fix access above array bounds
> 
> Miguel Di Ciurcio Filho (2):
>       monitor: make 'info snapshots' show only fully available snapshots
>       savevm: Generate a name when run without one

Anthony, I think you already pulled the patches for stable-0.13 that I
sent on the same day, but these patches for master still seem to be missing.

Kevin

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2010-11-04 13:15 Kevin Wolf
  0 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2010-11-04 13:15 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 5fc9cfedfa09199e10b5f9b67dcd286bfeae4f7a:

  Fold send_all() wrapper unix_write() into one function (2010-11-03 12:48:09 -0500)

are available in the git repository at:
  git://repo.or.cz/qemu/kevin.git for-anthony

Blue Swirl (1):
      block: avoid a warning on 64 bit hosts with long as int64_t

Kevin Wolf (9):
      scsi-disk: Implement rerror option
      block: Allow bdrv_flush to return errors
      scsi-disk: Complete failed requests in scsi_disk_emulate_command
      scsi-disk: Implement werror for flushes
      vpc: Implement bdrv_flush
      qcow2: Invalidate cache after failed read
      ide: Handle immediate bdrv_aio_flush failure
      virtio-blk: Handle immediate flush failure properly
      scsi-disk: Fix immediate failure of bdrv_aio_*

 block.c                |   21 ++++++-
 block.h                |    2 +-
 block/blkdebug.c       |    4 +-
 block/blkverify.c      |    8 +-
 block/cow.c            |    4 +-
 block/qcow.c           |    4 +-
 block/qcow2-cluster.c  |    1 +
 block/qcow2-refcount.c |    1 +
 block/qcow2.c          |    4 +-
 block/raw-posix.c      |    4 +-
 block/raw-win32.c      |    9 +++-
 block/raw.c            |    4 +-
 block/vdi.c            |    4 +-
 block/vmdk.c           |    4 +-
 block/vpc.c            |   21 ++++---
 block_int.h            |    2 +-
 blockdev.c             |    6 +-
 hw/ide/core.c          |   12 +++-
 hw/scsi-disk.c         |  147 +++++++++++++++++++++++++++++++----------------
 hw/virtio-blk.c        |    2 +-
 20 files changed, 172 insertions(+), 92 deletions(-)

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2011-04-13 12:05 Kevin Wolf
  0 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2011-04-13 12:05 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 9df38c47d01eb1fd7eb9d60ac70a4170e638b4a2:

  target-arm: Detect tininess before rounding for FP operations (2011-04-12 23:33:33 +0200)

are available in the git repository at:
  git://repo.or.cz/qemu/kevin.git for-anthony

Amit Shah (7):
      atapi: Drives can be locked without media present
      atapi: Report correct errors on guest eject request
      atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change
      atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function
      atapi: GESN: Use structs for commonly-used field types
      atapi: GESN: Standardise event response handling for future additions
      atapi: GESN: implement 'media' subcommand

Anthony Liguori (1):
      qed: Add support for zero clusters

Mitnick Lyu (1):
      vpc.c: Use get_option_parameter() does the search

Stefan Hajnoczi (1):
      docs: Describe zero data clusters in QED specification

 block/qed-check.c       |    5 +-
 block/qed-cluster.c     |   31 +++++---
 block/qed.c             |   21 ++++-
 block/qed.h             |   26 ++++++
 block/vpc.c             |    8 +--
 docs/specs/qed_spec.txt |    8 ++
 hw/ide/core.c           |  204 ++++++++++++++++++++++++++++++++++++++++-------
 hw/ide/internal.h       |    6 ++
 8 files changed, 258 insertions(+), 51 deletions(-)

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2012-08-15 13:56 Kevin Wolf
  2012-08-15 19:49 ` Anthony Liguori
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Wolf @ 2012-08-15 13:56 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 03834e22abafbc8dc4052d46a5ccd6dd135a54a3:

  Merge remote-tracking branch 'origin/master' into staging (2012-08-14 15:19:50 -0500)

are available in the git repository at:

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

Corey Bryant (7):
      qemu-char: Add MSG_CMSG_CLOEXEC flag to recvmsg
      qapi: Introduce add-fd, remove-fd, query-fdsets
      block: Prevent detection of /dev/fdset/ as floppy
      block: Convert open calls to qemu_open
      block: Convert close calls to qemu_close
      block: Enable qemu_open/close to work with fd sets
      monitor: Clean up fd sets on monitor disconnect

Kevin Wolf (2):
      block: Flush parent to OS with cache=unsafe
      qemu-iotests: Fix 030 after switch to GenericError

Stefan Priebe (1):
      iscsi: Fix NULL dereferences / races between task completion and abort

 Makefile               |    6 +-
 block.c                |    3 +-
 block/iscsi.c          |   55 ++++-----
 block/raw-posix.c      |   46 ++++----
 block/raw-win32.c      |    6 +-
 block/vdi.c            |    5 +-
 block/vmdk.c           |   25 ++---
 block/vpc.c            |    4 +-
 block/vvfat.c          |   16 ++--
 cutils.c               |    5 +
 monitor.c              |  294 ++++++++++++++++++++++++++++++++++++++++++++++++
 monitor.h              |    5 +
 osdep.c                |  116 +++++++++++++++++++
 qapi-schema.json       |   98 ++++++++++++++++
 qemu-char.c            |   12 ++-
 qemu-common.h          |    2 +
 qemu-tool.c            |   20 ++++
 qemu-user.c            |   20 ++++
 qmp-commands.hx        |  122 ++++++++++++++++++++
 savevm.c               |    4 +-
 tests/Makefile         |    2 +-
 tests/qemu-iotests/030 |    6 +-
 22 files changed, 776 insertions(+), 96 deletions(-)

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

* Re: [Qemu-devel] [PULL 00/10] Block patches
  2012-08-15 13:56 Kevin Wolf
@ 2012-08-15 19:49 ` Anthony Liguori
  0 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-08-15 19:49 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

Kevin Wolf <kwolf@redhat.com> writes:

> The following changes since commit 03834e22abafbc8dc4052d46a5ccd6dd135a54a3:
>
>   Merge remote-tracking branch 'origin/master' into staging (2012-08-14 15:19:50 -0500)
>
> are available in the git repository at:
>
>   http://repo.or.cz/r/qemu/kevin.git for-anthony
>

Pulled. Thanks.

Regards,

Anthony Liguori

> Corey Bryant (7):
>       qemu-char: Add MSG_CMSG_CLOEXEC flag to recvmsg
>       qapi: Introduce add-fd, remove-fd, query-fdsets
>       block: Prevent detection of /dev/fdset/ as floppy
>       block: Convert open calls to qemu_open
>       block: Convert close calls to qemu_close
>       block: Enable qemu_open/close to work with fd sets
>       monitor: Clean up fd sets on monitor disconnect
>
> Kevin Wolf (2):
>       block: Flush parent to OS with cache=unsafe
>       qemu-iotests: Fix 030 after switch to GenericError
>
> Stefan Priebe (1):
>       iscsi: Fix NULL dereferences / races between task completion and abort
>
>  Makefile               |    6 +-
>  block.c                |    3 +-
>  block/iscsi.c          |   55 ++++-----
>  block/raw-posix.c      |   46 ++++----
>  block/raw-win32.c      |    6 +-
>  block/vdi.c            |    5 +-
>  block/vmdk.c           |   25 ++---
>  block/vpc.c            |    4 +-
>  block/vvfat.c          |   16 ++--
>  cutils.c               |    5 +
>  monitor.c              |  294 ++++++++++++++++++++++++++++++++++++++++++++++++
>  monitor.h              |    5 +
>  osdep.c                |  116 +++++++++++++++++++
>  qapi-schema.json       |   98 ++++++++++++++++
>  qemu-char.c            |   12 ++-
>  qemu-common.h          |    2 +
>  qemu-tool.c            |   20 ++++
>  qemu-user.c            |   20 ++++
>  qmp-commands.hx        |  122 ++++++++++++++++++++
>  savevm.c               |    4 +-
>  tests/Makefile         |    2 +-
>  tests/qemu-iotests/030 |    6 +-
>  22 files changed, 776 insertions(+), 96 deletions(-)

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2013-06-04 12:45 Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 01/10] qemu-iotests: fix 054 cluster size help output Kevin Wolf
                   ` (10 more replies)
  0 siblings, 11 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 171392406d8e230d62e5ebf4805f71460854b8ec:

  gtk: don't use g_object_unref on GdkCursor (2013-06-03 16:14:05 -0500)

are available in the git repository at:

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

for you to fetch changes up to 5b91704469c0f801e0219f26458356872c4145ab:

  block: dump snapshot and image info to specified output (2013-06-04 13:56:30 +0200)

----------------------------------------------------------------
Fam Zheng (1):
      block: add block driver read only whitelist

Stefan Hajnoczi (6):
      qemu-iotests: fix 054 cluster size help output
      qemu-iotests: make assert_no_active_block_jobs() common
      qemu-iotests: make cancel_and_wait() common
      qemu-iotests: make compare_images() common
      qemu-iotests: make create_image() common
      block: drop bs_snapshots global variable

Wenchao Xia (3):
      block: move snapshot code in block.c to block/snapshot.c
      block: move qmp and info dump related code to block/qapi.c
      block: dump snapshot and image info to specified output

 block.c                       | 356 ++++------------------------------------
 block/Makefile.objs           |   1 +
 block/qapi.c                  | 366 ++++++++++++++++++++++++++++++++++++++++++
 block/snapshot.c              | 157 ++++++++++++++++++
 blockdev.c                    |   4 +-
 configure                     |  20 ++-
 hw/block/xen_disk.c           |   8 +-
 include/block/block.h         |  31 +---
 include/block/block_int.h     |   1 +
 include/block/qapi.h          |  43 +++++
 include/block/snapshot.h      |  53 ++++++
 qemu-img.c                    | 163 +------------------
 savevm.c                      |  40 ++---
 scripts/create_config         |  11 +-
 tests/qemu-iotests/030        |  99 ++++--------
 tests/qemu-iotests/041        | 181 ++++++++-------------
 tests/qemu-iotests/054.out    |   2 +-
 tests/qemu-iotests/iotests.py |  38 +++++
 18 files changed, 843 insertions(+), 731 deletions(-)
 create mode 100644 block/qapi.c
 create mode 100644 block/snapshot.c
 create mode 100644 include/block/qapi.h
 create mode 100644 include/block/snapshot.h

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

* [Qemu-devel] [PULL 01/10] qemu-iotests: fix 054 cluster size help output
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 02/10] block: add block driver read only whitelist Kevin Wolf
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Commit f3f4d2c09b9cf46903ba38425ec46c44185162bd added a hint to increase
the cluster size when a large image cannot be created.  Test 054 now has
outdated output and fails because the golden output does not match.

This patch updates the 054 golden output.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/054.out | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/054.out b/tests/qemu-iotests/054.out
index 0b2fe30..2f357c2 100644
--- a/tests/qemu-iotests/054.out
+++ b/tests/qemu-iotests/054.out
@@ -1,7 +1,7 @@
 QA output created by 054
 
 creating too large image (1 EB)
-qemu-img: The image size is too large for file format 'qcow2'
+qemu-img: The image size is too large for file format 'qcow2' (try using a larger cluster size)
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976 
 
 creating too large image (1 EB) using qcow2.py
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 02/10] block: add block driver read only whitelist
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 01/10] qemu-iotests: fix 054 cluster size help output Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 03/10] qemu-iotests: make assert_no_active_block_jobs() common Kevin Wolf
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

We may want to include a driver in the whitelist for read only tasks
such as diagnosing or exporting guest data (with libguestfs as a good
example). This patch introduces a readonly whitelist option, and for
backward compatibility, the old configure option --block-drv-whitelist
is now an alias to rw whitelist.

Drivers in readonly list is only permitted to open file readonly, and
returns -ENOTSUP for RW opening.

E.g. To include vmdk readonly, and others read+write:
    ./configure --target-list=x86_64-softmmu \
                --block-drv-rw-whitelist=qcow2,raw,file,qed \
                --block-drv-ro-whitelist=vmdk

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c               | 43 +++++++++++++++++++++++++++----------------
 blockdev.c            |  4 ++--
 configure             | 20 +++++++++++++++-----
 hw/block/xen_disk.c   |  8 ++++++--
 include/block/block.h |  3 ++-
 scripts/create_config | 11 +++++++++--
 6 files changed, 61 insertions(+), 28 deletions(-)

diff --git a/block.c b/block.c
index 3f87489..65c0b60 100644
--- a/block.c
+++ b/block.c
@@ -328,28 +328,40 @@ BlockDriver *bdrv_find_format(const char *format_name)
     return NULL;
 }
 
-static int bdrv_is_whitelisted(BlockDriver *drv)
+static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
 {
-    static const char *whitelist[] = {
-        CONFIG_BDRV_WHITELIST
+    static const char *whitelist_rw[] = {
+        CONFIG_BDRV_RW_WHITELIST
+    };
+    static const char *whitelist_ro[] = {
+        CONFIG_BDRV_RO_WHITELIST
     };
     const char **p;
 
-    if (!whitelist[0])
+    if (!whitelist_rw[0] && !whitelist_ro[0]) {
         return 1;               /* no whitelist, anything goes */
+    }
 
-    for (p = whitelist; *p; p++) {
+    for (p = whitelist_rw; *p; p++) {
         if (!strcmp(drv->format_name, *p)) {
             return 1;
         }
     }
+    if (read_only) {
+        for (p = whitelist_ro; *p; p++) {
+            if (!strcmp(drv->format_name, *p)) {
+                return 1;
+            }
+        }
+    }
     return 0;
 }
 
-BlockDriver *bdrv_find_whitelisted_format(const char *format_name)
+BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
+                                          bool read_only)
 {
     BlockDriver *drv = bdrv_find_format(format_name);
-    return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
+    return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL;
 }
 
 typedef struct CreateCo {
@@ -684,10 +696,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
 
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        return -ENOTSUP;
-    }
-
     /* bdrv_open() with directly using a protocol as drv. This layer is already
      * opened, so assign it to bs (while file becomes a closed BlockDriverState)
      * and return immediately. */
@@ -698,9 +706,15 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     bs->open_flags = flags;
     bs->buffer_alignment = 512;
+    open_flags = bdrv_open_flags(bs, flags);
+    bs->read_only = !(open_flags & BDRV_O_RDWR);
+
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
+        return -ENOTSUP;
+    }
 
     assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */
-    if ((flags & BDRV_O_RDWR) && (flags & BDRV_O_COPY_ON_READ)) {
+    if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) {
         bdrv_enable_copy_on_read(bs);
     }
 
@@ -714,9 +728,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     bs->opaque = g_malloc0(drv->instance_size);
 
     bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB);
-    open_flags = bdrv_open_flags(bs, flags);
-
-    bs->read_only = !(open_flags & BDRV_O_RDWR);
 
     /* Open the image, either directly or using a protocol */
     if (drv->bdrv_file_open) {
@@ -801,7 +812,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
     /* Find the right block driver */
     drvname = qdict_get_try_str(options, "driver");
     if (drvname) {
-        drv = bdrv_find_whitelisted_format(drvname);
+        drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
         qdict_del(options, "driver");
     } else if (filename) {
         drv = bdrv_find_protocol(filename);
diff --git a/blockdev.c b/blockdev.c
index d1ec99a..b9b2d10 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -477,7 +477,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
             error_printf("\n");
             return NULL;
         }
-        drv = bdrv_find_whitelisted_format(buf);
+        drv = bdrv_find_whitelisted_format(buf, ro);
         if (!drv) {
             error_report("'%s' invalid format", buf);
             return NULL;
@@ -1096,7 +1096,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
     }
 
     if (format) {
-        drv = bdrv_find_whitelisted_format(format);
+        drv = bdrv_find_whitelisted_format(format, bs->read_only);
         if (!drv) {
             error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
             return;
diff --git a/configure b/configure
index 70c41b0..1654413 100755
--- a/configure
+++ b/configure
@@ -123,7 +123,8 @@ interp_prefix="/usr/gnemul/qemu-%M"
 static="no"
 cross_prefix=""
 audio_drv_list=""
-block_drv_whitelist=""
+block_drv_rw_whitelist=""
+block_drv_ro_whitelist=""
 host_cc="cc"
 libs_softmmu=""
 libs_tools=""
@@ -708,7 +709,9 @@ for opt do
   ;;
   --audio-drv-list=*) audio_drv_list="$optarg"
   ;;
-  --block-drv-whitelist=*) block_drv_whitelist=`echo "$optarg" | sed -e 's/,/ /g'`
+  --block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=`echo "$optarg" | sed -e 's/,/ /g'`
+  ;;
+  --block-drv-ro-whitelist=*) block_drv_ro_whitelist=`echo "$optarg" | sed -e 's/,/ /g'`
   ;;
   --enable-debug-tcg) debug_tcg="yes"
   ;;
@@ -1049,7 +1052,12 @@ echo "  --disable-cocoa          disable Cocoa (Mac OS X only)"
 echo "  --enable-cocoa           enable Cocoa (default on Mac OS X)"
 echo "  --audio-drv-list=LIST    set audio drivers list:"
 echo "                           Available drivers: $audio_possible_drivers"
-echo "  --block-drv-whitelist=L  set block driver whitelist"
+echo "  --block-drv-whitelist=L  Same as --block-drv-rw-whitelist=L"
+echo "  --block-drv-rw-whitelist=L"
+echo "                           set block driver read-write whitelist"
+echo "                           (affects only QEMU, not qemu-img)"
+echo "  --block-drv-ro-whitelist=L"
+echo "                           set block driver read-only whitelist"
 echo "                           (affects only QEMU, not qemu-img)"
 echo "  --enable-mixemu          enable mixer emulation"
 echo "  --disable-xen            disable xen backend driver support"
@@ -3481,7 +3489,8 @@ echo "curses support    $curses"
 echo "curl support      $curl"
 echo "mingw32 support   $mingw32"
 echo "Audio drivers     $audio_drv_list"
-echo "Block whitelist   $block_drv_whitelist"
+echo "Block whitelist (rw) $block_drv_rw_whitelist"
+echo "Block whitelist (ro) $block_drv_ro_whitelist"
 echo "Mixer emulation   $mixemu"
 echo "VirtFS support    $virtfs"
 echo "VNC support       $vnc"
@@ -3662,7 +3671,8 @@ fi
 if test "$audio_win_int" = "yes" ; then
   echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak
 fi
-echo "CONFIG_BDRV_WHITELIST=$block_drv_whitelist" >> $config_host_mak
+echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak
+echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak
 if test "$mixemu" = "yes" ; then
   echo "CONFIG_MIXEMU=y" >> $config_host_mak
 fi
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 0ac65d4..247f32f 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -780,11 +780,13 @@ static int blk_connect(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
     int pers, index, qflags;
+    bool readonly = true;
 
     /* read-only ? */
     qflags = BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
     if (strcmp(blkdev->mode, "w") == 0) {
         qflags |= BDRV_O_RDWR;
+        readonly = false;
     }
 
     /* init qemu block driver */
@@ -795,8 +797,10 @@ static int blk_connect(struct XenDevice *xendev)
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
         blkdev->bs = bdrv_new(blkdev->dev);
         if (blkdev->bs) {
-            if (bdrv_open(blkdev->bs, blkdev->filename, NULL, qflags,
-                        bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) {
+            BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
+                                                           readonly);
+            if (bdrv_open(blkdev->bs,
+                          blkdev->filename, NULL, qflags, drv) != 0) {
                 bdrv_delete(blkdev->bs);
                 blkdev->bs = NULL;
             }
diff --git a/include/block/block.h b/include/block/block.h
index 1251c5c..5604418 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -124,7 +124,8 @@ void bdrv_init(void);
 void bdrv_init_with_whitelist(void);
 BlockDriver *bdrv_find_protocol(const char *filename);
 BlockDriver *bdrv_find_format(const char *format_name);
-BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
+BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
+                                          bool readonly);
 int bdrv_create(BlockDriver *drv, const char* filename,
     QEMUOptionParameter *options);
 int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
diff --git a/scripts/create_config b/scripts/create_config
index c471e8c..258513a 100755
--- a/scripts/create_config
+++ b/scripts/create_config
@@ -34,8 +34,15 @@ case $line in
     done
     echo ""
     ;;
- CONFIG_BDRV_WHITELIST=*)
-    echo "#define CONFIG_BDRV_WHITELIST \\"
+ CONFIG_BDRV_RW_WHITELIST=*)
+    echo "#define CONFIG_BDRV_RW_WHITELIST\\"
+    for drv in ${line#*=}; do
+      echo "    \"${drv}\",\\"
+    done
+    echo "    NULL"
+    ;;
+ CONFIG_BDRV_RO_WHITELIST=*)
+    echo "#define CONFIG_BDRV_RO_WHITELIST\\"
     for drv in ${line#*=}; do
       echo "    \"${drv}\",\\"
     done
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 03/10] qemu-iotests: make assert_no_active_block_jobs() common
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 01/10] qemu-iotests: fix 054 cluster size help output Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 02/10] block: add block driver read only whitelist Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 04/10] qemu-iotests: make cancel_and_wait() common Kevin Wolf
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Tests 030 and 041 both use query-block-jobs to check whether any block
jobs are active.  Make this code common so that 'drive-backup' and other
new feature tests will be able to reuse it.

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/030        | 54 ++++++++++++++++++--------------------
 tests/qemu-iotests/041        | 60 ++++++++++++++++++++-----------------------
 tests/qemu-iotests/iotests.py |  4 +++
 3 files changed, 57 insertions(+), 61 deletions(-)

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index dd4ef11..03dd6a6 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -31,10 +31,6 @@ test_img = os.path.join(iotests.test_dir, 'test.img')
 class ImageStreamingTestCase(iotests.QMPTestCase):
     '''Abstract base class for image streaming test cases'''
 
-    def assert_no_active_streams(self):
-        result = self.vm.qmp('query-block-jobs')
-        self.assert_qmp(result, 'return', [])
-
     def cancel_and_wait(self, drive='drive0'):
         '''Cancel a block job and wait for it to finish'''
         result = self.vm.qmp('block-job-cancel', device=drive)
@@ -48,7 +44,7 @@ class ImageStreamingTestCase(iotests.QMPTestCase):
                     self.assert_qmp(event, 'data/device', drive)
                     cancelled = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
     def create_image(self, name, size):
         file = open(name, 'w')
@@ -77,7 +73,7 @@ class TestSingleDrive(ImageStreamingTestCase):
         os.remove(backing_img)
 
     def test_stream(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -92,7 +88,7 @@ class TestSingleDrive(ImageStreamingTestCase):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
         self.assertEqual(qemu_io('-c', 'map', backing_img),
@@ -100,7 +96,7 @@ class TestSingleDrive(ImageStreamingTestCase):
                          'image file map does not match backing file after streaming')
 
     def test_stream_pause(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -129,7 +125,7 @@ class TestSingleDrive(ImageStreamingTestCase):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
         self.assertEqual(qemu_io('-c', 'map', backing_img),
@@ -137,7 +133,7 @@ class TestSingleDrive(ImageStreamingTestCase):
                          'image file map does not match backing file after streaming')
 
     def test_stream_partial(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
         self.assert_qmp(result, 'return', {})
@@ -152,7 +148,7 @@ class TestSingleDrive(ImageStreamingTestCase):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
         self.assertEqual(qemu_io('-c', 'map', mid_img),
@@ -177,7 +173,7 @@ class TestSmallerBackingFile(ImageStreamingTestCase):
     # If this hangs, then you are missing a fix to complete streaming when the
     # end of the backing file is reached.
     def test_stream(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -192,7 +188,7 @@ class TestSmallerBackingFile(ImageStreamingTestCase):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
 class TestErrors(ImageStreamingTestCase):
@@ -243,7 +239,7 @@ class TestEIO(TestErrors):
         os.remove(self.blkdebug_file)
 
     def test_report(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -265,11 +261,11 @@ class TestEIO(TestErrors):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
     def test_ignore(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
         self.assert_qmp(result, 'return', {})
@@ -293,11 +289,11 @@ class TestEIO(TestErrors):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
     def test_stop(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
         self.assert_qmp(result, 'return', {})
@@ -331,11 +327,11 @@ class TestEIO(TestErrors):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
     def test_enospc(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
         self.assert_qmp(result, 'return', {})
@@ -357,7 +353,7 @@ class TestEIO(TestErrors):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
 class TestENOSPC(TestErrors):
@@ -379,7 +375,7 @@ class TestENOSPC(TestErrors):
         os.remove(self.blkdebug_file)
 
     def test_enospc(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
         self.assert_qmp(result, 'return', {})
@@ -413,7 +409,7 @@ class TestENOSPC(TestErrors):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
 class TestStreamStop(ImageStreamingTestCase):
@@ -431,7 +427,7 @@ class TestStreamStop(ImageStreamingTestCase):
         os.remove(backing_img)
 
     def test_stream_stop(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -459,7 +455,7 @@ class TestSetSpeed(ImageStreamingTestCase):
     # This is a short performance test which is not run by default.
     # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
     def perf_test_throughput(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -477,10 +473,10 @@ class TestSetSpeed(ImageStreamingTestCase):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
     def test_set_speed(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
@@ -511,12 +507,12 @@ class TestSetSpeed(ImageStreamingTestCase):
         self.cancel_and_wait()
 
     def test_set_speed_invalid(self):
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', speed=-1)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
-        self.assert_no_active_streams()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 720eeff..ff89427 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -32,10 +32,6 @@ target_img = os.path.join(iotests.test_dir, 'target.img')
 class ImageMirroringTestCase(iotests.QMPTestCase):
     '''Abstract base class for image mirroring test cases'''
 
-    def assert_no_active_mirrors(self):
-        result = self.vm.qmp('query-block-jobs')
-        self.assert_qmp(result, 'return', [])
-
     def cancel_and_wait(self, drive='drive0', wait_ready=True):
         '''Cancel a block job and wait for it to finish'''
         if wait_ready:
@@ -64,7 +60,7 @@ class ImageMirroringTestCase(iotests.QMPTestCase):
                         self.assert_qmp(event, 'data/len', self.image_len)
                     cancelled = True
 
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
     def complete_and_wait(self, drive='drive0', wait_ready=True):
         '''Complete a block job and wait for it to finish'''
@@ -91,7 +87,7 @@ class ImageMirroringTestCase(iotests.QMPTestCase):
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
     def create_image(self, name, size):
         file = open(name, 'w')
@@ -142,7 +138,7 @@ class TestSingleDrive(ImageMirroringTestCase):
             pass
 
     def test_complete(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -156,7 +152,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_cancel(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -168,7 +164,7 @@ class TestSingleDrive(ImageMirroringTestCase):
         self.vm.shutdown()
 
     def test_cancel_after_ready(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -182,7 +178,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_pause(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -208,7 +204,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_small_buffer(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         # A small buffer is rounded up automatically
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
@@ -223,7 +219,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_small_buffer2(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,size=%d'
                         % (TestSingleDrive.image_len, TestSingleDrive.image_len), target_img)
@@ -239,7 +235,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_large_cluster(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s'
                         % (TestSingleDrive.image_len, backing_img), target_img)
@@ -294,7 +290,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
         os.remove(target_img)
 
     def test_complete(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img)
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
@@ -309,7 +305,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_cancel(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img)
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
@@ -324,7 +320,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_large_cluster(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         # qemu-img create fails if the image is not there
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'size=%d'
@@ -365,7 +361,7 @@ class TestMirrorResized(ImageMirroringTestCase):
             pass
 
     def test_complete_top(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='top',
                              target=target_img)
@@ -379,7 +375,7 @@ class TestMirrorResized(ImageMirroringTestCase):
                         'target image does not match source after mirroring')
 
     def test_complete_full(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -443,7 +439,7 @@ new_state = "1"
         os.remove(self.blkdebug_file)
 
     def test_report_read(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -467,11 +463,11 @@ new_state = "1"
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
     def test_ignore_read(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img, on_source_error='ignore')
@@ -487,7 +483,7 @@ new_state = "1"
         self.vm.shutdown()
 
     def test_large_cluster(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         # Test COW into the target image.  The first half of the
         # cluster at MIRROR_GRANULARITY has to be copied from
@@ -513,7 +509,7 @@ new_state = "1"
                         'target image does not match source after mirroring')
 
     def test_stop_read(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img, on_source_error='stop')
@@ -544,7 +540,7 @@ new_state = "1"
         self.assert_qmp(result, 'return[0]/io-status', 'ok')
 
         self.complete_and_wait(wait_ready=False)
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
 class TestWriteErrors(ImageMirroringTestCase):
@@ -594,7 +590,7 @@ new_state = "1"
         os.remove(self.blkdebug_file)
 
     def test_report_write(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              mode='existing', target=self.target_img)
@@ -618,11 +614,11 @@ new_state = "1"
                     self.assert_qmp(event, 'data/len', self.image_len)
                     completed = True
 
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
     def test_ignore_write(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              mode='existing', target=self.target_img,
@@ -639,7 +635,7 @@ new_state = "1"
         self.vm.shutdown()
 
     def test_stop_write(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              mode='existing', target=self.target_img,
@@ -671,7 +667,7 @@ new_state = "1"
                     ready = True
 
         self.complete_and_wait(wait_ready=False)
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
 class TestSetSpeed(ImageMirroringTestCase):
@@ -690,7 +686,7 @@ class TestSetSpeed(ImageMirroringTestCase):
         os.remove(target_img)
 
     def test_set_speed(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
@@ -723,13 +719,13 @@ class TestSetSpeed(ImageMirroringTestCase):
         self.cancel_and_wait()
 
     def test_set_speed_invalid(self):
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img, speed=-1)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
-        self.assert_no_active_mirrors()
+        self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
                              target=target_img)
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 569ca3d..0e7862c 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -170,6 +170,10 @@ class QMPTestCase(unittest.TestCase):
         result = self.dictpath(d, path)
         self.assertEqual(result, value, 'values not equal "%s" and "%s"' % (str(result), str(value)))
 
+    def assert_no_active_block_jobs(self):
+        result = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(result, 'return', [])
+
 def notrun(reason):
     '''Skip this test suite'''
     # Each test in qemu-iotests has a number ("seq")
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 04/10] qemu-iotests: make cancel_and_wait() common
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (2 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 03/10] qemu-iotests: make assert_no_active_block_jobs() common Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 05/10] qemu-iotests: make compare_images() common Kevin Wolf
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

The cancel_and_wait() function has been duplicated in 030 and 041.  Move
it into iotests.py and let it return the event so tests can perform
additional asserts.

Note that 041's cancel_and_wait(wait_ready=True) is replaced by
wait_ready_and_cancel(), which uses the new wait_ready() and
cancel_and_wait() underneath.

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/030        | 15 -----------
 tests/qemu-iotests/041        | 58 +++++++++++++++----------------------------
 tests/qemu-iotests/iotests.py | 18 ++++++++++++++
 3 files changed, 38 insertions(+), 53 deletions(-)

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 03dd6a6..1f55095 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -31,21 +31,6 @@ test_img = os.path.join(iotests.test_dir, 'test.img')
 class ImageStreamingTestCase(iotests.QMPTestCase):
     '''Abstract base class for image streaming test cases'''
 
-    def cancel_and_wait(self, drive='drive0'):
-        '''Cancel a block job and wait for it to finish'''
-        result = self.vm.qmp('block-job-cancel', device=drive)
-        self.assert_qmp(result, 'return', {})
-
-        cancelled = False
-        while not cancelled:
-            for event in self.vm.get_qmp_events(wait=True):
-                if event['event'] == 'BLOCK_JOB_CANCELLED':
-                    self.assert_qmp(event, 'data/type', 'stream')
-                    self.assert_qmp(event, 'data/device', drive)
-                    cancelled = True
-
-        self.assert_no_active_block_jobs()
-
     def create_image(self, name, size):
         file = open(name, 'w')
         i = 0
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index ff89427..c4ce75e 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -32,46 +32,28 @@ target_img = os.path.join(iotests.test_dir, 'target.img')
 class ImageMirroringTestCase(iotests.QMPTestCase):
     '''Abstract base class for image mirroring test cases'''
 
-    def cancel_and_wait(self, drive='drive0', wait_ready=True):
-        '''Cancel a block job and wait for it to finish'''
-        if wait_ready:
-            ready = False
-            while not ready:
-                for event in self.vm.get_qmp_events(wait=True):
-                    if event['event'] == 'BLOCK_JOB_READY':
-                        self.assert_qmp(event, 'data/type', 'mirror')
-                        self.assert_qmp(event, 'data/device', drive)
-                        ready = True
-
-        result = self.vm.qmp('block-job-cancel', device=drive,
-                             force=not wait_ready)
-        self.assert_qmp(result, 'return', {})
-
-        cancelled = False
-        while not cancelled:
+    def wait_ready(self, drive='drive0'):
+        '''Wait until a block job BLOCK_JOB_READY event'''
+        ready = False
+        while not ready:
             for event in self.vm.get_qmp_events(wait=True):
-                if event['event'] == 'BLOCK_JOB_COMPLETED' or \
-                   event['event'] == 'BLOCK_JOB_CANCELLED':
+                if event['event'] == 'BLOCK_JOB_READY':
                     self.assert_qmp(event, 'data/type', 'mirror')
                     self.assert_qmp(event, 'data/device', drive)
-                    if wait_ready:
-                        self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
-                        self.assert_qmp(event, 'data/offset', self.image_len)
-                        self.assert_qmp(event, 'data/len', self.image_len)
-                    cancelled = True
+                    ready = True
 
-        self.assert_no_active_block_jobs()
+    def wait_ready_and_cancel(self, drive='drive0'):
+        self.wait_ready(drive)
+        event = self.cancel_and_wait()
+        self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
+        self.assert_qmp(event, 'data/type', 'mirror')
+        self.assert_qmp(event, 'data/offset', self.image_len)
+        self.assert_qmp(event, 'data/len', self.image_len)
 
     def complete_and_wait(self, drive='drive0', wait_ready=True):
         '''Complete a block job and wait for it to finish'''
         if wait_ready:
-            ready = False
-            while not ready:
-                for event in self.vm.get_qmp_events(wait=True):
-                    if event['event'] == 'BLOCK_JOB_READY':
-                        self.assert_qmp(event, 'data/type', 'mirror')
-                        self.assert_qmp(event, 'data/device', drive)
-                        ready = True
+            self.wait_ready()
 
         result = self.vm.qmp('block-job-complete', device=drive)
         self.assert_qmp(result, 'return', {})
@@ -158,7 +140,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                              target=target_img)
         self.assert_qmp(result, 'return', {})
 
-        self.cancel_and_wait(wait_ready=False)
+        self.cancel_and_wait(force=True)
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', test_img)
         self.vm.shutdown()
@@ -170,7 +152,7 @@ class TestSingleDrive(ImageMirroringTestCase):
                              target=target_img)
         self.assert_qmp(result, 'return', {})
 
-        self.cancel_and_wait()
+        self.wait_ready_and_cancel()
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', test_img)
         self.vm.shutdown()
@@ -312,7 +294,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
                              mode='existing', target=target_img)
         self.assert_qmp(result, 'return', {})
 
-        self.cancel_and_wait()
+        self.wait_ready_and_cancel()
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', test_img)
         self.vm.shutdown()
@@ -705,7 +687,7 @@ class TestSetSpeed(ImageMirroringTestCase):
         self.assert_qmp(result, 'return[0]/device', 'drive0')
         self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
 
-        self.cancel_and_wait()
+        self.wait_ready_and_cancel()
 
         # Check setting speed in drive-mirror works
         result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
@@ -716,7 +698,7 @@ class TestSetSpeed(ImageMirroringTestCase):
         self.assert_qmp(result, 'return[0]/device', 'drive0')
         self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
 
-        self.cancel_and_wait()
+        self.wait_ready_and_cancel()
 
     def test_set_speed_invalid(self):
         self.assert_no_active_block_jobs()
@@ -734,7 +716,7 @@ class TestSetSpeed(ImageMirroringTestCase):
         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
-        self.cancel_and_wait()
+        self.wait_ready_and_cancel()
 
 if __name__ == '__main__':
     iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 0e7862c..bc9c71b 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -174,6 +174,24 @@ class QMPTestCase(unittest.TestCase):
         result = self.vm.qmp('query-block-jobs')
         self.assert_qmp(result, 'return', [])
 
+    def cancel_and_wait(self, drive='drive0', force=False):
+        '''Cancel a block job and wait for it to finish, returning the event'''
+        result = self.vm.qmp('block-job-cancel', device=drive, force=force)
+        self.assert_qmp(result, 'return', {})
+
+        cancelled = False
+        result = None
+        while not cancelled:
+            for event in self.vm.get_qmp_events(wait=True):
+                if event['event'] == 'BLOCK_JOB_COMPLETED' or \
+                   event['event'] == 'BLOCK_JOB_CANCELLED':
+                    self.assert_qmp(event, 'data/device', drive)
+                    result = event
+                    cancelled = True
+
+        self.assert_no_active_block_jobs()
+        return result
+
 def notrun(reason):
     '''Skip this test suite'''
     # Each test in qemu-iotests has a number ("seq")
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 05/10] qemu-iotests: make compare_images() common
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (3 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 04/10] qemu-iotests: make cancel_and_wait() common Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 06/10] qemu-iotests: make create_image() common Kevin Wolf
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

The iotests.compare_images() function returns True if two image files
have the identical data.  Previously this was implemented by converting
images to raw and then comparing their contents using Python.  Since
"qemu-img compare" is now available and is more efficient, switch to it.

This function will be reused by the 'drive-backup' test case.

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/041        | 41 ++++++++++-------------------------------
 tests/qemu-iotests/iotests.py |  5 +++++
 2 files changed, 15 insertions(+), 31 deletions(-)

diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index c4ce75e..7702074 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -80,27 +80,6 @@ class ImageMirroringTestCase(iotests.QMPTestCase):
             i = i + 512
         file.close()
 
-    def compare_images(self, img1, img2):
-        try:
-            qemu_img('convert', '-f', iotests.imgfmt, '-O', 'raw', img1, img1 + '.raw')
-            qemu_img('convert', '-f', iotests.imgfmt, '-O', 'raw', img2, img2 + '.raw')
-            file1 = open(img1 + '.raw', 'r')
-            file2 = open(img2 + '.raw', 'r')
-            return file1.read() == file2.read()
-        finally:
-            if file1 is not None:
-                file1.close()
-            if file2 is not None:
-                file2.close()
-            try:
-                os.remove(img1 + '.raw')
-            except OSError:
-                pass
-            try:
-                os.remove(img2 + '.raw')
-            except OSError:
-                pass
-
 class TestSingleDrive(ImageMirroringTestCase):
     image_len = 1 * 1024 * 1024 # MB
 
@@ -130,7 +109,7 @@ class TestSingleDrive(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', target_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_cancel(self):
@@ -156,7 +135,7 @@ class TestSingleDrive(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', test_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_pause(self):
@@ -182,7 +161,7 @@ class TestSingleDrive(ImageMirroringTestCase):
 
         self.complete_and_wait()
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_small_buffer(self):
@@ -197,7 +176,7 @@ class TestSingleDrive(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', target_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_small_buffer2(self):
@@ -213,7 +192,7 @@ class TestSingleDrive(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', target_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_large_cluster(self):
@@ -229,7 +208,7 @@ class TestSingleDrive(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', target_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_medium_not_found(self):
@@ -256,7 +235,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
 
     def compare_images(self, img1, img2):
         self.create_image(target_backing_img, TestMirrorNoBacking.image_len)
-        return ImageMirroringTestCase.compare_images(self, img1, img2)
+        return iotests.compare_images(img1, img2)
 
     def setUp(self):
         self.create_image(backing_img, TestMirrorNoBacking.image_len)
@@ -353,7 +332,7 @@ class TestMirrorResized(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', target_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_complete_full(self):
@@ -367,7 +346,7 @@ class TestMirrorResized(ImageMirroringTestCase):
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/file', target_img)
         self.vm.shutdown()
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
 class TestReadErrors(ImageMirroringTestCase):
@@ -487,7 +466,7 @@ new_state = "1"
 
         # Detach blkdebug to compare images successfully
         qemu_img('rebase', '-f', iotests.imgfmt, '-u', '-b', backing_img, test_img)
-        self.assertTrue(self.compare_images(test_img, target_img),
+        self.assertTrue(iotests.compare_images(test_img, target_img),
                         'target image does not match source after mirroring')
 
     def test_stop_read(self):
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index bc9c71b..733b82b 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -51,6 +51,11 @@ def qemu_io(*args):
     args = qemu_io_args + list(args)
     return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
 
+def compare_images(img1, img2):
+    '''Return True if two image files are identical'''
+    return qemu_img('compare', '-f', imgfmt,
+                    '-F', imgfmt, img1, img2) == 0
+
 class VM(object):
     '''A QEMU VM'''
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 06/10] qemu-iotests: make create_image() common
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (4 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 05/10] qemu-iotests: make compare_images() common Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 07/10] block: drop bs_snapshots global variable Kevin Wolf
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Both 030 and 041 use create_image().  Move it to iotests.py.

Also drop ImageStreamingTestCase since the class now has no methods.

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/030        | 32 +++++++++-----------------------
 tests/qemu-iotests/041        | 24 +++++++-----------------
 tests/qemu-iotests/iotests.py | 11 +++++++++++
 3 files changed, 27 insertions(+), 40 deletions(-)

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 1f55095..ae56f3b 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -22,30 +22,16 @@ import time
 import os
 import iotests
 from iotests import qemu_img, qemu_io
-import struct
 
 backing_img = os.path.join(iotests.test_dir, 'backing.img')
 mid_img = os.path.join(iotests.test_dir, 'mid.img')
 test_img = os.path.join(iotests.test_dir, 'test.img')
 
-class ImageStreamingTestCase(iotests.QMPTestCase):
-    '''Abstract base class for image streaming test cases'''
-
-    def create_image(self, name, size):
-        file = open(name, 'w')
-        i = 0
-        while i < size:
-            sector = struct.pack('>l504xl', i / 512, i / 512)
-            file.write(sector)
-            i = i + 512
-        file.close()
-
-
-class TestSingleDrive(ImageStreamingTestCase):
+class TestSingleDrive(iotests.QMPTestCase):
     image_len = 1 * 1024 * 1024 # MB
 
     def setUp(self):
-        self.create_image(backing_img, TestSingleDrive.image_len)
+        iotests.create_image(backing_img, TestSingleDrive.image_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
         self.vm = iotests.VM().add_drive(test_img)
@@ -145,12 +131,12 @@ class TestSingleDrive(ImageStreamingTestCase):
         self.assert_qmp(result, 'error/class', 'DeviceNotFound')
 
 
-class TestSmallerBackingFile(ImageStreamingTestCase):
+class TestSmallerBackingFile(iotests.QMPTestCase):
     backing_len = 1 * 1024 * 1024 # MB
     image_len = 2 * backing_len
 
     def setUp(self):
-        self.create_image(backing_img, self.backing_len)
+        iotests.create_image(backing_img, self.backing_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len))
         self.vm = iotests.VM().add_drive(test_img)
         self.vm.launch()
@@ -176,7 +162,7 @@ class TestSmallerBackingFile(ImageStreamingTestCase):
         self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
-class TestErrors(ImageStreamingTestCase):
+class TestErrors(iotests.QMPTestCase):
     image_len = 2 * 1024 * 1024 # MB
 
     # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
@@ -208,7 +194,7 @@ new_state = "1"
 class TestEIO(TestErrors):
     def setUp(self):
         self.blkdebug_file = backing_img + ".blkdebug"
-        self.create_image(backing_img, TestErrors.image_len)
+        iotests.create_image(backing_img, TestErrors.image_len)
         self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
         qemu_img('create', '-f', iotests.imgfmt,
                  '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
@@ -344,7 +330,7 @@ class TestEIO(TestErrors):
 class TestENOSPC(TestErrors):
     def setUp(self):
         self.blkdebug_file = backing_img + ".blkdebug"
-        self.create_image(backing_img, TestErrors.image_len)
+        iotests.create_image(backing_img, TestErrors.image_len)
         self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
         qemu_img('create', '-f', iotests.imgfmt,
                  '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
@@ -397,7 +383,7 @@ class TestENOSPC(TestErrors):
         self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
-class TestStreamStop(ImageStreamingTestCase):
+class TestStreamStop(iotests.QMPTestCase):
     image_len = 8 * 1024 * 1024 * 1024 # GB
 
     def setUp(self):
@@ -423,7 +409,7 @@ class TestStreamStop(ImageStreamingTestCase):
 
         self.cancel_and_wait()
 
-class TestSetSpeed(ImageStreamingTestCase):
+class TestSetSpeed(iotests.QMPTestCase):
     image_len = 80 * 1024 * 1024 # MB
 
     def setUp(self):
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 7702074..1e923e7 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -22,7 +22,6 @@ import time
 import os
 import iotests
 from iotests import qemu_img, qemu_io
-import struct
 
 backing_img = os.path.join(iotests.test_dir, 'backing.img')
 target_backing_img = os.path.join(iotests.test_dir, 'target-backing.img')
@@ -71,20 +70,11 @@ class ImageMirroringTestCase(iotests.QMPTestCase):
 
         self.assert_no_active_block_jobs()
 
-    def create_image(self, name, size):
-        file = open(name, 'w')
-        i = 0
-        while i < size:
-            sector = struct.pack('>l504xl', i / 512, i / 512)
-            file.write(sector)
-            i = i + 512
-        file.close()
-
 class TestSingleDrive(ImageMirroringTestCase):
     image_len = 1 * 1024 * 1024 # MB
 
     def setUp(self):
-        self.create_image(backing_img, TestSingleDrive.image_len)
+        iotests.create_image(backing_img, TestSingleDrive.image_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
         self.vm = iotests.VM().add_drive(test_img)
         self.vm.launch()
@@ -230,15 +220,15 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
     image_len = 2 * 1024 * 1024 # MB
 
     def complete_and_wait(self, drive='drive0', wait_ready=True):
-        self.create_image(target_backing_img, TestMirrorNoBacking.image_len)
+        iotests.create_image(target_backing_img, TestMirrorNoBacking.image_len)
         return ImageMirroringTestCase.complete_and_wait(self, drive, wait_ready)
 
     def compare_images(self, img1, img2):
-        self.create_image(target_backing_img, TestMirrorNoBacking.image_len)
+        iotests.create_image(target_backing_img, TestMirrorNoBacking.image_len)
         return iotests.compare_images(img1, img2)
 
     def setUp(self):
-        self.create_image(backing_img, TestMirrorNoBacking.image_len)
+        iotests.create_image(backing_img, TestMirrorNoBacking.image_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
         self.vm = iotests.VM().add_drive(test_img)
         self.vm.launch()
@@ -306,7 +296,7 @@ class TestMirrorResized(ImageMirroringTestCase):
     image_len = 2 * 1024 * 1024 # MB
 
     def setUp(self):
-        self.create_image(backing_img, TestMirrorResized.backing_len)
+        iotests.create_image(backing_img, TestMirrorResized.backing_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
         qemu_img('resize', test_img, '2M')
         self.vm = iotests.VM().add_drive(test_img)
@@ -381,7 +371,7 @@ new_state = "1"
 
     def setUp(self):
         self.blkdebug_file = backing_img + ".blkdebug"
-        self.create_image(backing_img, TestReadErrors.image_len)
+        iotests.create_image(backing_img, TestReadErrors.image_len)
         self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
         qemu_img('create', '-f', iotests.imgfmt,
                  '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
@@ -536,7 +526,7 @@ new_state = "1"
 
     def setUp(self):
         self.blkdebug_file = target_img + ".blkdebug"
-        self.create_image(backing_img, TestWriteErrors.image_len)
+        iotests.create_image(backing_img, TestWriteErrors.image_len)
         self.create_blkdebug_file(self.blkdebug_file, "write_aio", 5)
         qemu_img('create', '-f', iotests.imgfmt, '-obacking_file=%s' %(backing_img), test_img)
         self.vm = iotests.VM().add_drive(test_img)
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 733b82b..8a8f181 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -23,6 +23,7 @@ import string
 import unittest
 import sys; sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'QMP'))
 import qmp
+import struct
 
 __all__ = ['imgfmt', 'imgproto', 'test_dir' 'qemu_img', 'qemu_io',
            'VM', 'QMPTestCase', 'notrun', 'main']
@@ -56,6 +57,16 @@ def compare_images(img1, img2):
     return qemu_img('compare', '-f', imgfmt,
                     '-F', imgfmt, img1, img2) == 0
 
+def create_image(name, size):
+    '''Create a fully-allocated raw image with sector markers'''
+    file = open(name, 'w')
+    i = 0
+    while i < size:
+        sector = struct.pack('>l504xl', i / 512, i / 512)
+        file.write(sector)
+        i = i + 512
+    file.close()
+
 class VM(object):
     '''A QEMU VM'''
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 07/10] block: drop bs_snapshots global variable
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (5 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 06/10] qemu-iotests: make create_image() common Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 08/10] block: move snapshot code in block.c to block/snapshot.c Kevin Wolf
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

The bs_snapshots global variable points to the BlockDriverState which
will be used to save vmstate.  This is really a savevm.c concept but was
moved into block.c:bdrv_snapshots() when it became clear that hotplug
could result in a dangling pointer.

While auditing the block layer's global state I came upon bs_snapshots
and realized that a variable is not necessary here.  Simply find the
first BlockDriverState capable of internal snapshots each time this is
needed.

The behavior of bdrv_snapshots() is preserved across hotplug because new
drives are always appended to the bdrv_states list.  This means that
calling the new find_vmstate_bs() function is idempotent - it returns
the same BlockDriverState unless it was hot-unplugged.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c               | 28 ----------------------------
 include/block/block.h |  1 -
 savevm.c              | 19 +++++++++++++++----
 3 files changed, 15 insertions(+), 33 deletions(-)

diff --git a/block.c b/block.c
index 65c0b60..e046a31 100644
--- a/block.c
+++ b/block.c
@@ -99,9 +99,6 @@ static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
 static QLIST_HEAD(, BlockDriver) bdrv_drivers =
     QLIST_HEAD_INITIALIZER(bdrv_drivers);
 
-/* The device to use for VM snapshots */
-static BlockDriverState *bs_snapshots;
-
 /* If non-zero, use only whitelisted block drivers */
 static int use_bdrv_whitelist;
 
@@ -1368,9 +1365,6 @@ void bdrv_close(BlockDriverState *bs)
     notifier_list_notify(&bs->close_notifiers, bs);
 
     if (bs->drv) {
-        if (bs == bs_snapshots) {
-            bs_snapshots = NULL;
-        }
         if (bs->backing_hd) {
             bdrv_delete(bs->backing_hd);
             bs->backing_hd = NULL;
@@ -1602,7 +1596,6 @@ void bdrv_delete(BlockDriverState *bs)
 
     bdrv_close(bs);
 
-    assert(bs != bs_snapshots);
     g_free(bs);
 }
 
@@ -1646,9 +1639,6 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
 {
     bs->dev_ops = ops;
     bs->dev_opaque = opaque;
-    if (bdrv_dev_has_removable_media(bs) && bs == bs_snapshots) {
-        bs_snapshots = NULL;
-    }
 }
 
 void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
@@ -3392,24 +3382,6 @@ int bdrv_is_snapshot(BlockDriverState *bs)
     return !!(bs->open_flags & BDRV_O_SNAPSHOT);
 }
 
-BlockDriverState *bdrv_snapshots(void)
-{
-    BlockDriverState *bs;
-
-    if (bs_snapshots) {
-        return bs_snapshots;
-    }
-
-    bs = NULL;
-    while ((bs = bdrv_next(bs))) {
-        if (bdrv_can_snapshot(bs)) {
-            bs_snapshots = bs;
-            return bs;
-        }
-    }
-    return NULL;
-}
-
 int bdrv_snapshot_create(BlockDriverState *bs,
                          QEMUSnapshotInfo *sn_info)
 {
diff --git a/include/block/block.h b/include/block/block.h
index 5604418..8965536 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -333,7 +333,6 @@ BlockInfo *bdrv_query_info(BlockDriverState *s);
 BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 int bdrv_can_snapshot(BlockDriverState *bs);
 int bdrv_is_snapshot(BlockDriverState *bs);
-BlockDriverState *bdrv_snapshots(void);
 int bdrv_snapshot_create(BlockDriverState *bs,
                          QEMUSnapshotInfo *sn_info);
 int bdrv_snapshot_goto(BlockDriverState *bs,
diff --git a/savevm.c b/savevm.c
index 4e0fab6..b11dbf6 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2262,6 +2262,17 @@ out:
     return ret;
 }
 
+static BlockDriverState *find_vmstate_bs(void)
+{
+    BlockDriverState *bs = NULL;
+    while ((bs = bdrv_next(bs))) {
+        if (bdrv_can_snapshot(bs)) {
+            return bs;
+        }
+    }
+    return NULL;
+}
+
 static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
                               const char *name)
 {
@@ -2338,7 +2349,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
         }
     }
 
-    bs = bdrv_snapshots();
+    bs = find_vmstate_bs();
     if (!bs) {
         monitor_printf(mon, "No block device can accept snapshots\n");
         return;
@@ -2440,7 +2451,7 @@ int load_vmstate(const char *name)
     QEMUFile *f;
     int ret;
 
-    bs_vm_state = bdrv_snapshots();
+    bs_vm_state = find_vmstate_bs();
     if (!bs_vm_state) {
         error_report("No block device supports snapshots");
         return -ENOTSUP;
@@ -2519,7 +2530,7 @@ void do_delvm(Monitor *mon, const QDict *qdict)
     int ret;
     const char *name = qdict_get_str(qdict, "name");
 
-    bs = bdrv_snapshots();
+    bs = find_vmstate_bs();
     if (!bs) {
         monitor_printf(mon, "No block device supports snapshots\n");
         return;
@@ -2551,7 +2562,7 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict)
     int *available_snapshots;
     char buf[256];
 
-    bs = bdrv_snapshots();
+    bs = find_vmstate_bs();
     if (!bs) {
         monitor_printf(mon, "No available block device supports snapshots\n");
         return;
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 08/10] block: move snapshot code in block.c to block/snapshot.c
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (6 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 07/10] block: drop bs_snapshots global variable Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 09/10] block: move qmp and info dump related code to block/qapi.c Kevin Wolf
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

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

All snapshot related code, except bdrv_snapshot_dump() and
bdrv_is_snapshot(), is moved to block/snapshot.c. bdrv_snapshot_dump()
will be moved to another file later. bdrv_is_snapshot() is not related
with internal snapshot. It also fixes small code style errors reported
by check script.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c                  | 100 ------------------------------
 block/Makefile.objs      |   1 +
 block/snapshot.c         | 157 +++++++++++++++++++++++++++++++++++++++++++++++
 include/block/block.h    |  26 ++------
 include/block/snapshot.h |  53 ++++++++++++++++
 savevm.c                 |  23 +------
 6 files changed, 217 insertions(+), 143 deletions(-)
 create mode 100644 block/snapshot.c
 create mode 100644 include/block/snapshot.h

diff --git a/block.c b/block.c
index e046a31..6212aae 100644
--- a/block.c
+++ b/block.c
@@ -3357,111 +3357,11 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
     return false;
 }
 
-/**************************************************************/
-/* handling of snapshots */
-
-int bdrv_can_snapshot(BlockDriverState *bs)
-{
-    BlockDriver *drv = bs->drv;
-    if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
-        return 0;
-    }
-
-    if (!drv->bdrv_snapshot_create) {
-        if (bs->file != NULL) {
-            return bdrv_can_snapshot(bs->file);
-        }
-        return 0;
-    }
-
-    return 1;
-}
-
 int bdrv_is_snapshot(BlockDriverState *bs)
 {
     return !!(bs->open_flags & BDRV_O_SNAPSHOT);
 }
 
-int bdrv_snapshot_create(BlockDriverState *bs,
-                         QEMUSnapshotInfo *sn_info)
-{
-    BlockDriver *drv = bs->drv;
-    if (!drv)
-        return -ENOMEDIUM;
-    if (drv->bdrv_snapshot_create)
-        return drv->bdrv_snapshot_create(bs, sn_info);
-    if (bs->file)
-        return bdrv_snapshot_create(bs->file, sn_info);
-    return -ENOTSUP;
-}
-
-int bdrv_snapshot_goto(BlockDriverState *bs,
-                       const char *snapshot_id)
-{
-    BlockDriver *drv = bs->drv;
-    int ret, open_ret;
-
-    if (!drv)
-        return -ENOMEDIUM;
-    if (drv->bdrv_snapshot_goto)
-        return drv->bdrv_snapshot_goto(bs, snapshot_id);
-
-    if (bs->file) {
-        drv->bdrv_close(bs);
-        ret = bdrv_snapshot_goto(bs->file, snapshot_id);
-        open_ret = drv->bdrv_open(bs, NULL, bs->open_flags);
-        if (open_ret < 0) {
-            bdrv_delete(bs->file);
-            bs->drv = NULL;
-            return open_ret;
-        }
-        return ret;
-    }
-
-    return -ENOTSUP;
-}
-
-int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
-{
-    BlockDriver *drv = bs->drv;
-    if (!drv)
-        return -ENOMEDIUM;
-    if (drv->bdrv_snapshot_delete)
-        return drv->bdrv_snapshot_delete(bs, snapshot_id);
-    if (bs->file)
-        return bdrv_snapshot_delete(bs->file, snapshot_id);
-    return -ENOTSUP;
-}
-
-int bdrv_snapshot_list(BlockDriverState *bs,
-                       QEMUSnapshotInfo **psn_info)
-{
-    BlockDriver *drv = bs->drv;
-    if (!drv)
-        return -ENOMEDIUM;
-    if (drv->bdrv_snapshot_list)
-        return drv->bdrv_snapshot_list(bs, psn_info);
-    if (bs->file)
-        return bdrv_snapshot_list(bs->file, psn_info);
-    return -ENOTSUP;
-}
-
-int bdrv_snapshot_load_tmp(BlockDriverState *bs,
-        const char *snapshot_name)
-{
-    BlockDriver *drv = bs->drv;
-    if (!drv) {
-        return -ENOMEDIUM;
-    }
-    if (!bs->read_only) {
-        return -EINVAL;
-    }
-    if (drv->bdrv_snapshot_load_tmp) {
-        return drv->bdrv_snapshot_load_tmp(bs, snapshot_name);
-    }
-    return -ENOTSUP;
-}
-
 /* backing_file can either be relative, or absolute, or a protocol.  If it is
  * relative, it must be relative to the chain.  So, passing in bs->filename
  * from a BDS as backing_file should not be done, as that may be relative to
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 5f0358a..8670999 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -4,6 +4,7 @@ block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-obj-y += qed-check.o
 block-obj-y += vhdx.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
+block-obj-y += snapshot.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
diff --git a/block/snapshot.c b/block/snapshot.c
new file mode 100644
index 0000000..6c6d9de
--- /dev/null
+++ b/block/snapshot.c
@@ -0,0 +1,157 @@
+/*
+ * Block layer snapshot related functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "block/snapshot.h"
+#include "block/block_int.h"
+
+int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
+                       const char *name)
+{
+    QEMUSnapshotInfo *sn_tab, *sn;
+    int nb_sns, i, ret;
+
+    ret = -ENOENT;
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+    if (nb_sns < 0) {
+        return ret;
+    }
+    for (i = 0; i < nb_sns; i++) {
+        sn = &sn_tab[i];
+        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
+            *sn_info = *sn;
+            ret = 0;
+            break;
+        }
+    }
+    g_free(sn_tab);
+    return ret;
+}
+
+int bdrv_can_snapshot(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
+        return 0;
+    }
+
+    if (!drv->bdrv_snapshot_create) {
+        if (bs->file != NULL) {
+            return bdrv_can_snapshot(bs->file);
+        }
+        return 0;
+    }
+
+    return 1;
+}
+
+int bdrv_snapshot_create(BlockDriverState *bs,
+                         QEMUSnapshotInfo *sn_info)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (drv->bdrv_snapshot_create) {
+        return drv->bdrv_snapshot_create(bs, sn_info);
+    }
+    if (bs->file) {
+        return bdrv_snapshot_create(bs->file, sn_info);
+    }
+    return -ENOTSUP;
+}
+
+int bdrv_snapshot_goto(BlockDriverState *bs,
+                       const char *snapshot_id)
+{
+    BlockDriver *drv = bs->drv;
+    int ret, open_ret;
+
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (drv->bdrv_snapshot_goto) {
+        return drv->bdrv_snapshot_goto(bs, snapshot_id);
+    }
+
+    if (bs->file) {
+        drv->bdrv_close(bs);
+        ret = bdrv_snapshot_goto(bs->file, snapshot_id);
+        open_ret = drv->bdrv_open(bs, NULL, bs->open_flags);
+        if (open_ret < 0) {
+            bdrv_delete(bs->file);
+            bs->drv = NULL;
+            return open_ret;
+        }
+        return ret;
+    }
+
+    return -ENOTSUP;
+}
+
+int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (drv->bdrv_snapshot_delete) {
+        return drv->bdrv_snapshot_delete(bs, snapshot_id);
+    }
+    if (bs->file) {
+        return bdrv_snapshot_delete(bs->file, snapshot_id);
+    }
+    return -ENOTSUP;
+}
+
+int bdrv_snapshot_list(BlockDriverState *bs,
+                       QEMUSnapshotInfo **psn_info)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (drv->bdrv_snapshot_list) {
+        return drv->bdrv_snapshot_list(bs, psn_info);
+    }
+    if (bs->file) {
+        return bdrv_snapshot_list(bs->file, psn_info);
+    }
+    return -ENOTSUP;
+}
+
+int bdrv_snapshot_load_tmp(BlockDriverState *bs,
+        const char *snapshot_name)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv) {
+        return -ENOMEDIUM;
+    }
+    if (!bs->read_only) {
+        return -EINVAL;
+    }
+    if (drv->bdrv_snapshot_load_tmp) {
+        return drv->bdrv_snapshot_load_tmp(bs, snapshot_name);
+    }
+    return -ENOTSUP;
+}
diff --git a/include/block/block.h b/include/block/block.h
index 8965536..a50a75f 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -7,6 +7,11 @@
 #include "block/coroutine.h"
 #include "qapi/qmp/qobject.h"
 #include "qapi-types.h"
+/*
+ * snapshot.h is needed since bdrv_snapshot_dump(), it can be removed when the
+ * function is moved to other file.
+ */
+#include "block/snapshot.h"
 
 /* block.c */
 typedef struct BlockDriver BlockDriver;
@@ -27,17 +32,6 @@ typedef struct BlockFragInfo {
     uint64_t compressed_clusters;
 } BlockFragInfo;
 
-typedef struct QEMUSnapshotInfo {
-    char id_str[128]; /* unique snapshot id */
-    /* the following fields are informative. They are not needed for
-       the consistency of the snapshot */
-    char name[256]; /* user chosen name */
-    uint64_t vm_state_size; /* VM state info size */
-    uint32_t date_sec; /* UTC date of the snapshot */
-    uint32_t date_nsec;
-    uint64_t vm_clock_nsec; /* VM clock relative to boot */
-} QEMUSnapshotInfo;
-
 /* Callbacks for block device models */
 typedef struct BlockDevOps {
     /*
@@ -331,17 +325,7 @@ void bdrv_get_full_backing_filename(BlockDriverState *bs,
                                     char *dest, size_t sz);
 BlockInfo *bdrv_query_info(BlockDriverState *s);
 BlockStats *bdrv_query_stats(const BlockDriverState *bs);
-int bdrv_can_snapshot(BlockDriverState *bs);
 int bdrv_is_snapshot(BlockDriverState *bs);
-int bdrv_snapshot_create(BlockDriverState *bs,
-                         QEMUSnapshotInfo *sn_info);
-int bdrv_snapshot_goto(BlockDriverState *bs,
-                       const char *snapshot_id);
-int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
-int bdrv_snapshot_list(BlockDriverState *bs,
-                       QEMUSnapshotInfo **psn_info);
-int bdrv_snapshot_load_tmp(BlockDriverState *bs,
-                           const char *snapshot_name);
 char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
 
 char *get_human_readable_size(char *buf, int buf_size, int64_t size);
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
new file mode 100644
index 0000000..eaf61f0
--- /dev/null
+++ b/include/block/snapshot.h
@@ -0,0 +1,53 @@
+/*
+ * Block layer snapshot related functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SNAPSHOT_H
+#define SNAPSHOT_H
+
+#include "qemu-common.h"
+
+typedef struct QEMUSnapshotInfo {
+    char id_str[128]; /* unique snapshot id */
+    /* the following fields are informative. They are not needed for
+       the consistency of the snapshot */
+    char name[256]; /* user chosen name */
+    uint64_t vm_state_size; /* VM state info size */
+    uint32_t date_sec; /* UTC date of the snapshot */
+    uint32_t date_nsec;
+    uint64_t vm_clock_nsec; /* VM clock relative to boot */
+} QEMUSnapshotInfo;
+
+int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
+                       const char *name);
+int bdrv_can_snapshot(BlockDriverState *bs);
+int bdrv_snapshot_create(BlockDriverState *bs,
+                         QEMUSnapshotInfo *sn_info);
+int bdrv_snapshot_goto(BlockDriverState *bs,
+                       const char *snapshot_id);
+int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
+int bdrv_snapshot_list(BlockDriverState *bs,
+                       QEMUSnapshotInfo **psn_info);
+int bdrv_snapshot_load_tmp(BlockDriverState *bs,
+                           const char *snapshot_name);
+#endif
diff --git a/savevm.c b/savevm.c
index b11dbf6..916080d 100644
--- a/savevm.c
+++ b/savevm.c
@@ -40,6 +40,7 @@
 #include "trace.h"
 #include "qemu/bitops.h"
 #include "qemu/iov.h"
+#include "block/snapshot.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
@@ -2273,28 +2274,6 @@ static BlockDriverState *find_vmstate_bs(void)
     return NULL;
 }
 
-static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
-                              const char *name)
-{
-    QEMUSnapshotInfo *sn_tab, *sn;
-    int nb_sns, i, ret;
-
-    ret = -ENOENT;
-    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
-    if (nb_sns < 0)
-        return ret;
-    for(i = 0; i < nb_sns; i++) {
-        sn = &sn_tab[i];
-        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
-            *sn_info = *sn;
-            ret = 0;
-            break;
-        }
-    }
-    g_free(sn_tab);
-    return ret;
-}
-
 /*
  * Deletes snapshots of a given name in all opened images.
  */
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 09/10] block: move qmp and info dump related code to block/qapi.c
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (7 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 08/10] block: move snapshot code in block.c to block/snapshot.c Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-04 12:45 ` [Qemu-devel] [PULL 10/10] block: dump snapshot and image info to specified output Kevin Wolf
  2013-06-17 21:17 ` [Qemu-devel] [PULL 00/10] Block patches Anthony Liguori
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

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

This patch is a pure code move patch, except following modification:
1 get_human_readable_size() is changed to static function.
2 dump_human_image_info() is renamed to bdrv_image_info_dump().
3 in qmp_query_block() and qmp_query_blockstats, use bdrv_next(bs)
instead of direct traverse of global array 'bdrv_states'.
4 collect_snapshots() and collect_image_info() are renamed, unused parameter
*fmt in collect_image_info() is removed.
5 code style fix.

To avoid conflict and tip better, macro in header file is BLOCK_QAPI_H
instead of QAPI_H. Now block.h and snapshot.h are at the same level in
include path, block_int.h and qapi.h will both include them.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c                   | 185 ------------------------
 block/Makefile.objs       |   2 +-
 block/qapi.c              | 360 ++++++++++++++++++++++++++++++++++++++++++++++
 include/block/block.h     |   9 --
 include/block/block_int.h |   1 +
 include/block/qapi.h      |  41 ++++++
 qemu-img.c                | 156 +-------------------
 savevm.c                  |   1 +
 8 files changed, 408 insertions(+), 347 deletions(-)
 create mode 100644 block/qapi.c
 create mode 100644 include/block/qapi.h

diff --git a/block.c b/block.c
index 6212aae..3f616de 100644
--- a/block.c
+++ b/block.c
@@ -3100,128 +3100,6 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
     return data.ret;
 }
 
-BlockInfo *bdrv_query_info(BlockDriverState *bs)
-{
-    BlockInfo *info = g_malloc0(sizeof(*info));
-    info->device = g_strdup(bs->device_name);
-    info->type = g_strdup("unknown");
-    info->locked = bdrv_dev_is_medium_locked(bs);
-    info->removable = bdrv_dev_has_removable_media(bs);
-
-    if (bdrv_dev_has_removable_media(bs)) {
-        info->has_tray_open = true;
-        info->tray_open = bdrv_dev_is_tray_open(bs);
-    }
-
-    if (bdrv_iostatus_is_enabled(bs)) {
-        info->has_io_status = true;
-        info->io_status = bs->iostatus;
-    }
-
-    if (bs->dirty_bitmap) {
-        info->has_dirty = true;
-        info->dirty = g_malloc0(sizeof(*info->dirty));
-        info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE;
-        info->dirty->granularity =
-            ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap));
-    }
-
-    if (bs->drv) {
-        info->has_inserted = true;
-        info->inserted = g_malloc0(sizeof(*info->inserted));
-        info->inserted->file = g_strdup(bs->filename);
-        info->inserted->ro = bs->read_only;
-        info->inserted->drv = g_strdup(bs->drv->format_name);
-        info->inserted->encrypted = bs->encrypted;
-        info->inserted->encryption_key_missing = bdrv_key_required(bs);
-
-        if (bs->backing_file[0]) {
-            info->inserted->has_backing_file = true;
-            info->inserted->backing_file = g_strdup(bs->backing_file);
-        }
-
-        info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs);
-
-        if (bs->io_limits_enabled) {
-            info->inserted->bps =
-                           bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
-            info->inserted->bps_rd =
-                           bs->io_limits.bps[BLOCK_IO_LIMIT_READ];
-            info->inserted->bps_wr =
-                           bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE];
-            info->inserted->iops =
-                           bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
-            info->inserted->iops_rd =
-                           bs->io_limits.iops[BLOCK_IO_LIMIT_READ];
-            info->inserted->iops_wr =
-                           bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
-        }
-    }
-    return info;
-}
-
-BlockInfoList *qmp_query_block(Error **errp)
-{
-    BlockInfoList *head = NULL, **p_next = &head;
-    BlockDriverState *bs;
-
-    QTAILQ_FOREACH(bs, &bdrv_states, list) {
-        BlockInfoList *info = g_malloc0(sizeof(*info));
-        info->value = bdrv_query_info(bs);
-
-        *p_next = info;
-        p_next = &info->next;
-    }
-
-    return head;
-}
-
-BlockStats *bdrv_query_stats(const BlockDriverState *bs)
-{
-    BlockStats *s;
-
-    s = g_malloc0(sizeof(*s));
-
-    if (bs->device_name[0]) {
-        s->has_device = true;
-        s->device = g_strdup(bs->device_name);
-    }
-
-    s->stats = g_malloc0(sizeof(*s->stats));
-    s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ];
-    s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE];
-    s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ];
-    s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE];
-    s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
-    s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH];
-    s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE];
-    s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ];
-    s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH];
-
-    if (bs->file) {
-        s->has_parent = true;
-        s->parent = bdrv_query_stats(bs->file);
-    }
-
-    return s;
-}
-
-BlockStatsList *qmp_query_blockstats(Error **errp)
-{
-    BlockStatsList *head = NULL, **p_next = &head;
-    BlockDriverState *bs;
-
-    QTAILQ_FOREACH(bs, &bdrv_states, list) {
-        BlockStatsList *info = g_malloc0(sizeof(*info));
-        info->value = bdrv_query_stats(bs);
-
-        *p_next = info;
-        p_next = &info->next;
-    }
-
-    return head;
-}
-
 const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
 {
     if (bs->backing_hd && bs->backing_hd->encrypted)
@@ -3457,69 +3335,6 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
     return curr_bs;
 }
 
-#define NB_SUFFIXES 4
-
-char *get_human_readable_size(char *buf, int buf_size, int64_t size)
-{
-    static const char suffixes[NB_SUFFIXES] = "KMGT";
-    int64_t base;
-    int i;
-
-    if (size <= 999) {
-        snprintf(buf, buf_size, "%" PRId64, size);
-    } else {
-        base = 1024;
-        for(i = 0; i < NB_SUFFIXES; i++) {
-            if (size < (10 * base)) {
-                snprintf(buf, buf_size, "%0.1f%c",
-                         (double)size / base,
-                         suffixes[i]);
-                break;
-            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
-                snprintf(buf, buf_size, "%" PRId64 "%c",
-                         ((size + (base >> 1)) / base),
-                         suffixes[i]);
-                break;
-            }
-            base = base * 1024;
-        }
-    }
-    return buf;
-}
-
-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
-{
-    char buf1[128], date_buf[128], clock_buf[128];
-    struct tm tm;
-    time_t ti;
-    int64_t secs;
-
-    if (!sn) {
-        snprintf(buf, buf_size,
-                 "%-10s%-20s%7s%20s%15s",
-                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
-    } else {
-        ti = sn->date_sec;
-        localtime_r(&ti, &tm);
-        strftime(date_buf, sizeof(date_buf),
-                 "%Y-%m-%d %H:%M:%S", &tm);
-        secs = sn->vm_clock_nsec / 1000000000;
-        snprintf(clock_buf, sizeof(clock_buf),
-                 "%02d:%02d:%02d.%03d",
-                 (int)(secs / 3600),
-                 (int)((secs / 60) % 60),
-                 (int)(secs % 60),
-                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
-        snprintf(buf, buf_size,
-                 "%-10s%-20s%7s%20s%15s",
-                 sn->id_str, sn->name,
-                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
-                 date_buf,
-                 clock_buf);
-    }
-    return buf;
-}
-
 /**************************************************************/
 /* async I/Os */
 
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 8670999..2981654 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -4,7 +4,7 @@ block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-obj-y += qed-check.o
 block-obj-y += vhdx.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
-block-obj-y += snapshot.o
+block-obj-y += snapshot.o qapi.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
diff --git a/block/qapi.c b/block/qapi.c
new file mode 100644
index 0000000..155e77e
--- /dev/null
+++ b/block/qapi.c
@@ -0,0 +1,360 @@
+/*
+ * Block layer qmp and info dump related functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "block/qapi.h"
+#include "block/block_int.h"
+#include "qmp-commands.h"
+
+void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info)
+{
+    int i, sn_count;
+    QEMUSnapshotInfo *sn_tab = NULL;
+    SnapshotInfoList *info_list, *cur_item = NULL;
+    sn_count = bdrv_snapshot_list(bs, &sn_tab);
+
+    for (i = 0; i < sn_count; i++) {
+        info->has_snapshots = true;
+        info_list = g_new0(SnapshotInfoList, 1);
+
+        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;
+
+        /* XXX: waiting for the qapi to support qemu-queue.h types */
+        if (!cur_item) {
+            info->snapshots = cur_item = info_list;
+        } else {
+            cur_item->next = info_list;
+            cur_item = info_list;
+        }
+
+    }
+
+    g_free(sn_tab);
+}
+
+void bdrv_collect_image_info(BlockDriverState *bs,
+                             ImageInfo *info,
+                             const char *filename)
+{
+    uint64_t total_sectors;
+    char backing_filename[1024];
+    char backing_filename2[1024];
+    BlockDriverInfo bdi;
+
+    bdrv_get_geometry(bs, &total_sectors);
+
+    info->filename        = g_strdup(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);
+    info->has_actual_size = info->actual_size >= 0;
+    if (bdrv_is_encrypted(bs)) {
+        info->encrypted = true;
+        info->has_encrypted = true;
+    }
+    if (bdrv_get_info(bs, &bdi) >= 0) {
+        if (bdi.cluster_size != 0) {
+            info->cluster_size = bdi.cluster_size;
+            info->has_cluster_size = true;
+        }
+        info->dirty_flag = bdi.is_dirty;
+        info->has_dirty_flag = true;
+    }
+    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
+    if (backing_filename[0] != '\0') {
+        info->backing_filename = g_strdup(backing_filename);
+        info->has_backing_filename = true;
+        bdrv_get_full_backing_filename(bs, backing_filename2,
+                                       sizeof(backing_filename2));
+
+        if (strcmp(backing_filename, backing_filename2) != 0) {
+            info->full_backing_filename =
+                        g_strdup(backing_filename2);
+            info->has_full_backing_filename = true;
+        }
+
+        if (bs->backing_format[0]) {
+            info->backing_filename_format = g_strdup(bs->backing_format);
+            info->has_backing_filename_format = true;
+        }
+    }
+}
+
+BlockInfo *bdrv_query_info(BlockDriverState *bs)
+{
+    BlockInfo *info = g_malloc0(sizeof(*info));
+    info->device = g_strdup(bs->device_name);
+    info->type = g_strdup("unknown");
+    info->locked = bdrv_dev_is_medium_locked(bs);
+    info->removable = bdrv_dev_has_removable_media(bs);
+
+    if (bdrv_dev_has_removable_media(bs)) {
+        info->has_tray_open = true;
+        info->tray_open = bdrv_dev_is_tray_open(bs);
+    }
+
+    if (bdrv_iostatus_is_enabled(bs)) {
+        info->has_io_status = true;
+        info->io_status = bs->iostatus;
+    }
+
+    if (bs->dirty_bitmap) {
+        info->has_dirty = true;
+        info->dirty = g_malloc0(sizeof(*info->dirty));
+        info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE;
+        info->dirty->granularity =
+         ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap));
+    }
+
+    if (bs->drv) {
+        info->has_inserted = true;
+        info->inserted = g_malloc0(sizeof(*info->inserted));
+        info->inserted->file = g_strdup(bs->filename);
+        info->inserted->ro = bs->read_only;
+        info->inserted->drv = g_strdup(bs->drv->format_name);
+        info->inserted->encrypted = bs->encrypted;
+        info->inserted->encryption_key_missing = bdrv_key_required(bs);
+
+        if (bs->backing_file[0]) {
+            info->inserted->has_backing_file = true;
+            info->inserted->backing_file = g_strdup(bs->backing_file);
+        }
+
+        info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs);
+
+        if (bs->io_limits_enabled) {
+            info->inserted->bps =
+                           bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
+            info->inserted->bps_rd =
+                           bs->io_limits.bps[BLOCK_IO_LIMIT_READ];
+            info->inserted->bps_wr =
+                           bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE];
+            info->inserted->iops =
+                           bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
+            info->inserted->iops_rd =
+                           bs->io_limits.iops[BLOCK_IO_LIMIT_READ];
+            info->inserted->iops_wr =
+                           bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
+        }
+    }
+    return info;
+}
+
+BlockStats *bdrv_query_stats(const BlockDriverState *bs)
+{
+    BlockStats *s;
+
+    s = g_malloc0(sizeof(*s));
+
+    if (bs->device_name[0]) {
+        s->has_device = true;
+        s->device = g_strdup(bs->device_name);
+    }
+
+    s->stats = g_malloc0(sizeof(*s->stats));
+    s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ];
+    s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE];
+    s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ];
+    s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE];
+    s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
+    s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH];
+    s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE];
+    s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ];
+    s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH];
+
+    if (bs->file) {
+        s->has_parent = true;
+        s->parent = bdrv_query_stats(bs->file);
+    }
+
+    return s;
+}
+
+BlockInfoList *qmp_query_block(Error **errp)
+{
+    BlockInfoList *head = NULL, **p_next = &head;
+    BlockDriverState *bs = NULL;
+
+     while ((bs = bdrv_next(bs))) {
+        BlockInfoList *info = g_malloc0(sizeof(*info));
+        info->value = bdrv_query_info(bs);
+
+        *p_next = info;
+        p_next = &info->next;
+    }
+
+    return head;
+}
+
+BlockStatsList *qmp_query_blockstats(Error **errp)
+{
+    BlockStatsList *head = NULL, **p_next = &head;
+    BlockDriverState *bs = NULL;
+
+     while ((bs = bdrv_next(bs))) {
+        BlockStatsList *info = g_malloc0(sizeof(*info));
+        info->value = bdrv_query_stats(bs);
+
+        *p_next = info;
+        p_next = &info->next;
+    }
+
+    return head;
+}
+
+#define NB_SUFFIXES 4
+
+static char *get_human_readable_size(char *buf, int buf_size, int64_t size)
+{
+    static const char suffixes[NB_SUFFIXES] = "KMGT";
+    int64_t base;
+    int i;
+
+    if (size <= 999) {
+        snprintf(buf, buf_size, "%" PRId64, size);
+    } else {
+        base = 1024;
+        for (i = 0; i < NB_SUFFIXES; i++) {
+            if (size < (10 * base)) {
+                snprintf(buf, buf_size, "%0.1f%c",
+                         (double)size / base,
+                         suffixes[i]);
+                break;
+            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
+                snprintf(buf, buf_size, "%" PRId64 "%c",
+                         ((size + (base >> 1)) / base),
+                         suffixes[i]);
+                break;
+            }
+            base = base * 1024;
+        }
+    }
+    return buf;
+}
+
+char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
+{
+    char buf1[128], date_buf[128], clock_buf[128];
+    struct tm tm;
+    time_t ti;
+    int64_t secs;
+
+    if (!sn) {
+        snprintf(buf, buf_size,
+                 "%-10s%-20s%7s%20s%15s",
+                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
+    } else {
+        ti = sn->date_sec;
+        localtime_r(&ti, &tm);
+        strftime(date_buf, sizeof(date_buf),
+                 "%Y-%m-%d %H:%M:%S", &tm);
+        secs = sn->vm_clock_nsec / 1000000000;
+        snprintf(clock_buf, sizeof(clock_buf),
+                 "%02d:%02d:%02d.%03d",
+                 (int)(secs / 3600),
+                 (int)((secs / 60) % 60),
+                 (int)(secs % 60),
+                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
+        snprintf(buf, buf_size,
+                 "%-10s%-20s%7s%20s%15s",
+                 sn->id_str, sn->name,
+                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
+                 date_buf,
+                 clock_buf);
+    }
+    return buf;
+}
+
+void bdrv_image_info_dump(ImageInfo *info)
+{
+    char size_buf[128], dsize_buf[128];
+    if (!info->has_actual_size) {
+        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
+    } else {
+        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
+                                info->actual_size);
+    }
+    get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
+    printf("image: %s\n"
+           "file format: %s\n"
+           "virtual size: %s (%" PRId64 " bytes)\n"
+           "disk size: %s\n",
+           info->filename, info->format, size_buf,
+           info->virtual_size,
+           dsize_buf);
+
+    if (info->has_encrypted && info->encrypted) {
+        printf("encrypted: yes\n");
+    }
+
+    if (info->has_cluster_size) {
+        printf("cluster_size: %" PRId64 "\n", info->cluster_size);
+    }
+
+    if (info->has_dirty_flag && info->dirty_flag) {
+        printf("cleanly shut down: no\n");
+    }
+
+    if (info->has_backing_filename) {
+        printf("backing file: %s", info->backing_filename);
+        if (info->has_full_backing_filename) {
+            printf(" (actual path: %s)", info->full_backing_filename);
+        }
+        putchar('\n');
+        if (info->has_backing_filename_format) {
+            printf("backing file format: %s\n", info->backing_filename_format);
+        }
+    }
+
+    if (info->has_snapshots) {
+        SnapshotInfoList *elem;
+        char buf[256];
+
+        printf("Snapshot list:\n");
+        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+
+        /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but
+         * we convert to the block layer's native QEMUSnapshotInfo for now.
+         */
+        for (elem = info->snapshots; elem; elem = elem->next) {
+            QEMUSnapshotInfo sn = {
+                .vm_state_size = elem->value->vm_state_size,
+                .date_sec = elem->value->date_sec,
+                .date_nsec = elem->value->date_nsec,
+                .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL +
+                                 elem->value->vm_clock_nsec,
+            };
+
+            pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
+            pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
+            printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn));
+        }
+    }
+}
diff --git a/include/block/block.h b/include/block/block.h
index a50a75f..dc5b388 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -7,11 +7,6 @@
 #include "block/coroutine.h"
 #include "qapi/qmp/qobject.h"
 #include "qapi-types.h"
-/*
- * snapshot.h is needed since bdrv_snapshot_dump(), it can be removed when the
- * function is moved to other file.
- */
-#include "block/snapshot.h"
 
 /* block.c */
 typedef struct BlockDriver BlockDriver;
@@ -323,12 +318,8 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
                                char *filename, int filename_size);
 void bdrv_get_full_backing_filename(BlockDriverState *bs,
                                     char *dest, size_t sz);
-BlockInfo *bdrv_query_info(BlockDriverState *s);
-BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 int bdrv_is_snapshot(BlockDriverState *bs);
-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
 
-char *get_human_readable_size(char *buf, int buf_size, int64_t size);
 int path_is_absolute(const char *path);
 void path_combine(char *dest, int dest_size,
                   const char *base_path,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 6078dd3..ba52247 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -33,6 +33,7 @@
 #include "qapi/qmp/qerror.h"
 #include "monitor/monitor.h"
 #include "qemu/hbitmap.h"
+#include "block/snapshot.h"
 
 #define BLOCK_FLAG_ENCRYPT          1
 #define BLOCK_FLAG_COMPAT6          4
diff --git a/include/block/qapi.h b/include/block/qapi.h
new file mode 100644
index 0000000..55d1848
--- /dev/null
+++ b/include/block/qapi.h
@@ -0,0 +1,41 @@
+/*
+ * Block layer qmp and info dump related functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef BLOCK_QAPI_H
+#define BLOCK_QAPI_H
+
+#include "qapi-types.h"
+#include "block/block.h"
+#include "block/snapshot.h"
+
+void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info);
+void bdrv_collect_image_info(BlockDriverState *bs,
+                             ImageInfo *info,
+                             const char *filename);
+BlockInfo *bdrv_query_info(BlockDriverState *s);
+BlockStats *bdrv_query_stats(const BlockDriverState *bs);
+
+char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
+void bdrv_image_info_dump(ImageInfo *info);
+#endif
diff --git a/qemu-img.c b/qemu-img.c
index cd096a1..5d1e480 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -30,6 +30,7 @@
 #include "qemu/osdep.h"
 #include "sysemu/sysemu.h"
 #include "block/block_int.h"
+#include "block/qapi.h"
 #include <getopt.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -1584,39 +1585,6 @@ static void dump_json_image_info_list(ImageInfoList *list)
     QDECREF(str);
 }
 
-static void collect_snapshots(BlockDriverState *bs , ImageInfo *info)
-{
-    int i, sn_count;
-    QEMUSnapshotInfo *sn_tab = NULL;
-    SnapshotInfoList *info_list, *cur_item = NULL;
-    sn_count = bdrv_snapshot_list(bs, &sn_tab);
-
-    for (i = 0; i < sn_count; i++) {
-        info->has_snapshots = true;
-        info_list = g_new0(SnapshotInfoList, 1);
-
-        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;
-
-        /* XXX: waiting for the qapi to support qemu-queue.h types */
-        if (!cur_item) {
-            info->snapshots = cur_item = info_list;
-        } else {
-            cur_item->next = info_list;
-            cur_item = info_list;
-        }
-
-    }
-
-    g_free(sn_tab);
-}
-
 static void dump_json_image_info(ImageInfo *info)
 {
     Error *errp = NULL;
@@ -1634,122 +1602,6 @@ static void dump_json_image_info(ImageInfo *info)
     QDECREF(str);
 }
 
-static void collect_image_info(BlockDriverState *bs,
-                   ImageInfo *info,
-                   const char *filename,
-                   const char *fmt)
-{
-    uint64_t total_sectors;
-    char backing_filename[1024];
-    char backing_filename2[1024];
-    BlockDriverInfo bdi;
-
-    bdrv_get_geometry(bs, &total_sectors);
-
-    info->filename        = g_strdup(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);
-    info->has_actual_size = info->actual_size >= 0;
-    if (bdrv_is_encrypted(bs)) {
-        info->encrypted = true;
-        info->has_encrypted = true;
-    }
-    if (bdrv_get_info(bs, &bdi) >= 0) {
-        if (bdi.cluster_size != 0) {
-            info->cluster_size = bdi.cluster_size;
-            info->has_cluster_size = true;
-        }
-        info->dirty_flag = bdi.is_dirty;
-        info->has_dirty_flag = true;
-    }
-    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
-    if (backing_filename[0] != '\0') {
-        info->backing_filename = g_strdup(backing_filename);
-        info->has_backing_filename = true;
-        bdrv_get_full_backing_filename(bs, backing_filename2,
-                                       sizeof(backing_filename2));
-
-        if (strcmp(backing_filename, backing_filename2) != 0) {
-            info->full_backing_filename =
-                        g_strdup(backing_filename2);
-            info->has_full_backing_filename = true;
-        }
-
-        if (bs->backing_format[0]) {
-            info->backing_filename_format = g_strdup(bs->backing_format);
-            info->has_backing_filename_format = true;
-        }
-    }
-}
-
-static void dump_human_image_info(ImageInfo *info)
-{
-    char size_buf[128], dsize_buf[128];
-    if (!info->has_actual_size) {
-        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
-    } else {
-        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
-                                info->actual_size);
-    }
-    get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
-    printf("image: %s\n"
-           "file format: %s\n"
-           "virtual size: %s (%" PRId64 " bytes)\n"
-           "disk size: %s\n",
-           info->filename, info->format, size_buf,
-           info->virtual_size,
-           dsize_buf);
-
-    if (info->has_encrypted && info->encrypted) {
-        printf("encrypted: yes\n");
-    }
-
-    if (info->has_cluster_size) {
-        printf("cluster_size: %" PRId64 "\n", info->cluster_size);
-    }
-
-    if (info->has_dirty_flag && info->dirty_flag) {
-        printf("cleanly shut down: no\n");
-    }
-
-    if (info->has_backing_filename) {
-        printf("backing file: %s", info->backing_filename);
-        if (info->has_full_backing_filename) {
-            printf(" (actual path: %s)", info->full_backing_filename);
-        }
-        putchar('\n');
-        if (info->has_backing_filename_format) {
-            printf("backing file format: %s\n", info->backing_filename_format);
-        }
-    }
-
-    if (info->has_snapshots) {
-        SnapshotInfoList *elem;
-        char buf[256];
-
-        printf("Snapshot list:\n");
-        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
-
-        /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but
-         * we convert to the block layer's native QEMUSnapshotInfo for now.
-         */
-        for (elem = info->snapshots; elem; elem = elem->next) {
-            QEMUSnapshotInfo sn = {
-                .vm_state_size = elem->value->vm_state_size,
-                .date_sec = elem->value->date_sec,
-                .date_nsec = elem->value->date_nsec,
-                .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL +
-                                 elem->value->vm_clock_nsec,
-            };
-
-            pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
-            pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
-            printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn));
-        }
-    }
-}
-
 static void dump_human_image_info_list(ImageInfoList *list)
 {
     ImageInfoList *elem;
@@ -1761,7 +1613,7 @@ static void dump_human_image_info_list(ImageInfoList *list)
         }
         delim = true;
 
-        dump_human_image_info(elem->value);
+        bdrv_image_info_dump(elem->value);
     }
 }
 
@@ -1811,8 +1663,8 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         }
 
         info = g_new0(ImageInfo, 1);
-        collect_image_info(bs, info, filename, fmt);
-        collect_snapshots(bs, info);
+        bdrv_collect_image_info(bs, info, filename);
+        bdrv_collect_snapshots(bs, info);
 
         elem = g_new0(ImageInfoList, 1);
         elem->value = info;
diff --git a/savevm.c b/savevm.c
index 916080d..a886514 100644
--- a/savevm.c
+++ b/savevm.c
@@ -41,6 +41,7 @@
 #include "qemu/bitops.h"
 #include "qemu/iov.h"
 #include "block/snapshot.h"
+#include "block/qapi.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 10/10] block: dump snapshot and image info to specified output
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (8 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 09/10] block: move qmp and info dump related code to block/qapi.c Kevin Wolf
@ 2013-06-04 12:45 ` Kevin Wolf
  2013-06-17 21:17 ` [Qemu-devel] [PULL 00/10] Block patches Anthony Liguori
  10 siblings, 0 replies; 26+ messages in thread
From: Kevin Wolf @ 2013-06-04 12:45 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

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

bdrv_snapshot_dump() and bdrv_image_info_dump() do not dump to a buffer now,
some internal buffers are still used for format control, which have no
chance to be truncated. As a result, these two functions have no more issue
of truncation, and they can be used by both qemu and qemu-img with correct
parameter specified.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qapi.c         | 66 ++++++++++++++++++++++++++++------------------------
 include/block/qapi.h |  6 +++--
 qemu-img.c           |  9 +++----
 savevm.c             |  7 +++---
 4 files changed, 49 insertions(+), 39 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index 155e77e..794dbf8 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -259,7 +259,8 @@ static char *get_human_readable_size(char *buf, int buf_size, int64_t size)
     return buf;
 }
 
-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
+void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
+                        QEMUSnapshotInfo *sn)
 {
     char buf1[128], date_buf[128], clock_buf[128];
     struct tm tm;
@@ -267,9 +268,9 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
     int64_t secs;
 
     if (!sn) {
-        snprintf(buf, buf_size,
-                 "%-10s%-20s%7s%20s%15s",
-                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
+        func_fprintf(f,
+                     "%-10s%-20s%7s%20s%15s",
+                     "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
     } else {
         ti = sn->date_sec;
         localtime_r(&ti, &tm);
@@ -282,17 +283,18 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
                  (int)((secs / 60) % 60),
                  (int)(secs % 60),
                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
-        snprintf(buf, buf_size,
-                 "%-10s%-20s%7s%20s%15s",
-                 sn->id_str, sn->name,
-                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
-                 date_buf,
-                 clock_buf);
+        func_fprintf(f,
+                     "%-10s%-20s%7s%20s%15s",
+                     sn->id_str, sn->name,
+                     get_human_readable_size(buf1, sizeof(buf1),
+                                             sn->vm_state_size),
+                     date_buf,
+                     clock_buf);
     }
-    return buf;
 }
 
-void bdrv_image_info_dump(ImageInfo *info)
+void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
+                          ImageInfo *info)
 {
     char size_buf[128], dsize_buf[128];
     if (!info->has_actual_size) {
@@ -302,43 +304,46 @@ void bdrv_image_info_dump(ImageInfo *info)
                                 info->actual_size);
     }
     get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
-    printf("image: %s\n"
-           "file format: %s\n"
-           "virtual size: %s (%" PRId64 " bytes)\n"
-           "disk size: %s\n",
-           info->filename, info->format, size_buf,
-           info->virtual_size,
-           dsize_buf);
+    func_fprintf(f,
+                 "image: %s\n"
+                 "file format: %s\n"
+                 "virtual size: %s (%" PRId64 " bytes)\n"
+                 "disk size: %s\n",
+                 info->filename, info->format, size_buf,
+                 info->virtual_size,
+                 dsize_buf);
 
     if (info->has_encrypted && info->encrypted) {
-        printf("encrypted: yes\n");
+        func_fprintf(f, "encrypted: yes\n");
     }
 
     if (info->has_cluster_size) {
-        printf("cluster_size: %" PRId64 "\n", info->cluster_size);
+        func_fprintf(f, "cluster_size: %" PRId64 "\n",
+                       info->cluster_size);
     }
 
     if (info->has_dirty_flag && info->dirty_flag) {
-        printf("cleanly shut down: no\n");
+        func_fprintf(f, "cleanly shut down: no\n");
     }
 
     if (info->has_backing_filename) {
-        printf("backing file: %s", info->backing_filename);
+        func_fprintf(f, "backing file: %s", info->backing_filename);
         if (info->has_full_backing_filename) {
-            printf(" (actual path: %s)", info->full_backing_filename);
+            func_fprintf(f, " (actual path: %s)", info->full_backing_filename);
         }
-        putchar('\n');
+        func_fprintf(f, "\n");
         if (info->has_backing_filename_format) {
-            printf("backing file format: %s\n", info->backing_filename_format);
+            func_fprintf(f, "backing file format: %s\n",
+                         info->backing_filename_format);
         }
     }
 
     if (info->has_snapshots) {
         SnapshotInfoList *elem;
-        char buf[256];
 
-        printf("Snapshot list:\n");
-        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+        func_fprintf(f, "Snapshot list:\n");
+        bdrv_snapshot_dump(func_fprintf, f, NULL);
+        func_fprintf(f, "\n");
 
         /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but
          * we convert to the block layer's native QEMUSnapshotInfo for now.
@@ -354,7 +359,8 @@ void bdrv_image_info_dump(ImageInfo *info)
 
             pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
             pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
-            printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn));
+            bdrv_snapshot_dump(func_fprintf, f, &sn);
+            func_fprintf(f, "\n");
         }
     }
 }
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 55d1848..e6e568d 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -36,6 +36,8 @@ void bdrv_collect_image_info(BlockDriverState *bs,
 BlockInfo *bdrv_query_info(BlockDriverState *s);
 BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 
-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
-void bdrv_image_info_dump(ImageInfo *info);
+void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
+                        QEMUSnapshotInfo *sn);
+void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
+                          ImageInfo *info);
 #endif
diff --git a/qemu-img.c b/qemu-img.c
index 5d1e480..82c7977 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1554,16 +1554,17 @@ static void dump_snapshots(BlockDriverState *bs)
 {
     QEMUSnapshotInfo *sn_tab, *sn;
     int nb_sns, i;
-    char buf[256];
 
     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
     if (nb_sns <= 0)
         return;
     printf("Snapshot list:\n");
-    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+    bdrv_snapshot_dump(fprintf, stdout, NULL);
+    printf("\n");
     for(i = 0; i < nb_sns; i++) {
         sn = &sn_tab[i];
-        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+        bdrv_snapshot_dump(fprintf, stdout, sn);
+        printf("\n");
     }
     g_free(sn_tab);
 }
@@ -1613,7 +1614,7 @@ static void dump_human_image_info_list(ImageInfoList *list)
         }
         delim = true;
 
-        bdrv_image_info_dump(elem->value);
+        bdrv_image_info_dump(fprintf, stdout, elem->value);
     }
 }
 
diff --git a/savevm.c b/savevm.c
index a886514..2ce439f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2540,7 +2540,6 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict)
     int nb_sns, i, ret, available;
     int total;
     int *available_snapshots;
-    char buf[256];
 
     bs = find_vmstate_bs();
     if (!bs) {
@@ -2583,10 +2582,12 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict)
     }
 
     if (total > 0) {
-        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+        bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, NULL);
+        monitor_printf(mon, "\n");
         for (i = 0; i < total; i++) {
             sn = &sn_tab[available_snapshots[i]];
-            monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+            bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, sn);
+            monitor_printf(mon, "\n");
         }
     } else {
         monitor_printf(mon, "There is no suitable snapshot available\n");
-- 
1.8.1.4

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

* Re: [Qemu-devel] [PULL 00/10] Block patches
  2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
                   ` (9 preceding siblings ...)
  2013-06-04 12:45 ` [Qemu-devel] [PULL 10/10] block: dump snapshot and image info to specified output Kevin Wolf
@ 2013-06-17 21:17 ` Anthony Liguori
  10 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2013-06-17 21:17 UTC (permalink / raw)
  To: Kevin Wolf, anthony; +Cc: qemu-devel

Pulled.  Thanks.

Regards,

Anthony Liguori

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2015-06-12 14:57 Stefan Hajnoczi
  2015-06-15  9:42 ` Peter Maydell
  0 siblings, 1 reply; 26+ messages in thread
From: Stefan Hajnoczi @ 2015-06-12 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Peter Maydell, Stefan Hajnoczi

The following changes since commit d8e3b729cf452d2689c8669f1ec18158db29fd5a:

  Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2015-06-11 15:33:38 +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 2db33f88d2b340c049c576ad75d442e4b6ffe768:

  qemu-iotests: expand test 093 to support group throttling (2015-06-12 14:00:00 +0100)

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

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

Alberto Garcia (7):
  throttle: Add throttle group infrastructure
  throttle: Add throttle group infrastructure tests
  throttle: Add throttle group support
  throttle: acquire the ThrottleGroup lock in bdrv_swap()
  throttle: add the name of the ThrottleGroup to BlockDeviceInfo
  throttle: Update throttle infrastructure copyright
  qemu-iotests: expand test 093 to support group throttling

Benoît Canet (1):
  throttle: Extract timers from ThrottleState into a separate structure

Kevin Wolf (1):
  raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size

Stefan Hajnoczi (1):
  Revert "iothread: release iothread around aio_poll"

 async.c                         |   8 +-
 block.c                         |  38 ++-
 block/Makefile.objs             |   1 +
 block/io.c                      |  71 ++----
 block/qapi.c                    |   8 +-
 block/raw-posix.c               |   5 +-
 block/throttle-groups.c         | 496 ++++++++++++++++++++++++++++++++++++++++
 blockdev.c                      |  38 ++-
 hmp.c                           |  10 +-
 include/block/block.h           |   3 +-
 include/block/block_int.h       |   7 +-
 include/block/throttle-groups.h |  46 ++++
 include/qemu/throttle.h         |  46 ++--
 iothread.c                      |  11 +-
 qapi/block-core.json            |  29 ++-
 qemu-options.hx                 |   1 +
 qmp-commands.hx                 |   3 +-
 tests/qemu-iotests/093          |  89 ++++---
 tests/test-aio.c                |  19 +-
 tests/test-throttle.c           | 163 +++++++++----
 util/throttle.c                 |  81 ++++---
 21 files changed, 954 insertions(+), 219 deletions(-)
 create mode 100644 block/throttle-groups.c
 create mode 100644 include/block/throttle-groups.h

-- 
2.4.2

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

* Re: [Qemu-devel] [PULL 00/10] Block patches
  2015-06-12 14:57 Stefan Hajnoczi
@ 2015-06-15  9:42 ` Peter Maydell
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2015-06-15  9:42 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: Kevin Wolf, QEMU Developers

On 12 June 2015 at 15:57, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> The following changes since commit d8e3b729cf452d2689c8669f1ec18158db29fd5a:
>
>   Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2015-06-11 15:33:38 +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 2db33f88d2b340c049c576ad75d442e4b6ffe768:
>
>   qemu-iotests: expand test 093 to support group throttling (2015-06-12 14:00:00 +0100)
>

Applied, thanks.

-- PMM

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

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

The following changes since commit c688084506cf2cf2eba4ba9df4e91abb6e3dab83:

  Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-secrets-base-2015-12-18-1' into staging (2015-12-18 17:04:15 +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 723697551a7e926abe7d3c7f2966012b8075143d:

  sdhci: add optional quirk property to disable card insertion/removal interrupts (2015-12-22 16:34:26 +0800)

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

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

Andrew Baumann (2):
  sdhci: don't raise a command index error for an unexpected response
  sdhci: add optional quirk property to disable card insertion/removal
    interrupts

Gonglei (1):
  virtio-blk: trivial code optimization

Peter Crosthwaite (1):
  sd: sdhci: Delete over-zealous power check

Stefan Hajnoczi (4):
  block: add BlockLimits.max_iov field
  block-backend: add blk_get_max_iov()
  block: replace IOV_MAX with BlockLimits.max_iov
  block/mirror: replace IOV_MAX with blk_get_max_iov()

Vladimir Sementsov-Ogievskiy (1):
  parallels: add format spec

Yang Wei (1):
  scripts/gdb: Fix a python exception in mtree.py

 MAINTAINERS                    |   1 +
 block/block-backend.c          |   5 +
 block/io.c                     |  10 +-
 block/mirror.c                 |   6 +-
 docs/specs/parallels.txt       | 228 +++++++++++++++++++++++++++++++++++++++++
 hw/block/virtio-blk.c          |  28 ++---
 hw/sd/sdhci.c                  |  10 +-
 include/block/block_int.h      |   3 +
 include/hw/sd/sdhci.h          |   1 +
 include/sysemu/block-backend.h |   1 +
 scripts/qemugdb/mtree.py       |  10 +-
 11 files changed, 272 insertions(+), 31 deletions(-)
 create mode 100644 docs/specs/parallels.txt

-- 
2.5.0

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

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

On 22 December 2015 at 08:54, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> The following changes since commit c688084506cf2cf2eba4ba9df4e91abb6e3dab83:
>
>   Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-secrets-base-2015-12-18-1' into staging (2015-12-18 17:04:15 +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 723697551a7e926abe7d3c7f2966012b8075143d:
>
>   sdhci: add optional quirk property to disable card insertion/removal interrupts (2015-12-22 16:34:26 +0800)
>
> ----------------------------------------------------------------
>
> ----------------------------------------------------------------
>
> Andrew Baumann (2):
>   sdhci: don't raise a command index error for an unexpected response
>   sdhci: add optional quirk property to disable card insertion/removal
>     interrupts
>
> Gonglei (1):
>   virtio-blk: trivial code optimization
>
> Peter Crosthwaite (1):
>   sd: sdhci: Delete over-zealous power check
>
> Stefan Hajnoczi (4):
>   block: add BlockLimits.max_iov field
>   block-backend: add blk_get_max_iov()
>   block: replace IOV_MAX with BlockLimits.max_iov
>   block/mirror: replace IOV_MAX with blk_get_max_iov()
>
> Vladimir Sementsov-Ogievskiy (1):
>   parallels: add format spec
>
> Yang Wei (1):
>   scripts/gdb: Fix a python exception in mtree.py
>
>  MAINTAINERS                    |   1 +
>  block/block-backend.c          |   5 +
>  block/io.c                     |  10 +-
>  block/mirror.c                 |   6 +-
>  docs/specs/parallels.txt       | 228 +++++++++++++++++++++++++++++++++++++++++
>  hw/block/virtio-blk.c          |  28 ++---
>  hw/sd/sdhci.c                  |  10 +-
>  include/block/block_int.h      |   3 +
>  include/hw/sd/sdhci.h          |   1 +
>  include/sysemu/block-backend.h |   1 +
>  scripts/qemugdb/mtree.py       |  10 +-
>  11 files changed, 272 insertions(+), 31 deletions(-)
>  create mode 100644 docs/specs/parallels.txt

Applied, thanks.

-- PMM

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2016-06-29  3:10 Jeff Cody
  2016-06-29 18:13 ` Peter Maydell
  0 siblings, 1 reply; 26+ messages in thread
From: Jeff Cody @ 2016-06-29  3:10 UTC (permalink / raw)
  To: qemu-block; +Cc: peter.maydell, jcody, qemu-devel

The following changes since commit d7f30403576f04f1f3a5fb5a1d18cba8dfa7a6d2:

  cputlb: don't cpu_abort() if guest tries to execute outside RAM or RAM (2016-06-28 18:50:53 +0100)

are available in the git repository at:

  git@github.com:codyprime/qemu-kvm-jtc.git tags/block-pull-request

for you to fetch changes up to 15d6729850728ee49859711dd40b00d8d85d94ee:

  mirror: fix misleading comments (2016-06-28 23:08:25 -0400)

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

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

Changlong Xie (2):
  blockjob: assert(cb) when create job
  mirror: fix misleading comments

Denis V. Lunev (1):
  mirror: fix trace_mirror_yield_in_flight usage in mirror_iteration()

Jeff Cody (1):
  block/gluster: add support for selecting debug logging level

John Snow (3):
  mirror: clarify mirror_do_read return code
  mirror: limit niov to IOV_MAX elements, again
  iotests: add small-granularity mirror test

Niels de Vos (1):
  block/gluster: add support for SEEK_DATA/SEEK_HOLE

Peter Lieven (2):
  block/nfs: refuse readahead if cache.direct is on
  block/nfs: add support for libnfs pagecache

 block/backup.c             |   1 -
 block/gluster.c            | 230 +++++++++++++++++++++++++++++++++++++++++++--
 block/mirror.c             |  14 ++-
 block/nfs.c                |  55 ++++++++++-
 blockjob.c                 |   1 +
 tests/qemu-iotests/041     |  30 ++++++
 tests/qemu-iotests/041.out |   4 +-
 7 files changed, 317 insertions(+), 18 deletions(-)

-- 
1.9.3

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

* Re: [Qemu-devel] [PULL 00/10] Block patches
  2016-06-29  3:10 Jeff Cody
@ 2016-06-29 18:13 ` Peter Maydell
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2016-06-29 18:13 UTC (permalink / raw)
  To: Jeff Cody; +Cc: Qemu-block, QEMU Developers

On 29 June 2016 at 04:10, Jeff Cody <jcody@redhat.com> wrote:
> The following changes since commit d7f30403576f04f1f3a5fb5a1d18cba8dfa7a6d2:
>
>   cputlb: don't cpu_abort() if guest tries to execute outside RAM or RAM (2016-06-28 18:50:53 +0100)
>
> are available in the git repository at:
>
>   git@github.com:codyprime/qemu-kvm-jtc.git tags/block-pull-request
>
> for you to fetch changes up to 15d6729850728ee49859711dd40b00d8d85d94ee:
>
>   mirror: fix misleading comments (2016-06-28 23:08:25 -0400)
>
> ----------------------------------------------------------------
>
> ----------------------------------------------------------------

Applied, thanks.

-- PMM

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

* [Qemu-devel] [PULL 00/10] Block patches
@ 2017-12-18 21:08 Jeff Cody
  2017-12-19 19:10 ` Peter Maydell
  0 siblings, 1 reply; 26+ messages in thread
From: Jeff Cody @ 2017-12-18 21:08 UTC (permalink / raw)
  To: qemu-block; +Cc: peter.maydell, jcody, vsementsov, jsnow, qemu-devel

The following changes since commit 411ad78115ebeb3411cf4b7622784b93dfabe259:

  Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2017-12-15-1' into staging (2017-12-17 15:27:41 +0000)

are available in the git repository at:

  git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request

for you to fetch changes up to 996922de45299878cdc4c15b72b19edf2bc618a4:

  block/curl: fix minor memory leaks (2017-12-18 15:44:39 -0500)

----------------------------------------------------------------
Blockjob and protocol patches
----------------------------------------------------------------

Jeff Cody (4):
  block/sheepdog: remove spurious NULL check
  block/sheepdog: code beautification
  block/curl: check error return of curl_global_init()
  block/curl: fix minor memory leaks

John Snow (1):
  blockjob: kick jobs on set-speed

Vladimir Sementsov-Ogievskiy (5):
  hbitmap: add next_zero function
  backup: move from done_bitmap to copy_bitmap
  backup: init copy_bitmap from sync_bitmap for incremental
  backup: simplify non-dirty bits progress processing
  backup: use copy_bitmap in incremental backup

 block/backup.c               | 116 +++++++++++++++++-------------
 block/curl.c                 |  24 +++++--
 block/dirty-bitmap.c         |   5 ++
 block/sheepdog.c             | 166 +++++++++++++++++++++----------------------
 blockjob.c                   |  30 +++++++-
 include/block/dirty-bitmap.h |   1 +
 include/qemu/hbitmap.h       |   8 +++
 tests/test-hbitmap.c         |  61 ++++++++++++++++
 util/hbitmap.c               |  39 ++++++++++
 9 files changed, 309 insertions(+), 141 deletions(-)

-- 
2.9.5

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

* Re: [Qemu-devel] [PULL 00/10] Block patches
  2017-12-18 21:08 Jeff Cody
@ 2017-12-19 19:10 ` Peter Maydell
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2017-12-19 19:10 UTC (permalink / raw)
  To: Jeff Cody
  Cc: Qemu-block, Vladimir Sementsov-Ogievskiy, John Snow,
	QEMU Developers

On 18 December 2017 at 21:08, Jeff Cody <jcody@redhat.com> wrote:
> The following changes since commit 411ad78115ebeb3411cf4b7622784b93dfabe259:
>
>   Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2017-12-15-1' into staging (2017-12-17 15:27:41 +0000)
>
> are available in the git repository at:
>
>   git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request
>
> for you to fetch changes up to 996922de45299878cdc4c15b72b19edf2bc618a4:
>
>   block/curl: fix minor memory leaks (2017-12-18 15:44:39 -0500)
>
> ----------------------------------------------------------------
> Blockjob and protocol patches
> ----------------------------------------------------------------
>

Applied, thanks.

-- PMM

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

end of thread, other threads:[~2017-12-19 19:11 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-04 12:45 [Qemu-devel] [PULL 00/10] Block patches Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 01/10] qemu-iotests: fix 054 cluster size help output Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 02/10] block: add block driver read only whitelist Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 03/10] qemu-iotests: make assert_no_active_block_jobs() common Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 04/10] qemu-iotests: make cancel_and_wait() common Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 05/10] qemu-iotests: make compare_images() common Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 06/10] qemu-iotests: make create_image() common Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 07/10] block: drop bs_snapshots global variable Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 08/10] block: move snapshot code in block.c to block/snapshot.c Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 09/10] block: move qmp and info dump related code to block/qapi.c Kevin Wolf
2013-06-04 12:45 ` [Qemu-devel] [PULL 10/10] block: dump snapshot and image info to specified output Kevin Wolf
2013-06-17 21:17 ` [Qemu-devel] [PULL 00/10] Block patches Anthony Liguori
  -- strict thread matches above, loose matches on Subject: below --
2017-12-18 21:08 Jeff Cody
2017-12-19 19:10 ` Peter Maydell
2016-06-29  3:10 Jeff Cody
2016-06-29 18:13 ` Peter Maydell
2015-12-22  8:54 Stefan Hajnoczi
2015-12-22 14:47 ` Peter Maydell
2015-06-12 14:57 Stefan Hajnoczi
2015-06-15  9:42 ` Peter Maydell
2012-08-15 13:56 Kevin Wolf
2012-08-15 19:49 ` Anthony Liguori
2011-04-13 12:05 Kevin Wolf
2010-11-04 13:15 Kevin Wolf
2010-08-30 16:32 Kevin Wolf
2010-09-06 15:07 ` 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).