diff mbox

[1/6] block/qapi: Add cache information to query-block

Message ID 1410881796-18452-2-git-send-email-kwolf@redhat.com
State New
Headers show

Commit Message

Kevin Wolf Sept. 16, 2014, 3:36 p.m. UTC
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qapi.c               | 10 ++++++++++
 hmp.c                      |  8 ++++++++
 qapi/block-core.json       |  4 +++-
 tests/qemu-iotests/051.out |  1 +
 tests/qemu-iotests/067.out | 10 +++++-----
 5 files changed, 27 insertions(+), 6 deletions(-)

 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}

Comments

Markus Armbruster Sept. 18, 2014, 11:04 a.m. UTC | #1
Kevin Wolf <kwolf@redhat.com> writes:

> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  block/qapi.c               | 10 ++++++++++
>  hmp.c                      |  8 ++++++++
>  qapi/block-core.json       |  4 +++-
>  tests/qemu-iotests/051.out |  1 +
>  tests/qemu-iotests/067.out | 10 +++++-----
>  5 files changed, 27 insertions(+), 6 deletions(-)
>
> diff --git a/block/qapi.c b/block/qapi.c
> index 9733ebd..6b43bc3 100644
> --- a/block/qapi.c
> +++ b/block/qapi.c
> @@ -46,6 +46,16 @@ BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs)
>      info->encrypted              = bs->encrypted;
>      info->encryption_key_missing = bdrv_key_required(bs);
>  
> +    info->cache = g_new(BlockdevCacheOptions, 1);
> +    *info->cache = (BlockdevCacheOptions) {
> +        .writeback      = bdrv_enable_write_cache(bs),
> +        .has_writeback  = true,
> +        .direct         = !!(bs->open_flags & BDRV_O_NOCACHE),
> +        .has_direct     = true,
> +        .no_flush       = !!(bs->open_flags & BDRV_O_NO_FLUSH),
> +        .has_no_flush   = true,
> +    };
> +

Awkward optionality.  I'm going to discuss this below, in the context of
the schema change.

>      if (bs->node_name[0]) {
>          info->has_node_name = true;
>          info->node_name = g_strdup(bs->node_name);
> diff --git a/hmp.c b/hmp.c
> index 40a90da..c3846b8 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -294,6 +294,7 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
>  {
>      BlockInfoList *block_list, *info;
>      ImageInfo *image_info;
> +    BlockDeviceInfo *inserted;
>      const char *device = qdict_get_try_str(qdict, "device");
>      bool verbose = qdict_get_try_bool(qdict, "verbose", 0);
>  
> @@ -335,6 +336,13 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
>              continue;
>          }
>  
> +        inserted = info->value->inserted;
> +
> +        monitor_printf(mon, "    Cache mode:       %s%s%s\n",
> +                       inserted->cache->writeback ? "writeback" : "writethrough",
> +                       inserted->cache->direct ? ", direct" : "",
> +                       inserted->cache->no_flush ? ", ignore flushes" : "");
> +

If !inserted->cache->writeback && inserted->cache->direct, this prints
"    Cache mode:       , writeback".

>          if (info->value->inserted->has_backing_file) {
>              monitor_printf(mon,
>                             "    Backing file:     %s "
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 95dcd81..c53b587 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -238,6 +238,8 @@
>  #
>  # @iops_size: #optional an I/O size in bytes (Since 1.7)
>  #
> +# @cache: the cache mode used for the block device (since: 2.2)
> +#
>  # Since: 0.14.0
>  #
>  ##
> @@ -252,7 +254,7 @@
>              '*bps_max': 'int', '*bps_rd_max': 'int',
>              '*bps_wr_max': 'int', '*iops_max': 'int',
>              '*iops_rd_max': 'int', '*iops_wr_max': 'int',
> -            '*iops_size': 'int' } }
> +            '*iops_size': 'int', 'cache': 'BlockdevCacheOptions' } }
>  
>  ##
>  # @BlockDeviceIoStatus:

Before this patch, QAPI type BlockdevCacheOptions is used only as a
member of BlockdevOptionsBase.

BlockdevOptionsBase is a collection configuration settings.
Consequently, it's a complex type whose members are optional exactly
when the configuration setting is optional.  Makes sense.

Complication: a few options are wrapped in another complex type,
BlockdevCacheOptions.  It's optional, but that's not sufficient, it's
members are all optional, too.

BlockdevCacheOptions is the only complex member of BlockdevOptionsBase.
The others are all simple or enum.

In this patch, you reuse BlockdevCacheOptions for a purpose other than
configuration: *querying* configuration.  In the query result, neither
the complex type nor its members are optional.  The schema reflects the
former (the patch hunk has 'cache', not '*cache'), but not the latter.

Do we want the schema to reflect reality accurately?

If no, we should still document the places where it doesn't, like this
one.

If yes, how can we fix this particular inaccuracy?

The obvious solution is not to reuse BlockdevCacheOptions.  Create a
second type, identical except for its members aren't optional.

Another idea is to add means to the schema to declare a member "deep
optional": not just the member is optional, but if it's present, its
members are optional, too.  Begs the question whether its member's
member's are optional.  Hmm.

Yet another idea is to declare nesting configuration options stupid, and
just not do it, but it may be too late for that.

Other ideas?

[...]
Markus Armbruster Sept. 18, 2014, 11:38 a.m. UTC | #2
Markus Armbruster <armbru@redhat.com> writes:

> Kevin Wolf <kwolf@redhat.com> writes:
[...]
>> @@ -335,6 +336,13 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
>>              continue;
>>          }
>>  
>> +        inserted = info->value->inserted;
>> +
>> +        monitor_printf(mon, "    Cache mode:       %s%s%s\n",
>> +                       inserted->cache->writeback ? "writeback" : "writethrough",
>> +                       inserted->cache->direct ? ", direct" : "",
>> +                       inserted->cache->no_flush ? ", ignore flushes" : "");
>> +
>
> If !inserted->cache->writeback && inserted->cache->direct, this prints
> "    Cache mode:       , writeback".

Nevermind, I can't read.

[...]
Kevin Wolf Sept. 18, 2014, 11:53 a.m. UTC | #3
Am 18.09.2014 um 13:04 hat Markus Armbruster geschrieben:
> Before this patch, QAPI type BlockdevCacheOptions is used only as a
> member of BlockdevOptionsBase.
> 
> BlockdevOptionsBase is a collection configuration settings.
> Consequently, it's a complex type whose members are optional exactly
> when the configuration setting is optional.  Makes sense.
> 
> Complication: a few options are wrapped in another complex type,
> BlockdevCacheOptions.  It's optional, but that's not sufficient, it's
> members are all optional, too.
> 
> BlockdevCacheOptions is the only complex member of BlockdevOptionsBase.
> The others are all simple or enum.
> 
> In this patch, you reuse BlockdevCacheOptions for a purpose other than
> configuration: *querying* configuration.  In the query result, neither
> the complex type nor its members are optional.  The schema reflects the
> former (the patch hunk has 'cache', not '*cache'), but not the latter.
> 
> Do we want the schema to reflect reality accurately?
> 
> If no, we should still document the places where it doesn't, like this
> one.

That's a fair requirement. If anything is optional in a return value, we
should specify the conditions under which it is there or missing.
Including, of course, if it's always or never there.

> If yes, how can we fix this particular inaccuracy?
> 
> The obvious solution is not to reuse BlockdevCacheOptions.  Create a
> second type, identical except for its members aren't optional.

I can introduce a BlockdevCacheInfo instead. While I'm not completely
excited about having two structs for each option dict (one for
configuring, one for querying), there's precedence for this and it's at
least a small struct this time.

> Another idea is to add means to the schema to declare a member "deep
> optional": not just the member is optional, but if it's present, its
> members are optional, too.  Begs the question whether its member's
> member's are optional.  Hmm.

"deep optional" doesn't sound like it makes a lot of sense conceptually,
even if it might happen to be a hack that gets us the right result in
this one specific case.

> Yet another idea is to declare nesting configuration options stupid, and
> just not do it, but it may be too late for that.
> 
> Other ideas?

I think the choice is between adding BlockdevCacheInfo and changing
documentation while reusing BlockdevCacheOptions. Both are fine with me.
Which one do you prefer?

Kevin
Markus Armbruster Sept. 18, 2014, 12:46 p.m. UTC | #4
Kevin Wolf <kwolf@redhat.com> writes:

> Am 18.09.2014 um 13:04 hat Markus Armbruster geschrieben:
>> Before this patch, QAPI type BlockdevCacheOptions is used only as a
>> member of BlockdevOptionsBase.
>> 
>> BlockdevOptionsBase is a collection configuration settings.
>> Consequently, it's a complex type whose members are optional exactly
>> when the configuration setting is optional.  Makes sense.
>> 
>> Complication: a few options are wrapped in another complex type,
>> BlockdevCacheOptions.  It's optional, but that's not sufficient, it's
>> members are all optional, too.
>> 
>> BlockdevCacheOptions is the only complex member of BlockdevOptionsBase.
>> The others are all simple or enum.
>> 
>> In this patch, you reuse BlockdevCacheOptions for a purpose other than
>> configuration: *querying* configuration.  In the query result, neither
>> the complex type nor its members are optional.  The schema reflects the
>> former (the patch hunk has 'cache', not '*cache'), but not the latter.
>> 
>> Do we want the schema to reflect reality accurately?
>> 
>> If no, we should still document the places where it doesn't, like this
>> one.
>
> That's a fair requirement. If anything is optional in a return value, we
> should specify the conditions under which it is there or missing.
> Including, of course, if it's always or never there.

Writing documentation saying an optional member is in fact not optional
feels weird, and saying it's never there feels even weirder :)

>> If yes, how can we fix this particular inaccuracy?
>> 
>> The obvious solution is not to reuse BlockdevCacheOptions.  Create a
>> second type, identical except for its members aren't optional.
>
> I can introduce a BlockdevCacheInfo instead. While I'm not completely
> excited about having two structs for each option dict (one for
> configuring, one for querying), there's precedence for this and it's at
> least a small struct this time.

I'm not excited about the additional types, either.

>> Another idea is to add means to the schema to declare a member "deep
>> optional": not just the member is optional, but if it's present, its
>> members are optional, too.  Begs the question whether its member's
>> member's are optional.  Hmm.
>
> "deep optional" doesn't sound like it makes a lot of sense conceptually,
> even if it might happen to be a hack that gets us the right result in
> this one specific case.
>
>> Yet another idea is to declare nesting configuration options stupid, and
>> just not do it, but it may be too late for that.
>> 
>> Other ideas?
>
> I think the choice is between adding BlockdevCacheInfo and changing
> documentation while reusing BlockdevCacheOptions. Both are fine with me.
> Which one do you prefer?

I'm leaning towards adding BlockdevCacheInfo, because you say there's
precedence, and because I like the schema to be accurate more than I
dislike the additional type.
Eric Blake Sept. 18, 2014, 12:49 p.m. UTC | #5
On 09/18/2014 05:53 AM, Kevin Wolf wrote:
> Am 18.09.2014 um 13:04 hat Markus Armbruster geschrieben:
>> Before this patch, QAPI type BlockdevCacheOptions is used only as a
>> member of BlockdevOptionsBase.
>>
>> BlockdevOptionsBase is a collection configuration settings.
>> Consequently, it's a complex type whose members are optional exactly
>> when the configuration setting is optional.  Makes sense.
>>
>> Complication: a few options are wrapped in another complex type,
>> BlockdevCacheOptions.  It's optional, but that's not sufficient, it's
>> members are all optional, too.
>>

> I think the choice is between adding BlockdevCacheInfo and changing
> documentation while reusing BlockdevCacheOptions. Both are fine with me.
> Which one do you prefer?

Those two options sound the best to me as well; I'm fine with either,
although I have a slight preference for just documenting on
BlockdevCacheOptions that members are optional on input but will all be
present when generated as output.
diff mbox

Patch

diff --git a/block/qapi.c b/block/qapi.c
index 9733ebd..6b43bc3 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -46,6 +46,16 @@  BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs)
     info->encrypted              = bs->encrypted;
     info->encryption_key_missing = bdrv_key_required(bs);
 
+    info->cache = g_new(BlockdevCacheOptions, 1);
+    *info->cache = (BlockdevCacheOptions) {
+        .writeback      = bdrv_enable_write_cache(bs),
+        .has_writeback  = true,
+        .direct         = !!(bs->open_flags & BDRV_O_NOCACHE),
+        .has_direct     = true,
+        .no_flush       = !!(bs->open_flags & BDRV_O_NO_FLUSH),
+        .has_no_flush   = true,
+    };
+
     if (bs->node_name[0]) {
         info->has_node_name = true;
         info->node_name = g_strdup(bs->node_name);
diff --git a/hmp.c b/hmp.c
index 40a90da..c3846b8 100644
--- a/hmp.c
+++ b/hmp.c
@@ -294,6 +294,7 @@  void hmp_info_block(Monitor *mon, const QDict *qdict)
 {
     BlockInfoList *block_list, *info;
     ImageInfo *image_info;
+    BlockDeviceInfo *inserted;
     const char *device = qdict_get_try_str(qdict, "device");
     bool verbose = qdict_get_try_bool(qdict, "verbose", 0);
 
@@ -335,6 +336,13 @@  void hmp_info_block(Monitor *mon, const QDict *qdict)
             continue;
         }
 
+        inserted = info->value->inserted;
+
+        monitor_printf(mon, "    Cache mode:       %s%s%s\n",
+                       inserted->cache->writeback ? "writeback" : "writethrough",
+                       inserted->cache->direct ? ", direct" : "",
+                       inserted->cache->no_flush ? ", ignore flushes" : "");
+
         if (info->value->inserted->has_backing_file) {
             monitor_printf(mon,
                            "    Backing file:     %s "
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 95dcd81..c53b587 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -238,6 +238,8 @@ 
 #
 # @iops_size: #optional an I/O size in bytes (Since 1.7)
 #
+# @cache: the cache mode used for the block device (since: 2.2)
+#
 # Since: 0.14.0
 #
 ##
@@ -252,7 +254,7 @@ 
             '*bps_max': 'int', '*bps_rd_max': 'int',
             '*bps_wr_max': 'int', '*iops_max': 'int',
             '*iops_rd_max': 'int', '*iops_wr_max': 'int',
-            '*iops_size': 'int' } }
+            '*iops_size': 'int', 'cache': 'BlockdevCacheOptions' } }
 
 ##
 # @BlockDeviceIoStatus:
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index a3f2820..fee597e 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -50,6 +50,7 @@  Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DI
 QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
 ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
+    Cache mode:       writeback
     Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
 (qemu) qququiquit
 
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 7e090b9..3774c95 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -6,7 +6,7 @@  Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0
 QMP_VERSION
 {"return": {}}
-{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
@@ -24,7 +24,7 @@  QMP_VERSION
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
 QMP_VERSION
 {"return": {}}
-{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"return": {}}
@@ -44,7 +44,7 @@  Testing:
 QMP_VERSION
 {"return": {}}
 {"return": "OK\r\n"}
-{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"return": {}}
@@ -64,14 +64,14 @@  Testing:
 QMP_VERSION
 {"return": {}}
 {"return": {}}
-{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "RESET"}
-{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unkno!
 wn"}]}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}