All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/42] Block layer patches
@ 2016-09-05 18:13 Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 01/42] ide: ide-cd without drive property for empty drive Kevin Wolf
                   ` (44 more replies)
  0 siblings, 45 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

The following changes since commit e87d397e5ef66276ccc49b829527d605ca07d0ad:

  Open 2.8 development tree (2016-09-05 11:38:54 +0100)

are available in the git repository at:

  git://repo.or.cz/qemu/kevin.git tags/for-upstream

for you to fetch changes up to 1585512ba88324844c2722fd977b126fc2748604:

  coroutine: reduce stack size to 64kB (2016-09-05 19:06:49 +0200)

----------------------------------------------------------------
Block layer patches

----------------------------------------------------------------
Kevin Wolf (19):
      ide: ide-cd without drive property for empty drive
      scsi: scsi-cd without drive property for empty drive
      block: Accept node-name for block-stream
      block: Accept node-name for block-commit
      block: Accept node-name for blockdev-backup
      block: Accept node-name for blockdev-mirror
      block: Accept node-name for blockdev-snapshot-delete-internal-sync
      block: Accept node-name for blockdev-snapshot-internal-sync
      block: Accept node-name for change-backing-file
      block: Accept node-name for drive-backup
      block: Accept node-name for drive-mirror
      nbd-server: Use a separate BlockBackend
      nbd-server: Allow node name for nbd-server-add
      test-coroutine: Fix coroutine pool corruption
      coroutine: Let CoMutex remember who holds it
      coroutine: Assert that no locks are held on termination
      block jobs: Improve error message for missing job ID
      qemu-iotests: Log QMP traffic in debug mode
      block: Allow node name for 'qemu-io' HMP command

Pavel Butsykin (17):
      block: switch blk_write_compressed() to byte-based interface
      block: Convert bdrv_pwrite_compressed() to BdrvChild
      block/io: reuse bdrv_co_pwritev() for write compressed
      qcow2: add qcow2_co_pwritev_compressed
      qcow2: cleanup qcow2_co_pwritev_compressed to avoid the recursion
      vmdk: add vmdk_co_pwritev_compressed
      qcow: add qcow_co_pwritev_compressed
      qcow: cleanup qcow_co_pwritev_compressed to avoid the recursion
      block: remove BlockDriver.bdrv_write_compressed
      block/io: turn on dirty_bitmaps for the compressed writes
      block: simplify drive-backup
      block: simplify blockdev-backup
      drive-backup: added support for data compression
      blockdev-backup: added support for data compression
      qemu-iotests: test backup compression in 055
      qemu-iotests: add vmdk for test backup compression in 055
      qcow2: fix iovec size at qcow2_co_pwritev_compressed

Peter Lieven (6):
      oslib-posix: add helpers for stack alloc and free
      coroutine: add a macro for the coroutine stack size
      coroutine-ucontext: use helper for allocating stack memory
      coroutine-sigaltstack: use helper for allocating stack memory
      oslib-posix: add a configure switch to debug stack usage
      coroutine: reduce stack size to 64kB

 block.c                        |   2 +
 block/backup.c                 |  12 +-
 block/block-backend.c          |  43 +++--
 block/io.c                     |  48 ++----
 block/qcow.c                   | 113 +++++-------
 block/qcow2.c                  | 128 +++++---------
 block/vmdk.c                   |  55 +-----
 blockdev-nbd.c                 |  21 +--
 blockdev.c                     | 380 ++++++++++++++---------------------------
 blockjob.c                     |   4 +
 configure                      |  19 +++
 hmp-commands.hx                |   8 +-
 hmp.c                          |  37 ++--
 hw/ide/qdev.c                  |  20 ++-
 hw/scsi/scsi-disk.c            |   5 +
 include/block/block.h          |   5 +-
 include/block/block_int.h      |   5 +-
 include/block/nbd.h            |   3 +-
 include/qemu/coroutine.h       |   1 +
 include/qemu/coroutine_int.h   |   3 +
 include/sysemu/block-backend.h |   5 +-
 include/sysemu/os-posix.h      |  27 +++
 nbd/server.c                   |  25 ++-
 qapi/block-core.json           |  42 +++--
 qapi/block.json                |  14 +-
 qemu-img.c                     |   8 +-
 qemu-io-cmds.c                 |   2 +-
 qemu-nbd.c                     |   4 +-
 qmp-commands.hx                |  34 ++--
 tests/qemu-iotests/030         |   2 +-
 tests/qemu-iotests/041         |   8 +-
 tests/qemu-iotests/055         | 125 +++++++++++++-
 tests/qemu-iotests/055.out     |   4 +-
 tests/qemu-iotests/057         |   4 +-
 tests/qemu-iotests/iotests.py  |  15 +-
 tests/test-coroutine.c         |   7 +
 util/coroutine-sigaltstack.c   |   7 +-
 util/coroutine-ucontext.c      |   9 +-
 util/coroutine-win32.c         |   2 +-
 util/oslib-posix.c             |  84 +++++++++
 util/qemu-coroutine-lock.c     |  14 ++
 util/qemu-coroutine.c          |   1 +
 42 files changed, 728 insertions(+), 627 deletions(-)

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

* [Qemu-devel] [PULL 01/42] ide: ide-cd without drive property for empty drive
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 02/42] scsi: scsi-cd " Kevin Wolf
                   ` (43 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

This allows the creation of an empty ide-cd device without manually
creating a BlockBackend.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
 hw/ide/qdev.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 67c76bf..2eb055a 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -75,10 +75,6 @@ static int ide_qdev_init(DeviceState *qdev)
     IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
 
-    if (!dev->conf.blk) {
-        error_report("No drive specified");
-        goto err;
-    }
     if (dev->unit == -1) {
         dev->unit = bus->master ? 1 : 0;
     }
@@ -158,6 +154,16 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
     IDEState *s = bus->ifs + dev->unit;
     Error *err = NULL;
 
+    if (!dev->conf.blk) {
+        if (kind != IDE_CD) {
+            error_report("No drive specified");
+            return -1;
+        } else {
+            /* Anonymous BlockBackend for an empty drive */
+            dev->conf.blk = blk_new();
+        }
+    }
+
     if (dev->conf.discard_granularity == -1) {
         dev->conf.discard_granularity = 512;
     } else if (dev->conf.discard_granularity &&
@@ -257,7 +263,11 @@ static int ide_cd_initfn(IDEDevice *dev)
 
 static int ide_drive_initfn(IDEDevice *dev)
 {
-    DriveInfo *dinfo = blk_legacy_dinfo(dev->conf.blk);
+    DriveInfo *dinfo = NULL;
+
+    if (dev->conf.blk) {
+        dinfo = blk_legacy_dinfo(dev->conf.blk);
+    }
 
     return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
 }
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 02/42] scsi: scsi-cd without drive property for empty drive
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 01/42] ide: ide-cd without drive property for empty drive Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 03/42] block: Accept node-name for block-stream Kevin Wolf
                   ` (42 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

This allows the creation of an empty scsi-cd device without manually
creating a BlockBackend.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 hw/scsi/scsi-disk.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 836a155..99c9d61 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2359,6 +2359,11 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
 static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+
+    if (!dev->conf.blk) {
+        dev->conf.blk = blk_new();
+    }
+
     s->qdev.blocksize = 2048;
     s->qdev.type = TYPE_ROM;
     s->features |= 1 << SCSI_DISK_F_REMOVABLE;
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 03/42] block: Accept node-name for block-stream
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 01/42] ide: ide-cd without drive property for empty drive Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 02/42] scsi: scsi-cd " Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 04/42] block: Accept node-name for block-commit Kevin Wolf
                   ` (41 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
block-stream to accept a node-name without lifting the restriction that
we're operating at a root node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/block-backend.c          | 16 ++++++++++++++++
 blockdev.c                     | 37 +++++++++++++++++++++++++------------
 include/sysemu/block-backend.h |  1 +
 qapi/block-core.json           |  5 +----
 qmp-commands.hx                |  2 +-
 tests/qemu-iotests/030         |  2 +-
 6 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index effa038..dc2bc60 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -410,6 +410,22 @@ bool bdrv_has_blk(BlockDriverState *bs)
 }
 
 /*
+ * Returns true if @bs has only BlockBackends as parents.
+ */
+bool bdrv_is_root_node(BlockDriverState *bs)
+{
+    BdrvChild *c;
+
+    QLIST_FOREACH(c, &bs->parents, next_parent) {
+        if (c->role != &child_root) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/*
  * Return @blk's DriveInfo if any, else null.
  */
 DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
diff --git a/blockdev.c b/blockdev.c
index 2161400..68b6741 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1174,6 +1174,28 @@ fail:
     return dinfo;
 }
 
+static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_lookup_bs(name, name, errp);
+    if (bs == NULL) {
+        return NULL;
+    }
+
+    if (!bdrv_is_root_node(bs)) {
+        error_setg(errp, "Need a root block node");
+        return NULL;
+    }
+
+    if (!bdrv_is_inserted(bs)) {
+        error_setg(errp, "Device has no medium");
+        return NULL;
+    }
+
+    return bs;
+}
+
 void hmp_commit(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_str(qdict, "device");
@@ -2983,7 +3005,6 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
                       bool has_on_error, BlockdevOnError on_error,
                       Error **errp)
 {
-    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *base_bs = NULL;
     AioContext *aio_context;
@@ -2994,22 +3015,14 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
         on_error = BLOCKDEV_ON_ERROR_REPORT;
     }
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, errp);
+    if (!bs) {
         return;
     }
 
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, "Device '%s' has no medium", device);
-        goto out;
-    }
-    bs = blk_bs(blk);
-
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
         goto out;
     }
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 2da4905..bb4fa82 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -98,6 +98,7 @@ BlockDriverState *blk_bs(BlockBackend *blk);
 void blk_remove_bs(BlockBackend *blk);
 void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs);
 bool bdrv_has_blk(BlockDriverState *bs);
+bool bdrv_is_root_node(BlockDriverState *bs);
 
 void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow);
 void blk_iostatus_enable(BlockBackend *blk);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 5e2d7d7..a2d1834 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1462,7 +1462,7 @@
 # @job-id: #optional identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
-# @device: the device name
+# @device: the device name or node-name of a root node
 #
 # @base:   #optional the common backing file name
 #
@@ -1487,9 +1487,6 @@
 #            'stop' and 'enospc' can only be used if the block device
 #            supports io-status (see BlockInfo).  Since 1.3.
 #
-# Returns: Nothing on success
-#          If @device does not exist, DeviceNotFound
-#
 # Since: 1.1
 ##
 { 'command': 'block-stream',
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 6866264..48b7fdc 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1120,7 +1120,7 @@ Arguments:
 
 - "job-id": Identifier for the newly-created block job. If omitted,
             the device name will be used. (json-string, optional)
-- "device": The device's ID, must be unique (json-string)
+- "device": The device name or node-name of a root node (json-string)
 - "base": The file name of the backing image above which copying starts
           (json-string, optional)
 - "backing-file": The backing file string to write into the active layer. This
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 3ac2443..107049b 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -126,7 +126,7 @@ class TestSingleDrive(iotests.QMPTestCase):
 
     def test_device_not_found(self):
         result = self.vm.qmp('block-stream', device='nonexistent')
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
 
 class TestSmallerBackingFile(iotests.QMPTestCase):
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 04/42] block: Accept node-name for block-commit
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (2 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 03/42] block: Accept node-name for block-stream Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 05/42] block: Accept node-name for blockdev-backup Kevin Wolf
                   ` (40 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
block-commit to accept a node-name without lifting the restriction that
we're operating at a root node.

As libvirt makes use of the DeviceNotFound error class, we must add
explicit code to retain this behaviour because qmp_get_root_bs() only
returns GenericErrors.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 blockdev.c           | 23 +++++++++++------------
 qapi/block-core.json |  2 +-
 qmp-commands.hx      |  2 +-
 3 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 68b6741..7619ad4 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3068,7 +3068,6 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
                       bool has_speed, int64_t speed,
                       Error **errp)
 {
-    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *base_bs, *top_bs;
     AioContext *aio_context;
@@ -3087,22 +3086,22 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
      *  live commit feature versions; for this to work, we must make sure to
      *  perform the device lookup before any generic errors that may occur in a
      *  scenario in which all optional arguments are omitted. */
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, &local_err);
+    if (!bs) {
+        bs = bdrv_lookup_bs(device, device, NULL);
+        if (!bs) {
+            error_free(local_err);
+            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+                      "Device '%s' not found", device);
+        } else {
+            error_propagate(errp, local_err);
+        }
         return;
     }
 
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, "Device '%s' has no medium", device);
-        goto out;
-    }
-    bs = blk_bs(blk);
-
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, errp)) {
         goto out;
     }
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a2d1834..04076c8 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1020,7 +1020,7 @@
 # @job-id: #optional identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
-# @device:  the name of the device
+# @device:  the device name or node-name of a root node
 #
 # @base:   #optional The file name of the backing image to write data into.
 #                    If not specified, this is the deepest backing image
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 48b7fdc..b534660 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1166,7 +1166,7 @@ Arguments:
 
 - "job-id": Identifier for the newly-created block job. If omitted,
             the device name will be used. (json-string, optional)
-- "device": The device's ID, must be unique (json-string)
+- "device": The device name or node-name of a root node (json-string)
 - "base": The file name of the backing image to write data into.
           If not specified, this is the deepest backing image
           (json-string, optional)
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 05/42] block: Accept node-name for blockdev-backup
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (3 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 04/42] block: Accept node-name for block-commit Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 06/42] block: Accept node-name for blockdev-mirror Kevin Wolf
                   ` (39 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
blockdev-backup and the corresponding transaction action to accept a
node-name without lifting the restriction that we're operating at a root
node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 31 ++++++++-----------------------
 qapi/block-core.json |  2 +-
 qmp-commands.hx      |  2 +-
 3 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 7619ad4..46beafd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1959,21 +1959,14 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
 {
     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
     BlockdevBackup *backup;
-    BlockBackend *blk;
-    BlockDriverState *target;
+    BlockDriverState *bs, *target;
     Error *local_err = NULL;
 
     assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
     backup = common->action->u.blockdev_backup.data;
 
-    blk = blk_by_name(backup->device);
-    if (!blk) {
-        error_setg(errp, "Device '%s' not found", backup->device);
-        return;
-    }
-
-    if (!blk_is_available(blk)) {
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
+    bs = qmp_get_root_bs(backup->device, errp);
+    if (!bs) {
         return;
     }
 
@@ -1983,14 +1976,14 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
     }
 
     /* AioContext is released in .clean() */
-    state->aio_context = blk_get_aio_context(blk);
+    state->aio_context = bdrv_get_aio_context(bs);
     if (state->aio_context != bdrv_get_aio_context(target)) {
         state->aio_context = NULL;
         error_setg(errp, "Backup between two IO threads is not implemented");
         return;
     }
     aio_context_acquire(state->aio_context);
-    state->bs = blk_bs(blk);
+    state->bs = bs;
     bdrv_drained_begin(state->bs);
 
     do_blockdev_backup(backup->has_job_id ? backup->job_id : NULL,
@@ -3335,7 +3328,6 @@ void do_blockdev_backup(const char *job_id, const char *device,
                          BlockdevOnError on_target_error,
                          BlockJobTxn *txn, Error **errp)
 {
-    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *target_bs;
     Error *local_err = NULL;
@@ -3351,21 +3343,14 @@ void do_blockdev_backup(const char *job_id, const char *device,
         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
     }
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_setg(errp, "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, errp);
+    if (!bs) {
         return;
     }
 
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, "Device '%s' has no medium", device);
-        goto out;
-    }
-    bs = blk_bs(blk);
-
     target_bs = bdrv_lookup_bs(target, target, errp);
     if (!target_bs) {
         goto out;
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 04076c8..53f46b6 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -925,7 +925,7 @@
 # @job-id: #optional identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
-# @device: the name of the device which should be copied.
+# @device: the device name or node-name of a root node which should be copied.
 #
 # @target: the device name or node-name of the backup target node.
 #
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b534660..2077585 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1288,7 +1288,7 @@ Arguments:
 
 - "job-id": Identifier for the newly-created block job. If omitted,
             the device name will be used. (json-string, optional)
-- "device": the name of the device which should be copied.
+- "device": the device name or node-name of a root node which should be copied.
             (json-string)
 - "target": the name of the backup target device. (json-string)
 - "sync": what parts of the disk image should be copied to the destination;
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 06/42] block: Accept node-name for blockdev-mirror
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (4 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 05/42] block: Accept node-name for blockdev-backup Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 07/42] block: Accept node-name for blockdev-snapshot-delete-internal-sync Kevin Wolf
                   ` (38 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
blockdev-mirror to accept a node-name without lifting the restriction
that we're operating at a root node.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 10 +---------
 qapi/block-core.json |  3 ++-
 qmp-commands.hx      |  3 ++-
 3 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 46beafd..ccff1f7 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3627,21 +3627,13 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
                          Error **errp)
 {
     BlockDriverState *bs;
-    BlockBackend *blk;
     BlockDriverState *target_bs;
     AioContext *aio_context;
     BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
     Error *local_err = NULL;
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_setg(errp, "Device '%s' not found", device);
-        return;
-    }
-    bs = blk_bs(blk);
-
+    bs = qmp_get_root_bs(device, errp);
     if (!bs) {
-        error_setg(errp, "Device '%s' has no media", device);
         return;
     }
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 53f46b6..bcb37db 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1277,7 +1277,8 @@
 # @job-id: #optional identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
-# @device: the name of the device whose writes should be mirrored.
+# @device: The device name or node-name of a root node whose writes should be
+#          mirrored.
 #
 # @target: the id or node-name of the block device to mirror to. This mustn't be
 #          attached to guest.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2077585..034d517 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1747,7 +1747,8 @@ Arguments:
 
 - "job-id": Identifier for the newly-created block job. If omitted,
             the device name will be used. (json-string, optional)
-- "device": device name to operate on (json-string)
+- "device": The device name or node-name of a root node whose writes should be
+            mirrored (json-string)
 - "target": device name to mirror to (json-string)
 - "replaces": the block driver node name to replace when finished
               (json-string, optional)
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 07/42] block: Accept node-name for blockdev-snapshot-delete-internal-sync
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (5 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 06/42] block: Accept node-name for blockdev-mirror Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 08/42] block: Accept node-name for blockdev-snapshot-internal-sync Kevin Wolf
                   ` (37 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
blockdev-snapshot-delete-internal-sync to accept a node-name without
lifting the restriction that we're operating at a root node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c             | 16 +++-------------
 qapi/block.json        |  5 +++--
 qmp-commands.hx        |  2 +-
 tests/qemu-iotests/057 |  2 +-
 4 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index ccff1f7..9feffcd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1306,21 +1306,17 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
                                                          Error **errp)
 {
     BlockDriverState *bs;
-    BlockBackend *blk;
     AioContext *aio_context;
     QEMUSnapshotInfo sn;
     Error *local_err = NULL;
     SnapshotInfo *info = NULL;
     int ret;
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, errp);
+    if (!bs) {
         return NULL;
     }
-
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
     if (!has_id) {
@@ -1336,12 +1332,6 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
         goto out_aio_context;
     }
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, "Device '%s' has no medium", device);
-        goto out_aio_context;
-    }
-    bs = blk_bs(blk);
-
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) {
         goto out_aio_context;
     }
diff --git a/qapi/block.json b/qapi/block.json
index 937337d..c0e831f 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -99,14 +99,15 @@
 # both. One of the name or id is required. Return SnapshotInfo for the
 # successfully deleted snapshot.
 #
-# @device: the name of the device to delete the snapshot from
+# @device: the device name or node-name of a root node to delete the snapshot
+#          from
 #
 # @id: optional the snapshot's ID to be deleted
 #
 # @name: optional the snapshot's name to be deleted
 #
 # Returns: SnapshotInfo on success
-#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not a valid block device, GenericError
 #          If snapshot not found, GenericError
 #          If the format of the image used does not support it,
 #          BlockFormatFeatureNotSupported
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 034d517..6793c8d 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1639,7 +1639,7 @@ fail.
 
 Arguments:
 
-- "device": device name (json-string)
+- "device": the device name or node-name of a root node (json-string)
 - "id": ID of the snapshot (json-string, optional)
 - "name": name of the snapshot (json-string, optional)
 
diff --git a/tests/qemu-iotests/057 b/tests/qemu-iotests/057
index 9cdd582..bb6c06a 100755
--- a/tests/qemu-iotests/057
+++ b/tests/qemu-iotests/057
@@ -239,7 +239,7 @@ class TestSnapshotDelete(ImageSnapshotTestCase):
         result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
                               device = 'drive_error',
                               id = '0')
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_error_no_id_and_name(self):
         result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 08/42] block: Accept node-name for blockdev-snapshot-internal-sync
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (6 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 07/42] block: Accept node-name for blockdev-snapshot-delete-internal-sync Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 09/42] block: Accept node-name for change-backing-file Kevin Wolf
                   ` (36 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
blockdev-snapshot-internal-sync to accept a node-name without lifting
the restriction that we're operating at a root node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c             | 15 +++------------
 qapi/block.json        |  5 +++--
 qmp-commands.hx        |  6 ++++--
 tests/qemu-iotests/057 |  2 +-
 4 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 9feffcd..f775bbd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1511,7 +1511,6 @@ static void internal_snapshot_prepare(BlkActionState *common,
     Error *local_err = NULL;
     const char *device;
     const char *name;
-    BlockBackend *blk;
     BlockDriverState *bs;
     QEMUSnapshotInfo old_sn, *sn;
     bool ret;
@@ -1534,23 +1533,15 @@ static void internal_snapshot_prepare(BlkActionState *common,
         return;
     }
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, errp);
+    if (!bs) {
         return;
     }
 
     /* AioContext is released in .clean() */
-    state->aio_context = blk_get_aio_context(blk);
+    state->aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(state->aio_context);
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
-        return;
-    }
-    bs = blk_bs(blk);
-
     state->bs = bs;
     bdrv_drained_begin(bs);
 
diff --git a/qapi/block.json b/qapi/block.json
index c0e831f..db05169 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -58,7 +58,8 @@
 ##
 # @BlockdevSnapshotInternal
 #
-# @device: the name of the device to generate the snapshot from
+# @device: the device name or node-name of a root node to generate the snapshot
+#          from
 #
 # @name: the name of the internal snapshot to be created
 #
@@ -80,7 +81,7 @@
 # For the arguments, see the documentation of BlockdevSnapshotInternal.
 #
 # Returns: nothing on success
-#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not a valid block device, GenericError
 #          If any snapshot matching @name exists, or @name is empty,
 #          GenericError
 #          If the format of the image used does not support it,
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 6793c8d..eb27360 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1407,7 +1407,8 @@ actions array:
       - "mode": whether and how QEMU should create the snapshot file
         (NewImageMode, optional, default "absolute-paths")
       When "type" is "blockdev-snapshot-internal-sync":
-      - "device": device name to snapshot (json-string)
+      - "device": the device name or node-name of a root node to snapshot
+                  (json-string)
       - "name": name of the new snapshot (json-string)
 
 Example:
@@ -1608,7 +1609,8 @@ name already exists, the operation will fail.
 
 Arguments:
 
-- "device": device name to snapshot (json-string)
+- "device": the device name or node-name of a root node to snapshot
+            (json-string)
 - "name": name of the new snapshot (json-string)
 
 Example:
diff --git a/tests/qemu-iotests/057 b/tests/qemu-iotests/057
index bb6c06a..9f0a5a3 100755
--- a/tests/qemu-iotests/057
+++ b/tests/qemu-iotests/057
@@ -182,7 +182,7 @@ class TestSingleTransaction(ImageSnapshotTestCase):
                               'name': 'a' },
                   }]
         result = self.vm.qmp('transaction', actions = actions)
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_error_exist(self):
         self.createSnapshotInTransaction(1)
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 09/42] block: Accept node-name for change-backing-file
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (7 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 08/42] block: Accept node-name for blockdev-snapshot-internal-sync Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 10/42] block: Accept node-name for drive-backup Kevin Wolf
                   ` (35 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
change-backing-file to accept a node-name without lifting the
restriction that we're operating at a root node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 15 +++------------
 qapi/block-core.json |  3 ++-
 qmp-commands.hx      |  3 ++-
 3 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index f775bbd..a42c802 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3755,7 +3755,6 @@ void qmp_change_backing_file(const char *device,
                              const char *backing_file,
                              Error **errp)
 {
-    BlockBackend *blk;
     BlockDriverState *bs = NULL;
     AioContext *aio_context;
     BlockDriverState *image_bs = NULL;
@@ -3764,22 +3763,14 @@ void qmp_change_backing_file(const char *device,
     int open_flags;
     int ret;
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, errp);
+    if (!bs) {
         return;
     }
 
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, "Device '%s' has no medium", device);
-        goto out;
-    }
-    bs = blk_bs(blk);
-
     image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index bcb37db..d25ba46 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -998,7 +998,8 @@
 # @image-node-name: The name of the block driver state node of the
 #                   image to modify.
 #
-# @device:          The name of the device that owns image-node-name.
+# @device:          The device name or node-name of the root node that owns
+#                   image-node-name.
 #
 # @backing-file:    The string to write as the backing file.  This
 #                   string is not validated, so care should be taken
diff --git a/qmp-commands.hx b/qmp-commands.hx
index eb27360..c4ca603 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1806,7 +1806,8 @@ Arguments:
                         "device".
                         (json-string, optional)
 
-- "device":             The name of the device.
+- "device":             The device name or node-name of the root node that owns
+                        image-node-name.
                         (json-string)
 
 - "backing-file":       The string to write as the backing file.  This string is
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 10/42] block: Accept node-name for drive-backup
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (8 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 09/42] block: Accept node-name for change-backing-file Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 11/42] block: Accept node-name for drive-mirror Kevin Wolf
                   ` (34 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
drive-backup and the corresponding transaction action to accept a
node-name without lifting the restriction that we're operating at a root
node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c             | 36 +++++++++---------------------------
 qapi/block-core.json   |  4 ++--
 qmp-commands.hx        |  2 +-
 tests/qemu-iotests/055 |  7 ++-----
 4 files changed, 14 insertions(+), 35 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index a42c802..773336c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1856,30 +1856,23 @@ static void do_drive_backup(const char *job_id, const char *device,
 static void drive_backup_prepare(BlkActionState *common, Error **errp)
 {
     DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
-    BlockBackend *blk;
+    BlockDriverState *bs;
     DriveBackup *backup;
     Error *local_err = NULL;
 
     assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
     backup = common->action->u.drive_backup.data;
 
-    blk = blk_by_name(backup->device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", backup->device);
-        return;
-    }
-
-    if (!blk_is_available(blk)) {
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
+    bs = qmp_get_root_bs(backup->device, errp);
+    if (!bs) {
         return;
     }
 
     /* AioContext is released in .clean() */
-    state->aio_context = blk_get_aio_context(blk);
+    state->aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(state->aio_context);
-    bdrv_drained_begin(blk_bs(blk));
-    state->bs = blk_bs(blk);
+    bdrv_drained_begin(bs);
+    state->bs = bs;
 
     do_drive_backup(backup->has_job_id ? backup->job_id : NULL,
                     backup->device, backup->target,
@@ -3153,7 +3146,6 @@ static void do_drive_backup(const char *job_id, const char *device,
                             BlockdevOnError on_target_error,
                             BlockJobTxn *txn, Error **errp)
 {
-    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *target_bs;
     BlockDriverState *source = NULL;
@@ -3177,24 +3169,14 @@ static void do_drive_backup(const char *job_id, const char *device,
         mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
     }
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
+    bs = qmp_get_root_bs(device, errp);
+    if (!bs) {
         return;
     }
 
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    /* Although backup_run has this check too, we need to use bs->drv below, so
-     * do an early check redundantly. */
-    if (!blk_is_available(blk)) {
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
-        goto out;
-    }
-    bs = blk_bs(blk);
-
     if (!has_format) {
         format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
     }
diff --git a/qapi/block-core.json b/qapi/block-core.json
index d25ba46..f081eb8 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -876,7 +876,7 @@
 # @job-id: #optional identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
-# @device: the name of the device which should be copied.
+# @device: the device name or node-name of a root node which should be copied.
 #
 # @target: the target of the new image. If the file exists, or if it
 #          is a device, the existing file/device will be used as the new
@@ -1087,7 +1087,7 @@
 # For the arguments, see the documentation of DriveBackup.
 #
 # Returns: nothing on success
-#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not a valid block device, GenericError
 #
 # Since 1.6
 ##
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c4ca603..c5e6cd5 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1235,7 +1235,7 @@ Arguments:
 
 - "job-id": Identifier for the newly-created block job. If omitted,
             the device name will be used. (json-string, optional)
-- "device": the name of the device which should be copied.
+- "device": the device name or node-name of a root node which should be copied.
             (json-string)
 - "target": the target of the new image. If the file exists, or if it is a
             device, the existing file/device will be used as the new
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index c8e3578..8113c61 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -134,10 +134,7 @@ class TestSingleDrive(iotests.QMPTestCase):
 
     def do_test_device_not_found(self, cmd, **args):
         result = self.vm.qmp(cmd, **args)
-        if cmd == 'drive-backup':
-            self.assert_qmp(result, 'error/class', 'DeviceNotFound')
-        else:
-            self.assert_qmp(result, 'error/class', 'GenericError')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_device_not_found(self):
         self.do_test_device_not_found('drive-backup', device='nonexistent',
@@ -371,7 +368,7 @@ class TestSingleTransaction(iotests.QMPTestCase):
                           'sync': 'full' },
             }
         ])
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
         result = self.vm.qmp('transaction', actions=[{
                 'type': 'blockdev-backup',
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 11/42] block: Accept node-name for drive-mirror
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (9 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 10/42] block: Accept node-name for drive-backup Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 12/42] nbd-server: Use a separate BlockBackend Kevin Wolf
                   ` (33 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
drive-mirror to accept a node-name without lifting the restriction that
we're operating at a root node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c             | 14 +++-----------
 qapi/block-core.json   |  5 +++--
 qmp-commands.hx        |  3 ++-
 tests/qemu-iotests/041 |  8 +++-----
 4 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 773336c..a392e08 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3429,7 +3429,6 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
 void qmp_drive_mirror(DriveMirror *arg, Error **errp)
 {
     BlockDriverState *bs;
-    BlockBackend *blk;
     BlockDriverState *source, *target_bs;
     AioContext *aio_context;
     BlockMirrorBackingMode backing_mode;
@@ -3439,21 +3438,14 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
     int64_t size;
     const char *format = arg->format;
 
-    blk = blk_by_name(arg->device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", arg->device);
+    bs = qmp_get_root_bs(arg->device, errp);
+    if (!bs) {
         return;
     }
 
-    aio_context = blk_get_aio_context(blk);
+    aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!blk_is_available(blk)) {
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, arg->device);
-        goto out;
-    }
-    bs = blk_bs(blk);
     if (!arg->has_mode) {
         arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
     }
diff --git a/qapi/block-core.json b/qapi/block-core.json
index f081eb8..fba1718 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1128,7 +1128,7 @@
 # See DriveMirror for parameter descriptions
 #
 # Returns: nothing on success
-#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not a valid block device, GenericError
 #
 # Since 1.3
 ##
@@ -1143,7 +1143,8 @@
 # @job-id: #optional identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
-# @device:  the name of the device whose writes should be mirrored.
+# @device:  the device name or node-name of a root node whose writes should be
+#           mirrored.
 #
 # @target: the target of the new image. If the file exists, or if it
 #          is a device, the existing file/device will be used as the new
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c5e6cd5..956f1b0 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1689,7 +1689,8 @@ Arguments:
 
 - "job-id": Identifier for the newly-created block job. If omitted,
             the device name will be used. (json-string, optional)
-- "device": device name to operate on (json-string)
+- "device": the device name or node-name of a root node whose writes should be
+            mirrored. (json-string)
 - "target": name of new image file (json-string)
 - "format": format of new image (json-string, optional)
 - "node-name": the name of the new block driver state in the node graph
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index cbf5e0b..80939c0 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -38,7 +38,6 @@ class TestSingleDrive(iotests.QMPTestCase):
     image_len = 1 * 1024 * 1024 # MB
     qmp_cmd = 'drive-mirror'
     qmp_target = target_img
-    not_found_error = 'DeviceNotFound'
 
     def setUp(self):
         iotests.create_image(backing_img, self.image_len)
@@ -176,7 +175,7 @@ class TestSingleDrive(iotests.QMPTestCase):
 
         result = self.vm.qmp(self.qmp_cmd, device='ide1-cd0', sync='full',
                              target=self.qmp_target)
-        self.assert_qmp(result, 'error/class', self.not_found_error)
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_image_not_found(self):
         result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
@@ -186,12 +185,11 @@ class TestSingleDrive(iotests.QMPTestCase):
     def test_device_not_found(self):
         result = self.vm.qmp(self.qmp_cmd, device='nonexistent', sync='full',
                              target=self.qmp_target)
-        self.assert_qmp(result, 'error/class', self.not_found_error)
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
 class TestSingleBlockdev(TestSingleDrive):
     qmp_cmd = 'blockdev-mirror'
     qmp_target = 'node1'
-    not_found_error = 'GenericError'
 
     def setUp(self):
         TestSingleDrive.setUp(self)
@@ -922,7 +920,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
                              node_name='repair0',
                              replaces='img1',
                              target=quorum_repair_img, format=iotests.imgfmt)
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_wrong_sync_mode(self):
         if not self.has_quorum():
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 12/42] nbd-server: Use a separate BlockBackend
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (10 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 11/42] block: Accept node-name for drive-mirror Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 13/42] nbd-server: Allow node name for nbd-server-add Kevin Wolf
                   ` (32 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

The builtin NBD server uses its own BlockBackend now instead of reusing
the monitor/guest device one.

This means that it has its own writethrough setting now. The builtin
NBD server always uses writeback caching now regardless of whether the
guest device has WCE enabled. qemu-nbd respects the cache mode given on
the command line.

We still need to keep a reference to the monitor BB because we put an
eject notifier on it, but we don't use it for any I/O.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block.c             |  2 ++
 blockdev-nbd.c      |  4 ++--
 include/block/nbd.h |  3 ++-
 nbd/server.c        | 25 ++++++++++++++++++++-----
 qemu-nbd.c          |  4 ++--
 5 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/block.c b/block.c
index 30d64e6..101f8c6 100644
--- a/block.c
+++ b/block.c
@@ -25,6 +25,7 @@
 #include "trace.h"
 #include "block/block_int.h"
 #include "block/blockjob.h"
+#include "block/nbd.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "qapi/qmp/qerror.h"
@@ -2206,6 +2207,7 @@ static void bdrv_close(BlockDriverState *bs)
 void bdrv_close_all(void)
 {
     block_job_cancel_sync_all();
+    nbd_export_close_all();
 
     /* Drop references from requests still in flight, such as canceled block
      * jobs whose AIO context has not been polled yet */
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 12cae0e..c437d32 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -176,8 +176,8 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
         writable = false;
     }
 
-    exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL,
-                         errp);
+    exp = nbd_export_new(blk_bs(blk), 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
+                         NULL, false, blk, errp);
     if (!exp) {
         return;
     }
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 1897557..80610ff 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -103,8 +103,9 @@ int nbd_disconnect(int fd);
 typedef struct NBDExport NBDExport;
 typedef struct NBDClient NBDClient;
 
-NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
+NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
                           uint16_t nbdflags, void (*close)(NBDExport *),
+                          bool writethrough, BlockBackend *on_eject_blk,
                           Error **errp);
 void nbd_export_close(NBDExport *exp);
 void nbd_export_get(NBDExport *exp);
diff --git a/nbd/server.c b/nbd/server.c
index 80fbb4d..472f584 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -69,6 +69,7 @@ struct NBDExport {
 
     AioContext *ctx;
 
+    BlockBackend *eject_notifier_blk;
     Notifier eject_notifier;
 };
 
@@ -807,11 +808,18 @@ static void nbd_eject_notifier(Notifier *n, void *data)
     nbd_export_close(exp);
 }
 
-NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
+NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
                           uint16_t nbdflags, void (*close)(NBDExport *),
+                          bool writethrough, BlockBackend *on_eject_blk,
                           Error **errp)
 {
+    BlockBackend *blk;
     NBDExport *exp = g_malloc0(sizeof(NBDExport));
+
+    blk = blk_new();
+    blk_insert_bs(blk, bs);
+    blk_set_enable_write_cache(blk, !writethrough);
+
     exp->refcount = 1;
     QTAILQ_INIT(&exp->clients);
     exp->blk = blk;
@@ -827,11 +835,14 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
 
     exp->close = close;
     exp->ctx = blk_get_aio_context(blk);
-    blk_ref(blk);
     blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
 
-    exp->eject_notifier.notify = nbd_eject_notifier;
-    blk_add_remove_bs_notifier(blk, &exp->eject_notifier);
+    if (on_eject_blk) {
+        blk_ref(on_eject_blk);
+        exp->eject_notifier_blk = on_eject_blk;
+        exp->eject_notifier.notify = nbd_eject_notifier;
+        blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier);
+    }
 
     /*
      * NBD exports are used for non-shared storage migration.  Make sure
@@ -844,6 +855,7 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
     return exp;
 
 fail:
+    blk_unref(blk);
     g_free(exp);
     return NULL;
 }
@@ -914,7 +926,10 @@ void nbd_export_put(NBDExport *exp)
         }
 
         if (exp->blk) {
-            notifier_remove(&exp->eject_notifier);
+            if (exp->eject_notifier_blk) {
+                notifier_remove(&exp->eject_notifier);
+                blk_unref(exp->eject_notifier_blk);
+            }
             blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
                                             blk_aio_detach, exp);
             blk_unref(exp->blk);
diff --git a/qemu-nbd.c b/qemu-nbd.c
index e3571c2..99297a5 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -910,8 +910,8 @@ int main(int argc, char **argv)
         }
     }
 
-    exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed,
-                         &local_err);
+    exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed,
+                         writethrough, NULL, &local_err);
     if (!exp) {
         error_report_err(local_err);
         exit(EXIT_FAILURE);
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 13/42] nbd-server: Allow node name for nbd-server-add
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (11 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 12/42] nbd-server: Use a separate BlockBackend Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 14/42] block: switch blk_write_compressed() to byte-based interface Kevin Wolf
                   ` (31 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

There is no reason why an NBD server couldn't be started for any node,
even if it's not on the top level. This converts nbd-server-add to
accept a node-name.

Note that there is a semantic difference between using a BlockBackend
name and the node name of its root: In the former case, the NBD server
is closed on eject; in the latter case, the NBD server doesn't drop its
reference and keeps the image file open this way.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 blockdev-nbd.c  | 21 +++++++++------------
 qapi/block.json |  4 ++--
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index c437d32..ca41cc6 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -145,7 +145,8 @@ void qmp_nbd_server_start(SocketAddress *addr,
 void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
                         Error **errp)
 {
-    BlockBackend *blk;
+    BlockDriverState *bs = NULL;
+    BlockBackend *on_eject_blk;
     NBDExport *exp;
 
     if (!nbd_server) {
@@ -158,26 +159,22 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
         return;
     }
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-                  "Device '%s' not found", device);
-        return;
-    }
-    if (!blk_is_inserted(blk)) {
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+    on_eject_blk = blk_by_name(device);
+
+    bs = bdrv_lookup_bs(device, device, errp);
+    if (!bs) {
         return;
     }
 
     if (!has_writable) {
         writable = false;
     }
-    if (blk_is_read_only(blk)) {
+    if (bdrv_is_read_only(bs)) {
         writable = false;
     }
 
-    exp = nbd_export_new(blk_bs(blk), 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
-                         NULL, false, blk, errp);
+    exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
+                         NULL, false, on_eject_blk, errp);
     if (!exp) {
         return;
     }
diff --git a/qapi/block.json b/qapi/block.json
index db05169..8b08bd2 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -161,9 +161,9 @@
 ##
 # @nbd-server-add:
 #
-# Export a device to QEMU's embedded NBD server.
+# Export a block node to QEMU's embedded NBD server.
 #
-# @device: Block device to be exported
+# @device: The device name or node name of the node to be exported
 #
 # @writable: Whether clients should be able to write to the device via the
 #     NBD connection (default false). #optional
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 14/42] block: switch blk_write_compressed() to byte-based interface
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (12 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 13/42] nbd-server: Allow node name for nbd-server-add Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 15/42] block: Convert bdrv_pwrite_compressed() to BdrvChild Kevin Wolf
                   ` (30 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

This is a preparatory patch, which continues the general trend of the
transition to the byte-based interfaces. bdrv_check_request() and
blk_check_request() are no longer used, thus we can remove them.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/block-backend.c          | 23 ++++-------------------
 block/io.c                     | 22 +++++++---------------
 include/block/block.h          |  4 ++--
 include/sysemu/block-backend.h |  4 ++--
 qemu-img.c                     |  6 ++++--
 qemu-io-cmds.c                 |  2 +-
 6 files changed, 20 insertions(+), 41 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index dc2bc60..4c704a1 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -743,21 +743,6 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
     return 0;
 }
 
-static int blk_check_request(BlockBackend *blk, int64_t sector_num,
-                             int nb_sectors)
-{
-    if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
-        return -EIO;
-    }
-
-    if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
-        return -EIO;
-    }
-
-    return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
-                                  nb_sectors * BDRV_SECTOR_SIZE);
-}
-
 int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
                                unsigned int bytes, QEMUIOVector *qiov,
                                BdrvRequestFlags flags)
@@ -1500,15 +1485,15 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
                           flags | BDRV_REQ_ZERO_WRITE);
 }
 
-int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
-                         const uint8_t *buf, int nb_sectors)
+int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
+                          int count)
 {
-    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    int ret = blk_check_byte_request(blk, offset, count);
     if (ret < 0) {
         return ret;
     }
 
-    return bdrv_write_compressed(blk_bs(blk), sector_num, buf, nb_sectors);
+    return bdrv_pwrite_compressed(blk_bs(blk), offset, buf, count);
 }
 
 int blk_truncate(BlockBackend *blk, int64_t offset)
diff --git a/block/io.c b/block/io.c
index 420944d..da874d0 100644
--- a/block/io.c
+++ b/block/io.c
@@ -540,17 +540,6 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
     return 0;
 }
 
-static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
-                              int nb_sectors)
-{
-    if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
-        return -EIO;
-    }
-
-    return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
-                                   nb_sectors * BDRV_SECTOR_SIZE);
-}
-
 typedef struct RwCo {
     BdrvChild *child;
     int64_t offset;
@@ -1879,8 +1868,8 @@ int bdrv_is_allocated_above(BlockDriverState *top,
     return 0;
 }
 
-int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
-                          const uint8_t *buf, int nb_sectors)
+int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset,
+                           const void *buf, int bytes)
 {
     BlockDriver *drv = bs->drv;
     int ret;
@@ -1891,14 +1880,17 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
     if (!drv->bdrv_write_compressed) {
         return -ENOTSUP;
     }
-    ret = bdrv_check_request(bs, sector_num, nb_sectors);
+    ret = bdrv_check_byte_request(bs, offset, bytes);
     if (ret < 0) {
         return ret;
     }
 
     assert(QLIST_EMPTY(&bs->dirty_bitmaps));
+    assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
+    assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
 
-    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
+    return drv->bdrv_write_compressed(bs, offset >> BDRV_SECTOR_BITS, buf,
+                                      bytes >> BDRV_SECTOR_BITS);
 }
 
 typedef struct BdrvVmstateCo {
diff --git a/include/block/block.h b/include/block/block.h
index 11c162d..b4a97f2 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -399,8 +399,8 @@ const char *bdrv_get_node_name(const BlockDriverState *bs);
 const char *bdrv_get_device_name(const BlockDriverState *bs);
 const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
 int bdrv_get_flags(BlockDriverState *bs);
-int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
-                          const uint8_t *buf, int nb_sectors);
+int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset,
+                           const void *buf, int bytes);
 int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
 ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
 void bdrv_round_sectors_to_clusters(BlockDriverState *bs,
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index bb4fa82..4808a96 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -204,8 +204,8 @@ void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
                   BlockCompletionFunc *cb, void *opaque);
 int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
                                       int count, BdrvRequestFlags flags);
-int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
-                         const uint8_t *buf, int nb_sectors);
+int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
+                          int count);
 int blk_truncate(BlockBackend *blk, int64_t offset);
 int blk_pdiscard(BlockBackend *blk, int64_t offset, int count);
 int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
diff --git a/qemu-img.c b/qemu-img.c
index f204d041..ef0157a 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1590,7 +1590,9 @@ static int convert_write(ImgConvertState *s, int64_t sector_num, int nb_sectors,
                     break;
                 }
 
-                ret = blk_write_compressed(s->target, sector_num, buf, n);
+                ret = blk_pwrite_compressed(s->target,
+                                            sector_num << BDRV_SECTOR_BITS,
+                                            buf, n << BDRV_SECTOR_BITS);
                 if (ret < 0) {
                     return ret;
                 }
@@ -1727,7 +1729,7 @@ static int convert_do_copy(ImgConvertState *s)
 
     if (s->compressed) {
         /* signal EOF to align */
-        ret = blk_write_compressed(s->target, 0, NULL, 0);
+        ret = blk_pwrite_compressed(s->target, 0, NULL, 0);
         if (ret < 0) {
             goto fail;
         }
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 25954f5..3a3838a 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -504,7 +504,7 @@ static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
         return -ERANGE;
     }
 
-    ret = blk_write_compressed(blk, offset >> 9, (uint8_t *)buf, count >> 9);
+    ret = blk_pwrite_compressed(blk, offset, buf, count);
     if (ret < 0) {
         return ret;
     }
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 15/42] block: Convert bdrv_pwrite_compressed() to BdrvChild
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (13 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 14/42] block: switch blk_write_compressed() to byte-based interface Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 16/42] block/io: reuse bdrv_co_pwritev() for write compressed Kevin Wolf
                   ` (29 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/block-backend.c | 2 +-
 block/io.c            | 3 ++-
 include/block/block.h | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 4c704a1..76ea459 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1493,7 +1493,7 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
         return ret;
     }
 
-    return bdrv_pwrite_compressed(blk_bs(blk), offset, buf, count);
+    return bdrv_pwrite_compressed(blk->root, offset, buf, count);
 }
 
 int blk_truncate(BlockBackend *blk, int64_t offset)
diff --git a/block/io.c b/block/io.c
index da874d0..c528fea 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1868,9 +1868,10 @@ int bdrv_is_allocated_above(BlockDriverState *top,
     return 0;
 }
 
-int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset,
+int bdrv_pwrite_compressed(BdrvChild *child, int64_t offset,
                            const void *buf, int bytes)
 {
+    BlockDriverState *bs = child->bs;
     BlockDriver *drv = bs->drv;
     int ret;
 
diff --git a/include/block/block.h b/include/block/block.h
index b4a97f2..7bb5ddb 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -399,7 +399,7 @@ const char *bdrv_get_node_name(const BlockDriverState *bs);
 const char *bdrv_get_device_name(const BlockDriverState *bs);
 const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
 int bdrv_get_flags(BlockDriverState *bs);
-int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset,
+int bdrv_pwrite_compressed(BdrvChild *child, int64_t offset,
                            const void *buf, int bytes);
 int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
 ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 16/42] block/io: reuse bdrv_co_pwritev() for write compressed
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (14 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 15/42] block: Convert bdrv_pwrite_compressed() to BdrvChild Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 17/42] qcow2: add qcow2_co_pwritev_compressed Kevin Wolf
                   ` (28 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

For bdrv_pwrite_compressed() it looks like most of the code creating
coroutine is duplicated in bdrv_prwv_co(). So we can just add a flag
(BDRV_REQ_WRITE_COMPRESSED) and use bdrv_prwv_co() as a generic one.
In the end we get coroutine oriented function for write compressed by using
bdrv_co_pwritev/blk_co_pwritev with BDRV_REQ_WRITE_COMPRESSED flag.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/io.c                | 56 +++++++++++++++++++++++++++++++++--------------
 include/block/block.h     |  3 ++-
 include/block/block_int.h |  3 +++
 qemu-img.c                |  2 +-
 4 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/block/io.c b/block/io.c
index c528fea..d402076 100644
--- a/block/io.c
+++ b/block/io.c
@@ -886,6 +886,20 @@ emulate_flags:
     return ret;
 }
 
+static int coroutine_fn
+bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
+                               uint64_t bytes, QEMUIOVector *qiov)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv->bdrv_co_pwritev_compressed) {
+        return -ENOTSUP;
+    }
+
+    assert(QLIST_EMPTY(&bs->dirty_bitmaps));
+    return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
+}
+
 static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
         int64_t offset, unsigned int bytes, QEMUIOVector *qiov)
 {
@@ -1555,9 +1569,14 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
         bytes = ROUND_UP(bytes, align);
     }
 
-    ret = bdrv_aligned_pwritev(bs, &req, offset, bytes, align,
-                               use_local_qiov ? &local_qiov : qiov,
-                               flags);
+    if (flags & BDRV_REQ_WRITE_COMPRESSED) {
+        ret = bdrv_driver_pwritev_compressed(
+                bs, offset, bytes, use_local_qiov ? &local_qiov : qiov);
+    } else {
+        ret = bdrv_aligned_pwritev(bs, &req, offset, bytes, align,
+                                   use_local_qiov ? &local_qiov : qiov,
+                                   flags);
+    }
 
 fail:
 
@@ -1873,25 +1892,30 @@ int bdrv_pwrite_compressed(BdrvChild *child, int64_t offset,
 {
     BlockDriverState *bs = child->bs;
     BlockDriver *drv = bs->drv;
-    int ret;
+    QEMUIOVector qiov;
+    struct iovec iov;
 
     if (!drv) {
         return -ENOMEDIUM;
     }
-    if (!drv->bdrv_write_compressed) {
-        return -ENOTSUP;
-    }
-    ret = bdrv_check_byte_request(bs, offset, bytes);
-    if (ret < 0) {
-        return ret;
+    if (drv->bdrv_write_compressed) {
+        int ret = bdrv_check_byte_request(bs, offset, bytes);
+        if (ret < 0) {
+            return ret;
+        }
+        assert(QLIST_EMPTY(&bs->dirty_bitmaps));
+        assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
+        assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+        return drv->bdrv_write_compressed(bs, offset >> BDRV_SECTOR_BITS, buf,
+                                          bytes >> BDRV_SECTOR_BITS);
     }
+    iov = (struct iovec) {
+        .iov_base = (void *)buf,
+        .iov_len = bytes,
+    };
+    qemu_iovec_init_external(&qiov, &iov, 1);
 
-    assert(QLIST_EMPTY(&bs->dirty_bitmaps));
-    assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
-    assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
-
-    return drv->bdrv_write_compressed(bs, offset >> BDRV_SECTOR_BITS, buf,
-                                      bytes >> BDRV_SECTOR_BITS);
+    return bdrv_prwv_co(child, offset, &qiov, true, BDRV_REQ_WRITE_COMPRESSED);
 }
 
 typedef struct BdrvVmstateCo {
diff --git a/include/block/block.h b/include/block/block.h
index 7bb5ddb..d8dacd2 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -65,9 +65,10 @@ typedef enum {
     BDRV_REQ_MAY_UNMAP          = 0x4,
     BDRV_REQ_NO_SERIALISING     = 0x8,
     BDRV_REQ_FUA                = 0x10,
+    BDRV_REQ_WRITE_COMPRESSED   = 0x20,
 
     /* Mask of valid flags */
-    BDRV_REQ_MASK               = 0x1f,
+    BDRV_REQ_MASK               = 0x3f,
 } BdrvRequestFlags;
 
 typedef struct BlockSizes {
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1e939de..42f8f84 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -207,6 +207,9 @@ struct BlockDriver {
     int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
                                  const uint8_t *buf, int nb_sectors);
 
+    int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
+        uint64_t offset, uint64_t bytes, QEMUIOVector *qiov);
+
     int (*bdrv_snapshot_create)(BlockDriverState *bs,
                                 QEMUSnapshotInfo *sn_info);
     int (*bdrv_snapshot_goto)(BlockDriverState *bs,
diff --git a/qemu-img.c b/qemu-img.c
index ef0157a..c2ea494 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2034,7 +2034,7 @@ static int img_convert(int argc, char **argv)
         const char *preallocation =
             qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
 
-        if (!drv->bdrv_write_compressed) {
+        if (!drv->bdrv_write_compressed && !drv->bdrv_co_pwritev_compressed) {
             error_report("Compression not supported for this file format");
             ret = -1;
             goto out;
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 17/42] qcow2: add qcow2_co_pwritev_compressed
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (15 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 16/42] block/io: reuse bdrv_co_pwritev() for write compressed Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 18/42] qcow2: cleanup qcow2_co_pwritev_compressed to avoid the recursion Kevin Wolf
                   ` (27 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Added implementation of the qcow2_co_pwritev_compressed function that
will allow us to safely use compressed writes for the qcow2 from running
VMs.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2.c | 124 +++++++++++++++++++++++-----------------------------------
 1 file changed, 50 insertions(+), 74 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 91ef4df..1cbaa8f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2533,84 +2533,49 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
     return 0;
 }
 
-typedef struct Qcow2WriteCo {
-    BlockDriverState *bs;
-    int64_t sector_num;
-    const uint8_t *buf;
-    int nb_sectors;
-    int ret;
-} Qcow2WriteCo;
-
-static void qcow2_write_co_entry(void *opaque)
-{
-    Qcow2WriteCo *co = opaque;
-    QEMUIOVector qiov;
-    uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE;
-    uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE;
-
-    struct iovec iov = (struct iovec) {
-        .iov_base   = (uint8_t*) co->buf,
-        .iov_len    = bytes,
-    };
-    qemu_iovec_init_external(&qiov, &iov, 1);
-
-    co->ret = qcow2_co_pwritev(co->bs, offset, bytes, &qiov, 0);
-}
-
-/* Wrapper for non-coroutine contexts */
-static int qcow2_write(BlockDriverState *bs, int64_t sector_num,
-                       const uint8_t *buf, int nb_sectors)
-{
-    Coroutine *co;
-    AioContext *aio_context = bdrv_get_aio_context(bs);
-    Qcow2WriteCo data = {
-        .bs         = bs,
-        .sector_num = sector_num,
-        .buf        = buf,
-        .nb_sectors = nb_sectors,
-        .ret        = -EINPROGRESS,
-    };
-    co = qemu_coroutine_create(qcow2_write_co_entry, &data);
-    qemu_coroutine_enter(co);
-    while (data.ret == -EINPROGRESS) {
-        aio_poll(aio_context, true);
-    }
-    return data.ret;
-}
-
 /* XXX: put compressed sectors first, then all the cluster aligned
    tables to avoid losing bytes in alignment */
-static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
-                                  const uint8_t *buf, int nb_sectors)
+static coroutine_fn int
+qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
+                            uint64_t bytes, QEMUIOVector *qiov)
 {
     BDRVQcow2State *s = bs->opaque;
+    QEMUIOVector hd_qiov;
+    struct iovec iov;
     z_stream strm;
     int ret, out_len;
-    uint8_t *out_buf;
+    uint8_t *buf, *out_buf;
     uint64_t cluster_offset;
 
-    if (nb_sectors == 0) {
+    if (bytes == 0) {
         /* align end of file to a sector boundary to ease reading with
            sector based I/Os */
         cluster_offset = bdrv_getlength(bs->file->bs);
         return bdrv_truncate(bs->file->bs, cluster_offset);
     }
 
-    if (nb_sectors != s->cluster_sectors) {
+    if (bytes != s->cluster_size) {
         ret = -EINVAL;
 
         /* Zero-pad last write if image size is not cluster aligned */
-        if (sector_num + nb_sectors == bs->total_sectors &&
-            nb_sectors < s->cluster_sectors) {
+        if (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS &&
+            bytes < s->cluster_size)
+        {
             uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
             memset(pad_buf, 0, s->cluster_size);
-            memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
-            ret = qcow2_write_compressed(bs, sector_num,
-                                         pad_buf, s->cluster_sectors);
+            qemu_iovec_to_buf(qiov, 0, pad_buf, s->cluster_size);
+            iov = (struct iovec) {
+                .iov_base   = pad_buf,
+                .iov_len    = s->cluster_size,
+            };
+            qemu_iovec_init_external(&hd_qiov, &iov, 1);
+            ret = qcow2_co_pwritev_compressed(bs, offset, bytes, &hd_qiov);
             qemu_vfree(pad_buf);
         }
         return ret;
     }
+    buf = qemu_blockalign(bs, s->cluster_size);
+    qemu_iovec_to_buf(qiov, 0, buf, s->cluster_size);
 
     out_buf = g_malloc(s->cluster_size);
 
@@ -2641,33 +2606,44 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
     if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
         /* could not compress: write normal cluster */
-        ret = qcow2_write(bs, sector_num, buf, s->cluster_sectors);
+        ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);
         if (ret < 0) {
             goto fail;
         }
-    } else {
-        cluster_offset = qcow2_alloc_compressed_cluster_offset(bs,
-            sector_num << 9, out_len);
-        if (!cluster_offset) {
-            ret = -EIO;
-            goto fail;
-        }
-        cluster_offset &= s->cluster_offset_mask;
+        goto success;
+    }
 
-        ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
-        if (ret < 0) {
-            goto fail;
-        }
+    qemu_co_mutex_lock(&s->lock);
+    cluster_offset =
+        qcow2_alloc_compressed_cluster_offset(bs, offset, out_len);
+    if (!cluster_offset) {
+        qemu_co_mutex_unlock(&s->lock);
+        ret = -EIO;
+        goto fail;
+    }
+    cluster_offset &= s->cluster_offset_mask;
 
-        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
-        ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
-        if (ret < 0) {
-            goto fail;
-        }
+    ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
+    qemu_co_mutex_unlock(&s->lock);
+    if (ret < 0) {
+        goto fail;
     }
 
+    iov = (struct iovec) {
+        .iov_base   = out_buf,
+        .iov_len    = out_len,
+    };
+    qemu_iovec_init_external(&hd_qiov, &iov, 1);
+
+    BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
+    ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
+    if (ret < 0) {
+        goto fail;
+    }
+success:
     ret = 0;
 fail:
+    qemu_vfree(buf);
     g_free(out_buf);
     return ret;
 }
@@ -3412,7 +3388,7 @@ BlockDriver bdrv_qcow2 = {
     .bdrv_co_pwrite_zeroes  = qcow2_co_pwrite_zeroes,
     .bdrv_co_pdiscard       = qcow2_co_pdiscard,
     .bdrv_truncate          = qcow2_truncate,
-    .bdrv_write_compressed  = qcow2_write_compressed,
+    .bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
     .bdrv_make_empty        = qcow2_make_empty,
 
     .bdrv_snapshot_create   = qcow2_snapshot_create,
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 18/42] qcow2: cleanup qcow2_co_pwritev_compressed to avoid the recursion
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (16 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 17/42] qcow2: add qcow2_co_pwritev_compressed Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 19/42] vmdk: add vmdk_co_pwritev_compressed Kevin Wolf
                   ` (26 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Now that the function uses a vector instead of a buffer, there is no
need to use recursive code.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2.c | 24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 1cbaa8f..adf4514 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2554,27 +2554,17 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
         return bdrv_truncate(bs->file->bs, cluster_offset);
     }
 
+    buf = qemu_blockalign(bs, s->cluster_size);
     if (bytes != s->cluster_size) {
-        ret = -EINVAL;
-
-        /* Zero-pad last write if image size is not cluster aligned */
-        if (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS &&
-            bytes < s->cluster_size)
+        if (bytes > s->cluster_size ||
+            offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
         {
-            uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
-            memset(pad_buf, 0, s->cluster_size);
-            qemu_iovec_to_buf(qiov, 0, pad_buf, s->cluster_size);
-            iov = (struct iovec) {
-                .iov_base   = pad_buf,
-                .iov_len    = s->cluster_size,
-            };
-            qemu_iovec_init_external(&hd_qiov, &iov, 1);
-            ret = qcow2_co_pwritev_compressed(bs, offset, bytes, &hd_qiov);
-            qemu_vfree(pad_buf);
+            qemu_vfree(buf);
+            return -EINVAL;
         }
-        return ret;
+        /* Zero-pad last write if image size is not cluster aligned */
+        memset(buf + bytes, 0, s->cluster_size - bytes);
     }
-    buf = qemu_blockalign(bs, s->cluster_size);
     qemu_iovec_to_buf(qiov, 0, buf, s->cluster_size);
 
     out_buf = g_malloc(s->cluster_size);
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 19/42] vmdk: add vmdk_co_pwritev_compressed
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (17 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 18/42] qcow2: cleanup qcow2_co_pwritev_compressed to avoid the recursion Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 20/42] qcow: add qcow_co_pwritev_compressed Kevin Wolf
                   ` (25 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Added implementation of the vmdk_co_pwritev_compressed function that
will allow us to safely use compressed writes for the vmdk from running
VMs.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vmdk.c | 55 +++++--------------------------------------------------
 1 file changed, 5 insertions(+), 50 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index 46d474e..a11c27a 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1645,56 +1645,11 @@ vmdk_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
     return ret;
 }
 
-typedef struct VmdkWriteCompressedCo {
-    BlockDriverState *bs;
-    int64_t sector_num;
-    const uint8_t *buf;
-    int nb_sectors;
-    int ret;
-} VmdkWriteCompressedCo;
-
-static void vmdk_co_write_compressed(void *opaque)
-{
-    VmdkWriteCompressedCo *co = opaque;
-    QEMUIOVector local_qiov;
-    uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE;
-    uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE;
-
-    struct iovec iov = (struct iovec) {
-        .iov_base   = (uint8_t*) co->buf,
-        .iov_len    = bytes,
-    };
-    qemu_iovec_init_external(&local_qiov, &iov, 1);
-
-    co->ret = vmdk_pwritev(co->bs, offset, bytes, &local_qiov, false, false);
-}
-
-static int vmdk_write_compressed(BlockDriverState *bs,
-                                 int64_t sector_num,
-                                 const uint8_t *buf,
-                                 int nb_sectors)
+static int coroutine_fn
+vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
+                           uint64_t bytes, QEMUIOVector *qiov)
 {
-    BDRVVmdkState *s = bs->opaque;
-
-    if (s->num_extents == 1 && s->extents[0].compressed) {
-        Coroutine *co;
-        AioContext *aio_context = bdrv_get_aio_context(bs);
-        VmdkWriteCompressedCo data = {
-            .bs         = bs,
-            .sector_num = sector_num,
-            .buf        = buf,
-            .nb_sectors = nb_sectors,
-            .ret        = -EINPROGRESS,
-        };
-        co = qemu_coroutine_create(vmdk_co_write_compressed, &data);
-        qemu_coroutine_enter(co);
-        while (data.ret == -EINPROGRESS) {
-            aio_poll(aio_context, true);
-        }
-        return data.ret;
-    } else {
-        return -ENOTSUP;
-    }
+    return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
 }
 
 static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
@@ -2393,7 +2348,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_reopen_prepare          = vmdk_reopen_prepare,
     .bdrv_co_preadv               = vmdk_co_preadv,
     .bdrv_co_pwritev              = vmdk_co_pwritev,
-    .bdrv_write_compressed        = vmdk_write_compressed,
+    .bdrv_co_pwritev_compressed   = vmdk_co_pwritev_compressed,
     .bdrv_co_pwrite_zeroes        = vmdk_co_pwrite_zeroes,
     .bdrv_close                   = vmdk_close,
     .bdrv_create                  = vmdk_create,
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 20/42] qcow: add qcow_co_pwritev_compressed
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (18 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 19/42] vmdk: add vmdk_co_pwritev_compressed Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 21/42] qcow: cleanup qcow_co_pwritev_compressed to avoid the recursion Kevin Wolf
                   ` (24 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Added implementation of the qcow_co_pwritev_compressed function that
will allow us to safely use compressed writes for the qcow from running
VMs.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow.c | 109 +++++++++++++++++++++++------------------------------------
 1 file changed, 42 insertions(+), 67 deletions(-)

diff --git a/block/qcow.c b/block/qcow.c
index 6f9b2e2..1b9c911 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -913,75 +913,42 @@ static int qcow_make_empty(BlockDriverState *bs)
     return 0;
 }
 
-typedef struct QcowWriteCo {
-    BlockDriverState *bs;
-    int64_t sector_num;
-    const uint8_t *buf;
-    int nb_sectors;
-    int ret;
-} QcowWriteCo;
-
-static void qcow_write_co_entry(void *opaque)
-{
-    QcowWriteCo *co = opaque;
-    QEMUIOVector qiov;
-
-    struct iovec iov = (struct iovec) {
-        .iov_base   = (uint8_t*) co->buf,
-        .iov_len    = co->nb_sectors * BDRV_SECTOR_SIZE,
-    };
-    qemu_iovec_init_external(&qiov, &iov, 1);
-
-    co->ret = qcow_co_writev(co->bs, co->sector_num, co->nb_sectors, &qiov);
-}
-
-/* Wrapper for non-coroutine contexts */
-static int qcow_write(BlockDriverState *bs, int64_t sector_num,
-                      const uint8_t *buf, int nb_sectors)
-{
-    Coroutine *co;
-    AioContext *aio_context = bdrv_get_aio_context(bs);
-    QcowWriteCo data = {
-        .bs         = bs,
-        .sector_num = sector_num,
-        .buf        = buf,
-        .nb_sectors = nb_sectors,
-        .ret        = -EINPROGRESS,
-    };
-    co = qemu_coroutine_create(qcow_write_co_entry, &data);
-    qemu_coroutine_enter(co);
-    while (data.ret == -EINPROGRESS) {
-        aio_poll(aio_context, true);
-    }
-    return data.ret;
-}
-
 /* XXX: put compressed sectors first, then all the cluster aligned
    tables to avoid losing bytes in alignment */
-static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
-                                 const uint8_t *buf, int nb_sectors)
+static coroutine_fn int
+qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
+                           uint64_t bytes, QEMUIOVector *qiov)
 {
     BDRVQcowState *s = bs->opaque;
+    QEMUIOVector hd_qiov;
+    struct iovec iov;
     z_stream strm;
     int ret, out_len;
-    uint8_t *out_buf;
+    uint8_t *buf, *out_buf;
     uint64_t cluster_offset;
 
-    if (nb_sectors != s->cluster_sectors) {
+    if (bytes != s->cluster_size) {
         ret = -EINVAL;
 
         /* Zero-pad last write if image size is not cluster aligned */
-        if (sector_num + nb_sectors == bs->total_sectors &&
-            nb_sectors < s->cluster_sectors) {
+        if (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS &&
+            bytes < s->cluster_size)
+        {
             uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
             memset(pad_buf, 0, s->cluster_size);
-            memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
-            ret = qcow_write_compressed(bs, sector_num,
-                                        pad_buf, s->cluster_sectors);
+            qemu_iovec_to_buf(qiov, 0, pad_buf, s->cluster_size);
+            iov = (struct iovec) {
+                .iov_base   = pad_buf,
+                .iov_len    = s->cluster_size,
+            };
+            qemu_iovec_init_external(&hd_qiov, &iov, 1);
+            ret = qcow_co_pwritev_compressed(bs, offset, bytes, &hd_qiov);
             qemu_vfree(pad_buf);
         }
         return ret;
     }
+    buf = qemu_blockalign(bs, s->cluster_size);
+    qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
 
     out_buf = g_malloc(s->cluster_size);
 
@@ -1012,27 +979,35 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
     if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
         /* could not compress: write normal cluster */
-        ret = qcow_write(bs, sector_num, buf, s->cluster_sectors);
-        if (ret < 0) {
-            goto fail;
-        }
-    } else {
-        cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
-                                            out_len, 0, 0);
-        if (cluster_offset == 0) {
-            ret = -EIO;
-            goto fail;
-        }
-
-        cluster_offset &= s->cluster_offset_mask;
-        ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
+        ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
+                             bytes >> BDRV_SECTOR_BITS, qiov);
         if (ret < 0) {
             goto fail;
         }
+        goto success;
+    }
+    qemu_co_mutex_lock(&s->lock);
+    cluster_offset = get_cluster_offset(bs, offset, 2, out_len, 0, 0);
+    qemu_co_mutex_unlock(&s->lock);
+    if (cluster_offset == 0) {
+        ret = -EIO;
+        goto fail;
     }
+    cluster_offset &= s->cluster_offset_mask;
 
+    iov = (struct iovec) {
+        .iov_base   = out_buf,
+        .iov_len    = out_len,
+    };
+    qemu_iovec_init_external(&hd_qiov, &iov, 1);
+    ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
+    if (ret < 0) {
+        goto fail;
+    }
+success:
     ret = 0;
 fail:
+    qemu_vfree(buf);
     g_free(out_buf);
     return ret;
 }
@@ -1085,7 +1060,7 @@ static BlockDriver bdrv_qcow = {
 
     .bdrv_set_key           = qcow_set_key,
     .bdrv_make_empty        = qcow_make_empty,
-    .bdrv_write_compressed  = qcow_write_compressed,
+    .bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
     .bdrv_get_info          = qcow_get_info,
 
     .create_opts            = &qcow_create_opts,
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 21/42] qcow: cleanup qcow_co_pwritev_compressed to avoid the recursion
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (19 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 20/42] qcow: add qcow_co_pwritev_compressed Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 22/42] block: remove BlockDriver.bdrv_write_compressed Kevin Wolf
                   ` (23 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Now that the function uses a vector instead of a buffer, there is no
need to use recursive code.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow.c | 24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/block/qcow.c b/block/qcow.c
index 1b9c911..94f01b3 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -927,27 +927,17 @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
     uint8_t *buf, *out_buf;
     uint64_t cluster_offset;
 
+    buf = qemu_blockalign(bs, s->cluster_size);
     if (bytes != s->cluster_size) {
-        ret = -EINVAL;
-
-        /* Zero-pad last write if image size is not cluster aligned */
-        if (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS &&
-            bytes < s->cluster_size)
+        if (bytes > s->cluster_size ||
+            offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
         {
-            uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
-            memset(pad_buf, 0, s->cluster_size);
-            qemu_iovec_to_buf(qiov, 0, pad_buf, s->cluster_size);
-            iov = (struct iovec) {
-                .iov_base   = pad_buf,
-                .iov_len    = s->cluster_size,
-            };
-            qemu_iovec_init_external(&hd_qiov, &iov, 1);
-            ret = qcow_co_pwritev_compressed(bs, offset, bytes, &hd_qiov);
-            qemu_vfree(pad_buf);
+            qemu_vfree(buf);
+            return -EINVAL;
         }
-        return ret;
+        /* Zero-pad last write if image size is not cluster aligned */
+        memset(buf + bytes, 0, s->cluster_size - bytes);
     }
-    buf = qemu_blockalign(bs, s->cluster_size);
     qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
 
     out_buf = g_malloc(s->cluster_size);
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 22/42] block: remove BlockDriver.bdrv_write_compressed
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (20 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 21/42] qcow: cleanup qcow_co_pwritev_compressed to avoid the recursion Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 23/42] block/io: turn on dirty_bitmaps for the compressed writes Kevin Wolf
                   ` (22 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

There are no block drivers left that implement the old
.bdrv_write_compressed interface, so it can be removed. Also now we have
no need to use the bdrv_pwrite_compressed function and we can remove it
entirely.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/block-backend.c     |  8 ++------
 block/io.c                | 31 -------------------------------
 include/block/block.h     |  2 --
 include/block/block_int.h |  3 ---
 qemu-img.c                |  2 +-
 5 files changed, 3 insertions(+), 43 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 76ea459..d1349d9 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1488,12 +1488,8 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
 int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
                           int count)
 {
-    int ret = blk_check_byte_request(blk, offset, count);
-    if (ret < 0) {
-        return ret;
-    }
-
-    return bdrv_pwrite_compressed(blk->root, offset, buf, count);
+    return blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
+                   BDRV_REQ_WRITE_COMPRESSED);
 }
 
 int blk_truncate(BlockBackend *blk, int64_t offset)
diff --git a/block/io.c b/block/io.c
index d402076..0339911 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1887,37 +1887,6 @@ int bdrv_is_allocated_above(BlockDriverState *top,
     return 0;
 }
 
-int bdrv_pwrite_compressed(BdrvChild *child, int64_t offset,
-                           const void *buf, int bytes)
-{
-    BlockDriverState *bs = child->bs;
-    BlockDriver *drv = bs->drv;
-    QEMUIOVector qiov;
-    struct iovec iov;
-
-    if (!drv) {
-        return -ENOMEDIUM;
-    }
-    if (drv->bdrv_write_compressed) {
-        int ret = bdrv_check_byte_request(bs, offset, bytes);
-        if (ret < 0) {
-            return ret;
-        }
-        assert(QLIST_EMPTY(&bs->dirty_bitmaps));
-        assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
-        assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
-        return drv->bdrv_write_compressed(bs, offset >> BDRV_SECTOR_BITS, buf,
-                                          bytes >> BDRV_SECTOR_BITS);
-    }
-    iov = (struct iovec) {
-        .iov_base = (void *)buf,
-        .iov_len = bytes,
-    };
-    qemu_iovec_init_external(&qiov, &iov, 1);
-
-    return bdrv_prwv_co(child, offset, &qiov, true, BDRV_REQ_WRITE_COMPRESSED);
-}
-
 typedef struct BdrvVmstateCo {
     BlockDriverState    *bs;
     QEMUIOVector        *qiov;
diff --git a/include/block/block.h b/include/block/block.h
index d8dacd2..7edce5c 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -400,8 +400,6 @@ const char *bdrv_get_node_name(const BlockDriverState *bs);
 const char *bdrv_get_device_name(const BlockDriverState *bs);
 const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
 int bdrv_get_flags(BlockDriverState *bs);
-int bdrv_pwrite_compressed(BdrvChild *child, int64_t offset,
-                           const void *buf, int bytes);
 int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
 ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
 void bdrv_round_sectors_to_clusters(BlockDriverState *bs,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 42f8f84..9c61f49 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -204,9 +204,6 @@ struct BlockDriver {
     bool has_variable_length;
     int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
 
-    int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
-                                 const uint8_t *buf, int nb_sectors);
-
     int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
         uint64_t offset, uint64_t bytes, QEMUIOVector *qiov);
 
diff --git a/qemu-img.c b/qemu-img.c
index c2ea494..1090286 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2034,7 +2034,7 @@ static int img_convert(int argc, char **argv)
         const char *preallocation =
             qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
 
-        if (!drv->bdrv_write_compressed && !drv->bdrv_co_pwritev_compressed) {
+        if (!drv->bdrv_co_pwritev_compressed) {
             error_report("Compression not supported for this file format");
             ret = -1;
             goto out;
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 23/42] block/io: turn on dirty_bitmaps for the compressed writes
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (21 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 22/42] block: remove BlockDriver.bdrv_write_compressed Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 24/42] block: simplify drive-backup Kevin Wolf
                   ` (21 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Previously was added the assert:

  commit 1755da16e32c15b22a521e8a38539e4b5cf367f3
  Author: Paolo Bonzini <pbonzini@redhat.com>
  Date:   Thu Oct 18 16:49:18 2012 +0200
  block: introduce new dirty bitmap functionality

Now the compressed write is always in coroutine and setting the bits is
done after the write, so that we can return the dirty_bitmaps for the
compressed writes.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/io.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/block/io.c b/block/io.c
index 0339911..fdf7080 100644
--- a/block/io.c
+++ b/block/io.c
@@ -896,7 +896,6 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
         return -ENOTSUP;
     }
 
-    assert(QLIST_EMPTY(&bs->dirty_bitmaps));
     return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
 }
 
@@ -1318,6 +1317,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
     } else if (flags & BDRV_REQ_ZERO_WRITE) {
         bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
         ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
+    } else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
+        ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov);
     } else if (bytes <= max_transfer) {
         bdrv_debug_event(bs, BLKDBG_PWRITEV);
         ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
@@ -1569,14 +1570,9 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
         bytes = ROUND_UP(bytes, align);
     }
 
-    if (flags & BDRV_REQ_WRITE_COMPRESSED) {
-        ret = bdrv_driver_pwritev_compressed(
-                bs, offset, bytes, use_local_qiov ? &local_qiov : qiov);
-    } else {
-        ret = bdrv_aligned_pwritev(bs, &req, offset, bytes, align,
-                                   use_local_qiov ? &local_qiov : qiov,
-                                   flags);
-    }
+    ret = bdrv_aligned_pwritev(bs, &req, offset, bytes, align,
+                               use_local_qiov ? &local_qiov : qiov,
+                               flags);
 
 fail:
 
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 24/42] block: simplify drive-backup
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (22 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 23/42] block/io: turn on dirty_bitmaps for the compressed writes Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 25/42] block: simplify blockdev-backup Kevin Wolf
                   ` (20 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Now that we can support boxed commands, use it to greatly reduce the
number of parameters (and likelihood of getting out of sync) when
adjusting drive-backup parameters.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 blockdev.c           | 111 +++++++++++++++++----------------------------------
 hmp.c                |  21 +++++-----
 qapi/block-core.json |   3 +-
 3 files changed, 48 insertions(+), 87 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index a392e08..539aa7d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1841,17 +1841,8 @@ typedef struct DriveBackupState {
     BlockJob *job;
 } DriveBackupState;
 
-static void do_drive_backup(const char *job_id, const char *device,
-                            const char *target, bool has_format,
-                            const char *format, enum MirrorSyncMode sync,
-                            bool has_mode, enum NewImageMode mode,
-                            bool has_speed, int64_t speed,
-                            bool has_bitmap, const char *bitmap,
-                            bool has_on_source_error,
-                            BlockdevOnError on_source_error,
-                            bool has_on_target_error,
-                            BlockdevOnError on_target_error,
-                            BlockJobTxn *txn, Error **errp);
+static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
+                            Error **errp);
 
 static void drive_backup_prepare(BlkActionState *common, Error **errp)
 {
@@ -1874,16 +1865,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
     bdrv_drained_begin(bs);
     state->bs = bs;
 
-    do_drive_backup(backup->has_job_id ? backup->job_id : NULL,
-                    backup->device, backup->target,
-                    backup->has_format, backup->format,
-                    backup->sync,
-                    backup->has_mode, backup->mode,
-                    backup->has_speed, backup->speed,
-                    backup->has_bitmap, backup->bitmap,
-                    backup->has_on_source_error, backup->on_source_error,
-                    backup->has_on_target_error, backup->on_target_error,
-                    common->block_job_txn, &local_err);
+    do_drive_backup(backup, common->block_job_txn, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -3134,17 +3116,7 @@ out:
     aio_context_release(aio_context);
 }
 
-static void do_drive_backup(const char *job_id, const char *device,
-                            const char *target, bool has_format,
-                            const char *format, enum MirrorSyncMode sync,
-                            bool has_mode, enum NewImageMode mode,
-                            bool has_speed, int64_t speed,
-                            bool has_bitmap, const char *bitmap,
-                            bool has_on_source_error,
-                            BlockdevOnError on_source_error,
-                            bool has_on_target_error,
-                            BlockdevOnError on_target_error,
-                            BlockJobTxn *txn, Error **errp)
+static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn, Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *target_bs;
@@ -3156,20 +3128,23 @@ static void do_drive_backup(const char *job_id, const char *device,
     int flags;
     int64_t size;
 
-    if (!has_speed) {
-        speed = 0;
+    if (!backup->has_speed) {
+        backup->speed = 0;
     }
-    if (!has_on_source_error) {
-        on_source_error = BLOCKDEV_ON_ERROR_REPORT;
+    if (!backup->has_on_source_error) {
+        backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
     }
-    if (!has_on_target_error) {
-        on_target_error = BLOCKDEV_ON_ERROR_REPORT;
+    if (!backup->has_on_target_error) {
+        backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
     }
-    if (!has_mode) {
-        mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+    if (!backup->has_mode) {
+        backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+    }
+    if (!backup->has_job_id) {
+        backup->job_id = NULL;
     }
 
-    bs = qmp_get_root_bs(device, errp);
+    bs = qmp_get_root_bs(backup->device, errp);
     if (!bs) {
         return;
     }
@@ -3177,8 +3152,9 @@ static void do_drive_backup(const char *job_id, const char *device,
     aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    if (!has_format) {
-        format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
+    if (!backup->has_format) {
+        backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
+                         NULL : (char*) bs->drv->format_name;
     }
 
     /* Early check to avoid creating target */
@@ -3190,13 +3166,13 @@ static void do_drive_backup(const char *job_id, const char *device,
 
     /* See if we have a backing HD we can use to create our new image
      * on top of. */
-    if (sync == MIRROR_SYNC_MODE_TOP) {
+    if (backup->sync == MIRROR_SYNC_MODE_TOP) {
         source = backing_bs(bs);
         if (!source) {
-            sync = MIRROR_SYNC_MODE_FULL;
+            backup->sync = MIRROR_SYNC_MODE_FULL;
         }
     }
-    if (sync == MIRROR_SYNC_MODE_NONE) {
+    if (backup->sync == MIRROR_SYNC_MODE_NONE) {
         source = bs;
     }
 
@@ -3206,14 +3182,14 @@ static void do_drive_backup(const char *job_id, const char *device,
         goto out;
     }
 
-    if (mode != NEW_IMAGE_MODE_EXISTING) {
-        assert(format);
+    if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
+        assert(backup->format);
         if (source) {
-            bdrv_img_create(target, format, source->filename,
+            bdrv_img_create(backup->target, backup->format, source->filename,
                             source->drv->format_name, NULL,
                             size, flags, &local_err, false);
         } else {
-            bdrv_img_create(target, format, NULL, NULL, NULL,
+            bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
                             size, flags, &local_err, false);
         }
     }
@@ -3223,29 +3199,29 @@ static void do_drive_backup(const char *job_id, const char *device,
         goto out;
     }
 
-    if (format) {
+    if (backup->format) {
         options = qdict_new();
-        qdict_put(options, "driver", qstring_from_str(format));
+        qdict_put(options, "driver", qstring_from_str(backup->format));
     }
 
-    target_bs = bdrv_open(target, NULL, options, flags, errp);
+    target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
     if (!target_bs) {
         goto out;
     }
 
     bdrv_set_aio_context(target_bs, aio_context);
 
-    if (has_bitmap) {
-        bmap = bdrv_find_dirty_bitmap(bs, bitmap);
+    if (backup->has_bitmap) {
+        bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
         if (!bmap) {
-            error_setg(errp, "Bitmap '%s' could not be found", bitmap);
+            error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
             bdrv_unref(target_bs);
             goto out;
         }
     }
 
-    backup_start(job_id, bs, target_bs, speed, sync, bmap,
-                 on_source_error, on_target_error,
+    backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
+                 bmap, backup->on_source_error, backup->on_target_error,
                  block_job_cb, bs, txn, &local_err);
     bdrv_unref(target_bs);
     if (local_err != NULL) {
@@ -3257,24 +3233,9 @@ out:
     aio_context_release(aio_context);
 }
 
-void qmp_drive_backup(bool has_job_id, const char *job_id,
-                      const char *device, const char *target,
-                      bool has_format, const char *format,
-                      enum MirrorSyncMode sync,
-                      bool has_mode, enum NewImageMode mode,
-                      bool has_speed, int64_t speed,
-                      bool has_bitmap, const char *bitmap,
-                      bool has_on_source_error, BlockdevOnError on_source_error,
-                      bool has_on_target_error, BlockdevOnError on_target_error,
-                      Error **errp)
+void qmp_drive_backup(DriveBackup *arg, Error **errp)
 {
-    return do_drive_backup(has_job_id ? job_id : NULL, device, target,
-                           has_format, format, sync,
-                           has_mode, mode, has_speed, speed,
-                           has_bitmap, bitmap,
-                           has_on_source_error, on_source_error,
-                           has_on_target_error, on_target_error,
-                           NULL, errp);
+    return do_drive_backup(arg, NULL, errp);
 }
 
 BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
diff --git a/hmp.c b/hmp.c
index cc2056e..3c06200 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1109,8 +1109,16 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
     const char *format = qdict_get_try_str(qdict, "format");
     bool reuse = qdict_get_try_bool(qdict, "reuse", false);
     bool full = qdict_get_try_bool(qdict, "full", false);
-    enum NewImageMode mode;
     Error *err = NULL;
+    DriveBackup backup = {
+        .device = (char *)device,
+        .target = (char *)filename,
+        .has_format = !!format,
+        .format = (char *)format,
+        .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
+        .has_mode = true,
+        .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
+    };
 
     if (!filename) {
         error_setg(&err, QERR_MISSING_PARAMETER, "target");
@@ -1118,16 +1126,7 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    if (reuse) {
-        mode = NEW_IMAGE_MODE_EXISTING;
-    } else {
-        mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
-    }
-
-    qmp_drive_backup(false, NULL, device, filename, !!format, format,
-                     full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
-                     true, mode, false, 0, false, NULL,
-                     false, 0, false, 0, &err);
+    qmp_drive_backup(&backup, &err);
     hmp_handle_error(mon, &err);
 }
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index fba1718..2bc51df 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1091,7 +1091,8 @@
 #
 # Since 1.6
 ##
-{ 'command': 'drive-backup', 'data': 'DriveBackup' }
+{ 'command': 'drive-backup', 'boxed': true,
+  'data': 'DriveBackup' }
 
 ##
 # @blockdev-backup
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 25/42] block: simplify blockdev-backup
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (23 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 24/42] block: simplify drive-backup Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression Kevin Wolf
                   ` (19 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Now that we can support boxed commands, use it to greatly reduce the
number of parameters (and likelihood of getting out of sync) when
adjusting blockdev-backup parameters.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 blockdev.c           | 66 ++++++++++++++++------------------------------------
 qapi/block-core.json |  6 ++++-
 2 files changed, 25 insertions(+), 47 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 539aa7d..5f1b015 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1902,14 +1902,8 @@ typedef struct BlockdevBackupState {
     AioContext *aio_context;
 } BlockdevBackupState;
 
-static void do_blockdev_backup(const char *job_id, const char *device,
-                               const char *target, enum MirrorSyncMode sync,
-                               bool has_speed, int64_t speed,
-                               bool has_on_source_error,
-                               BlockdevOnError on_source_error,
-                               bool has_on_target_error,
-                               BlockdevOnError on_target_error,
-                               BlockJobTxn *txn, Error **errp);
+static void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
+                               Error **errp);
 
 static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
 {
@@ -1942,12 +1936,7 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
     state->bs = bs;
     bdrv_drained_begin(state->bs);
 
-    do_blockdev_backup(backup->has_job_id ? backup->job_id : NULL,
-                       backup->device, backup->target, backup->sync,
-                       backup->has_speed, backup->speed,
-                       backup->has_on_source_error, backup->on_source_error,
-                       backup->has_on_target_error, backup->on_target_error,
-                       common->block_job_txn, &local_err);
+    do_blockdev_backup(backup, common->block_job_txn, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -3243,31 +3232,27 @@ BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
     return bdrv_named_nodes_list(errp);
 }
 
-void do_blockdev_backup(const char *job_id, const char *device,
-                        const char *target, enum MirrorSyncMode sync,
-                         bool has_speed, int64_t speed,
-                         bool has_on_source_error,
-                         BlockdevOnError on_source_error,
-                         bool has_on_target_error,
-                         BlockdevOnError on_target_error,
-                         BlockJobTxn *txn, Error **errp)
+void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn, Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *target_bs;
     Error *local_err = NULL;
     AioContext *aio_context;
 
-    if (!has_speed) {
-        speed = 0;
+    if (!backup->has_speed) {
+        backup->speed = 0;
     }
-    if (!has_on_source_error) {
-        on_source_error = BLOCKDEV_ON_ERROR_REPORT;
+    if (!backup->has_on_source_error) {
+        backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
     }
-    if (!has_on_target_error) {
-        on_target_error = BLOCKDEV_ON_ERROR_REPORT;
+    if (!backup->has_on_target_error) {
+        backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
+    }
+    if (!backup->has_job_id) {
+        backup->job_id = NULL;
     }
 
-    bs = qmp_get_root_bs(device, errp);
+    bs = qmp_get_root_bs(backup->device, errp);
     if (!bs) {
         return;
     }
@@ -3275,7 +3260,7 @@ void do_blockdev_backup(const char *job_id, const char *device,
     aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
 
-    target_bs = bdrv_lookup_bs(target, target, errp);
+    target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
     if (!target_bs) {
         goto out;
     }
@@ -3291,8 +3276,9 @@ void do_blockdev_backup(const char *job_id, const char *device,
             goto out;
         }
     }
-    backup_start(job_id, bs, target_bs, speed, sync, NULL, on_source_error,
-                 on_target_error, block_job_cb, bs, txn, &local_err);
+    backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
+                 NULL, backup->on_source_error, backup->on_target_error,
+                 block_job_cb, bs, txn, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
     }
@@ -3300,21 +3286,9 @@ out:
     aio_context_release(aio_context);
 }
 
-void qmp_blockdev_backup(bool has_job_id, const char *job_id,
-                         const char *device, const char *target,
-                         enum MirrorSyncMode sync,
-                         bool has_speed, int64_t speed,
-                         bool has_on_source_error,
-                         BlockdevOnError on_source_error,
-                         bool has_on_target_error,
-                         BlockdevOnError on_target_error,
-                         Error **errp)
+void qmp_blockdev_backup(BlockdevBackup *arg, Error **errp)
 {
-    do_blockdev_backup(has_job_id ? job_id : NULL, device, target,
-                       sync, has_speed, speed,
-                       has_on_source_error, on_source_error,
-                       has_on_target_error, on_target_error,
-                       NULL, errp);
+    do_blockdev_backup(arg, NULL, errp);
 }
 
 /* Parameter check and block job starting for drive mirroring.
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 2bc51df..4c8cf05 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1105,9 +1105,13 @@
 #
 # For the arguments, see the documentation of BlockdevBackup.
 #
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#
 # Since 2.3
 ##
-{ 'command': 'blockdev-backup', 'data': 'BlockdevBackup' }
+{ 'command': 'blockdev-backup', 'boxed': true,
+  'data': 'BlockdevBackup' }
 
 
 ##
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (24 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 25/42] block: simplify blockdev-backup Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-16 15:15   ` Eric Blake
  2016-09-05 18:13 ` [Qemu-devel] [PULL 27/42] blockdev-backup: " Kevin Wolf
                   ` (18 subsequent siblings)
  44 siblings, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

The idea is simple - backup is "written-once" data. It is written block
by block and it is large enough. It would be nice to save storage
space and compress it.

The patch adds a flag to the qmp/hmp drive-backup command which enables
block compression. Compression should be implemented in the format driver
to enable this feature.

There are some limitations of the format driver to allow compressed writes.
We can write data only once. Though for backup this is perfectly fine.
These limitations are maintained by the driver and the error will be
reported if we are doing something wrong.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/backup.c            | 12 +++++++++++-
 blockdev.c                |  9 ++++++---
 hmp-commands.hx           |  8 +++++---
 hmp.c                     |  3 +++
 include/block/block_int.h |  1 +
 qapi/block-core.json      |  5 ++++-
 qmp-commands.hx           |  5 ++++-
 7 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/block/backup.c b/block/backup.c
index 2c05323..bb3bb9a 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -47,6 +47,7 @@ typedef struct BackupBlockJob {
     uint64_t sectors_read;
     unsigned long *done_bitmap;
     int64_t cluster_size;
+    bool compress;
     NotifierWithReturn before_write;
     QLIST_HEAD(, CowRequest) inflight_reqs;
 } BackupBlockJob;
@@ -154,7 +155,8 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
                                        bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
         } else {
             ret = blk_co_pwritev(job->target, start * job->cluster_size,
-                                 bounce_qiov.size, &bounce_qiov, 0);
+                                 bounce_qiov.size, &bounce_qiov,
+                                 job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
         }
         if (ret < 0) {
             trace_backup_do_cow_write_fail(job, start, ret);
@@ -477,6 +479,7 @@ static void coroutine_fn backup_run(void *opaque)
 void backup_start(const char *job_id, BlockDriverState *bs,
                   BlockDriverState *target, int64_t speed,
                   MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
+                  bool compress,
                   BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
                   BlockCompletionFunc *cb, void *opaque,
@@ -507,6 +510,12 @@ void backup_start(const char *job_id, BlockDriverState *bs,
         return;
     }
 
+    if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
+        error_setg(errp, "Compression is not supported for this drive %s",
+                   bdrv_get_device_name(target));
+        return;
+    }
+
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
         return;
     }
@@ -555,6 +564,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
     job->sync_mode = sync_mode;
     job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
                        sync_bitmap : NULL;
+    job->compress = compress;
 
     /* If there is no backing file on the target, we cannot rely on COW if our
      * backup cluster size is smaller than the target cluster size. Even for
diff --git a/blockdev.c b/blockdev.c
index 5f1b015..f5857d0 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3132,6 +3132,9 @@ static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn, Error **errp)
     if (!backup->has_job_id) {
         backup->job_id = NULL;
     }
+    if (!backup->has_compress) {
+        backup->compress = false;
+    }
 
     bs = qmp_get_root_bs(backup->device, errp);
     if (!bs) {
@@ -3210,8 +3213,8 @@ static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn, Error **errp)
     }
 
     backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
-                 bmap, backup->on_source_error, backup->on_target_error,
-                 block_job_cb, bs, txn, &local_err);
+                 bmap, backup->compress, backup->on_source_error,
+                 backup->on_target_error, block_job_cb, bs, txn, &local_err);
     bdrv_unref(target_bs);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
@@ -3277,7 +3280,7 @@ void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn, Error **errp)
         }
     }
     backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
-                 NULL, backup->on_source_error, backup->on_target_error,
+                 NULL, false, backup->on_source_error, backup->on_target_error,
                  block_job_cb, bs, txn, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 848efee..74f32e5 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1182,8 +1182,8 @@ ETEXI
 
     {
         .name       = "drive_backup",
-        .args_type  = "reuse:-n,full:-f,device:B,target:s,format:s?",
-        .params     = "[-n] [-f] device target [format]",
+        .args_type  = "reuse:-n,full:-f,compress:-c,device:B,target:s,format:s?",
+        .params     = "[-n] [-f] [-c] device target [format]",
         .help       = "initiates a point-in-time\n\t\t\t"
                       "copy for a device. The device's contents are\n\t\t\t"
                       "copied to the new image file, excluding data that\n\t\t\t"
@@ -1191,7 +1191,9 @@ ETEXI
                       "The -n flag requests QEMU to reuse the image found\n\t\t\t"
                       "in new-image-file, instead of recreating it from scratch.\n\t\t\t"
                       "The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
-                      "so that the result does not need a backing file.\n\t\t\t",
+                      "so that the result does not need a backing file.\n\t\t\t"
+                      "The -c flag requests QEMU to compress backup data\n\t\t\t"
+                      "(if the target format supports it).\n\t\t\t",
         .mhandler.cmd = hmp_drive_backup,
     },
 STEXI
diff --git a/hmp.c b/hmp.c
index 3c06200..a7dfe6f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1109,6 +1109,7 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
     const char *format = qdict_get_try_str(qdict, "format");
     bool reuse = qdict_get_try_bool(qdict, "reuse", false);
     bool full = qdict_get_try_bool(qdict, "full", false);
+    bool compress = qdict_get_try_bool(qdict, "compress", false);
     Error *err = NULL;
     DriveBackup backup = {
         .device = (char *)device,
@@ -1118,6 +1119,8 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
         .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
         .has_mode = true,
         .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
+        .has_compress = !!compress,
+        .compress = compress,
     };
 
     if (!filename) {
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 9c61f49..0ca6a78 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -765,6 +765,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
 void backup_start(const char *job_id, BlockDriverState *bs,
                   BlockDriverState *target, int64_t speed,
                   MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
+                  bool compress,
                   BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
                   BlockCompletionFunc *cb, void *opaque,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 4c8cf05..300a68b 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -898,6 +898,9 @@
 #          Must be present if sync is "incremental", must NOT be present
 #          otherwise. (Since 2.4)
 #
+# @compress: #optional true to compress data, if the target format supports it.
+#            (default: false) (since 2.7)
+#
 # @on-source-error: #optional the action to take on an error on the source,
 #                   default 'report'.  'stop' and 'enospc' can only be used
 #                   if the block device supports io-status (see BlockInfo).
@@ -915,7 +918,7 @@
 { 'struct': 'DriveBackup',
   'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
             '*format': 'str', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
-            '*speed': 'int', '*bitmap': 'str',
+            '*speed': 'int', '*bitmap': 'str', '*compress': 'bool',
             '*on-source-error': 'BlockdevOnError',
             '*on-target-error': 'BlockdevOnError' } }
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 956f1b0..d1593c9 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1217,7 +1217,8 @@ EQMP
     {
         .name       = "drive-backup",
         .args_type  = "job-id:s?,sync:s,device:B,target:s,speed:i?,mode:s?,"
-                      "format:s?,bitmap:s?,on-source-error:s?,on-target-error:s?",
+                      "format:s?,bitmap:s?,compress:b?,"
+                      "on-source-error:s?,on-target-error:s?",
         .mhandler.cmd_new = qmp_marshal_drive_backup,
     },
 
@@ -1253,6 +1254,8 @@ Arguments:
 - "mode": whether and how QEMU should create a new image
           (NewImageMode, optional, default 'absolute-paths')
 - "speed": the maximum speed, in bytes per second (json-int, optional)
+- "compress": true to compress data, if the target format supports it.
+              (json-bool, optional, default false)
 - "on-source-error": the action to take on an error on the source, default
                      'report'.  'stop' and 'enospc' can only be used
                      if the block device supports io-status.
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 27/42] blockdev-backup: added support for data compression
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (25 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-16 15:15   ` Eric Blake
  2016-09-05 18:13 ` [Qemu-devel] [PULL 28/42] qemu-iotests: test backup compression in 055 Kevin Wolf
                   ` (17 subsequent siblings)
  44 siblings, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

The idea is simple - backup is "written-once" data. It is written block
by block and it is large enough. It would be nice to save storage
space and compress it.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 blockdev.c           | 7 +++++--
 qapi/block-core.json | 4 ++++
 qmp-commands.hx      | 4 +++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index f5857d0..97062e3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3254,6 +3254,9 @@ void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn, Error **errp)
     if (!backup->has_job_id) {
         backup->job_id = NULL;
     }
+    if (!backup->has_compress) {
+        backup->compress = false;
+    }
 
     bs = qmp_get_root_bs(backup->device, errp);
     if (!bs) {
@@ -3280,8 +3283,8 @@ void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn, Error **errp)
         }
     }
     backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
-                 NULL, false, backup->on_source_error, backup->on_target_error,
-                 block_job_cb, bs, txn, &local_err);
+                 NULL, backup->compress, backup->on_source_error,
+                 backup->on_target_error, block_job_cb, bs, txn, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
     }
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 300a68b..31f9990 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -939,6 +939,9 @@
 # @speed: #optional the maximum speed, in bytes per second. The default is 0,
 #         for unlimited.
 #
+# @compress: #optional true to compress data, if the target format supports it.
+#            (default: false) (since 2.7)
+#
 # @on-source-error: #optional the action to take on an error on the source,
 #                   default 'report'.  'stop' and 'enospc' can only be used
 #                   if the block device supports io-status (see BlockInfo).
@@ -957,6 +960,7 @@
   'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
             'sync': 'MirrorSyncMode',
             '*speed': 'int',
+            '*compress': 'bool',
             '*on-source-error': 'BlockdevOnError',
             '*on-target-error': 'BlockdevOnError' } }
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index d1593c9..ba2a916 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1275,7 +1275,7 @@ EQMP
 
     {
         .name       = "blockdev-backup",
-        .args_type  = "job-id:s?,sync:s,device:B,target:B,speed:i?,"
+        .args_type  = "job-id:s?,sync:s,device:B,target:B,speed:i?,compress:b?,"
                       "on-source-error:s?,on-target-error:s?",
         .mhandler.cmd_new = qmp_marshal_blockdev_backup,
     },
@@ -1299,6 +1299,8 @@ Arguments:
           sectors allocated in the topmost image, or "none" to only replicate
           new I/O (MirrorSyncMode).
 - "speed": the maximum speed, in bytes per second (json-int, optional)
+- "compress": true to compress data, if the target format supports it.
+              (json-bool, optional, default false)
 - "on-source-error": the action to take on an error on the source, default
                      'report'.  'stop' and 'enospc' can only be used
                      if the block device supports io-status.
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 28/42] qemu-iotests: test backup compression in 055
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (26 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 27/42] blockdev-backup: " Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 29/42] qemu-iotests: add vmdk for " Kevin Wolf
                   ` (16 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Added cases to check the backup compression out of qcow2, raw in qcow2
on drive-backup and blockdev-backup.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/055        | 97 +++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/055.out    |  4 +-
 tests/qemu-iotests/iotests.py | 10 ++---
 3 files changed, 104 insertions(+), 7 deletions(-)

diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index 8113c61..0e1326c 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -448,5 +448,102 @@ class TestSingleTransaction(iotests.QMPTestCase):
         self.assert_qmp(result, 'error/class', 'GenericError')
         self.assert_no_active_block_jobs()
 
+
+class TestDriveCompression(iotests.QMPTestCase):
+    image_len = 64 * 1024 * 1024 # MB
+    outfmt = 'qcow2'
+
+    def setUp(self):
+        # Write data to the image so we can compare later
+        qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestDriveCompression.image_len))
+        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img)
+        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img)
+        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
+        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
+
+        qemu_img('create', '-f', TestDriveCompression.outfmt, blockdev_target_img,
+                 str(TestDriveCompression.image_len))
+        self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img,
+                                                             format=TestDriveCompression.outfmt)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(test_img)
+        os.remove(blockdev_target_img)
+        try:
+            os.remove(target_img)
+        except OSError:
+            pass
+
+    def do_test_compress_complete(self, cmd, **args):
+        self.assert_no_active_block_jobs()
+
+        result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+        self.assert_qmp(result, 'return', {})
+
+        self.wait_until_completed()
+
+        self.vm.shutdown()
+        self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
+                                               iotests.imgfmt, TestDriveCompression.outfmt),
+                        'target image does not match source after backup')
+
+    def test_complete_compress_drive_backup(self):
+        self.do_test_compress_complete('drive-backup', target=blockdev_target_img, mode='existing')
+
+    def test_complete_compress_blockdev_backup(self):
+        self.do_test_compress_complete('blockdev-backup', target='drive1')
+
+    def do_test_compress_cancel(self, cmd, **args):
+        self.assert_no_active_block_jobs()
+
+        result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+        self.assert_qmp(result, 'return', {})
+
+        event = self.cancel_and_wait()
+        self.assert_qmp(event, 'data/type', 'backup')
+
+    def test_compress_cancel_drive_backup(self):
+        self.do_test_compress_cancel('drive-backup', target=blockdev_target_img, mode='existing')
+
+    def test_compress_cancel_blockdev_backup(self):
+        self.do_test_compress_cancel('blockdev-backup', target='drive1')
+
+    def do_test_compress_pause(self, cmd, **args):
+        self.assert_no_active_block_jobs()
+
+        self.vm.pause_drive('drive0')
+        result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('block-job-pause', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        self.vm.resume_drive('drive0')
+        time.sleep(1)
+        result = self.vm.qmp('query-block-jobs')
+        offset = self.dictpath(result, 'return[0]/offset')
+
+        time.sleep(1)
+        result = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(result, 'return[0]/offset', offset)
+
+        result = self.vm.qmp('block-job-resume', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        self.wait_until_completed()
+
+        self.vm.shutdown()
+        self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
+                                               iotests.imgfmt, TestDriveCompression.outfmt),
+                        'target image does not match source after backup')
+
+    def test_compress_pause_drive_backup(self):
+        self.do_test_compress_pause('drive-backup', target=blockdev_target_img, mode='existing')
+
+    def test_compress_pause_blockdev_backup(self):
+        self.do_test_compress_pause('blockdev-backup', target='drive1')
+
 if __name__ == '__main__':
     iotests.main(supported_fmts=['raw', 'qcow2'])
diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out
index 42314e9..5ce2f9a 100644
--- a/tests/qemu-iotests/055.out
+++ b/tests/qemu-iotests/055.out
@@ -1,5 +1,5 @@
-........................
+..............................
 ----------------------------------------------------------------------
-Ran 24 tests
+Ran 30 tests
 
 OK
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index dbe0ee5..69aa41e 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -86,10 +86,10 @@ def qemu_io(*args):
         sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
     return subp.communicate()[0]
 
-def compare_images(img1, img2):
+def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
     '''Return True if two image files are identical'''
-    return qemu_img('compare', '-f', imgfmt,
-                    '-F', imgfmt, img1, img2) == 0
+    return qemu_img('compare', '-f', fmt1,
+                    '-F', fmt2, img1, img2) == 0
 
 def create_image(name, size):
     '''Create a fully-allocated raw image with sector markers'''
@@ -141,14 +141,14 @@ class VM(qtest.QEMUQtestMachine):
         self._args.append(opts)
         return self
 
-    def add_drive(self, path, opts='', interface='virtio'):
+    def add_drive(self, path, opts='', interface='virtio', format=imgfmt):
         '''Add a virtio-blk drive to the VM'''
         options = ['if=%s' % interface,
                    'id=drive%d' % self._num_drives]
 
         if path is not None:
             options.append('file=%s' % path)
-            options.append('format=%s' % imgfmt)
+            options.append('format=%s' % format)
             options.append('cache=%s' % cachemode)
 
         if opts:
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 29/42] qemu-iotests: add vmdk for test backup compression in 055
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (27 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 28/42] qemu-iotests: test backup compression in 055 Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 30/42] test-coroutine: Fix coroutine pool corruption Kevin Wolf
                   ` (15 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

The vmdk format has support for compression, it would be fine to add it for
the test backup compression

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/055 | 57 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 39 insertions(+), 18 deletions(-)

diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index 0e1326c..ff4535e 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -451,7 +451,8 @@ class TestSingleTransaction(iotests.QMPTestCase):
 
 class TestDriveCompression(iotests.QMPTestCase):
     image_len = 64 * 1024 * 1024 # MB
-    outfmt = 'qcow2'
+    fmt_supports_compression = [{'type': 'qcow2', 'args': ()},
+                                {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}]
 
     def setUp(self):
         # Write data to the image so we can compare later
@@ -461,12 +462,6 @@ class TestDriveCompression(iotests.QMPTestCase):
         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
 
-        qemu_img('create', '-f', TestDriveCompression.outfmt, blockdev_target_img,
-                 str(TestDriveCompression.image_len))
-        self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img,
-                                                             format=TestDriveCompression.outfmt)
-        self.vm.launch()
-
     def tearDown(self):
         self.vm.shutdown()
         os.remove(test_img)
@@ -476,7 +471,18 @@ class TestDriveCompression(iotests.QMPTestCase):
         except OSError:
             pass
 
-    def do_test_compress_complete(self, cmd, **args):
+    def do_prepare_drives(self, fmt, args):
+        self.vm = iotests.VM().add_drive(test_img)
+
+        qemu_img('create', '-f', fmt, blockdev_target_img,
+                 str(TestDriveCompression.image_len), *args)
+        self.vm.add_drive(blockdev_target_img, format=fmt)
+
+        self.vm.launch()
+
+    def do_test_compress_complete(self, cmd, format, **args):
+        self.do_prepare_drives(format['type'], format['args'])
+
         self.assert_no_active_block_jobs()
 
         result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
@@ -486,16 +492,21 @@ class TestDriveCompression(iotests.QMPTestCase):
 
         self.vm.shutdown()
         self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
-                                               iotests.imgfmt, TestDriveCompression.outfmt),
+                                               iotests.imgfmt, format['type']),
                         'target image does not match source after backup')
 
     def test_complete_compress_drive_backup(self):
-        self.do_test_compress_complete('drive-backup', target=blockdev_target_img, mode='existing')
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_complete('drive-backup', format,
+                                           target=blockdev_target_img, mode='existing')
 
     def test_complete_compress_blockdev_backup(self):
-        self.do_test_compress_complete('blockdev-backup', target='drive1')
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_complete('blockdev-backup', format, target='drive1')
+
+    def do_test_compress_cancel(self, cmd, format, **args):
+        self.do_prepare_drives(format['type'], format['args'])
 
-    def do_test_compress_cancel(self, cmd, **args):
         self.assert_no_active_block_jobs()
 
         result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
@@ -504,13 +515,20 @@ class TestDriveCompression(iotests.QMPTestCase):
         event = self.cancel_and_wait()
         self.assert_qmp(event, 'data/type', 'backup')
 
+        self.vm.shutdown()
+
     def test_compress_cancel_drive_backup(self):
-        self.do_test_compress_cancel('drive-backup', target=blockdev_target_img, mode='existing')
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_cancel('drive-backup', format,
+                                         target=blockdev_target_img, mode='existing')
 
     def test_compress_cancel_blockdev_backup(self):
-        self.do_test_compress_cancel('blockdev-backup', target='drive1')
+       for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_cancel('blockdev-backup', format, target='drive1')
+
+    def do_test_compress_pause(self, cmd, format, **args):
+        self.do_prepare_drives(format['type'], format['args'])
 
-    def do_test_compress_pause(self, cmd, **args):
         self.assert_no_active_block_jobs()
 
         self.vm.pause_drive('drive0')
@@ -536,14 +554,17 @@ class TestDriveCompression(iotests.QMPTestCase):
 
         self.vm.shutdown()
         self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
-                                               iotests.imgfmt, TestDriveCompression.outfmt),
+                                               iotests.imgfmt, format['type']),
                         'target image does not match source after backup')
 
     def test_compress_pause_drive_backup(self):
-        self.do_test_compress_pause('drive-backup', target=blockdev_target_img, mode='existing')
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_pause('drive-backup', format,
+                                        target=blockdev_target_img, mode='existing')
 
     def test_compress_pause_blockdev_backup(self):
-        self.do_test_compress_pause('blockdev-backup', target='drive1')
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_pause('blockdev-backup', format, target='drive1')
 
 if __name__ == '__main__':
     iotests.main(supported_fmts=['raw', 'qcow2'])
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 30/42] test-coroutine: Fix coroutine pool corruption
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (28 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 29/42] qemu-iotests: add vmdk for " Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 31/42] qcow2: fix iovec size at qcow2_co_pwritev_compressed Kevin Wolf
                   ` (14 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

The test case overwrites the Coroutine object with 0xff as a way to
assert that the coroutine isn't used any more. However, this means that
the coroutine pool now contains a corrupted object and later test cases
may get this corrupted object and crash.

This patch saves the real content of the object and restores it after
completing the test. The only use of the coroutine pool between those
two points is the deletion of co2. As this only means an insertion at
the head of an SLIST (release_pool or alloc_pool), it doesn't access the
invalid list pointers that co1 has during this period.

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

diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
index ee5e06d..6431dd6 100644
--- a/tests/test-coroutine.c
+++ b/tests/test-coroutine.c
@@ -139,13 +139,20 @@ static void test_co_queue(void)
 {
     Coroutine *c1;
     Coroutine *c2;
+    Coroutine tmp;
 
     c2 = qemu_coroutine_create(c2_fn, NULL);
     c1 = qemu_coroutine_create(c1_fn, c2);
 
     qemu_coroutine_enter(c1);
+
+    /* c1 shouldn't be used any more now; make sure we segfault if it is */
+    tmp = *c1;
     memset(c1, 0xff, sizeof(Coroutine));
     qemu_coroutine_enter(c2);
+
+    /* Must restore the coroutine now to avoid corrupted pool */
+    *c1 = tmp;
 }
 
 /*
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 31/42] qcow2: fix iovec size at qcow2_co_pwritev_compressed
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (29 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 30/42] test-coroutine: Fix coroutine pool corruption Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 32/42] coroutine: Let CoMutex remember who holds it Kevin Wolf
                   ` (13 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Pavel Butsykin <pbutsykin@virtuozzo.com>

Use bytes as the size would be more exact than s->cluster_size.  Although
qemu_iovec_to_buf() will not allow to go beyond the qiov.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index adf4514..c079aa8 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2565,7 +2565,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
         /* Zero-pad last write if image size is not cluster aligned */
         memset(buf + bytes, 0, s->cluster_size - bytes);
     }
-    qemu_iovec_to_buf(qiov, 0, buf, s->cluster_size);
+    qemu_iovec_to_buf(qiov, 0, buf, bytes);
 
     out_buf = g_malloc(s->cluster_size);
 
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 32/42] coroutine: Let CoMutex remember who holds it
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (30 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 31/42] qcow2: fix iovec size at qcow2_co_pwritev_compressed Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 33/42] coroutine: Assert that no locks are held on termination Kevin Wolf
                   ` (12 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In cases of deadlocks, knowing who holds a given CoMutex is really
helpful for debugging. Keeping the information around doesn't cost much
and allows us to add another assertion to keep the code correct, so
let's just add it.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/qemu/coroutine.h   | 1 +
 util/qemu-coroutine-lock.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index ac8d4c9..29a2078 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -143,6 +143,7 @@ bool qemu_co_queue_empty(CoQueue *queue);
  */
 typedef struct CoMutex {
     bool locked;
+    Coroutine *holder;
     CoQueue queue;
 } CoMutex;
 
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 22aa9ab..f30ee81 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -129,6 +129,7 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
     }
 
     mutex->locked = true;
+    mutex->holder = self;
 
     trace_qemu_co_mutex_lock_return(mutex, self);
 }
@@ -140,9 +141,11 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
     trace_qemu_co_mutex_unlock_entry(mutex, self);
 
     assert(mutex->locked == true);
+    assert(mutex->holder == self);
     assert(qemu_in_coroutine());
 
     mutex->locked = false;
+    mutex->holder = NULL;
     qemu_co_queue_next(&mutex->queue);
 
     trace_qemu_co_mutex_unlock_return(mutex, self);
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 33/42] coroutine: Assert that no locks are held on termination
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (31 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 32/42] coroutine: Let CoMutex remember who holds it Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 34/42] block jobs: Improve error message for missing job ID Kevin Wolf
                   ` (11 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

A coroutine that takes a lock must also release it again. If the
coroutine terminates without having released all its locks, it's buggy
and we'll probably run into a deadlock sooner or later. Make sure that
we don't get such cases.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/qemu/coroutine_int.h |  1 +
 util/qemu-coroutine-lock.c   | 11 +++++++++++
 util/qemu-coroutine.c        |  1 +
 3 files changed, 13 insertions(+)

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index 581a7f5..6df9d33 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -39,6 +39,7 @@ struct Coroutine {
     void *entry_arg;
     Coroutine *caller;
     QSLIST_ENTRY(Coroutine) pool_next;
+    size_t locks_held;
 
     /* Coroutines that should be woken up when we yield or terminate */
     QSIMPLEQ_HEAD(, Coroutine) co_queue_wakeup;
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index f30ee81..14cf9ce 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -130,6 +130,7 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
 
     mutex->locked = true;
     mutex->holder = self;
+    self->locks_held++;
 
     trace_qemu_co_mutex_lock_return(mutex, self);
 }
@@ -146,6 +147,7 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
 
     mutex->locked = false;
     mutex->holder = NULL;
+    self->locks_held--;
     qemu_co_queue_next(&mutex->queue);
 
     trace_qemu_co_mutex_unlock_return(mutex, self);
@@ -159,14 +161,19 @@ void qemu_co_rwlock_init(CoRwlock *lock)
 
 void qemu_co_rwlock_rdlock(CoRwlock *lock)
 {
+    Coroutine *self = qemu_coroutine_self();
+
     while (lock->writer) {
         qemu_co_queue_wait(&lock->queue);
     }
     lock->reader++;
+    self->locks_held++;
 }
 
 void qemu_co_rwlock_unlock(CoRwlock *lock)
 {
+    Coroutine *self = qemu_coroutine_self();
+
     assert(qemu_in_coroutine());
     if (lock->writer) {
         lock->writer = false;
@@ -179,12 +186,16 @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
             qemu_co_queue_next(&lock->queue);
         }
     }
+    self->locks_held--;
 }
 
 void qemu_co_rwlock_wrlock(CoRwlock *lock)
 {
+    Coroutine *self = qemu_coroutine_self();
+
     while (lock->writer || lock->reader) {
         qemu_co_queue_wait(&lock->queue);
     }
     lock->writer = true;
+    self->locks_held++;
 }
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
index 89f21a9..3cbf225 100644
--- a/util/qemu-coroutine.c
+++ b/util/qemu-coroutine.c
@@ -122,6 +122,7 @@ void qemu_coroutine_enter(Coroutine *co)
     case COROUTINE_YIELD:
         return;
     case COROUTINE_TERMINATE:
+        assert(!co->locks_held);
         trace_qemu_coroutine_terminate(co);
         coroutine_delete(co);
         return;
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 34/42] block jobs: Improve error message for missing job ID
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (32 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 33/42] coroutine: Assert that no locks are held on termination Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 35/42] qemu-iotests: Log QMP traffic in debug mode Kevin Wolf
                   ` (10 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

If a block job is started with a node name rather than a device name and
no explicit job ID is passed, it was reported that '' isn't a
well-formed ID. Which is correct, but we can make the message a little
bit nicer.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 blockjob.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/blockjob.c b/blockjob.c
index a5ba3be..a167f96 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -132,6 +132,10 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
 
     if (job_id == NULL) {
         job_id = bdrv_get_device_name(bs);
+        if (!*job_id) {
+            error_setg(errp, "An explicit job ID is required for this node");
+            return NULL;
+        }
     }
 
     if (!id_wellformed(job_id)) {
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 35/42] qemu-iotests: Log QMP traffic in debug mode
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (33 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 34/42] block jobs: Improve error message for missing job ID Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command Kevin Wolf
                   ` (9 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Python tests are already annoying enough to debug. With QMP traffic
available it's a little bit easier at least.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 tests/qemu-iotests/iotests.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 69aa41e..f1f36d7 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -50,6 +50,7 @@ cachemode = os.environ.get('CACHEMODE')
 qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
 
 socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
+debug = False
 
 def qemu_img(*args):
     '''Run qemu-img and return the exit code'''
@@ -134,6 +135,8 @@ class VM(qtest.QEMUQtestMachine):
     def __init__(self):
         super(VM, self).__init__(qemu_prog, qemu_opts, test_dir=test_dir,
                                  socket_scm_helper=socket_scm_helper)
+        if debug:
+            self._debug = True
         self._num_drives = 0
 
     def add_drive_raw(self, opts):
@@ -318,6 +321,8 @@ def verify_quorum():
 def main(supported_fmts=[], supported_oses=['linux']):
     '''Run tests'''
 
+    global debug
+
     # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
     # indicate that we're not being run via "check". There may be
     # other things set up by "check" that individual test cases rely
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (34 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 35/42] qemu-iotests: Log QMP traffic in debug mode Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-15 22:18   ` Paolo Bonzini
  2016-09-05 18:13 ` [Qemu-devel] [PULL 37/42] oslib-posix: add helpers for stack alloc and free Kevin Wolf
                   ` (8 subsequent siblings)
  44 siblings, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

When using a node name, create a temporary BlockBackend that is used to
run the qemu-io command.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 hmp.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/hmp.c b/hmp.c
index a7dfe6f..ad33b44 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1923,11 +1923,22 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
 void hmp_qemu_io(Monitor *mon, const QDict *qdict)
 {
     BlockBackend *blk;
+    BlockBackend *local_blk = NULL;
     const char* device = qdict_get_str(qdict, "device");
     const char* command = qdict_get_str(qdict, "command");
     Error *err = NULL;
 
     blk = blk_by_name(device);
+    if (!blk) {
+        BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
+        if (bs) {
+            blk = local_blk = blk_new();
+            blk_insert_bs(blk, bs);
+        } else {
+            goto fail;
+        }
+    }
+
     if (blk) {
         AioContext *aio_context = blk_get_aio_context(blk);
         aio_context_acquire(aio_context);
@@ -1940,6 +1951,8 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
                   "Device '%s' not found", device);
     }
 
+fail:
+    blk_unref(local_blk);
     hmp_handle_error(mon, &err);
 }
 
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 37/42] oslib-posix: add helpers for stack alloc and free
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (35 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 38/42] coroutine: add a macro for the coroutine stack size Kevin Wolf
                   ` (7 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

the allocated stack will be adjusted to the minimum supported stack size
by the OS and rounded up to be a multiple of the system pagesize.
Additionally an architecture dependent guard page is added to the stack
to catch stack overflows. The memory for the guard page is deductated from
stack memory so that the usable stack size is effectively reduced by the size
of one page. This is equivalent to how the glibc stack allocation routines
behave.

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/sysemu/os-posix.h | 27 ++++++++++++++++++++++++++
 util/oslib-posix.c        | 48 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)

diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 9c7dfdf..87e60fe 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -60,4 +60,31 @@ int qemu_utimens(const char *path, const qemu_timespec *times);
 
 bool is_daemonized(void);
 
+/**
+ * qemu_alloc_stack:
+ * @sz: size of required stack in bytes
+ *
+ * Allocate memory that can be used as a stack, for instance for
+ * coroutines. If the memory cannot be allocated, this function
+ * will abort (like g_malloc()). This function also inserts a
+ * guard page to catch a potential stack overflow. The memory
+ * for the guard page is deductated from stack memory so that
+ * the usable stack size is effectively sz bytes minus the size
+ * of one page.
+ *
+ * The allocated stack must be freed with qemu_free_stack().
+ *
+ * Returns: pointer to (the lowest address of) the stack memory.
+ */
+void *qemu_alloc_stack(size_t sz);
+
+/**
+ * qemu_free_stack:
+ * @stack: stack to free
+ * @sz: size of stack in bytes
+ *
+ * Free a stack allocated via qemu_alloc_stack().
+ */
+void qemu_free_stack(void *stack, size_t sz);
+
 #endif
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index f2d4e9e..74dbe1c 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -499,3 +499,51 @@ pid_t qemu_fork(Error **errp)
     }
     return pid;
 }
+
+static size_t adjust_stack_size(size_t sz, size_t pagesz)
+{
+#ifdef _SC_THREAD_STACK_MIN
+    /* avoid stacks smaller than _SC_THREAD_STACK_MIN */
+    long min_stack_sz = sysconf(_SC_THREAD_STACK_MIN);
+    sz = MAX(MAX(min_stack_sz, 0), sz);
+#endif
+    /* adjust stack size to a multiple of the page size */
+    sz = ROUND_UP(sz, pagesz);
+    return sz;
+}
+
+void *qemu_alloc_stack(size_t sz)
+{
+    void *ptr, *guardpage;
+    size_t pagesz = getpagesize();
+    sz = adjust_stack_size(sz, pagesz);
+
+    ptr = mmap(NULL, sz, PROT_READ | PROT_WRITE,
+               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (ptr == MAP_FAILED) {
+        abort();
+    }
+
+#if defined(HOST_IA64)
+    /* separate register stack */
+    guardpage = ptr + (((sz - pagesz) / 2) & ~pagesz);
+#elif defined(HOST_HPPA)
+    /* stack grows up */
+    guardpage = ptr + sz - pagesz;
+#else
+    /* stack grows down */
+    guardpage = ptr;
+#endif
+    if (mprotect(guardpage, pagesz, PROT_NONE) != 0) {
+        abort();
+    }
+
+    return ptr;
+}
+
+void qemu_free_stack(void *stack, size_t sz)
+{
+    size_t pagesz = getpagesize();
+    sz = adjust_stack_size(sz, pagesz);
+    munmap(stack, sz);
+}
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 38/42] coroutine: add a macro for the coroutine stack size
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (36 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 37/42] oslib-posix: add helpers for stack alloc and free Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 39/42] coroutine-ucontext: use helper for allocating stack memory Kevin Wolf
                   ` (6 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu/coroutine_int.h | 2 ++
 util/coroutine-sigaltstack.c | 2 +-
 util/coroutine-ucontext.c    | 2 +-
 util/coroutine-win32.c       | 2 +-
 4 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index 6df9d33..14d4f1d 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -28,6 +28,8 @@
 #include "qemu/queue.h"
 #include "qemu/coroutine.h"
 
+#define COROUTINE_STACK_SIZE (1 << 20)
+
 typedef enum {
     COROUTINE_YIELD = 1,
     COROUTINE_TERMINATE = 2,
diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index a7c3366..9c2854c 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -143,7 +143,7 @@ static void coroutine_trampoline(int signal)
 
 Coroutine *qemu_coroutine_new(void)
 {
-    const size_t stack_size = 1 << 20;
+    const size_t stack_size = COROUTINE_STACK_SIZE;
     CoroutineUContext *co;
     CoroutineThreadState *coTS;
     struct sigaction sa;
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index 2bb7e10..31254ab 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -82,7 +82,7 @@ static void coroutine_trampoline(int i0, int i1)
 
 Coroutine *qemu_coroutine_new(void)
 {
-    const size_t stack_size = 1 << 20;
+    const size_t stack_size = COROUTINE_STACK_SIZE;
     CoroutineUContext *co;
     ucontext_t old_uc, uc;
     sigjmp_buf old_env;
diff --git a/util/coroutine-win32.c b/util/coroutine-win32.c
index 02e28e8..de6bd4f 100644
--- a/util/coroutine-win32.c
+++ b/util/coroutine-win32.c
@@ -71,7 +71,7 @@ static void CALLBACK coroutine_trampoline(void *co_)
 
 Coroutine *qemu_coroutine_new(void)
 {
-    const size_t stack_size = 1 << 20;
+    const size_t stack_size = COROUTINE_STACK_SIZE;
     CoroutineWin32 *co;
 
     co = g_malloc0(sizeof(*co));
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 39/42] coroutine-ucontext: use helper for allocating stack memory
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (37 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 38/42] coroutine: add a macro for the coroutine stack size Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 40/42] coroutine-sigaltstack: " Kevin Wolf
                   ` (5 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 util/coroutine-ucontext.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index 31254ab..b7dea8c 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -82,7 +82,6 @@ static void coroutine_trampoline(int i0, int i1)
 
 Coroutine *qemu_coroutine_new(void)
 {
-    const size_t stack_size = COROUTINE_STACK_SIZE;
     CoroutineUContext *co;
     ucontext_t old_uc, uc;
     sigjmp_buf old_env;
@@ -101,17 +100,17 @@ Coroutine *qemu_coroutine_new(void)
     }
 
     co = g_malloc0(sizeof(*co));
-    co->stack = g_malloc(stack_size);
+    co->stack = qemu_alloc_stack(COROUTINE_STACK_SIZE);
     co->base.entry_arg = &old_env; /* stash away our jmp_buf */
 
     uc.uc_link = &old_uc;
     uc.uc_stack.ss_sp = co->stack;
-    uc.uc_stack.ss_size = stack_size;
+    uc.uc_stack.ss_size = COROUTINE_STACK_SIZE;
     uc.uc_stack.ss_flags = 0;
 
 #ifdef CONFIG_VALGRIND_H
     co->valgrind_stack_id =
-        VALGRIND_STACK_REGISTER(co->stack, co->stack + stack_size);
+        VALGRIND_STACK_REGISTER(co->stack, co->stack + COROUTINE_STACK_SIZE);
 #endif
 
     arg.p = co;
@@ -149,7 +148,7 @@ void qemu_coroutine_delete(Coroutine *co_)
     valgrind_stack_deregister(co);
 #endif
 
-    g_free(co->stack);
+    qemu_free_stack(co->stack, COROUTINE_STACK_SIZE);
     g_free(co);
 }
 
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 40/42] coroutine-sigaltstack: use helper for allocating stack memory
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (38 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 39/42] coroutine-ucontext: use helper for allocating stack memory Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 41/42] oslib-posix: add a configure switch to debug stack usage Kevin Wolf
                   ` (4 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 util/coroutine-sigaltstack.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index 9c2854c..ccf4861 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -143,7 +143,6 @@ static void coroutine_trampoline(int signal)
 
 Coroutine *qemu_coroutine_new(void)
 {
-    const size_t stack_size = COROUTINE_STACK_SIZE;
     CoroutineUContext *co;
     CoroutineThreadState *coTS;
     struct sigaction sa;
@@ -164,7 +163,7 @@ Coroutine *qemu_coroutine_new(void)
      */
 
     co = g_malloc0(sizeof(*co));
-    co->stack = g_malloc(stack_size);
+    co->stack = qemu_alloc_stack(COROUTINE_STACK_SIZE);
     co->base.entry_arg = &old_env; /* stash away our jmp_buf */
 
     coTS = coroutine_get_thread_state();
@@ -189,7 +188,7 @@ Coroutine *qemu_coroutine_new(void)
      * Set the new stack.
      */
     ss.ss_sp = co->stack;
-    ss.ss_size = stack_size;
+    ss.ss_size = COROUTINE_STACK_SIZE;
     ss.ss_flags = 0;
     if (sigaltstack(&ss, &oss) < 0) {
         abort();
@@ -253,7 +252,7 @@ void qemu_coroutine_delete(Coroutine *co_)
 {
     CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
 
-    g_free(co->stack);
+    qemu_free_stack(co->stack, COROUTINE_STACK_SIZE);
     g_free(co);
 }
 
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 41/42] oslib-posix: add a configure switch to debug stack usage
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (39 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 40/42] coroutine-sigaltstack: " Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-05 18:13 ` [Qemu-devel] [PULL 42/42] coroutine: reduce stack size to 64kB Kevin Wolf
                   ` (3 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

this adds a knob to track the maximum stack usage of stacks
created by qemu_alloc_stack.

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 configure          | 19 +++++++++++++++++++
 util/oslib-posix.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/configure b/configure
index 4b808f9..7e087c5 100755
--- a/configure
+++ b/configure
@@ -296,6 +296,7 @@ libiscsi=""
 libnfs=""
 coroutine=""
 coroutine_pool=""
+debug_stack_usage="no"
 seccomp=""
 glusterfs=""
 glusterfs_xlator_opt="no"
@@ -1005,6 +1006,8 @@ for opt do
   ;;
   --enable-coroutine-pool) coroutine_pool="yes"
   ;;
+  --enable-debug-stack-usage) debug_stack_usage="yes"
+  ;;
   --disable-docs) docs="no"
   ;;
   --enable-docs) docs="yes"
@@ -4306,6 +4309,17 @@ if test "$coroutine" = "gthread" -a "$coroutine_pool" = "yes"; then
   error_exit "'gthread' coroutine backend does not support pool (use --disable-coroutine-pool)"
 fi
 
+if test "$debug_stack_usage" = "yes"; then
+  if test "$cpu" = "ia64" -o "$cpu" = "hppa"; then
+    error_exit "stack usage debugging is not supported for $cpu"
+  fi
+  if test "$coroutine_pool" = "yes"; then
+    echo "WARN: disabling coroutine pool for stack usage debugging"
+    coroutine_pool=no
+  fi
+fi
+
+
 ##########################################
 # check if we have open_by_handle_at
 
@@ -4892,6 +4906,7 @@ echo "QGA MSI support   $guest_agent_msi"
 echo "seccomp support   $seccomp"
 echo "coroutine backend $coroutine"
 echo "coroutine pool    $coroutine_pool"
+echo "debug stack usage $debug_stack_usage"
 echo "GlusterFS support $glusterfs"
 echo "Archipelago support $archipelago"
 echo "gcov              $gcov_tool"
@@ -5360,6 +5375,10 @@ else
   echo "CONFIG_COROUTINE_POOL=0" >> $config_host_mak
 fi
 
+if test "$debug_stack_usage" = "yes" ; then
+  echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak
+fi
+
 if test "$open_by_handle_at" = "yes" ; then
   echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
 fi
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 74dbe1c..b33c1cd 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -50,6 +50,10 @@
 
 #include "qemu/mmap-alloc.h"
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#include "qemu/error-report.h"
+#endif
+
 int qemu_get_thread_id(void)
 {
 #if defined(__linux__)
@@ -515,6 +519,9 @@ static size_t adjust_stack_size(size_t sz, size_t pagesz)
 void *qemu_alloc_stack(size_t sz)
 {
     void *ptr, *guardpage;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+    void *ptr2;
+#endif
     size_t pagesz = getpagesize();
     sz = adjust_stack_size(sz, pagesz);
 
@@ -538,12 +545,41 @@ void *qemu_alloc_stack(size_t sz)
         abort();
     }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+    for (ptr2 = ptr + pagesz; ptr2 < ptr + sz; ptr2 += sizeof(uint32_t)) {
+        *(uint32_t *)ptr2 = 0xdeadbeaf;
+    }
+#endif
+
     return ptr;
 }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static __thread unsigned int max_stack_usage;
+#endif
+
 void qemu_free_stack(void *stack, size_t sz)
 {
+#ifdef CONFIG_DEBUG_STACK_USAGE
+    unsigned int usage;
+    void *ptr;
+#endif
     size_t pagesz = getpagesize();
     sz = adjust_stack_size(sz, pagesz);
+
+#ifdef CONFIG_DEBUG_STACK_USAGE
+    for (ptr = stack + pagesz; ptr < stack + sz; ptr += sizeof(uint32_t)) {
+        if (*(uint32_t *)ptr != 0xdeadbeaf) {
+            break;
+        }
+    }
+    usage = sz - (uintptr_t) (ptr - stack);
+    if (usage > max_stack_usage) {
+        error_report("thread %d max stack usage increased from %u to %u",
+                     qemu_get_thread_id(), max_stack_usage, usage);
+        max_stack_usage = usage;
+    }
+#endif
+
     munmap(stack, sz);
 }
-- 
1.8.3.1

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

* [Qemu-devel] [PULL 42/42] coroutine: reduce stack size to 64kB
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (40 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 41/42] oslib-posix: add a configure switch to debug stack usage Kevin Wolf
@ 2016-09-05 18:13 ` Kevin Wolf
  2016-09-06 10:12 ` [Qemu-devel] [PULL 00/42] Block layer patches Peter Maydell
                   ` (2 subsequent siblings)
  44 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2016-09-05 18:13 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

evaluation with the recently introduced maximum stack usage monitoring revealed
that the actual used stack size was never above 4kB so allocating 1MB stack
for each coroutine is a lot of wasted memory. So reduce the stack size to
64kB which should still give enough head room. The guard page added
in qemu_alloc_stack will catch a potential stack overflow introduced
by this commit.

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu/coroutine_int.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index 14d4f1d..fd71172 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -28,7 +28,7 @@
 #include "qemu/queue.h"
 #include "qemu/coroutine.h"
 
-#define COROUTINE_STACK_SIZE (1 << 20)
+#define COROUTINE_STACK_SIZE (1 << 16)
 
 typedef enum {
     COROUTINE_YIELD = 1,
-- 
1.8.3.1

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

* Re: [Qemu-devel] [PULL 00/42] Block layer patches
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (41 preceding siblings ...)
  2016-09-05 18:13 ` [Qemu-devel] [PULL 42/42] coroutine: reduce stack size to 64kB Kevin Wolf
@ 2016-09-06 10:12 ` Peter Maydell
  2016-09-06 10:36   ` Kevin Wolf
  2016-09-06 10:33 ` Peter Maydell
  2016-09-06 10:42 ` Peter Maydell
  44 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-09-06 10:12 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Qemu-block, QEMU Developers

On 5 September 2016 at 19:13, Kevin Wolf <kwolf@redhat.com> wrote:
> The following changes since commit e87d397e5ef66276ccc49b829527d605ca07d0ad:
>
>   Open 2.8 development tree (2016-09-05 11:38:54 +0100)
>
> are available in the git repository at:
>
>   git://repo.or.cz/qemu/kevin.git tags/for-upstream
>
> for you to fetch changes up to 1585512ba88324844c2722fd977b126fc2748604:
>
>   coroutine: reduce stack size to 64kB (2016-09-05 19:06:49 +0200)
>
> ----------------------------------------------------------------
> Block layer patches
>
> ----------------------------------------------------------------

I'm afraid this fails 'make check' on ppc64be:

MALLOC_PERTURB_=${MALLOC_PERTURB_:-$((RANDOM % 255 + 1))} gtester -k
--verbose -m=quick tests/test-coroutine
TEST: tests/test-coroutine... (pid=52932)
  /basic/co_queue:                                                     FAIL
GTester: last random seed: R02Sc3b6f36ad285d724ab0bb9d6b3b65ff7
(pid=52934)
  /basic/lifecycle:                                                    FAIL
GTester: last random seed: R02Sc30fe01c96aecf3873a5dab246c4945d
(pid=52935)
  /basic/yield:                                                        FAIL
GTester: last random seed: R02Sa343d307145707796c84673870963561
(pid=52936)
  /basic/nesting:                                                      FAIL
GTester: last random seed: R02S9d9c125c3934e5f3d4fd794a7a3026b6
(pid=52937)
  /basic/self:                                                         FAIL
GTester: last random seed: R02Sf30817e4d44892fff95286f50d30b375
(pid=52938)
  /basic/in_coroutine:                                                 FAIL
GTester: last random seed: R02S4048ae6da7f2fe5614e9cecf846f712b
(pid=52939)
  /basic/order:                                                        FAIL
GTester: last random seed: R02S4261fe2d21feaee583cdd9f2a2433f5a
(pid=52940)
FAIL: tests/test-coroutine

thanks
-- PMM

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

* Re: [Qemu-devel] [PULL 00/42] Block layer patches
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (42 preceding siblings ...)
  2016-09-06 10:12 ` [Qemu-devel] [PULL 00/42] Block layer patches Peter Maydell
@ 2016-09-06 10:33 ` Peter Maydell
  2016-09-06 10:42 ` Peter Maydell
  44 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-09-06 10:33 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Qemu-block, QEMU Developers

On 5 September 2016 at 19:13, Kevin Wolf <kwolf@redhat.com> wrote:
> The following changes since commit e87d397e5ef66276ccc49b829527d605ca07d0ad:
>
>   Open 2.8 development tree (2016-09-05 11:38:54 +0100)
>
> are available in the git repository at:
>
>   git://repo.or.cz/qemu/kevin.git tags/for-upstream
>
> for you to fetch changes up to 1585512ba88324844c2722fd977b126fc2748604:
>
>   coroutine: reduce stack size to 64kB (2016-09-05 19:06:49 +0200)
>
> ----------------------------------------------------------------
> Block layer patches
>

Also fails make check on 64-bit ARM:
QTEST_QEMU_BINARY=i386-softmmu/qemu-system-i386
QTEST_QEMU_IMG=qemu-img MALLOC_PERTURB_=${MA
LLOC_PERTURB_:-$((RANDOM % 255 + 1))} gtester -k --verbose -m=quick
tests/endianness-test te
sts/fdc-test tests/ide-test tests/ahci-test tests/hd-geo-test
tests/boot-order-test tests/bi
os-tables-test tests/pxe-test tests/rtc-test tests/ipmi-kcs-test
tests/ipmi-bt-test tests/i440fx-test tests/fw_cfg-test
tests/drive_del-test tests/wdt_ib700-test tests/tco-test
tests/e1000-test tests/e1000e-test tests/rtl8139-test tests/pcnet-test
tests/eepro100-test tests/ne2000-test tests/nvme-test tests/ac97-test
tests/es1370-test tests/virtio-net-test tests/virtio-balloon-test
tests/virtio-blk-test tests/virtio-rng-test tests/virtio-scsi-test
tests/virtio-9p-test tests/virtio-serial-test
tests/virtio-console-test tests/tpci200-test tests/ipoctal232-test
tests/display-vga-test tests/intel-hda-test tests/ivshmem-test
tests/vmxnet3-test tests/pvpanic-test tests/i82801b11-test
tests/ioh3420-test tests/usb-hcd-ohci-test tests/usb-hcd-uhci-test
tests/usb-hcd-ehci-test tests/usb-hcd-xhci-test tests/pc-cpu-test
tests/q35-test tests/test-netfilter tests/test-filter-mirror
tests/test-filter-redirector tests/postcopy-test
tests/device-introspect-test tests/qom-test
[...]

  /i386/ahci/cdrom/dma/single:                                         OK
  /i386/ahci/cdrom/dma/multi:                                          OK
  /i386/ahci/cdrom/pio/single:                                         OK
  /i386/ahci/cdrom/pio/multi:
Broken pipe
FAIL
GTester: last random seed: R02Se17b2766a5bd0a0d37b43149f90e36e1
(pid=28161)
FAIL: tests/ahci-test

thanks
-- PMM

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

* Re: [Qemu-devel] [PULL 00/42] Block layer patches
  2016-09-06 10:12 ` [Qemu-devel] [PULL 00/42] Block layer patches Peter Maydell
@ 2016-09-06 10:36   ` Kevin Wolf
  2016-09-16 13:25     ` Peter Lieven
  0 siblings, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2016-09-06 10:36 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Qemu-block, pl, pbonzini

Am 06.09.2016 um 12:12 hat Peter Maydell geschrieben:
> On 5 September 2016 at 19:13, Kevin Wolf <kwolf@redhat.com> wrote:
> > The following changes since commit e87d397e5ef66276ccc49b829527d605ca07d0ad:
> >
> >   Open 2.8 development tree (2016-09-05 11:38:54 +0100)
> >
> > are available in the git repository at:
> >
> >   git://repo.or.cz/qemu/kevin.git tags/for-upstream
> >
> > for you to fetch changes up to 1585512ba88324844c2722fd977b126fc2748604:
> >
> >   coroutine: reduce stack size to 64kB (2016-09-05 19:06:49 +0200)
> >
> > ----------------------------------------------------------------
> > Block layer patches
> >
> > ----------------------------------------------------------------
> 
> I'm afraid this fails 'make check' on ppc64be:
> 
> MALLOC_PERTURB_=${MALLOC_PERTURB_:-$((RANDOM % 255 + 1))} gtester -k
> --verbose -m=quick tests/test-coroutine
> TEST: tests/test-coroutine... (pid=52932)
>   /basic/co_queue:                                                     FAIL
> GTester: last random seed: R02Sc3b6f36ad285d724ab0bb9d6b3b65ff7
> (pid=52934)
>   /basic/lifecycle:                                                    FAIL
> GTester: last random seed: R02Sc30fe01c96aecf3873a5dab246c4945d
> (pid=52935)
>   /basic/yield:                                                        FAIL
> GTester: last random seed: R02Sa343d307145707796c84673870963561
> (pid=52936)
>   /basic/nesting:                                                      FAIL
> GTester: last random seed: R02S9d9c125c3934e5f3d4fd794a7a3026b6
> (pid=52937)
>   /basic/self:                                                         FAIL
> GTester: last random seed: R02Sf30817e4d44892fff95286f50d30b375
> (pid=52938)
>   /basic/in_coroutine:                                                 FAIL
> GTester: last random seed: R02S4048ae6da7f2fe5614e9cecf846f712b
> (pid=52939)
>   /basic/order:                                                        FAIL
> GTester: last random seed: R02S4261fe2d21feaee583cdd9f2a2433f5a
> (pid=52940)
> FAIL: tests/test-coroutine

Peter (Lieven), this is yours.

I'll drop the coroutine series from the pull request and send a v2.

Kevin

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

* Re: [Qemu-devel] [PULL 00/42] Block layer patches
  2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
                   ` (43 preceding siblings ...)
  2016-09-06 10:33 ` Peter Maydell
@ 2016-09-06 10:42 ` Peter Maydell
  44 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-09-06 10:42 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Qemu-block, QEMU Developers

On 5 September 2016 at 19:13, Kevin Wolf <kwolf@redhat.com> wrote:
> The following changes since commit e87d397e5ef66276ccc49b829527d605ca07d0ad:
>
>   Open 2.8 development tree (2016-09-05 11:38:54 +0100)
>
> are available in the git repository at:
>
>   git://repo.or.cz/qemu/kevin.git tags/for-upstream
>
> for you to fetch changes up to 1585512ba88324844c2722fd977b126fc2748604:
>
>   coroutine: reduce stack size to 64kB (2016-09-05 19:06:49 +0200)
>
> ----------------------------------------------------------------
> Block layer patches

make check on the clang sanitizer build failed too. Note that
the sanitizer "runtime error" messages are not fatal, so whatever
made the test fail was something else.

GTESTER check-qtest-i386
/home/petmay01/linaro/qemu-for-merges/qtest.c:497:16: runtime error:
null pointer passed as argument 1, which is declared to never be null
/usr/include/string.h:62:62: note: nonnull attribute specified here
/home/petmay01/linaro/qemu-for-merges/qtest.c:497:16: runtime error:
null pointer passed as argument 1, which is declared to never be null
/usr/include/string.h:62:62: note: nonnull attribute specified here
Broken pipe
GTester: last random seed: R02S47b95908b2d55cace56bbf395725386c
Broken pipe
GTester: last random seed: R02Sf7d2ad3c04d0dbe7e2835b41abe6ae94

thanks
-- PMM

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

* Re: [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command
  2016-09-05 18:13 ` [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command Kevin Wolf
@ 2016-09-15 22:18   ` Paolo Bonzini
  0 siblings, 0 replies; 51+ messages in thread
From: Paolo Bonzini @ 2016-09-15 22:18 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: qemu-devel



On 05/09/2016 20:13, Kevin Wolf wrote:
> When using a node name, create a temporary BlockBackend that is used to
> run the qemu-io command.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
>  hmp.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/hmp.c b/hmp.c
> index a7dfe6f..ad33b44 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1923,11 +1923,22 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
>  void hmp_qemu_io(Monitor *mon, const QDict *qdict)
>  {
>      BlockBackend *blk;
> +    BlockBackend *local_blk = NULL;
>      const char* device = qdict_get_str(qdict, "device");
>      const char* command = qdict_get_str(qdict, "command");
>      Error *err = NULL;
>  
>      blk = blk_by_name(device);
> +    if (!blk) {
> +        BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
> +        if (bs) {
> +            blk = local_blk = blk_new();
> +            blk_insert_bs(blk, bs);
> +        } else {
> +            goto fail;
> +        }
> +    }
> +
>      if (blk) {

Coverity notes that this "if" is now always taken.

Thanks,

Paolo

>          AioContext *aio_context = blk_get_aio_context(blk);
>          aio_context_acquire(aio_context);
> @@ -1940,6 +1951,8 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
>                    "Device '%s' not found", device);
>      }
>  
> +fail:
> +    blk_unref(local_blk);
>      hmp_handle_error(mon, &err);
>  }
>  
> 

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

* Re: [Qemu-devel] [PULL 00/42] Block layer patches
  2016-09-06 10:36   ` Kevin Wolf
@ 2016-09-16 13:25     ` Peter Lieven
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Lieven @ 2016-09-16 13:25 UTC (permalink / raw)
  To: Kevin Wolf, Peter Maydell; +Cc: QEMU Developers, Qemu-block, pbonzini

Am 06.09.2016 um 12:36 schrieb Kevin Wolf:
> Am 06.09.2016 um 12:12 hat Peter Maydell geschrieben:
>> On 5 September 2016 at 19:13, Kevin Wolf <kwolf@redhat.com> wrote:
>>> The following changes since commit e87d397e5ef66276ccc49b829527d605ca07d0ad:
>>>
>>>    Open 2.8 development tree (2016-09-05 11:38:54 +0100)
>>>
>>> are available in the git repository at:
>>>
>>>    git://repo.or.cz/qemu/kevin.git tags/for-upstream
>>>
>>> for you to fetch changes up to 1585512ba88324844c2722fd977b126fc2748604:
>>>
>>>    coroutine: reduce stack size to 64kB (2016-09-05 19:06:49 +0200)
>>>
>>> ----------------------------------------------------------------
>>> Block layer patches
>>>
>>> ----------------------------------------------------------------
>> I'm afraid this fails 'make check' on ppc64be:
>>
>> MALLOC_PERTURB_=${MALLOC_PERTURB_:-$((RANDOM % 255 + 1))} gtester -k
>> --verbose -m=quick tests/test-coroutine
>> TEST: tests/test-coroutine... (pid=52932)
>>    /basic/co_queue:                                                     FAIL
>> GTester: last random seed: R02Sc3b6f36ad285d724ab0bb9d6b3b65ff7
>> (pid=52934)
>>    /basic/lifecycle:                                                    FAIL
>> GTester: last random seed: R02Sc30fe01c96aecf3873a5dab246c4945d
>> (pid=52935)
>>    /basic/yield:                                                        FAIL
>> GTester: last random seed: R02Sa343d307145707796c84673870963561
>> (pid=52936)
>>    /basic/nesting:                                                      FAIL
>> GTester: last random seed: R02S9d9c125c3934e5f3d4fd794a7a3026b6
>> (pid=52937)
>>    /basic/self:                                                         FAIL
>> GTester: last random seed: R02Sf30817e4d44892fff95286f50d30b375
>> (pid=52938)
>>    /basic/in_coroutine:                                                 FAIL
>> GTester: last random seed: R02S4048ae6da7f2fe5614e9cecf846f712b
>> (pid=52939)
>>    /basic/order:                                                        FAIL
>> GTester: last random seed: R02S4261fe2d21feaee583cdd9f2a2433f5a
>> (pid=52940)
>> FAIL: tests/test-coroutine
> Peter (Lieven), this is yours.
>
> I'll drop the coroutine series from the pull request and send a v2.

Hi Kevin,

do you know how to check this on ppc64be? On x86_64 its working fine.

Thanks,
Peter

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

* Re: [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression
  2016-09-05 18:13 ` [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression Kevin Wolf
@ 2016-09-16 15:15   ` Eric Blake
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Blake @ 2016-09-16 15:15 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: qemu-devel

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

On 09/05/2016 01:13 PM, Kevin Wolf wrote:
> From: Pavel Butsykin <pbutsykin@virtuozzo.com>
> 
> The idea is simple - backup is "written-once" data. It is written block
> by block and it is large enough. It would be nice to save storage
> space and compress it.
> 
> The patch adds a flag to the qmp/hmp drive-backup command which enables
> block compression. Compression should be implemented in the format driver
> to enable this feature.
> 

> +++ b/qapi/block-core.json
> @@ -898,6 +898,9 @@
>  #          Must be present if sync is "incremental", must NOT be present
>  #          otherwise. (Since 2.4)
>  #
> +# @compress: #optional true to compress data, if the target format supports it.
> +#            (default: false) (since 2.7)

This missed 2.7; we need a followup patch to adjust it to 2.8.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

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

* Re: [Qemu-devel] [PULL 27/42] blockdev-backup: added support for data compression
  2016-09-05 18:13 ` [Qemu-devel] [PULL 27/42] blockdev-backup: " Kevin Wolf
@ 2016-09-16 15:15   ` Eric Blake
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Blake @ 2016-09-16 15:15 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: qemu-devel

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

On 09/05/2016 01:13 PM, Kevin Wolf wrote:
> From: Pavel Butsykin <pbutsykin@virtuozzo.com>
> 
> The idea is simple - backup is "written-once" data. It is written block
> by block and it is large enough. It would be nice to save storage
> space and compress it.
> 

> +++ b/qapi/block-core.json
> @@ -939,6 +939,9 @@
>  # @speed: #optional the maximum speed, in bytes per second. The default is 0,
>  #         for unlimited.
>  #
> +# @compress: #optional true to compress data, if the target format supports it.
> +#            (default: false) (since 2.7)

Again, 2.8.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

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

end of thread, other threads:[~2016-09-16 15:15 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-05 18:13 [Qemu-devel] [PULL 00/42] Block layer patches Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 01/42] ide: ide-cd without drive property for empty drive Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 02/42] scsi: scsi-cd " Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 03/42] block: Accept node-name for block-stream Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 04/42] block: Accept node-name for block-commit Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 05/42] block: Accept node-name for blockdev-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 06/42] block: Accept node-name for blockdev-mirror Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 07/42] block: Accept node-name for blockdev-snapshot-delete-internal-sync Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 08/42] block: Accept node-name for blockdev-snapshot-internal-sync Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 09/42] block: Accept node-name for change-backing-file Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 10/42] block: Accept node-name for drive-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 11/42] block: Accept node-name for drive-mirror Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 12/42] nbd-server: Use a separate BlockBackend Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 13/42] nbd-server: Allow node name for nbd-server-add Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 14/42] block: switch blk_write_compressed() to byte-based interface Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 15/42] block: Convert bdrv_pwrite_compressed() to BdrvChild Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 16/42] block/io: reuse bdrv_co_pwritev() for write compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 17/42] qcow2: add qcow2_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 18/42] qcow2: cleanup qcow2_co_pwritev_compressed to avoid the recursion Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 19/42] vmdk: add vmdk_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 20/42] qcow: add qcow_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 21/42] qcow: cleanup qcow_co_pwritev_compressed to avoid the recursion Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 22/42] block: remove BlockDriver.bdrv_write_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 23/42] block/io: turn on dirty_bitmaps for the compressed writes Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 24/42] block: simplify drive-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 25/42] block: simplify blockdev-backup Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 26/42] drive-backup: added support for data compression Kevin Wolf
2016-09-16 15:15   ` Eric Blake
2016-09-05 18:13 ` [Qemu-devel] [PULL 27/42] blockdev-backup: " Kevin Wolf
2016-09-16 15:15   ` Eric Blake
2016-09-05 18:13 ` [Qemu-devel] [PULL 28/42] qemu-iotests: test backup compression in 055 Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 29/42] qemu-iotests: add vmdk for " Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 30/42] test-coroutine: Fix coroutine pool corruption Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 31/42] qcow2: fix iovec size at qcow2_co_pwritev_compressed Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 32/42] coroutine: Let CoMutex remember who holds it Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 33/42] coroutine: Assert that no locks are held on termination Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 34/42] block jobs: Improve error message for missing job ID Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 35/42] qemu-iotests: Log QMP traffic in debug mode Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 36/42] block: Allow node name for 'qemu-io' HMP command Kevin Wolf
2016-09-15 22:18   ` Paolo Bonzini
2016-09-05 18:13 ` [Qemu-devel] [PULL 37/42] oslib-posix: add helpers for stack alloc and free Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 38/42] coroutine: add a macro for the coroutine stack size Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 39/42] coroutine-ucontext: use helper for allocating stack memory Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 40/42] coroutine-sigaltstack: " Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 41/42] oslib-posix: add a configure switch to debug stack usage Kevin Wolf
2016-09-05 18:13 ` [Qemu-devel] [PULL 42/42] coroutine: reduce stack size to 64kB Kevin Wolf
2016-09-06 10:12 ` [Qemu-devel] [PULL 00/42] Block layer patches Peter Maydell
2016-09-06 10:36   ` Kevin Wolf
2016-09-16 13:25     ` Peter Lieven
2016-09-06 10:33 ` Peter Maydell
2016-09-06 10:42 ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.