All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media
@ 2015-01-27 19:45 Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 01/50] blockdev: Allow creation of BDS trees without BB Max Reitz
                   ` (49 more replies)
  0 siblings, 50 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

** This is a resend due to me messing up John's CC in the first thread.
Sorry for the superfluous mails, but I feel like it's better to bother
you all with the same mails again than to keep bothering innocent
people. **

This series reworks a lot regarding BlockBackend and media. It is
essentially a v3 to the "blockdev: Add blockdev-change-medium with
read-only option" series (which is in fact a part of this series), but
of course does a lot more.

Basically, this series allows empty BlockBackends, that is BBs without a
BDS tree.

Before this series, empty drives are represented by a BlockBackend with
an empty BDS attached to it (a BDS with a NULL driver). However, now we
have BlockBackends, thus an empty drive should be represented by a
BlockBackend without any BDS tree attached to it. This is what this
series does.


I am CC'ing a lot of people (basically everyone who is working on the
block layer) due to the fact that this series touches a lot of places in
the block layer. Please pick out patches that seem to be relevant to
your area of expertise (e.g. there is an FDC tray patch for John; there
are some block job patches for Jeff; etc. pp.). I want to explicitly
encourage you to review only parts of this series! (Of course, reviewing
everything is fine, too :-))

Also, brace for a follow-up regarding bdrv_close_all() (there is a nice
bug in there which I found while working on this series).


This series depends on v3 (or any later version) of my series
'block: Remove "growable", add blk_new_open()'.


- Patches 1 and 2 make it possible to use blockdev-add without creating
  a BlockBackend. This is necessary because the QMP command introduced
  in patch 42 (blockdev-insert-medium) will insert a BDS tree (a medium)
  into a BlockBackend (a drive). Creating a BlockBackend for such a BDS
  tree would both be a hassle and a waste, so this makes it possible to
  omit creating a BB.
  Patches 35 and 36 are kind of a follow-up to these; but patch 35
  depends on patch 34 which is the reason why there is a large gap
  between patch 2 and 35.

- Patch 3 implements a tray status for floppy disk drives. See the
  commit message for more information on what this means.

- Patches 3 to 33 basically all prepare the block layer for having BBs
  without BDS trees. I will only list the most notable ones (patch 3,
  for instance, is not notable).
  They do so by moving some information into the BlockBackend, and
  primarily by intercepting accesses to empty BBs in the BB layer and
  resorting to default actions there.
  Furthermore, hopefully all non-BB calls to bdrv_*() functions are
  guarded by checking whether that BDS actually exists.

- Patch 6 makes blk_is_inserted() return true only if there is a BDS
  tree; furthermore, blk_is_available() is added which additionally
  checks whether the guest device tray is closed.

- Patches 7 and 8 are some kind of follow-up to patch 6; they make
  bdrv_is_inserted() actually useful (unless I'm not mistaken; maybe I
  am and they make bdrv_is_inserted() actually useless).

- Patches 9, 11 and 12 move some (root!) BDS fields into the BB, because
  that is where they belong. This way they survive a medium (BDS tree)
  change.

- Patch 10 is necessary because the structure moved in patch 11
  (BlockAcctStats) contains one field which does belong into the BDS
  (wr_highest_offset). Thus, this field is moved out of that structure
  into the BDS here.

- Patch 13 adds a structure to the BB which can save some options from
  the root BDS so they survive a medium change. In theory, those options
  should probably not survive a medium change (they are not really
  drive- but medium-related), but this is how the 'change' command
  always handled it so this structure (the BlockBackendRootState, BBRS)
  is required for compatibility.
  One of these options is the read-only status, for example.

- Patches 17 to 30 and patches 32 and 33 prepare functions in the block
  layer which directly access a BDS to cope with a non-existing BDS
  tree. Patch 31 is a prerequisite for patch 32.

- Patch 34 "gets down to business": Empty drives no longer have a BDS
  tree.

- Patches 35 and 36 are, as described above, a follow-up to patch 1.

- Patch 37 is the counterpart to patch 31, obviously.

- Patches 38 to 41 implement the basic QMP operations for tray and
  medium operation: blockdev-open-tray, blockdev-close-tray,
  blockdev-remove-medium and blockdev-insert-medium.

- Patches 42 and 43 reimplement 'eject' and 'change' using these new
  medium operations.

- With me now knowing exactly what 'change' does (because I
  reimplemented it), patch 44 became possible.

- Patches 45 to 48 are from v2 of series (slightly modified)
  "blockdev: Add blockdev-change-medium with read-only option"
  One modification are notes in patch 45 that blockdev-change-medium is
  preferred over simply 'change' [Eric] and what atomic operations
  blockdev-change-medium itself performs.

- Patch 50 adds a test for 'change' and all associated QMP commands,
  patch 49 makes small amendments to VM.add_drive() in iotests.py to
  make the new test work.


git-backport-diff output against v2 of
"blockdev: Add blockdev-change-medium with read-only option":

Key:
[----] : patches are identical
[####] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

045/50:[0007] [FC] 'qmp: Introduce blockdev-change-medium'
046/50:[----] [--] 'hmp: Use blockdev-change-medium for change command'
047/50:[0005] [FC] 'blockdev: Add read-only option to blockdev-change-medium'
048/50:[----] [--] 'hmp: Add read-only option to change command'

(rest is "downstream-only")


Max Reitz (50):
  blockdev: Allow creation of BDS trees without BB
  iotests: Only create BB if necessary
  hw/block/fdc: Implement tray status
  hw/usb-storage: Check whether BB is inserted
  block: Fix BB AIOCB AioContext without BDS
  block: Add blk_is_available()
  block: Make bdrv_is_inserted() recursive
  block/quorum: Implement bdrv_is_inserted()
  block: Move guest_block_size into BlockBackend
  block: Remove wr_highest_offset from BlockAcctStats
  block: Move BlockAcctStats into BlockBackend
  block: Move I/O status and error actions into BB
  block: Add BlockBackendRootState
  block: Make some BB functions fall back to BBRS
  block: Fail requests to empty BlockBackend
  block: Prepare remaining BB functions for NULL BDS
  block: Respect empty BB in bdrv_lookup_bs()
  block: Respect empty BB in bdrv_query_info()
  blockdev: Use BlockBackend for blockdev-backup TA
  blockdev: Check blk_is_available() in sn-del-int-sync
  blockdev: Check BB validity in internal snapshot TA
  blockdev: Check BB validity in drive-backup TA
  blockdev: Catch NULL BDS in block_set_io_throttle
  blockdev: Check BB validity in block-stream
  blockdev: Check BB validity in block-commit
  blockdev: Check BB validity in drive-backup
  blockdev: Check BB validity in blockdev-backup
  blockdev: Check BB validity in drive-mirror
  blockdev: Check BB validity in find_block_job()
  blockdev: Check BB validity in change-backing-file
  block: Add blk_insert_bs()
  blockdev: Check BB validity in eject and change
  blockdev: Respect NULL BDS in do_drive_del()
  blockdev: Do not create BDS for empty drive
  blockdev: Pull out blockdev option extraction
  blockdev: Allow more options for BB-less BDS tree
  block: Add blk_remove_bs()
  blockdev: Add blockdev-open-tray
  blockdev: Add blockdev-close-tray
  blockdev: Add blockdev-remove-medium
  blockdev: Add blockdev-insert-medium
  blockdev: Implement eject with basic operations
  blockdev: Implement change with basic operations
  block: Inquire tray state before tray-moved events
  qmp: Introduce blockdev-change-medium
  hmp: Use blockdev-change-medium for change command
  blockdev: Add read-only option to blockdev-change-medium
  hmp: Add read-only option to change command
  iotests: More options for VM.add_drive()
  iotests: Add test for change-related QMP commands

 block.c                        | 161 +-------
 block/accounting.c             |   9 -
 block/backup.c                 |  17 +-
 block/block-backend.c          | 356 ++++++++++++++--
 block/commit.c                 |   3 +-
 block/mirror.c                 |  17 +-
 block/qapi.c                   |  32 +-
 block/quorum.c                 |  16 +
 block/stream.c                 |   3 +-
 blockdev.c                     | 915 +++++++++++++++++++++++++++++------------
 blockjob.c                     |   5 +-
 hmp-commands.hx                |  20 +-
 hmp.c                          |  46 ++-
 hw/block/fdc.c                 |  20 +-
 hw/usb/dev-storage.c           |   2 +-
 include/block/accounting.h     |   3 -
 include/block/block.h          |  14 -
 include/block/block_int.h      |  22 +-
 include/qemu/typedefs.h        |   1 +
 include/sysemu/block-backend.h |  12 +
 include/sysemu/blockdev.h      |   2 -
 qapi-schema.json               |   3 +-
 qapi/block-core.json           | 110 +++++
 qmp-commands.hx                | 204 +++++++++
 qmp.c                          |   9 +-
 tests/fdc-test.c               |   4 +-
 tests/qemu-iotests/067.out     | 104 +----
 tests/qemu-iotests/071         |  50 ++-
 tests/qemu-iotests/071.out     |  16 +-
 tests/qemu-iotests/081         |  14 +-
 tests/qemu-iotests/081.out     |   7 +-
 tests/qemu-iotests/087         |  20 -
 tests/qemu-iotests/087.out     |  22 -
 tests/qemu-iotests/118         | 649 +++++++++++++++++++++++++++++
 tests/qemu-iotests/118.out     |   5 +
 tests/qemu-iotests/group       |   1 +
 tests/qemu-iotests/iotests.py  |   9 +-
 37 files changed, 2198 insertions(+), 705 deletions(-)
 create mode 100755 tests/qemu-iotests/118
 create mode 100644 tests/qemu-iotests/118.out

-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 01/50] blockdev: Allow creation of BDS trees without BB
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 02/50] iotests: Only create BB if necessary Max Reitz
                   ` (48 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

If the "id" field is missing from the options given to blockdev-add,
just omit the BlockBackend and create the BlockDriverState tree alone.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c                 | 38 +++++++++++++++++++++++++-------------
 tests/qemu-iotests/087     | 20 --------------------
 tests/qemu-iotests/087.out | 12 ------------
 3 files changed, 25 insertions(+), 45 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 7573746..81fa7bd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2844,17 +2844,12 @@ out:
 void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 {
     QmpOutputVisitor *ov = qmp_output_visitor_new();
-    BlockBackend *blk;
+    BlockDriverState *bs;
+    BlockBackend *blk = NULL;
     QObject *obj;
     QDict *qdict;
     Error *local_err = NULL;
 
-    /* Require an ID in the top level */
-    if (!options->has_id) {
-        error_setg(errp, "Block device needs an ID");
-        goto fail;
-    }
-
     /* TODO Sort it out in raw-posix and drive_new(): Reject aio=native with
      * cache.direct=false instead of silently switching to aio=threads, except
      * when called from drive_new().
@@ -2882,14 +2877,31 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    blk = blockdev_init(NULL, qdict, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        goto fail;
+    if (options->has_id) {
+        blk = blockdev_init(NULL, qdict, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            goto fail;
+        }
+
+        bs = blk_bs(blk);
+    } else {
+        int ret;
+
+        bs = NULL;
+        ret = bdrv_open(&bs, NULL, NULL, qdict, BDRV_O_RDWR | BDRV_O_CACHE_WB,
+                        NULL, errp);
+        if (ret < 0) {
+            goto fail;
+        }
     }
 
-    if (bdrv_key_required(blk_bs(blk))) {
-        blk_unref(blk);
+    if (bs && bdrv_key_required(bs)) {
+        if (blk) {
+            blk_unref(blk);
+        } else {
+            bdrv_unref(bs);
+        }
         error_setg(errp, "blockdev-add doesn't support encrypted devices");
         goto fail;
     }
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
index 8694749..4b2eddc 100755
--- a/tests/qemu-iotests/087
+++ b/tests/qemu-iotests/087
@@ -54,26 +54,6 @@ size=128M
 _make_test_img $size
 
 echo
-echo === Missing ID ===
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "blockdev-add",
-  "arguments": {
-      "options": {
-        "driver": "$IMGFMT",
-        "file": {
-            "driver": "file",
-            "filename": "$TEST_IMG"
-        }
-      }
-    }
-  }
-{ "execute": "quit" }
-EOF
-
-echo
 echo === Duplicate ID ===
 echo
 
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index 0ba2e43..681ef93 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -1,18 +1,6 @@
 QA output created by 087
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
 
-=== Missing ID ===
-
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Block device needs an ID"}}
-{"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
-
-
 === Duplicate ID ===
 
 Testing:
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 02/50] iotests: Only create BB if necessary
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 01/50] blockdev: Allow creation of BDS trees without BB Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 03/50] hw/block/fdc: Implement tray status Max Reitz
                   ` (47 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Tests 071 and 081 test giving references in blockdev-add. It is not
necessary to create a BlockBackend here, so omit it.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 tests/qemu-iotests/071     | 50 ++++++++++++++++++++++++++++++++++++++++++----
 tests/qemu-iotests/071.out | 12 +++++++----
 tests/qemu-iotests/081     | 14 ++++++++++++-
 tests/qemu-iotests/081.out |  5 +++--
 4 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
index 9eaa49b..68bedd4 100755
--- a/tests/qemu-iotests/071
+++ b/tests/qemu-iotests/071
@@ -104,11 +104,20 @@ echo
 echo "=== Testing blkdebug on existing block device ==="
 echo
 
-run_qemu -drive "file=$TEST_IMG,format=raw,if=none,id=drive0" <<EOF
+run_qemu <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
     "arguments": {
         "options": {
+            "node-name": "drive0",
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+    }
+}
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
             "driver": "$IMGFMT",
             "id": "drive0-debug",
             "file": {
@@ -133,11 +142,23 @@ echo
 echo "=== Testing blkverify on existing block device ==="
 echo
 
-run_qemu -drive "file=$TEST_IMG,format=$IMGFMT,if=none,id=drive0" <<EOF
+run_qemu <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
     "arguments": {
         "options": {
+            "node-name": "drive0",
+            "driver": "$IMGFMT",
+            "file": {
+                "driver": "file",
+                "filename": "$TEST_IMG"
+            }
+        }
+    }
+}
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
             "driver": "blkverify",
             "id": "drive0-verify",
             "test": "drive0",
@@ -163,11 +184,23 @@ echo
 echo "=== Testing blkverify on existing raw block device ==="
 echo
 
-run_qemu -drive "file=$TEST_IMG.base,format=raw,if=none,id=drive0" <<EOF
+run_qemu <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
     "arguments": {
         "options": {
+            "node-name": "drive0",
+            "driver": "raw",
+            "file": {
+                "driver": "file",
+                "filename": "$TEST_IMG.base"
+            }
+        }
+    }
+}
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
             "driver": "blkverify",
             "id": "drive0-verify",
             "test": {
@@ -193,11 +226,20 @@ echo
 echo "=== Testing blkdebug's set-state through QMP ==="
 echo
 
-run_qemu -drive "file=$TEST_IMG,format=raw,if=none,id=drive0" <<EOF
+run_qemu <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
     "arguments": {
         "options": {
+            "node-name": "drive0",
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+    }
+}
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
             "driver": "$IMGFMT",
             "id": "drive0-debug",
             "file": {
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index 9205ce2..c8ecfaf 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -42,10 +42,11 @@ read failed: Input/output error
 
 === Testing blkdebug on existing block device ===
 
-Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0
+Testing:
 QMP_VERSION
 {"return": {}}
 {"return": {}}
+{"return": {}}
 read failed: Input/output error
 {"return": ""}
 {"return": {}}
@@ -58,28 +59,31 @@ QEMU_PROG: Failed to flush the refcount block cache: Input/output error
 
 === Testing blkverify on existing block device ===
 
-Testing: -drive file=TEST_DIR/t.IMGFMT,format=IMGFMT,if=none,id=drive0
+Testing:
 QMP_VERSION
 {"return": {}}
 {"return": {}}
+{"return": {}}
 blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
 
 
 === Testing blkverify on existing raw block device ===
 
-Testing: -drive file=TEST_DIR/t.IMGFMT.base,format=raw,if=none,id=drive0
+Testing:
 QMP_VERSION
 {"return": {}}
 {"return": {}}
+{"return": {}}
 blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
 
 
 === Testing blkdebug's set-state through QMP ===
 
-Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0
+Testing:
 QMP_VERSION
 {"return": {}}
 {"return": {}}
+{"return": {}}
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": ""}
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
index d9b042c..5c8a8fa 100755
--- a/tests/qemu-iotests/081
+++ b/tests/qemu-iotests/081
@@ -101,11 +101,23 @@ $QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
 echo
 echo "== checking mixed reference/option specification =="
 
-run_qemu -drive "file=$TEST_DIR/2.raw,format=$IMGFMT,if=none,id=drive2" <<EOF
+run_qemu <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
     "arguments": {
         "options": {
+            "node-name": "drive2",
+            "driver": "raw",
+            "file": {
+                "driver": "file",
+                "filename": "$TEST_DIR/2.raw"
+            }
+        }
+    }
+}
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
             "driver": "quorum",
             "id": "drive0-quorum",
             "vote-threshold": 2,
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index 9f57d9d..2375916 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -26,11 +26,12 @@ read 10485760/10485760 bytes at offset 0
 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
 == checking mixed reference/option specification ==
-Testing: -drive file=TEST_DIR/2.IMGFMT,format=IMGFMT,if=none,id=drive2
+Testing:
 QMP_VERSION
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "", "sectors-count": 20480, "sector-num": 0}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "drive2", "sectors-count": 20480, "sector-num": 0}}
 read 10485760/10485760 bytes at offset 0
 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": ""}
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 03/50] hw/block/fdc: Implement tray status
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 01/50] blockdev: Allow creation of BDS trees without BB Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 02/50] iotests: Only create BB if necessary Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-30 21:04   ` John Snow
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 04/50] hw/usb-storage: Check whether BB is inserted Max Reitz
                   ` (46 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

The tray of an FDD is open iff there is no medium inserted (there are
only two states for an FDD: "medium inserted" or "no medium inserted").

This results in the tray being reported as open if qemu has been started
with the default floppy drive, which breaks some tests. Fix them.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 hw/block/fdc.c             | 20 +++++++++++++---
 tests/fdc-test.c           |  4 +---
 tests/qemu-iotests/067.out | 60 +++++++---------------------------------------
 tests/qemu-iotests/071.out |  2 --
 tests/qemu-iotests/081.out |  1 -
 tests/qemu-iotests/087.out |  5 ----
 6 files changed, 26 insertions(+), 66 deletions(-)

diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 2bf87c9..0c5a6b4 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -192,6 +192,8 @@ typedef struct FDrive {
     uint8_t ro;               /* Is read-only           */
     uint8_t media_changed;    /* Is media changed       */
     uint8_t media_rate;       /* Data rate of medium    */
+
+    bool media_inserted;      /* Is there a medium in the tray */
 } FDrive;
 
 static void fd_init(FDrive *drv)
@@ -261,7 +263,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
 #endif
         drv->head = head;
         if (drv->track != track) {
-            if (drv->blk != NULL && blk_is_inserted(drv->blk)) {
+            if (drv->media_inserted) {
                 drv->media_changed = 0;
             }
             ret = 1;
@@ -270,7 +272,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
         drv->sect = sect;
     }
 
-    if (drv->blk == NULL || !blk_is_inserted(drv->blk)) {
+    if (!drv->media_inserted) {
         ret = 2;
     }
 
@@ -296,7 +298,7 @@ static void fd_revalidate(FDrive *drv)
         ro = blk_is_read_only(drv->blk);
         pick_geometry(drv->blk, &nb_heads, &max_track,
                       &last_sect, drv->drive, &drive, &rate);
-        if (!blk_is_inserted(drv->blk)) {
+        if (!drv->media_inserted) {
             FLOPPY_DPRINTF("No disk in drive\n");
         } else {
             FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
@@ -2062,12 +2064,21 @@ static void fdctrl_change_cb(void *opaque, bool load)
 {
     FDrive *drive = opaque;
 
+    drive->media_inserted = load && drive->blk && blk_is_inserted(drive->blk);
+
     drive->media_changed = 1;
     fd_revalidate(drive);
 }
 
+static bool fdctrl_is_tray_open(void *opaque)
+{
+    FDrive *drive = opaque;
+    return !drive->media_inserted;
+}
+
 static const BlockDevOps fdctrl_block_ops = {
     .change_media_cb = fdctrl_change_cb,
+    .is_tray_open = fdctrl_is_tray_open,
 };
 
 /* Init functions */
@@ -2095,6 +2106,9 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
         fdctrl_change_cb(drive, 0);
         if (drive->blk) {
             blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive);
+            if (blk_is_inserted(drive->blk)) {
+                drive->media_inserted = true;
+            }
         }
     }
 }
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 3c6c83c..f287c10 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -293,9 +293,7 @@ static void test_media_insert(void)
     qmp_discard_response("{'execute':'change', 'arguments':{"
                          " 'device':'floppy0', 'target': %s, 'arg': 'raw' }}",
                          test_image);
-    qmp_discard_response(""); /* ignore event
-                                 (FIXME open -> open transition?!) */
-    qmp_discard_response(""); /* ignore event */
+    qmp_discard_response(""); /* ignore event (open -> close) */
 
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 00b3eae..42bae32 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -69,7 +69,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -131,7 +131,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -165,17 +165,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
         "tray-open": true
     }
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "floppy0",
-        "tray-open": true
-    }
-}
 
 
 === -drive/device_add and device_del ===
@@ -246,7 +235,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -312,7 +301,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -346,17 +335,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
         "tray-open": true
     }
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "floppy0",
-        "tray-open": true
-    }
-}
 
 
 === drive_add/device_add and device_del ===
@@ -386,7 +364,7 @@ Testing:
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -496,7 +474,7 @@ Testing:
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -530,17 +508,6 @@ Testing:
         "tray-open": true
     }
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "floppy0",
-        "tray-open": true
-    }
-}
 
 
 === blockdev_add/device_add and device_del ===
@@ -571,7 +538,7 @@ Testing:
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -681,7 +648,7 @@ Testing:
             "device": "floppy0",
             "locked": false,
             "removable": true,
-            "tray_open": false,
+            "tray_open": true,
             "type": "unknown"
         },
         {
@@ -760,16 +727,5 @@ Testing:
         "tray-open": true
     }
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "floppy0",
-        "tray-open": true
-    }
-}
 
 *** done
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index c8ecfaf..904ce15 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -52,7 +52,6 @@ read failed: Input/output error
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 QEMU_PROG: Failed to flush the L2 table cache: Input/output error
 QEMU_PROG: Failed to flush the refcount block cache: Input/output error
 
@@ -95,7 +94,6 @@ read failed: Input/output error
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 QEMU_PROG: Failed to flush the L2 table cache: Input/output error
 QEMU_PROG: Failed to flush the refcount block cache: Input/output error
 
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index 2375916..b1e4909 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -38,7 +38,6 @@ read 10485760/10485760 bytes at offset 0
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 
 == using quorum rewrite corrupted mode ==
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index 681ef93..033cc3b 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -15,7 +15,6 @@ QMP_VERSION
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 
 === aio=native without O_DIRECT ===
@@ -27,7 +26,6 @@ QMP_VERSION
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 
 === Encrypted image ===
@@ -40,7 +38,6 @@ QMP_VERSION
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 Testing:
 QMP_VERSION
@@ -49,7 +46,6 @@ QMP_VERSION
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 
 === Missing driver ===
@@ -62,6 +58,5 @@ QMP_VERSION
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 *** done
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 04/50] hw/usb-storage: Check whether BB is inserted
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (2 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 03/50] hw/block/fdc: Implement tray status Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 05/50] block: Fix BB AIOCB AioContext without BDS Max Reitz
                   ` (45 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Only call bdrv_key_required() on the BlockDriverState if the
BlockBackend has an inserted medium.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 hw/usb/dev-storage.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 4539733..3123baf 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -638,7 +638,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
     usb_msd_handle_reset(dev);
     s->scsi_dev = scsi_dev;
 
-    if (bdrv_key_required(blk_bs(blk))) {
+    if (blk_is_inserted(blk) && bdrv_key_required(blk_bs(blk))) {
         if (cur_mon) {
             monitor_read_bdrv_key_start(cur_mon, blk_bs(blk),
                                         usb_msd_password_cb, s);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 05/50] block: Fix BB AIOCB AioContext without BDS
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (3 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 04/50] hw/usb-storage: Check whether BB is inserted Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 06/50] block: Add blk_is_available() Max Reitz
                   ` (44 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Fix the BlockBackend's AIOCB AioContext for aborting AIO in case there
is no BDS. If there is no implementation of AIOCBInfo::get_aio_context()
the AioContext is derived from the BDS the AIOCB belongs to. If that BDS
is NULL (because it has been removed from the BB) this will not work.

This patch makes blk_get_aio_context() fall back to the main loop
context if the BDS pointer is NULL and implements
AIOCBInfo::get_aio_context() (blk_aiocb_get_aio_context()) which invokes
blk_get_aio_context().

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 96a5bc6..4c40747 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -18,6 +18,8 @@
 /* Number of coroutines to reserve per attached device model */
 #define COROUTINE_POOL_RESERVATION 64
 
+static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
+
 struct BlockBackend {
     char *name;
     int refcnt;
@@ -34,10 +36,12 @@ struct BlockBackend {
 typedef struct BlockBackendAIOCB {
     BlockAIOCB common;
     QEMUBH *bh;
+    BlockBackend *blk;
     int ret;
 } BlockBackendAIOCB;
 
 static const AIOCBInfo block_backend_aiocb_info = {
+    .get_aio_context = blk_aiocb_get_aio_context,
     .aiocb_size = sizeof(BlockBackendAIOCB),
 };
 
@@ -530,6 +534,7 @@ static BlockAIOCB *abort_aio_request(BlockBackend *blk, BlockCompletionFunc *cb,
     QEMUBH *bh;
 
     acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
+    acb->blk = blk;
     acb->ret = ret;
 
     bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb);
@@ -783,7 +788,17 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)
 
 AioContext *blk_get_aio_context(BlockBackend *blk)
 {
-    return bdrv_get_aio_context(blk->bs);
+    if (blk->bs) {
+        return bdrv_get_aio_context(blk->bs);
+    } else {
+        return qemu_get_aio_context();
+    }
+}
+
+static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
+{
+    BlockBackendAIOCB *blk_acb = DO_UPCAST(BlockBackendAIOCB, common, acb);
+    return blk_get_aio_context(blk_acb->blk);
 }
 
 void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 06/50] block: Add blk_is_available()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (4 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 05/50] block: Fix BB AIOCB AioContext without BDS Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 07/50] block: Make bdrv_is_inserted() recursive Max Reitz
                   ` (43 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

blk_is_available() returns true iff the BDS is inserted (which means
blk_bs() is not NULL and bdrv_is_inserted() returns true) and if the
tray of the guest device is closed.

blk_is_inserted() is changed to return true only if blk_bs() is not
NULL.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c          | 7 ++++++-
 include/sysemu/block-backend.h | 1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 4c40747..4a2428e 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -738,7 +738,12 @@ void blk_invalidate_cache(BlockBackend *blk, Error **errp)
 
 int blk_is_inserted(BlockBackend *blk)
 {
-    return bdrv_is_inserted(blk->bs);
+    return blk->bs && bdrv_is_inserted(blk->bs);
+}
+
+bool blk_is_available(BlockBackend *blk)
+{
+    return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
 }
 
 void blk_lock_medium(BlockBackend *blk, bool locked)
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index f39bb5c..f91f3c7 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -127,6 +127,7 @@ int blk_enable_write_cache(BlockBackend *blk);
 void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
 void blk_invalidate_cache(BlockBackend *blk, Error **errp);
 int blk_is_inserted(BlockBackend *blk);
+bool blk_is_available(BlockBackend *blk);
 void blk_lock_medium(BlockBackend *blk, bool locked);
 void blk_eject(BlockBackend *blk, bool eject_flag);
 int blk_get_flags(BlockBackend *blk);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 07/50] block: Make bdrv_is_inserted() recursive
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (5 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 06/50] block: Add blk_is_available() Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 08/50] block/quorum: Implement bdrv_is_inserted() Max Reitz
                   ` (42 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

If bdrv_is_inserted() is called on the top level BDS, it should make
sure all nodes in the BDS tree are actually inserted.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/block.c b/block.c
index 4a5f8fc..aff7682 100644
--- a/block.c
+++ b/block.c
@@ -5208,11 +5208,12 @@ int bdrv_is_inserted(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
 
-    if (!drv)
+    if (!drv) {
         return 0;
-    if (!drv->bdrv_is_inserted)
-        return 1;
-    return drv->bdrv_is_inserted(bs);
+    }
+    return (!drv->bdrv_is_inserted || drv->bdrv_is_inserted(bs)) &&
+           (!bs->file              || bdrv_is_inserted(bs->file)) &&
+           (!bs->backing_hd        || bdrv_is_inserted(bs->backing_hd));
 }
 
 /**
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 08/50] block/quorum: Implement bdrv_is_inserted()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (6 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 07/50] block: Make bdrv_is_inserted() recursive Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 09/50] block: Move guest_block_size into BlockBackend Max Reitz
                   ` (41 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

bdrv_is_inserted() should be invoked recursively on the children of
quorum.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/quorum.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/block/quorum.c b/block/quorum.c
index 437b122..7811c4a 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -1064,6 +1064,20 @@ static void quorum_refresh_filename(BlockDriverState *bs)
     bs->full_open_options = opts;
 }
 
+static int quorum_is_inserted(BlockDriverState *bs)
+{
+    BDRVQuorumState *s = bs->opaque;
+    int i;
+
+    for (i = 0; i < s->num_children; i++) {
+        if (!bdrv_is_inserted(s->bs[i])) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
 static BlockDriver bdrv_quorum = {
     .format_name                        = "quorum",
     .protocol_name                      = "quorum",
@@ -1087,6 +1101,8 @@ static BlockDriver bdrv_quorum = {
 
     .is_filter                          = true,
     .bdrv_recurse_is_first_non_filter   = quorum_recurse_is_first_non_filter,
+
+    .bdrv_is_inserted                   = quorum_is_inserted,
 };
 
 static void bdrv_quorum_init(void)
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 09/50] block: Move guest_block_size into BlockBackend
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (7 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 08/50] block/quorum: Implement bdrv_is_inserted() Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 10/50] block: Remove wr_highest_offset from BlockAcctStats Max Reitz
                   ` (40 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

guest_block_size is a guest device property so it should be moved into
the interface between block layer and guest devices, which is the
BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                   | 7 -------
 block/block-backend.c     | 7 +++++--
 include/block/block.h     | 1 -
 include/block/block_int.h | 3 ---
 4 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/block.c b/block.c
index aff7682..eff92ca 100644
--- a/block.c
+++ b/block.c
@@ -965,7 +965,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     }
 
     bs->open_flags = flags;
-    bs->guest_block_size = 512;
     bs->request_alignment = 512;
     bs->zero_beyond_eof = true;
     open_flags = bdrv_open_flags(bs, flags);
@@ -2039,7 +2038,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     /* move some fields that need to stay attached to the device */
 
     /* dev info */
-    bs_dest->guest_block_size   = bs_src->guest_block_size;
     bs_dest->copy_on_read       = bs_src->copy_on_read;
 
     bs_dest->enable_write_cache = bs_src->enable_write_cache;
@@ -5286,11 +5284,6 @@ BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
     return NULL;
 }
 
-void bdrv_set_guest_block_size(BlockDriverState *bs, int align)
-{
-    bs->guest_block_size = align;
-}
-
 void *qemu_blockalign(BlockDriverState *bs, size_t size)
 {
     return qemu_memalign(bdrv_opt_mem_align(bs), size);
diff --git a/block/block-backend.c b/block/block-backend.c
index 4a2428e..bf0fcc9 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -31,6 +31,9 @@ struct BlockBackend {
     /* TODO change to DeviceState when all users are qdevified */
     const BlockDevOps *dev_ops;
     void *dev_opaque;
+
+    /* the block size for which the guest device expects atomicity */
+    int guest_block_size;
 };
 
 typedef struct BlockBackendAIOCB {
@@ -334,7 +337,7 @@ void blk_detach_dev(BlockBackend *blk, void *dev)
     blk->dev = NULL;
     blk->dev_ops = NULL;
     blk->dev_opaque = NULL;
-    bdrv_set_guest_block_size(blk->bs, 512);
+    blk->guest_block_size = 512;
     blk_unref(blk);
 }
 
@@ -763,7 +766,7 @@ int blk_get_flags(BlockBackend *blk)
 
 void blk_set_guest_block_size(BlockBackend *blk, int align)
 {
-    bdrv_set_guest_block_size(blk->bs, align);
+    blk->guest_block_size = align;
 }
 
 void *blk_blockalign(BlockBackend *blk, size_t size)
diff --git a/include/block/block.h b/include/block/block.h
index 3082d2b..df656db 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -425,7 +425,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
 /* Returns the alignment in bytes that is required so that no bounce buffer
  * is required throughout the stack */
 size_t bdrv_opt_mem_align(BlockDriverState *bs);
-void bdrv_set_guest_block_size(BlockDriverState *bs, int align);
 void *qemu_blockalign(BlockDriverState *bs, size_t size);
 void *qemu_blockalign0(BlockDriverState *bs, size_t size);
 void *qemu_try_blockalign(BlockDriverState *bs, size_t size);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index b340e7e..c6ab73a 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -375,9 +375,6 @@ struct BlockDriverState {
     /* Alignment requirement for offset/length of I/O requests */
     unsigned int request_alignment;
 
-    /* the block size for which the guest device expects atomicity */
-    int guest_block_size;
-
     /* do we need to tell the quest if we have a volatile write cache? */
     int enable_write_cache;
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 10/50] block: Remove wr_highest_offset from BlockAcctStats
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (8 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 09/50] block: Move guest_block_size into BlockBackend Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 11/50] block: Move BlockAcctStats into BlockBackend Max Reitz
                   ` (39 subsequent siblings)
  49 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

BlockAcctStats contains statistics about the data transferred from and
to the device; wr_highest_offset does not fit in with the rest.

Furthermore, those statistics are supposed to be specific for a certain
device and not necessarily for a BDS (see the comment above
bdrv_get_stats()); on the other hand, wr_highest_offset may be a rather
important information to know for each BDS. When BlockAcctStats is
finally removed from the BDS, we will want to keep wr_highest_offset in
the BDS.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                    | 4 +++-
 block/accounting.c         | 9 ---------
 block/qapi.c               | 4 ++--
 include/block/accounting.h | 3 ---
 include/block/block_int.h  | 3 +++
 5 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/block.c b/block.c
index eff92ca..5db71c6 100644
--- a/block.c
+++ b/block.c
@@ -3312,7 +3312,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
 
     bdrv_set_dirty(bs, sector_num, nb_sectors);
 
-    block_acct_highest_sector(&bs->stats, sector_num, nb_sectors);
+    if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+        bs->wr_highest_sector = sector_num + nb_sectors - 1;
+    }
 
     if (ret >= 0) {
         bs->total_sectors = MAX(bs->total_sectors, sector_num + nb_sectors);
diff --git a/block/accounting.c b/block/accounting.c
index 18102f0..c77b6c2 100644
--- a/block/accounting.c
+++ b/block/accounting.c
@@ -45,12 +45,3 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie)
     stats->total_time_ns[cookie->type] +=
         qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - cookie->start_time_ns;
 }
-
-
-void block_acct_highest_sector(BlockAcctStats *stats, int64_t sector_num,
-                               unsigned int nb_sectors)
-{
-    if (stats->wr_highest_sector < sector_num + nb_sectors - 1) {
-        stats->wr_highest_sector = sector_num + nb_sectors - 1;
-    }
-}
diff --git a/block/qapi.c b/block/qapi.c
index 8c3b9d9..4e97574 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -338,13 +338,13 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs,
     s->stats->wr_bytes = bs->stats.nr_bytes[BLOCK_ACCT_WRITE];
     s->stats->rd_operations = bs->stats.nr_ops[BLOCK_ACCT_READ];
     s->stats->wr_operations = bs->stats.nr_ops[BLOCK_ACCT_WRITE];
-    s->stats->wr_highest_offset =
-        bs->stats.wr_highest_sector * BDRV_SECTOR_SIZE;
     s->stats->flush_operations = bs->stats.nr_ops[BLOCK_ACCT_FLUSH];
     s->stats->wr_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_WRITE];
     s->stats->rd_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_READ];
     s->stats->flush_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_FLUSH];
 
+    s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
+
     if (bs->file) {
         s->has_parent = true;
         s->parent = bdrv_query_stats(bs->file, query_backing);
diff --git a/include/block/accounting.h b/include/block/accounting.h
index 50b42b3..9089b67 100644
--- a/include/block/accounting.h
+++ b/include/block/accounting.h
@@ -39,7 +39,6 @@ typedef struct BlockAcctStats {
     uint64_t nr_bytes[BLOCK_MAX_IOTYPE];
     uint64_t nr_ops[BLOCK_MAX_IOTYPE];
     uint64_t total_time_ns[BLOCK_MAX_IOTYPE];
-    uint64_t wr_highest_sector;
 } BlockAcctStats;
 
 typedef struct BlockAcctCookie {
@@ -51,7 +50,5 @@ typedef struct BlockAcctCookie {
 void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
                       int64_t bytes, enum BlockAcctType type);
 void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie);
-void block_acct_highest_sector(BlockAcctStats *stats, int64_t sector_num,
-                               unsigned int nb_sectors);
 
 #endif
diff --git a/include/block/block_int.h b/include/block/block_int.h
index c6ab73a..e309d8a 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -366,6 +366,9 @@ struct BlockDriverState {
     /* I/O stats (display with "info blockstats"). */
     BlockAcctStats stats;
 
+    /* Highest sector index written to */
+    uint64_t wr_highest_sector;
+
     /* I/O Limits */
     BlockLimits bl;
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 11/50] block: Move BlockAcctStats into BlockBackend
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (9 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 10/50] block: Remove wr_highest_offset from BlockAcctStats Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 20:31   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 12/50] block: Move I/O status and error actions into BB Max Reitz
                   ` (38 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

As the comment above bdrv_get_stats() says, BlockAcctStats is something
which belongs to the device instead of each BlockDriverState. This patch
therefore moves it into the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                   | 11 -----------
 block/block-backend.c     |  5 ++++-
 block/qapi.c              | 20 ++++++++++++--------
 include/block/block.h     |  2 --
 include/block/block_int.h |  3 ---
 5 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/block.c b/block.c
index 5db71c6..17e4ee3 100644
--- a/block.c
+++ b/block.c
@@ -6119,14 +6119,3 @@ void bdrv_refresh_filename(BlockDriverState *bs)
         QDECREF(json);
     }
 }
-
-/* This accessor function purpose is to allow the device models to access the
- * BlockAcctStats structure embedded inside a BlockDriverState without being
- * aware of the BlockDriverState structure layout.
- * It will go away when the BlockAcctStats structure will be moved inside
- * the device models.
- */
-BlockAcctStats *bdrv_get_stats(BlockDriverState *bs)
-{
-    return &bs->stats;
-}
diff --git a/block/block-backend.c b/block/block-backend.c
index bf0fcc9..3d565d8 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -34,6 +34,9 @@ struct BlockBackend {
 
     /* the block size for which the guest device expects atomicity */
     int guest_block_size;
+
+    /* I/O stats (display with "info blockstats"). */
+    BlockAcctStats stats;
 };
 
 typedef struct BlockBackendAIOCB {
@@ -849,7 +852,7 @@ void blk_io_unplug(BlockBackend *blk)
 
 BlockAcctStats *blk_get_stats(BlockBackend *blk)
 {
-    return bdrv_get_stats(blk->bs);
+    return &blk->stats;
 }
 
 void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
diff --git a/block/qapi.c b/block/qapi.c
index 4e97574..7840c81 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -334,14 +334,18 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs,
     }
 
     s->stats = g_malloc0(sizeof(*s->stats));
-    s->stats->rd_bytes = bs->stats.nr_bytes[BLOCK_ACCT_READ];
-    s->stats->wr_bytes = bs->stats.nr_bytes[BLOCK_ACCT_WRITE];
-    s->stats->rd_operations = bs->stats.nr_ops[BLOCK_ACCT_READ];
-    s->stats->wr_operations = bs->stats.nr_ops[BLOCK_ACCT_WRITE];
-    s->stats->flush_operations = bs->stats.nr_ops[BLOCK_ACCT_FLUSH];
-    s->stats->wr_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_WRITE];
-    s->stats->rd_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_READ];
-    s->stats->flush_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_FLUSH];
+    if (bs->blk) {
+        BlockAcctStats *stats = blk_get_stats(bs->blk);
+
+        s->stats->rd_bytes = stats->nr_bytes[BLOCK_ACCT_READ];
+        s->stats->wr_bytes = stats->nr_bytes[BLOCK_ACCT_WRITE];
+        s->stats->rd_operations = stats->nr_ops[BLOCK_ACCT_READ];
+        s->stats->wr_operations = stats->nr_ops[BLOCK_ACCT_WRITE];
+        s->stats->flush_operations = stats->nr_ops[BLOCK_ACCT_FLUSH];
+        s->stats->wr_total_time_ns = stats->total_time_ns[BLOCK_ACCT_WRITE];
+        s->stats->rd_total_time_ns = stats->total_time_ns[BLOCK_ACCT_READ];
+        s->stats->flush_total_time_ns = stats->total_time_ns[BLOCK_ACCT_FLUSH];
+    }
 
     s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
 
diff --git a/include/block/block.h b/include/block/block.h
index df656db..8cd6b31 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -550,6 +550,4 @@ void bdrv_io_plug(BlockDriverState *bs);
 void bdrv_io_unplug(BlockDriverState *bs);
 void bdrv_flush_io_queue(BlockDriverState *bs);
 
-BlockAcctStats *bdrv_get_stats(BlockDriverState *bs);
-
 #endif
diff --git a/include/block/block_int.h b/include/block/block_int.h
index e309d8a..d023913 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -363,9 +363,6 @@ struct BlockDriverState {
     CoQueue      throttled_reqs[2];
     bool         io_limits_enabled;
 
-    /* I/O stats (display with "info blockstats"). */
-    BlockAcctStats stats;
-
     /* Highest sector index written to */
     uint64_t wr_highest_sector;
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 12/50] block: Move I/O status and error actions into BB
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (10 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 11/50] block: Move BlockAcctStats into BlockBackend Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 20:51   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 13/50] block: Add BlockBackendRootState Max Reitz
                   ` (37 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

These options are only relevant for the user of a whole BDS tree (like a
guest device or a block job) and should thus be moved into the
BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                        | 125 -----------------------------------------
 block/backup.c                 |  17 ++++--
 block/block-backend.c          | 116 ++++++++++++++++++++++++++++++++++++--
 block/commit.c                 |   3 +-
 block/mirror.c                 |  17 ++++--
 block/qapi.c                   |   4 +-
 block/stream.c                 |   3 +-
 blockdev.c                     |   6 +-
 blockjob.c                     |   5 +-
 include/block/block.h          |  11 ----
 include/block/block_int.h      |   6 --
 include/sysemu/block-backend.h |   7 +++
 qmp.c                          |   6 +-
 13 files changed, 158 insertions(+), 168 deletions(-)

diff --git a/block.c b/block.c
index 17e4ee3..9a0a510 100644
--- a/block.c
+++ b/block.c
@@ -371,7 +371,6 @@ BlockDriverState *bdrv_new(void)
     for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
         QLIST_INIT(&bs->op_blockers[i]);
     }
-    bdrv_iostatus_disable(bs);
     notifier_list_init(&bs->close_notifiers);
     notifier_with_return_list_init(&bs->before_write_notifiers);
     qemu_co_queue_init(&bs->throttled_reqs[0]);
@@ -2050,14 +2049,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     bs_dest->throttled_reqs[1]  = bs_src->throttled_reqs[1];
     bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;
 
-    /* r/w error */
-    bs_dest->on_read_error      = bs_src->on_read_error;
-    bs_dest->on_write_error     = bs_src->on_write_error;
-
-    /* i/o status */
-    bs_dest->iostatus_enabled   = bs_src->iostatus_enabled;
-    bs_dest->iostatus           = bs_src->iostatus;
-
     /* dirty bitmap */
     bs_dest->dirty_bitmaps      = bs_src->dirty_bitmaps;
 
@@ -3562,82 +3553,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
     *nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
 }
 
-void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
-                       BlockdevOnError on_write_error)
-{
-    bs->on_read_error = on_read_error;
-    bs->on_write_error = on_write_error;
-}
-
-BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read)
-{
-    return is_read ? bs->on_read_error : bs->on_write_error;
-}
-
-BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error)
-{
-    BlockdevOnError on_err = is_read ? bs->on_read_error : bs->on_write_error;
-
-    switch (on_err) {
-    case BLOCKDEV_ON_ERROR_ENOSPC:
-        return (error == ENOSPC) ?
-               BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
-    case BLOCKDEV_ON_ERROR_STOP:
-        return BLOCK_ERROR_ACTION_STOP;
-    case BLOCKDEV_ON_ERROR_REPORT:
-        return BLOCK_ERROR_ACTION_REPORT;
-    case BLOCKDEV_ON_ERROR_IGNORE:
-        return BLOCK_ERROR_ACTION_IGNORE;
-    default:
-        abort();
-    }
-}
-
-static void send_qmp_error_event(BlockDriverState *bs,
-                                 BlockErrorAction action,
-                                 bool is_read, int error)
-{
-    IoOperationType optype;
-
-    optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
-    qapi_event_send_block_io_error(bdrv_get_device_name(bs), optype, action,
-                                   bdrv_iostatus_is_enabled(bs),
-                                   error == ENOSPC, strerror(error),
-                                   &error_abort);
-}
-
-/* This is done by device models because, while the block layer knows
- * about the error, it does not know whether an operation comes from
- * the device or the block layer (from a job, for example).
- */
-void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
-                       bool is_read, int error)
-{
-    assert(error >= 0);
-
-    if (action == BLOCK_ERROR_ACTION_STOP) {
-        /* First set the iostatus, so that "info block" returns an iostatus
-         * that matches the events raised so far (an additional error iostatus
-         * is fine, but not a lost one).
-         */
-        bdrv_iostatus_set_err(bs, error);
-
-        /* Then raise the request to stop the VM and the event.
-         * qemu_system_vmstop_request_prepare has two effects.  First,
-         * it ensures that the STOP event always comes after the
-         * BLOCK_IO_ERROR event.  Second, it ensures that even if management
-         * can observe the STOP event and do a "cont" before the STOP
-         * event is issued, the VM will not stop.  In this case, vm_start()
-         * also ensures that the STOP/RESUME pair of events is emitted.
-         */
-        qemu_system_vmstop_request_prepare();
-        send_qmp_error_event(bs, action, is_read, error);
-        qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
-    } else {
-        send_qmp_error_event(bs, action, is_read, error);
-    }
-}
-
 int bdrv_is_read_only(BlockDriverState *bs)
 {
     return bs->read_only;
@@ -5536,46 +5451,6 @@ bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
     return true;
 }
 
-void bdrv_iostatus_enable(BlockDriverState *bs)
-{
-    bs->iostatus_enabled = true;
-    bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
-}
-
-/* The I/O status is only enabled if the drive explicitly
- * enables it _and_ the VM is configured to stop on errors */
-bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
-{
-    return (bs->iostatus_enabled &&
-           (bs->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
-            bs->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
-            bs->on_read_error == BLOCKDEV_ON_ERROR_STOP));
-}
-
-void bdrv_iostatus_disable(BlockDriverState *bs)
-{
-    bs->iostatus_enabled = false;
-}
-
-void bdrv_iostatus_reset(BlockDriverState *bs)
-{
-    if (bdrv_iostatus_is_enabled(bs)) {
-        bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
-        if (bs->job) {
-            block_job_iostatus_reset(bs->job);
-        }
-    }
-}
-
-void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
-{
-    assert(bdrv_iostatus_is_enabled(bs));
-    if (bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
-        bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
-                                         BLOCK_DEVICE_IO_STATUS_FAILED;
-    }
-}
-
 void bdrv_img_create(const char *filename, const char *fmt,
                      const char *base_filename, const char *base_fmt,
                      char *options, uint64_t img_size, int flags,
diff --git a/block/backup.c b/block/backup.c
index 1c535b1..014694f 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -20,6 +20,7 @@
 #include "block/block_int.h"
 #include "block/blockjob.h"
 #include "qemu/ratelimit.h"
+#include "sysemu/block-backend.h"
 
 #define BACKUP_CLUSTER_BITS 16
 #define BACKUP_CLUSTER_SIZE (1 << BACKUP_CLUSTER_BITS)
@@ -205,7 +206,9 @@ static void backup_iostatus_reset(BlockJob *job)
 {
     BackupBlockJob *s = container_of(job, BackupBlockJob, common);
 
-    bdrv_iostatus_reset(s->target);
+    if (s->target->blk) {
+        blk_iostatus_reset(s->target->blk);
+    }
 }
 
 static const BlockJobDriver backup_job_driver = {
@@ -265,8 +268,10 @@ static void coroutine_fn backup_run(void *opaque)
     job->bitmap = hbitmap_alloc(end, 0);
 
     bdrv_set_enable_write_cache(target, true);
-    bdrv_set_on_error(target, on_target_error, on_target_error);
-    bdrv_iostatus_enable(target);
+    if (target->blk) {
+        blk_set_on_error(target->blk, on_target_error, on_target_error);
+        blk_iostatus_enable(target->blk);
+    }
 
     bdrv_add_before_write_notifier(bs, &before_write);
 
@@ -359,7 +364,9 @@ static void coroutine_fn backup_run(void *opaque)
 
     hbitmap_free(job->bitmap);
 
-    bdrv_iostatus_disable(target);
+    if (target->blk) {
+        blk_iostatus_disable(target->blk);
+    }
     bdrv_op_unblock_all(target, job->common.blocker);
 
     data = g_malloc(sizeof(*data));
@@ -387,7 +394,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
 
     if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
          on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
-        !bdrv_iostatus_is_enabled(bs)) {
+        (!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
         error_set(errp, QERR_INVALID_PARAMETER, "on-source-error");
         return;
     }
diff --git a/block/block-backend.c b/block/block-backend.c
index 3d565d8..2a48e82 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -12,7 +12,9 @@
 
 #include "sysemu/block-backend.h"
 #include "block/block_int.h"
+#include "block/blockjob.h"
 #include "sysemu/blockdev.h"
+#include "sysemu/sysemu.h"
 #include "qapi-event.h"
 
 /* Number of coroutines to reserve per attached device model */
@@ -37,6 +39,10 @@ struct BlockBackend {
 
     /* I/O stats (display with "info blockstats"). */
     BlockAcctStats stats;
+
+    BlockdevOnError on_read_error, on_write_error;
+    bool iostatus_enabled;
+    BlockDeviceIoStatus iostatus;
 };
 
 typedef struct BlockBackendAIOCB {
@@ -313,7 +319,7 @@ int blk_attach_dev(BlockBackend *blk, void *dev)
     }
     blk_ref(blk);
     blk->dev = dev;
-    bdrv_iostatus_reset(blk->bs);
+    blk_iostatus_reset(blk);
     return 0;
 }
 
@@ -445,7 +451,47 @@ void blk_dev_resize_cb(BlockBackend *blk)
 
 void blk_iostatus_enable(BlockBackend *blk)
 {
-    bdrv_iostatus_enable(blk->bs);
+    blk->iostatus_enabled = true;
+    blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
+}
+
+/* The I/O status is only enabled if the drive explicitly
+ * enables it _and_ the VM is configured to stop on errors */
+bool blk_iostatus_is_enabled(const BlockBackend *blk)
+{
+    return (blk->iostatus_enabled &&
+           (blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
+            blk->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
+            blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
+}
+
+BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
+{
+    return blk->iostatus;
+}
+
+void blk_iostatus_disable(BlockBackend *blk)
+{
+    blk->iostatus_enabled = false;
+}
+
+void blk_iostatus_reset(BlockBackend *blk)
+{
+    if (blk_iostatus_is_enabled(blk)) {
+        blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
+        if (blk->bs && blk->bs->job) {
+            block_job_iostatus_reset(blk->bs->job);
+        }
+    }
+}
+
+void blk_iostatus_set_err(BlockBackend *blk, int error)
+{
+    assert(blk_iostatus_is_enabled(blk));
+    if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
+        blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
+                                          BLOCK_DEVICE_IO_STATUS_FAILED;
+    }
 }
 
 static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
@@ -700,21 +746,81 @@ void blk_drain_all(void)
     bdrv_drain_all();
 }
 
+void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
+                      BlockdevOnError on_write_error)
+{
+    blk->on_read_error = on_read_error;
+    blk->on_write_error = on_write_error;
+}
+
 BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
 {
-    return bdrv_get_on_error(blk->bs, is_read);
+    return is_read ? blk->on_read_error : blk->on_write_error;
 }
 
 BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
                                       int error)
 {
-    return bdrv_get_error_action(blk->bs, is_read, error);
+    BlockdevOnError on_err = blk_get_on_error(blk, is_read);
+
+    switch (on_err) {
+    case BLOCKDEV_ON_ERROR_ENOSPC:
+        return (error == ENOSPC) ?
+               BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
+    case BLOCKDEV_ON_ERROR_STOP:
+        return BLOCK_ERROR_ACTION_STOP;
+    case BLOCKDEV_ON_ERROR_REPORT:
+        return BLOCK_ERROR_ACTION_REPORT;
+    case BLOCKDEV_ON_ERROR_IGNORE:
+        return BLOCK_ERROR_ACTION_IGNORE;
+    default:
+        abort();
+    }
 }
 
+static void send_qmp_error_event(BlockBackend *blk,
+                                 BlockErrorAction action,
+                                 bool is_read, int error)
+{
+    IoOperationType optype;
+
+    optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
+    qapi_event_send_block_io_error(blk_name(blk), optype, action,
+                                   blk_iostatus_is_enabled(blk),
+                                   error == ENOSPC, strerror(error),
+                                   &error_abort);
+}
+
+/* This is done by device models because, while the block layer knows
+ * about the error, it does not know whether an operation comes from
+ * the device or the block layer (from a job, for example).
+ */
 void blk_error_action(BlockBackend *blk, BlockErrorAction action,
                       bool is_read, int error)
 {
-    bdrv_error_action(blk->bs, action, is_read, error);
+    assert(error >= 0);
+
+    if (action == BLOCK_ERROR_ACTION_STOP) {
+        /* First set the iostatus, so that "info block" returns an iostatus
+         * that matches the events raised so far (an additional error iostatus
+         * is fine, but not a lost one).
+         */
+        blk_iostatus_set_err(blk, error);
+
+        /* Then raise the request to stop the VM and the event.
+         * qemu_system_vmstop_request_prepare has two effects.  First,
+         * it ensures that the STOP event always comes after the
+         * BLOCK_IO_ERROR event.  Second, it ensures that even if management
+         * can observe the STOP event and do a "cont" before the STOP
+         * event is issued, the VM will not stop.  In this case, vm_start()
+         * also ensures that the STOP/RESUME pair of events is emitted.
+         */
+        qemu_system_vmstop_request_prepare();
+        send_qmp_error_event(blk, action, is_read, error);
+        qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
+    } else {
+        send_qmp_error_event(blk, action, is_read, error);
+    }
 }
 
 int blk_is_read_only(BlockBackend *blk)
diff --git a/block/commit.c b/block/commit.c
index cfa2bbe..77c7267 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -16,6 +16,7 @@
 #include "block/block_int.h"
 #include "block/blockjob.h"
 #include "qemu/ratelimit.h"
+#include "sysemu/block-backend.h"
 
 enum {
     /*
@@ -212,7 +213,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
 
     if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
          on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
-        !bdrv_iostatus_is_enabled(bs)) {
+        (!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
         error_setg(errp, "Invalid parameter combination");
         return;
     }
diff --git a/block/mirror.c b/block/mirror.c
index 4056164..dc19d55 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -14,6 +14,7 @@
 #include "trace.h"
 #include "block/blockjob.h"
 #include "block/block_int.h"
+#include "sysemu/block-backend.h"
 #include "qemu/ratelimit.h"
 #include "qemu/bitmap.h"
 
@@ -570,7 +571,9 @@ immediate_exit:
     g_free(s->cow_bitmap);
     g_free(s->in_flight_bitmap);
     bdrv_release_dirty_bitmap(bs, s->dirty_bitmap);
-    bdrv_iostatus_disable(s->target);
+    if (s->target->blk) {
+        blk_iostatus_disable(s->target->blk);
+    }
 
     data = g_malloc(sizeof(*data));
     data->ret = ret;
@@ -592,7 +595,9 @@ static void mirror_iostatus_reset(BlockJob *job)
 {
     MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
 
-    bdrv_iostatus_reset(s->target);
+    if (s->target->blk) {
+        blk_iostatus_reset(s->target->blk);
+    }
 }
 
 static void mirror_complete(BlockJob *job, Error **errp)
@@ -683,7 +688,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
 
     if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
          on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
-        !bdrv_iostatus_is_enabled(bs)) {
+        (!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
         error_set(errp, QERR_INVALID_PARAMETER, "on-source-error");
         return;
     }
@@ -708,8 +713,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
         return;
     }
     bdrv_set_enable_write_cache(s->target, true);
-    bdrv_set_on_error(s->target, on_target_error, on_target_error);
-    bdrv_iostatus_enable(s->target);
+    if (s->target->blk) {
+        blk_set_on_error(s->target->blk, on_target_error, on_target_error);
+        blk_iostatus_enable(s->target->blk);
+    }
     s->common.co = qemu_coroutine_create(mirror_run);
     trace_mirror_start(bs, s, s->common.co, opaque);
     qemu_coroutine_enter(s->common.co, s);
diff --git a/block/qapi.c b/block/qapi.c
index 7840c81..9a44d40 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -277,9 +277,9 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
         info->tray_open = blk_dev_is_tray_open(blk);
     }
 
-    if (bdrv_iostatus_is_enabled(bs)) {
+    if (blk_iostatus_is_enabled(blk)) {
         info->has_io_status = true;
-        info->io_status = bs->iostatus;
+        info->io_status = blk_iostatus(blk);
     }
 
     if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
diff --git a/block/stream.c b/block/stream.c
index a628901..728a3e9 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -15,6 +15,7 @@
 #include "block/block_int.h"
 #include "block/blockjob.h"
 #include "qemu/ratelimit.h"
+#include "sysemu/block-backend.h"
 
 enum {
     /*
@@ -249,7 +250,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
 
     if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
          on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
-        !bdrv_iostatus_is_enabled(bs)) {
+        (!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
         error_set(errp, QERR_INVALID_PARAMETER, "on-error");
         return;
     }
diff --git a/blockdev.c b/blockdev.c
index 81fa7bd..c9e9ab9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -545,7 +545,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
 
     bs->detect_zeroes = detect_zeroes;
 
-    bdrv_set_on_error(bs, on_read_error, on_write_error);
+    blk_set_on_error(blk, on_read_error, on_write_error);
 
     /* disk I/O throttling */
     if (throttle_enabled(&cfg)) {
@@ -2009,8 +2009,8 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     if (blk_get_attached_dev(blk)) {
         blk_hide_on_behalf_of_do_drive_del(blk);
         /* Further I/O must not pause the guest */
-        bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
-                          BLOCKDEV_ON_ERROR_REPORT);
+        blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
+                         BLOCKDEV_ON_ERROR_REPORT);
     } else {
         blk_unref(blk);
     }
diff --git a/blockjob.c b/blockjob.c
index ba2255d..fa60924 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -29,6 +29,7 @@
 #include "block/block.h"
 #include "block/blockjob.h"
 #include "block/block_int.h"
+#include "sysemu/block-backend.h"
 #include "qapi/qmp/qjson.h"
 #include "block/coroutine.h"
 #include "qmp-commands.h"
@@ -337,8 +338,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
     if (action == BLOCK_ERROR_ACTION_STOP) {
         block_job_pause(job);
         block_job_iostatus_set_err(job, error);
-        if (bs != job->bs) {
-            bdrv_iostatus_set_err(bs, error);
+        if (bs->blk && bs != job->bs) {
+            blk_iostatus_set_err(bs->blk, error);
         }
     }
     return action;
diff --git a/include/block/block.h b/include/block/block.h
index 8cd6b31..fa9dfd5 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -148,11 +148,6 @@ typedef enum BlockOpType {
     BLOCK_OP_TYPE_MAX,
 } BlockOpType;
 
-void bdrv_iostatus_enable(BlockDriverState *bs);
-void bdrv_iostatus_reset(BlockDriverState *bs);
-void bdrv_iostatus_disable(BlockDriverState *bs);
-bool bdrv_iostatus_is_enabled(const BlockDriverState *bs);
-void bdrv_iostatus_set_err(BlockDriverState *bs, int error);
 void bdrv_info_print(Monitor *mon, const QObject *data);
 void bdrv_info(Monitor *mon, QObject **ret_data);
 void bdrv_stats_print(Monitor *mon, const QObject *data);
@@ -351,12 +346,6 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
                             int64_t sector_num, int nb_sectors, int *pnum);
 
-void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
-                       BlockdevOnError on_write_error);
-BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read);
-BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error);
-void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
-                       bool is_read, int error);
 int bdrv_is_read_only(BlockDriverState *bs);
 int bdrv_is_sg(BlockDriverState *bs);
 int bdrv_enable_write_cache(BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index d023913..69668e4 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -378,12 +378,6 @@ struct BlockDriverState {
     /* do we need to tell the quest if we have a volatile write cache? */
     int enable_write_cache;
 
-    /* NOTE: the following infos are only hints for real hardware
-       drivers. They are not used by the block driver */
-    BlockdevOnError on_read_error, on_write_error;
-    bool iostatus_enabled;
-    BlockDeviceIoStatus iostatus;
-
     /* the following member gives a name to every node on the bs graph. */
     char node_name[32];
     /* element of the list of named nodes building the graph */
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index f91f3c7..c4a61c0 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -76,6 +76,11 @@ BlockDriverState *blk_bs(BlockBackend *blk);
 void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk);
 
 void blk_iostatus_enable(BlockBackend *blk);
+bool blk_iostatus_is_enabled(const BlockBackend *blk);
+BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk);
+void blk_iostatus_disable(BlockBackend *blk);
+void blk_iostatus_reset(BlockBackend *blk);
+void blk_iostatus_set_err(BlockBackend *blk, int error);
 int blk_attach_dev(BlockBackend *blk, void *dev);
 void blk_attach_dev_nofail(BlockBackend *blk, void *dev);
 void blk_detach_dev(BlockBackend *blk, void *dev);
@@ -116,6 +121,8 @@ int blk_co_flush(BlockBackend *blk);
 int blk_flush(BlockBackend *blk);
 int blk_flush_all(void);
 void blk_drain_all(void);
+void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
+                      BlockdevOnError on_write_error);
 BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read);
 BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
                                       int error);
diff --git a/qmp.c b/qmp.c
index 963305c..635d001 100644
--- a/qmp.c
+++ b/qmp.c
@@ -23,6 +23,7 @@
 #include "sysemu/arch_init.h"
 #include "hw/qdev.h"
 #include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "qom/qom-qobject.h"
 #include "qapi/qmp/qobject.h"
 #include "qapi/qmp-input-visitor.h"
@@ -150,6 +151,7 @@ SpiceInfo *qmp_query_spice(Error **errp)
 
 void qmp_cont(Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
 
     if (runstate_needs_reset()) {
@@ -159,8 +161,8 @@ void qmp_cont(Error **errp)
         return;
     }
 
-    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
-        bdrv_iostatus_reset(bs);
+    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+        blk_iostatus_reset(blk);
     }
     for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         if (bdrv_key_required(bs)) {
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 13/50] block: Add BlockBackendRootState
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (11 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 12/50] block: Move I/O status and error actions into BB Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:03   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 14/50] block: Make some BB functions fall back to BBRS Max Reitz
                   ` (36 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

This structure will store some of the state of the root BDS if the BDS
tree is removed, so that state can be restored once a new BDS tree is
inserted.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c          | 26 ++++++++++++++++++++++++++
 include/block/block_int.h      |  9 +++++++++
 include/qemu/typedefs.h        |  1 +
 include/sysemu/block-backend.h |  2 ++
 4 files changed, 38 insertions(+)

diff --git a/block/block-backend.c b/block/block-backend.c
index 2a48e82..7be03ee 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -37,6 +37,10 @@ struct BlockBackend {
     /* the block size for which the guest device expects atomicity */
     int guest_block_size;
 
+    /* If the BDS tree is removed, some of its options are stored here (which
+     * can be used to restore those options in the new BDS on insert) */
+    BlockBackendRootState root_state;
+
     /* I/O stats (display with "info blockstats"). */
     BlockAcctStats stats;
 
@@ -1014,3 +1018,25 @@ int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
 {
     return bdrv_load_vmstate(blk->bs, buf, pos, size);
 }
+
+/*
+ * Updates the BlockBackendRootState object with data from the currently
+ * attached BlockDriverState.
+ */
+void blk_update_root_state(BlockBackend *blk)
+{
+    assert(blk->bs);
+
+    blk->root_state.open_flags    = blk->bs->open_flags;
+    blk->root_state.read_only     = blk->bs->read_only;
+    blk->root_state.detect_zeroes = blk->bs->detect_zeroes;
+
+    blk->root_state.io_limits_enabled = blk->bs->io_limits_enabled;
+    throttle_get_config(&blk->bs->throttle_state,
+                        &blk->root_state.throttle_config);
+}
+
+BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
+{
+    return &blk->root_state;
+}
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 69668e4..91d21c5 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -406,6 +406,15 @@ struct BlockDriverState {
     NotifierWithReturn write_threshold_notifier;
 };
 
+struct BlockBackendRootState {
+    int open_flags;
+    bool read_only;
+    BlockdevDetectZeroesOptions detect_zeroes;
+
+    bool io_limits_enabled;
+    ThrottleConfig throttle_config;
+};
+
 
 /* Essential block drivers which must always be statically linked into qemu, and
  * which therefore can be accessed without using bdrv_find_format() */
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index cde3314..39a95dd 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -11,6 +11,7 @@ typedef struct AddressSpace AddressSpace;
 typedef struct AioContext AioContext;
 typedef struct AudioState AudioState;
 typedef struct BlockBackend BlockBackend;
+typedef struct BlockBackendRootState BlockBackendRootState;
 typedef struct BlockDriverState BlockDriverState;
 typedef struct BusClass BusClass;
 typedef struct BusState BusState;
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index c4a61c0..afb62e1 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -158,6 +158,8 @@ void blk_add_close_notifier(BlockBackend *blk, Notifier *notify);
 void blk_io_plug(BlockBackend *blk);
 void blk_io_unplug(BlockBackend *blk);
 BlockAcctStats *blk_get_stats(BlockBackend *blk);
+BlockBackendRootState *blk_get_root_state(BlockBackend *blk);
+void blk_update_root_state(BlockBackend *blk);
 
 void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
                   BlockCompletionFunc *cb, void *opaque);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 14/50] block: Make some BB functions fall back to BBRS
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (12 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 13/50] block: Add BlockBackendRootState Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:15   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 15/50] block: Fail requests to empty BlockBackend Max Reitz
                   ` (35 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

If there is no BDS tree attached to a BlockBackend, functions that can
do so should fall back to the BlockBackendRootState structure (which are
blk_is_read_only() and blk_get_flags(), because the read-only status and
the "open flags" are part of the BBRS).

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 7be03ee..62be370 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -829,7 +829,11 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
 
 int blk_is_read_only(BlockBackend *blk)
 {
-    return bdrv_is_read_only(blk->bs);
+    if (blk->bs) {
+        return bdrv_is_read_only(blk->bs);
+    } else {
+        return blk->root_state.read_only;
+    }
 }
 
 int blk_is_sg(BlockBackend *blk)
@@ -874,7 +878,11 @@ void blk_eject(BlockBackend *blk, bool eject_flag)
 
 int blk_get_flags(BlockBackend *blk)
 {
-    return bdrv_get_flags(blk->bs);
+    if (blk->bs) {
+        return bdrv_get_flags(blk->bs);
+    } else {
+        return blk->root_state.open_flags;
+    }
 }
 
 void blk_set_guest_block_size(BlockBackend *blk, int align)
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 15/50] block: Fail requests to empty BlockBackend
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (13 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 14/50] block: Make some BB functions fall back to BBRS Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:24   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS Max Reitz
                   ` (34 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

If there is no BlockDriverState in a BlockBackend or if the tray of the
guest device is open, fail all requests (where that is possible) with
-ENOMEDIUM.

The reason the status of the guest device is taken into account is
because once the guest device's tray is opened, any request on the same
BlockBackend as the guest uses should fail. If the BDS tree is supposed
to be usable even after ejecting it from the guest, a different
BlockBackend must be used.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 62be370..4f3122a 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -507,7 +507,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
         return -EIO;
     }
 
-    if (!blk_is_inserted(blk)) {
+    if (!blk_is_available(blk)) {
         return -ENOMEDIUM;
     }
 
@@ -635,6 +635,10 @@ int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count)
 
 int64_t blk_getlength(BlockBackend *blk)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_getlength(blk->bs);
 }
 
@@ -670,6 +674,10 @@ BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
 BlockAIOCB *blk_aio_flush(BlockBackend *blk,
                           BlockCompletionFunc *cb, void *opaque)
 {
+    if (!blk_is_available(blk)) {
+        return abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
+    }
+
     return bdrv_aio_flush(blk->bs, cb, opaque);
 }
 
@@ -711,12 +719,20 @@ int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs)
 
 int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_ioctl(blk->bs, req, buf);
 }
 
 BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
                           BlockCompletionFunc *cb, void *opaque)
 {
+    if (!blk_is_available(blk)) {
+        return abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
+    }
+
     return bdrv_aio_ioctl(blk->bs, req, buf, cb, opaque);
 }
 
@@ -732,11 +748,19 @@ int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
 
 int blk_co_flush(BlockBackend *blk)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_co_flush(blk->bs);
 }
 
 int blk_flush(BlockBackend *blk)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_flush(blk->bs);
 }
 
@@ -853,6 +877,11 @@ void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
 
 void blk_invalidate_cache(BlockBackend *blk, Error **errp)
 {
+    if (!blk->bs) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, blk->name);
+        return;
+    }
+
     bdrv_invalidate_cache(blk->bs, errp);
 }
 
@@ -1003,6 +1032,10 @@ int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
 
 int blk_truncate(BlockBackend *blk, int64_t offset)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_truncate(blk->bs, offset);
 }
 
@@ -1019,11 +1052,19 @@ int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
 int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
                      int64_t pos, int size)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_save_vmstate(blk->bs, buf, pos, size);
 }
 
 int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
 {
+    if (!blk_is_available(blk)) {
+        return -ENOMEDIUM;
+    }
+
     return bdrv_load_vmstate(blk->bs, buf, pos, size);
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (14 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 15/50] block: Fail requests to empty BlockBackend Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:36   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs() Max Reitz
                   ` (33 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

There are several BlockBackend functions which, in theory, cannot fail.
This patch makes them cope with the BlockDriverState pointer being NULL
by making them fall back to some default action like ignoring the value
in setters and returning the default in getters.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c | 70 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 15 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 4f3122a..760558f 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -644,7 +644,11 @@ int64_t blk_getlength(BlockBackend *blk)
 
 void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
 {
-    bdrv_get_geometry(blk->bs, nb_sectors_ptr);
+    if (!blk->bs) {
+        *nb_sectors_ptr = 0;
+    } else {
+        bdrv_get_geometry(blk->bs, nb_sectors_ptr);
+    }
 }
 
 BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num,
@@ -862,17 +866,27 @@ int blk_is_read_only(BlockBackend *blk)
 
 int blk_is_sg(BlockBackend *blk)
 {
+    if (!blk->bs) {
+        return 0;
+    }
+
     return bdrv_is_sg(blk->bs);
 }
 
 int blk_enable_write_cache(BlockBackend *blk)
 {
+    if (!blk->bs) {
+        return 0;
+    }
+
     return bdrv_enable_write_cache(blk->bs);
 }
 
 void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
 {
-    bdrv_set_enable_write_cache(blk->bs, wce);
+    if (blk->bs) {
+        bdrv_set_enable_write_cache(blk->bs, wce);
+    }
 }
 
 void blk_invalidate_cache(BlockBackend *blk, Error **errp)
@@ -897,12 +911,16 @@ bool blk_is_available(BlockBackend *blk)
 
 void blk_lock_medium(BlockBackend *blk, bool locked)
 {
-    bdrv_lock_medium(blk->bs, locked);
+    if (blk->bs) {
+        bdrv_lock_medium(blk->bs, locked);
+    }
 }
 
 void blk_eject(BlockBackend *blk, bool eject_flag)
 {
-    bdrv_eject(blk->bs, eject_flag);
+    if (blk->bs) {
+        bdrv_eject(blk->bs, eject_flag);
+    }
 }
 
 int blk_get_flags(BlockBackend *blk)
@@ -926,22 +944,32 @@ void *blk_blockalign(BlockBackend *blk, size_t size)
 
 bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
 {
+    if (!blk->bs) {
+        return false;
+    }
+
     return bdrv_op_is_blocked(blk->bs, op, errp);
 }
 
 void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
 {
-    bdrv_op_unblock(blk->bs, op, reason);
+    if (blk->bs) {
+        bdrv_op_unblock(blk->bs, op, reason);
+    }
 }
 
 void blk_op_block_all(BlockBackend *blk, Error *reason)
 {
-    bdrv_op_block_all(blk->bs, reason);
+    if (blk->bs) {
+        bdrv_op_block_all(blk->bs, reason);
+    }
 }
 
 void blk_op_unblock_all(BlockBackend *blk, Error *reason)
 {
-    bdrv_op_unblock_all(blk->bs, reason);
+    if (blk->bs) {
+        bdrv_op_unblock_all(blk->bs, reason);
+    }
 }
 
 AioContext *blk_get_aio_context(BlockBackend *blk)
@@ -961,15 +989,19 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
 
 void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
 {
-    bdrv_set_aio_context(blk->bs, new_context);
+    if (blk->bs) {
+        bdrv_set_aio_context(blk->bs, new_context);
+    }
 }
 
 void blk_add_aio_context_notifier(BlockBackend *blk,
         void (*attached_aio_context)(AioContext *new_context, void *opaque),
         void (*detach_aio_context)(void *opaque), void *opaque)
 {
-    bdrv_add_aio_context_notifier(blk->bs, attached_aio_context,
-                                  detach_aio_context, opaque);
+    if (blk->bs) {
+        bdrv_add_aio_context_notifier(blk->bs, attached_aio_context,
+                                      detach_aio_context, opaque);
+    }
 }
 
 void blk_remove_aio_context_notifier(BlockBackend *blk,
@@ -978,23 +1010,31 @@ void blk_remove_aio_context_notifier(BlockBackend *blk,
                                      void (*detach_aio_context)(void *),
                                      void *opaque)
 {
-    bdrv_remove_aio_context_notifier(blk->bs, attached_aio_context,
-                                     detach_aio_context, opaque);
+    if (blk->bs) {
+        bdrv_remove_aio_context_notifier(blk->bs, attached_aio_context,
+                                         detach_aio_context, opaque);
+    }
 }
 
 void blk_add_close_notifier(BlockBackend *blk, Notifier *notify)
 {
-    bdrv_add_close_notifier(blk->bs, notify);
+    if (blk->bs) {
+        bdrv_add_close_notifier(blk->bs, notify);
+    }
 }
 
 void blk_io_plug(BlockBackend *blk)
 {
-    bdrv_io_plug(blk->bs);
+    if (blk->bs) {
+        bdrv_io_plug(blk->bs);
+    }
 }
 
 void blk_io_unplug(BlockBackend *blk)
 {
-    bdrv_io_unplug(blk->bs);
+    if (blk->bs) {
+        bdrv_io_unplug(blk->bs);
+    }
 }
 
 BlockAcctStats *blk_get_stats(BlockBackend *blk)
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (15 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:56   ` Eric Blake
  2015-01-28 18:31   ` John Snow
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 18/50] block: Respect empty BB in bdrv_query_info() Max Reitz
                   ` (32 subsequent siblings)
  49 siblings, 2 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

blk_by_name() may return a BlockBackend for which blk_bs() returns NULL.
In this case, an error should be returned (instead of just returning
NULL without modifying *errp).

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/block.c b/block.c
index 9a0a510..b7e631c 100644
--- a/block.c
+++ b/block.c
@@ -3718,6 +3718,11 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
         blk = blk_by_name(device);
 
         if (blk) {
+            if (!blk_bs(blk)) {
+                error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+                return NULL;
+            }
+
             return blk_bs(blk);
         }
     }
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 18/50] block: Respect empty BB in bdrv_query_info()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (16 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs() Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:57   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA Max Reitz
                   ` (31 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/qapi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index 9a44d40..db42a6e 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -282,12 +282,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
         info->io_status = blk_iostatus(blk);
     }
 
-    if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
+    if (bs && !QLIST_EMPTY(&bs->dirty_bitmaps)) {
         info->has_dirty_bitmaps = true;
         info->dirty_bitmaps = bdrv_query_dirty_bitmaps(bs);
     }
 
-    if (bs->drv) {
+    if (bs && bs->drv) {
         info->has_inserted = true;
         info->inserted = bdrv_block_device_info(bs);
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (17 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 18/50] block: Respect empty BB in bdrv_query_info() Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 21:59   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 20/50] blockdev: Check blk_is_available() in sn-del-int-sync Max Reitz
                   ` (30 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

When preparing a blockdev-backup transaction, the BlockBackend should be
used because there may be no medium associated to the BB (which would
make bdrv_find() fail, whereas blk_by_name() does not).

This does not make a real difference because blockdev-backup will fail
without a medium anyway; however, it will have an impact on the error
returned ("device not found" vs. "no medium").

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index c9e9ab9..ae1137f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1562,27 +1562,27 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp)
 {
     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
     BlockdevBackup *backup;
-    BlockDriverState *bs, *target;
+    BlockBackend *blk, *target;
     Error *local_err = NULL;
 
     assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
     backup = common->action->blockdev_backup;
 
-    bs = bdrv_find(backup->device);
-    if (!bs) {
+    blk = blk_by_name(backup->device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
         return;
     }
 
-    target = bdrv_find(backup->target);
+    target = blk_by_name(backup->target);
     if (!target) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, backup->target);
         return;
     }
 
     /* AioContext is released in .clean() */
-    state->aio_context = bdrv_get_aio_context(bs);
-    if (state->aio_context != bdrv_get_aio_context(target)) {
+    state->aio_context = blk_get_aio_context(blk);
+    if (state->aio_context != blk_get_aio_context(target)) {
         state->aio_context = NULL;
         error_setg(errp, "Backup between two IO threads is not implemented");
         return;
@@ -1600,7 +1600,10 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp)
         return;
     }
 
-    state->bs = bs;
+    /* qmp_blockdev_backup() would have failed otherwise */
+    assert(blk_bs(blk));
+
+    state->bs = blk_bs(blk);
     state->job = state->bs->job;
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 20/50] blockdev: Check blk_is_available() in sn-del-int-sync
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (18 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 22:10   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 21/50] blockdev: Check BB validity in internal snapshot TA Max Reitz
                   ` (29 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Check whether the BlockBackend is actually available at the start of
snapshot-delete-internal-sync.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index ae1137f..858d181 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1096,18 +1096,23 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
                                                          const char *name,
                                                          Error **errp)
 {
-    BlockDriverState *bs = bdrv_find(device);
+    BlockBackend *blk;
+    BlockDriverState *bs;
     AioContext *aio_context;
     QEMUSnapshotInfo sn;
     Error *local_err = NULL;
     SnapshotInfo *info = NULL;
     int ret;
 
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return NULL;
     }
 
+    aio_context = blk_get_aio_context(blk);
+    aio_context_acquire(aio_context);
+
     if (!has_id) {
         id = NULL;
     }
@@ -1118,11 +1123,14 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
 
     if (!id && !name) {
         error_setg(errp, "Name or id must be provided");
-        return NULL;
+        goto out_aio_context;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
-    aio_context_acquire(aio_context);
+    if (!blk_is_available(blk)) {
+        error_set(errp, QERR_DEVICE_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;
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 21/50] blockdev: Check BB validity in internal snapshot TA
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (19 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 20/50] blockdev: Check blk_is_available() in sn-del-int-sync Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 23:02   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA Max Reitz
                   ` (28 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 858d181..012c603 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1217,6 +1217,7 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
     Error *local_err = NULL;
     const char *device;
     const char *name;
+    BlockBackend *blk;
     BlockDriverState *bs;
     QEMUSnapshotInfo old_sn, *sn;
     bool ret;
@@ -1235,20 +1236,21 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
     name = internal->name;
 
     /* 2. check for validation */
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
     /* AioContext is released in .clean() */
-    state->aio_context = bdrv_get_aio_context(bs);
+    state->aio_context = blk_get_aio_context(blk);
     aio_context_acquire(state->aio_context);
 
-    if (!bdrv_is_inserted(bs)) {
+    if (!blk_is_available(blk)) {
         error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
         return;
     }
+    bs = blk_bs(blk);
 
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) {
         return;
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (20 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 21/50] blockdev: Check BB validity in internal snapshot TA Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-27 23:44   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 23/50] blockdev: Catch NULL BDS in block_set_io_throttle Max Reitz
                   ` (27 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

In the drive-backup transaction, call blk_is_available() before using
blk_bs() to obtain the root BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 012c603..5f7eef5 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1507,23 +1507,28 @@ typedef struct DriveBackupState {
 static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
 {
     DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
-    BlockDriverState *bs;
+    BlockBackend *blk;
     DriveBackup *backup;
     Error *local_err = NULL;
 
     assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
     backup = common->action->drive_backup;
 
-    bs = bdrv_find(backup->device);
-    if (!bs) {
+    blk = blk_by_name(backup->device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
         return;
     }
 
     /* AioContext is released in .clean() */
-    state->aio_context = bdrv_get_aio_context(bs);
+    state->aio_context = blk_get_aio_context(blk);
     aio_context_acquire(state->aio_context);
 
+    if (!blk_is_available(blk)) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
+        return;
+    }
+
     qmp_drive_backup(backup->device, backup->target,
                      backup->has_format, backup->format,
                      backup->sync,
@@ -1537,7 +1542,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
         return;
     }
 
-    state->bs = bs;
+    state->bs = blk_bs(blk);
     state->job = state->bs->job;
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 23/50] blockdev: Catch NULL BDS in block_set_io_throttle
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (21 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-28 15:26   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 24/50] blockdev: Check BB validity in block-stream Max Reitz
                   ` (26 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Split bdrv_find() into blk_by_name() and blk_bs() to separate the
"no medium inserted" case from the "device not found" case.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 5f7eef5..9801a7e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1922,15 +1922,25 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                                int64_t iops_size, Error **errp)
 {
     ThrottleConfig cfg;
+    BlockBackend *blk;
     BlockDriverState *bs;
     AioContext *aio_context;
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
+    aio_context = blk_get_aio_context(blk);
+    aio_context_acquire(aio_context);
+
+    bs = blk_bs(blk);
+    if (!bs) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+        goto out;
+    }
+
     memset(&cfg, 0, sizeof(cfg));
     cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
     cfg.buckets[THROTTLE_BPS_READ].avg  = bps_rd;
@@ -1964,12 +1974,9 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
     }
 
     if (!check_throttle_config(&cfg, errp)) {
-        return;
+        goto out;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
-    aio_context_acquire(aio_context);
-
     if (!bs->io_limits_enabled && throttle_enabled(&cfg)) {
         bdrv_io_limits_enable(bs);
     } else if (bs->io_limits_enabled && !throttle_enabled(&cfg)) {
@@ -1980,6 +1987,7 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
         bdrv_set_io_limits(bs, &cfg);
     }
 
+out:
     aio_context_release(aio_context);
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 24/50] blockdev: Check BB validity in block-stream
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (22 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 23/50] blockdev: Catch NULL BDS in block_set_io_throttle Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-28 15:28   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 25/50] blockdev: Check BB validity in block-commit Max Reitz
                   ` (25 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 9801a7e..74d26a6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2142,6 +2142,7 @@ void qmp_block_stream(const char *device,
                       bool has_on_error, BlockdevOnError on_error,
                       Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *base_bs = NULL;
     AioContext *aio_context;
@@ -2152,15 +2153,21 @@ void qmp_block_stream(const char *device,
         on_error = BLOCKDEV_ON_ERROR_REPORT;
     }
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
+    if (!blk_is_available(blk)) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+        goto out;
+    }
+    bs = blk_bs(blk);
+
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
         goto out;
     }
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 25/50] blockdev: Check BB validity in block-commit
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (23 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 24/50] blockdev: Check BB validity in block-stream Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-28 16:09   ` Eric Blake
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 26/50] blockdev: Check BB validity in drive-backup Max Reitz
                   ` (24 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 74d26a6..431afcd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2213,6 +2213,7 @@ void qmp_block_commit(const char *device,
                       bool has_speed, int64_t speed,
                       Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *base_bs, *top_bs;
     AioContext *aio_context;
@@ -2231,15 +2232,21 @@ void qmp_block_commit(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. */
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
+    if (!blk_is_available(blk)) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+        goto out;
+    }
+    bs = blk_bs(blk);
+
     /* drain all i/o before commits */
     bdrv_drain_all();
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 26/50] blockdev: Check BB validity in drive-backup
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (24 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 25/50] blockdev: Check BB validity in block-commit Max Reitz
@ 2015-01-27 19:45 ` Max Reitz
  2015-01-28 16:20   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 27/50] blockdev: Check BB validity in blockdev-backup Max Reitz
                   ` (23 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend (instead of calling
bdrv_is_inserted() after bdrv_find()).

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 431afcd..9476c72 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2323,6 +2323,7 @@ void qmp_drive_backup(const char *device, const char *target,
                       bool has_on_target_error, BlockdevOnError on_target_error,
                       Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *target_bs;
     BlockDriverState *source = NULL;
@@ -2346,21 +2347,22 @@ void qmp_drive_backup(const char *device, const char *target,
         mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
     }
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     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 (!bdrv_is_inserted(bs)) {
+    if (!blk_is_available(blk)) {
         error_set(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;
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 27/50] blockdev: Check BB validity in blockdev-backup
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (25 preceding siblings ...)
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 26/50] blockdev: Check BB validity in drive-backup Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 16:42   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 28/50] blockdev: Check BB validity in drive-mirror Max Reitz
                   ` (22 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 9476c72..e335d06 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2452,6 +2452,7 @@ void qmp_blockdev_backup(const char *device, const char *target,
                          BlockdevOnError on_target_error,
                          Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *target_bs;
     Error *local_err = NULL;
@@ -2467,15 +2468,21 @@ void qmp_blockdev_backup(const char *device, const char *target,
         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
     }
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
+    if (!blk_is_available(blk)) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+        goto out;
+    }
+    bs = blk_bs(blk);
+
     target_bs = bdrv_find(target);
     if (!target_bs) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, target);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 28/50] blockdev: Check BB validity in drive-mirror
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (26 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 27/50] blockdev: Check BB validity in blockdev-backup Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 16:43   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 29/50] blockdev: Check BB validity in find_block_job() Max Reitz
                   ` (21 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index e335d06..4e12061 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2516,6 +2516,7 @@ void qmp_drive_mirror(const char *device, const char *target,
                       bool has_on_target_error, BlockdevOnError on_target_error,
                       Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriverState *source, *target_bs;
     AioContext *aio_context;
@@ -2555,19 +2556,20 @@ void qmp_drive_mirror(const char *device, const char *target,
         return;
     }
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
-    if (!bdrv_is_inserted(bs)) {
+    if (!blk_is_available(blk)) {
         error_set(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;
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 29/50] blockdev: Check BB validity in find_block_job()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (27 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 28/50] blockdev: Check BB validity in drive-mirror Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 16:44   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 30/50] blockdev: Check BB validity in change-backing-file Max Reitz
                   ` (20 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 4e12061..4bd52b8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2698,25 +2698,35 @@ out:
 /* Get the block job for a given device name and acquire its AioContext */
 static BlockJob *find_block_job(const char *device, AioContext **aio_context)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    *aio_context = NULL;
+
+    blk = blk_by_name(device);
+    if (!blk) {
         goto notfound;
     }
 
-    *aio_context = bdrv_get_aio_context(bs);
+    *aio_context = blk_get_aio_context(blk);
     aio_context_acquire(*aio_context);
 
+    if (!blk_is_available(blk)) {
+        goto notfound;
+    }
+    bs = blk_bs(blk);
+
     if (!bs->job) {
-        aio_context_release(*aio_context);
         goto notfound;
     }
 
     return bs->job;
 
 notfound:
-    *aio_context = NULL;
+    if (*aio_context) {
+        aio_context_release(*aio_context);
+        *aio_context = NULL;
+    }
     return NULL;
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 30/50] blockdev: Check BB validity in change-backing-file
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (28 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 29/50] blockdev: Check BB validity in find_block_job() Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 16:50   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs() Max Reitz
                   ` (19 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Call blk_is_available() before using blk_bs() to obtain the root
BlockDriverState behind the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 4bd52b8..7f4470f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2821,7 +2821,8 @@ void qmp_change_backing_file(const char *device,
                              const char *backing_file,
                              Error **errp)
 {
-    BlockDriverState *bs = NULL;
+    BlockBackend *blk;
+    BlockDriverState *bs;
     AioContext *aio_context;
     BlockDriverState *image_bs = NULL;
     Error *local_err = NULL;
@@ -2830,15 +2831,21 @@ void qmp_change_backing_file(const char *device,
     int ret;
 
     /* find the top layer BDS of the chain */
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
+    if (!blk_is_available(blk)) {
+        error_set(errp, QERR_DEVICE_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);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (29 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 30/50] blockdev: Check BB validity in change-backing-file Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 16:52   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 32/50] blockdev: Check BB validity in eject and change Max Reitz
                   ` (18 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

This function associates the given BlockDriverState with the given
BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c          | 16 ++++++++++++++++
 include/sysemu/block-backend.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/block/block-backend.c b/block/block-backend.c
index 760558f..656ebfc 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -312,6 +312,22 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
 }
 
 /*
+ * Associates a new BlockDriverState with @blk.
+ */
+void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
+{
+    if (bs->blk == blk) {
+        return;
+    }
+
+    assert(!blk->bs);
+    assert(!bs->blk);
+    bdrv_ref(bs);
+    blk->bs = bs;
+    bs->blk = blk;
+}
+
+/*
  * Attach device model @dev to @blk.
  * Return 0 on success, -EBUSY when a device model is attached already.
  */
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index afb62e1..b6cf5bf 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -72,6 +72,7 @@ BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 
 BlockDriverState *blk_bs(BlockBackend *blk);
+void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs);
 
 void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk);
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 32/50] blockdev: Check BB validity in eject and change
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (30 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs() Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 17:42   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 33/50] blockdev: Respect NULL BDS in do_drive_del() Max Reitz
                   ` (17 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Both commands will be reimplemented in a follow-up to this patch so this
does not need to be nice, it just has to work.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 7f4470f..f3091df 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1756,10 +1756,10 @@ static void eject_device(BlockBackend *blk, int force, Error **errp)
     BlockDriverState *bs = blk_bs(blk);
     AioContext *aio_context;
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
-    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
+    if (bs && bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
         goto out;
     }
     if (!blk_dev_has_removable_media(blk)) {
@@ -1777,7 +1777,9 @@ static void eject_device(BlockBackend *blk, int force, Error **errp)
         }
     }
 
-    bdrv_close(bs);
+    if (bs) {
+        bdrv_close(bs);
+    }
 
 out:
     aio_context_release(aio_context);
@@ -1830,18 +1832,21 @@ out:
 }
 
 /* Assumes AioContext is held */
-static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename,
+static void qmp_bdrv_open_encrypted(BlockDriverState **pbs,
+                                    const char *filename,
                                     int bdrv_flags, BlockDriver *drv,
                                     const char *password, Error **errp)
 {
+    BlockDriverState *bs;
     Error *local_err = NULL;
     int ret;
 
-    ret = bdrv_open(&bs, filename, NULL, NULL, bdrv_flags, drv, &local_err);
+    ret = bdrv_open(pbs, filename, NULL, NULL, bdrv_flags, drv, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         return;
     }
+    bs = *pbs;
 
     if (bdrv_key_required(bs)) {
         if (password) {
@@ -1865,6 +1870,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
     AioContext *aio_context;
     BlockDriver *drv = NULL;
     int bdrv_flags;
+    bool new_bs;
     Error *err = NULL;
 
     blk = blk_by_name(device);
@@ -1873,12 +1879,13 @@ void qmp_change_blockdev(const char *device, const char *filename,
         return;
     }
     bs = blk_bs(blk);
+    new_bs = !bs;
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
     if (format) {
-        drv = bdrv_find_whitelisted_format(format, bs->read_only);
+        drv = bdrv_find_whitelisted_format(format, blk_is_read_only(blk));
         if (!drv) {
             error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
             goto out;
@@ -1891,10 +1898,18 @@ void qmp_change_blockdev(const char *device, const char *filename,
         goto out;
     }
 
-    bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
-    bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
+    bdrv_flags = blk_is_read_only(blk) ? 0 : BDRV_O_RDWR;
+    bdrv_flags |= blk_get_root_state(blk)->open_flags & ~BDRV_O_RDWR;
 
-    qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp);
+    qmp_bdrv_open_encrypted(&bs, filename, bdrv_flags, drv, NULL, &err);
+    if (err) {
+        error_propagate(errp, err);
+    } else if (new_bs) {
+        blk_insert_bs(blk, bs);
+        /* Has been sent automatically by bdrv_open() if blk_bs(blk) was not
+         * NULL */
+        blk_dev_change_media_cb(blk, true);
+    }
 
 out:
     aio_context_release(aio_context);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 33/50] blockdev: Respect NULL BDS in do_drive_del()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (31 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 32/50] blockdev: Check BB validity in eject and change Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 17:45   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 34/50] blockdev: Do not create BDS for empty drive Max Reitz
                   ` (16 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index f3091df..f82b20c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2019,7 +2019,6 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
         error_report("Device '%s' not found", id);
         return -1;
     }
-    bs = blk_bs(blk);
 
     if (!blk_legacy_dinfo(blk)) {
         error_report("Deleting device added with blockdev-add"
@@ -2027,10 +2026,11 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    aio_context = bdrv_get_aio_context(bs);
+    aio_context = blk_get_aio_context(blk);
     aio_context_acquire(aio_context);
 
-    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
+    bs = blk_bs(blk);
+    if (bs && bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
         error_report("%s", error_get_pretty(local_err));
         error_free(local_err);
         aio_context_release(aio_context);
@@ -2039,8 +2039,10 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 
     /* quiesce block driver; prevent further io */
     bdrv_drain_all();
-    bdrv_flush(bs);
-    bdrv_close(bs);
+    if (bs) {
+        bdrv_flush(bs);
+        bdrv_close(bs);
+    }
 
     /* if we have a device attached to this BlockDriverState
      * then we need to make the drive anonymous until the device
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 34/50] blockdev: Do not create BDS for empty drive
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (32 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 33/50] blockdev: Respect NULL BDS in do_drive_del() Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 17:50   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 35/50] blockdev: Pull out blockdev option extraction Max Reitz
                   ` (15 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Do not use "rudimentary" BDSs for empty drives any longer (for
freshly created drives).

With this change, bdrv_close_all() has no effect on empty drives (whose
media were not changed) any longer. This breaks some test outputs, fix
them.

After a follow-up patch, empty drives will generally use a NULL BDS, not
only the freshly created drives.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c                 | 68 ++++++++++++++++++++++++++--------------------
 tests/qemu-iotests/067.out | 44 ------------------------------
 tests/qemu-iotests/071.out |  2 --
 tests/qemu-iotests/081.out |  1 -
 tests/qemu-iotests/087.out |  5 ----
 5 files changed, 38 insertions(+), 82 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index f82b20c..d99edbb 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -502,16 +502,40 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         goto early_err;
     }
 
+    if (snapshot) {
+        /* always use cache=unsafe with snapshot */
+        bdrv_flags &= ~BDRV_O_CACHE_MASK;
+        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
+    }
+
+    if (copy_on_read) {
+        bdrv_flags |= BDRV_O_COPY_ON_READ;
+    }
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        bdrv_flags |= BDRV_O_INCOMING;
+    }
+
+    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
+
     /* init */
     if ((!file || !*file) && !has_driver_specific_opts) {
-        blk = blk_new_with_bs(qemu_opts_id(opts), errp);
+        BlockBackendRootState *blk_rs;
+
+        blk = blk_new(qemu_opts_id(opts), errp);
         if (!blk) {
             goto early_err;
         }
 
-        bs = blk_bs(blk);
-        bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
-        bs->read_only = ro;
+        blk_rs = blk_get_root_state(blk);
+        blk_rs->open_flags    = bdrv_flags;
+        blk_rs->read_only     = ro;
+        blk_rs->detect_zeroes = detect_zeroes;
+
+        if (throttle_enabled(&cfg)) {
+            blk_rs->io_limits_enabled = true;
+            blk_rs->throttle_config = cfg;
+        }
 
         QDECREF(bs_opts);
     } else {
@@ -519,43 +543,27 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
             file = NULL;
         }
 
-        if (snapshot) {
-            /* always use cache=unsafe with snapshot */
-            bdrv_flags &= ~BDRV_O_CACHE_MASK;
-            bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
-        }
-
-        if (copy_on_read) {
-            bdrv_flags |= BDRV_O_COPY_ON_READ;
-        }
-
-        if (runstate_check(RUN_STATE_INMIGRATE)) {
-            bdrv_flags |= BDRV_O_INCOMING;
-        }
-
-        bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
-
         blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags,
                            errp);
         if (!blk) {
             goto err_no_bs_opts;
         }
         bs = blk_bs(blk);
-    }
 
-    bs->detect_zeroes = detect_zeroes;
+        bs->detect_zeroes = detect_zeroes;
 
-    blk_set_on_error(blk, on_read_error, on_write_error);
+        /* disk I/O throttling */
+        if (throttle_enabled(&cfg)) {
+            bdrv_io_limits_enable(bs);
+            bdrv_set_io_limits(bs, &cfg);
+        }
 
-    /* disk I/O throttling */
-    if (throttle_enabled(&cfg)) {
-        bdrv_io_limits_enable(bs);
-        bdrv_set_io_limits(bs, &cfg);
+        if (bdrv_key_required(bs)) {
+            autostart = 0;
+        }
     }
 
-    if (bdrv_key_required(bs)) {
-        autostart = 0;
-    }
+    blk_set_on_error(blk, on_read_error, on_write_error);
 
 err_no_bs_opts:
     qemu_opts_del(opts);
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 42bae32..47b0b68 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -154,17 +154,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
     },
     "event": "SHUTDOWN"
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "ide1-cd0",
-        "tray-open": true
-    }
-}
 
 
 === -drive/device_add and device_del ===
@@ -324,17 +313,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
     },
     "event": "SHUTDOWN"
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "ide1-cd0",
-        "tray-open": true
-    }
-}
 
 
 === drive_add/device_add and device_del ===
@@ -497,17 +475,6 @@ Testing:
     },
     "event": "SHUTDOWN"
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "ide1-cd0",
-        "tray-open": true
-    }
-}
 
 
 === blockdev_add/device_add and device_del ===
@@ -716,16 +683,5 @@ Testing:
     },
     "event": "SHUTDOWN"
 }
-{
-    "timestamp": {
-        "seconds":  TIMESTAMP,
-        "microseconds":  TIMESTAMP
-    },
-    "event": "DEVICE_TRAY_MOVED",
-    "data": {
-        "device": "ide1-cd0",
-        "tray-open": true
-    }
-}
 
 *** done
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index 904ce15..2b40ead 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -51,7 +51,6 @@ read failed: Input/output error
 {"return": ""}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 QEMU_PROG: Failed to flush the L2 table cache: Input/output error
 QEMU_PROG: Failed to flush the refcount block cache: Input/output error
 
@@ -93,7 +92,6 @@ read failed: Input/output error
 {"return": ""}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 QEMU_PROG: Failed to flush the L2 table cache: Input/output error
 QEMU_PROG: Failed to flush the refcount block cache: Input/output error
 
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index b1e4909..7063231 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -37,7 +37,6 @@ read 10485760/10485760 bytes at offset 0
 {"return": ""}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 
 
 == using quorum rewrite corrupted mode ==
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index 033cc3b..0efe971 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -14,7 +14,6 @@ QMP_VERSION
 {"error": {"class": "GenericError", "desc": "node-name=disk3 is conflicting with a device id"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 
 
 === aio=native without O_DIRECT ===
@@ -25,7 +24,6 @@ QMP_VERSION
 {"error": {"class": "GenericError", "desc": "aio=native requires cache.direct=true"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 
 
 === Encrypted image ===
@@ -37,7 +35,6 @@ QMP_VERSION
 {"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 
 Testing:
 QMP_VERSION
@@ -45,7 +42,6 @@ QMP_VERSION
 {"error": {"class": "GenericError", "desc": "Guest must be stopped for opening of encrypted image"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 
 
 === Missing driver ===
@@ -57,6 +53,5 @@ QMP_VERSION
 {"error": {"class": "GenericError", "desc": "Invalid parameter type for 'driver', expected: string"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
 
 *** done
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 35/50] blockdev: Pull out blockdev option extraction
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (33 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 34/50] blockdev: Do not create BDS for empty drive Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 19:23   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 36/50] blockdev: Allow more options for BB-less BDS tree Max Reitz
                   ` (14 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Extract some of the blockdev option extraction code from blockdev_init()
into an own function. This simplifies blockdev_init() and will allow
reusing the code in a different function added in a follow-up patch.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 201 +++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 108 insertions(+), 93 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index d99edbb..d573c5c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -341,24 +341,123 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
 
 typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
 
+static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
+    ThrottleConfig *throttle_cfg, BlockdevDetectZeroesOptions *detect_zeroes,
+    Error **errp)
+{
+    const char *discard, *aio;
+    Error *local_error = NULL;
+
+    if (!qemu_opt_get_bool(opts, "read-only", false)) {
+        *bdrv_flags |= BDRV_O_RDWR;
+    }
+    if (qemu_opt_get_bool(opts, "copy-on-read", false)) {
+        *bdrv_flags |= BDRV_O_COPY_ON_READ;
+    }
+
+    if ((discard = qemu_opt_get(opts, "discard")) != NULL) {
+        if (bdrv_parse_discard_flags(discard, bdrv_flags) != 0) {
+            error_setg(errp, "Invalid discard option");
+            return;
+        }
+    }
+
+    if (qemu_opt_get_bool(opts, "cache.writeback", true)) {
+        *bdrv_flags |= BDRV_O_CACHE_WB;
+    }
+    if (qemu_opt_get_bool(opts, "cache.direct", false)) {
+        *bdrv_flags |= BDRV_O_NOCACHE;
+    }
+    if (qemu_opt_get_bool(opts, "cache.no-flush", false)) {
+        *bdrv_flags |= BDRV_O_NO_FLUSH;
+    }
+
+#ifdef CONFIG_LINUX_AIO
+    if ((aio = qemu_opt_get(opts, "aio")) != NULL) {
+        if (!strcmp(aio, "native")) {
+            *bdrv_flags |= BDRV_O_NATIVE_AIO;
+        } else if (!strcmp(aio, "threads")) {
+            /* this is the default */
+        } else {
+           error_setg(errp, "invalid aio option");
+           return;
+        }
+    }
+#endif
+
+    /* disk I/O throttling */
+    memset(throttle_cfg, 0, sizeof(*throttle_cfg));
+    throttle_cfg->buckets[THROTTLE_BPS_TOTAL].avg =
+        qemu_opt_get_number(opts, "throttling.bps-total", 0);
+    throttle_cfg->buckets[THROTTLE_BPS_READ].avg  =
+        qemu_opt_get_number(opts, "throttling.bps-read", 0);
+    throttle_cfg->buckets[THROTTLE_BPS_WRITE].avg =
+        qemu_opt_get_number(opts, "throttling.bps-write", 0);
+    throttle_cfg->buckets[THROTTLE_OPS_TOTAL].avg =
+        qemu_opt_get_number(opts, "throttling.iops-total", 0);
+    throttle_cfg->buckets[THROTTLE_OPS_READ].avg =
+        qemu_opt_get_number(opts, "throttling.iops-read", 0);
+    throttle_cfg->buckets[THROTTLE_OPS_WRITE].avg =
+        qemu_opt_get_number(opts, "throttling.iops-write", 0);
+
+    throttle_cfg->buckets[THROTTLE_BPS_TOTAL].max =
+        qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
+    throttle_cfg->buckets[THROTTLE_BPS_READ].max  =
+        qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
+    throttle_cfg->buckets[THROTTLE_BPS_WRITE].max =
+        qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
+    throttle_cfg->buckets[THROTTLE_OPS_TOTAL].max =
+        qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
+    throttle_cfg->buckets[THROTTLE_OPS_READ].max =
+        qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
+    throttle_cfg->buckets[THROTTLE_OPS_WRITE].max =
+        qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
+
+    throttle_cfg->op_size =
+        qemu_opt_get_number(opts, "throttling.iops-size", 0);
+
+    if (!check_throttle_config(throttle_cfg, errp)) {
+        return;
+    }
+
+    *detect_zeroes =
+        qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
+                        qemu_opt_get(opts, "detect-zeroes"),
+                        BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
+                        BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
+                        &local_error);
+    if (local_error) {
+        error_propagate(errp, local_error);
+        return;
+    }
+
+    if (*detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
+        !(*bdrv_flags & BDRV_O_UNMAP))
+    {
+        error_setg(errp, "setting detect-zeroes to unmap is not allowed "
+                         "without setting discard operation to unmap");
+        return;
+    }
+
+}
+
 /* Takes the ownership of bs_opts */
 static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
                                    Error **errp)
 {
     const char *buf;
-    int ro = 0;
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
     BlockBackend *blk;
     BlockDriverState *bs;
     ThrottleConfig cfg;
     int snapshot = 0;
-    bool copy_on_read;
     Error *error = NULL;
     QemuOpts *opts;
     const char *id;
     bool has_driver_specific_opts;
-    BlockdevDetectZeroesOptions detect_zeroes;
+    BlockdevDetectZeroesOptions detect_zeroes =
+        BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
 
     /* Check common options by copying from bs_opts to opts, all other options
      * stay in bs_opts for processing by bdrv_open(). */
@@ -383,38 +482,13 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
 
     /* extract parameters */
     snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
-    ro = qemu_opt_get_bool(opts, "read-only", 0);
-    copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
-
-    if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
-        if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
-            error_setg(errp, "invalid discard option");
-            goto early_err;
-        }
-    }
 
-    if (qemu_opt_get_bool(opts, "cache.writeback", true)) {
-        bdrv_flags |= BDRV_O_CACHE_WB;
-    }
-    if (qemu_opt_get_bool(opts, "cache.direct", false)) {
-        bdrv_flags |= BDRV_O_NOCACHE;
-    }
-    if (qemu_opt_get_bool(opts, "cache.no-flush", false)) {
-        bdrv_flags |= BDRV_O_NO_FLUSH;
-    }
-
-#ifdef CONFIG_LINUX_AIO
-    if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
-        if (!strcmp(buf, "native")) {
-            bdrv_flags |= BDRV_O_NATIVE_AIO;
-        } else if (!strcmp(buf, "threads")) {
-            /* this is the default */
-        } else {
-           error_setg(errp, "invalid aio option");
-           goto early_err;
-        }
+    extract_common_blockdev_options(opts, &bdrv_flags, &cfg, &detect_zeroes,
+                                    &error);
+    if (error) {
+        error_propagate(errp, error);
+        goto early_err;
     }
-#endif
 
     if ((buf = qemu_opt_get(opts, "format")) != NULL) {
         if (is_help_option(buf)) {
@@ -431,41 +505,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         qdict_put_obj(bs_opts, "driver", QOBJECT(qstring_from_str(buf)));
     }
 
-    /* disk I/O throttling */
-    memset(&cfg, 0, sizeof(cfg));
-    cfg.buckets[THROTTLE_BPS_TOTAL].avg =
-        qemu_opt_get_number(opts, "throttling.bps-total", 0);
-    cfg.buckets[THROTTLE_BPS_READ].avg  =
-        qemu_opt_get_number(opts, "throttling.bps-read", 0);
-    cfg.buckets[THROTTLE_BPS_WRITE].avg =
-        qemu_opt_get_number(opts, "throttling.bps-write", 0);
-    cfg.buckets[THROTTLE_OPS_TOTAL].avg =
-        qemu_opt_get_number(opts, "throttling.iops-total", 0);
-    cfg.buckets[THROTTLE_OPS_READ].avg =
-        qemu_opt_get_number(opts, "throttling.iops-read", 0);
-    cfg.buckets[THROTTLE_OPS_WRITE].avg =
-        qemu_opt_get_number(opts, "throttling.iops-write", 0);
-
-    cfg.buckets[THROTTLE_BPS_TOTAL].max =
-        qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
-    cfg.buckets[THROTTLE_BPS_READ].max  =
-        qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
-    cfg.buckets[THROTTLE_BPS_WRITE].max =
-        qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
-    cfg.buckets[THROTTLE_OPS_TOTAL].max =
-        qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
-    cfg.buckets[THROTTLE_OPS_READ].max =
-        qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
-    cfg.buckets[THROTTLE_OPS_WRITE].max =
-        qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
-
-    cfg.op_size = qemu_opt_get_number(opts, "throttling.iops-size", 0);
-
-    if (!check_throttle_config(&cfg, &error)) {
-        error_propagate(errp, error);
-        goto early_err;
-    }
-
     on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
         on_write_error = parse_block_error_action(buf, 0, &error);
@@ -484,40 +523,16 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         }
     }
 
-    detect_zeroes =
-        qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
-                        qemu_opt_get(opts, "detect-zeroes"),
-                        BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
-                        BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
-                        &error);
-    if (error) {
-        error_propagate(errp, error);
-        goto early_err;
-    }
-
-    if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
-        !(bdrv_flags & BDRV_O_UNMAP)) {
-        error_setg(errp, "setting detect-zeroes to unmap is not allowed "
-                         "without setting discard operation to unmap");
-        goto early_err;
-    }
-
     if (snapshot) {
         /* always use cache=unsafe with snapshot */
         bdrv_flags &= ~BDRV_O_CACHE_MASK;
         bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
     }
 
-    if (copy_on_read) {
-        bdrv_flags |= BDRV_O_COPY_ON_READ;
-    }
-
     if (runstate_check(RUN_STATE_INMIGRATE)) {
         bdrv_flags |= BDRV_O_INCOMING;
     }
 
-    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
-
     /* init */
     if ((!file || !*file) && !has_driver_specific_opts) {
         BlockBackendRootState *blk_rs;
@@ -529,7 +544,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
 
         blk_rs = blk_get_root_state(blk);
         blk_rs->open_flags    = bdrv_flags;
-        blk_rs->read_only     = ro;
+        blk_rs->read_only     = !(bdrv_flags & BDRV_O_RDWR);
         blk_rs->detect_zeroes = detect_zeroes;
 
         if (throttle_enabled(&cfg)) {
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 36/50] blockdev: Allow more options for BB-less BDS tree
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (34 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 35/50] blockdev: Pull out blockdev option extraction Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 19:26   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 37/50] block: Add blk_remove_bs() Max Reitz
                   ` (13 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Most of the options which blockdev_init() parses for both the
BlockBackend and the root BDS are valid for just the root BDS as well
(e.g. read-only). This patch allows specifying these options even if not
creating a BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 150 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index d573c5c..2f3ccb5 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -591,6 +591,61 @@ err_no_opts:
     return NULL;
 }
 
+static QemuOptsList qemu_root_bds_opts;
+
+/* Takes the ownership of bs_opts */
+static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp)
+{
+    BlockDriverState *bs;
+    QemuOpts *opts;
+    Error *local_error = NULL;
+    ThrottleConfig cfg;
+    BlockdevDetectZeroesOptions detect_zeroes;
+    int ret;
+    int bdrv_flags = 0;
+
+    opts = qemu_opts_create(&qemu_root_bds_opts, NULL, 1, errp);
+    if (!opts) {
+        goto fail;
+    }
+
+    qemu_opts_absorb_qdict(opts, bs_opts, &local_error);
+    if (local_error) {
+        error_propagate(errp, local_error);
+        goto fail;
+    }
+
+    extract_common_blockdev_options(opts, &bdrv_flags, &cfg, &detect_zeroes,
+                                    &local_error);
+    if (local_error) {
+        error_propagate(errp, local_error);
+        goto fail;
+    }
+
+    bs = NULL;
+    ret = bdrv_open(&bs, NULL, NULL, bs_opts, bdrv_flags, NULL, errp);
+    if (ret < 0) {
+        goto fail_no_bs_opts;
+    }
+
+    bs->detect_zeroes = detect_zeroes;
+
+    /* disk I/O throttling */
+    if (throttle_enabled(&cfg)) {
+        bdrv_io_limits_enable(bs);
+        bdrv_set_io_limits(bs, &cfg);
+    }
+
+fail_no_bs_opts:
+    qemu_opts_del(opts);
+    return bs;
+
+fail:
+    qemu_opts_del(opts);
+    QDECREF(bs_opts);
+    return NULL;
+}
+
 static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to,
                             Error **errp)
 {
@@ -2994,12 +3049,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
         bs = blk_bs(blk);
     } else {
-        int ret;
-
-        bs = NULL;
-        ret = bdrv_open(&bs, NULL, NULL, qdict, BDRV_O_RDWR | BDRV_O_CACHE_WB,
-                        NULL, errp);
-        if (ret < 0) {
+        bs = bds_tree_init(qdict, errp);
+        if (!bs) {
             goto fail;
         }
     }
@@ -3150,6 +3201,99 @@ QemuOptsList qemu_common_drive_opts = {
     },
 };
 
+static QemuOptsList qemu_root_bds_opts = {
+    .name = "root-bds",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
+    .desc = {
+        {
+            .name = "discard",
+            .type = QEMU_OPT_STRING,
+            .help = "discard operation (ignore/off, unmap/on)",
+        },{
+            .name = "cache.writeback",
+            .type = QEMU_OPT_BOOL,
+            .help = "enables writeback mode for any caches",
+        },{
+            .name = "cache.direct",
+            .type = QEMU_OPT_BOOL,
+            .help = "enables use of O_DIRECT (bypass the host page cache)",
+        },{
+            .name = "cache.no-flush",
+            .type = QEMU_OPT_BOOL,
+            .help = "ignore any flush requests for the device",
+        },{
+            .name = "aio",
+            .type = QEMU_OPT_STRING,
+            .help = "host AIO implementation (threads, native)",
+        },{
+            .name = "read-only",
+            .type = QEMU_OPT_BOOL,
+            .help = "open drive file as read-only",
+        },{
+            .name = "throttling.iops-total",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total I/O operations per second",
+        },{
+            .name = "throttling.iops-read",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read operations per second",
+        },{
+            .name = "throttling.iops-write",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write operations per second",
+        },{
+            .name = "throttling.bps-total",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total bytes per second",
+        },{
+            .name = "throttling.bps-read",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read bytes per second",
+        },{
+            .name = "throttling.bps-write",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write bytes per second",
+        },{
+            .name = "throttling.iops-total-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "I/O operations burst",
+        },{
+            .name = "throttling.iops-read-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "I/O operations read burst",
+        },{
+            .name = "throttling.iops-write-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "I/O operations write burst",
+        },{
+            .name = "throttling.bps-total-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "total bytes burst",
+        },{
+            .name = "throttling.bps-read-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "total bytes read burst",
+        },{
+            .name = "throttling.bps-write-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "total bytes write burst",
+        },{
+            .name = "throttling.iops-size",
+            .type = QEMU_OPT_NUMBER,
+            .help = "when limiting by iops max size of an I/O in bytes",
+        },{
+            .name = "copy-on-read",
+            .type = QEMU_OPT_BOOL,
+            .help = "copy read data from backing file into image file",
+        },{
+            .name = "detect-zeroes",
+            .type = QEMU_OPT_STRING,
+            .help = "try to optimize zero writes (off, on, unmap)",
+        },
+        { /* end of list */ }
+    },
+};
+
 QemuOptsList qemu_drive_opts = {
     .name = "drive",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 37/50] block: Add blk_remove_bs()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (35 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 36/50] blockdev: Allow more options for BB-less BDS tree Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 19:49   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray Max Reitz
                   ` (12 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

This function removes the BlockDriverState associated with the given
BlockBackend from that BB and sets the BDS pointer in the BB to NULL.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c          | 22 +++++++++++++++++++++-
 include/sysemu/block-backend.h |  1 +
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 656ebfc..d2c1bff 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -312,6 +312,22 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
 }
 
 /*
+ * Disassociates the currently associated BlockDriverState from @blk.
+ */
+void blk_remove_bs(BlockBackend *blk)
+{
+    if (!blk->bs) {
+        return;
+    }
+
+    blk_update_root_state(blk);
+
+    bdrv_unref(blk->bs);
+    blk->bs->blk = NULL;
+    blk->bs = NULL;
+}
+
+/*
  * Associates a new BlockDriverState with @blk.
  */
 void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
@@ -321,9 +337,13 @@ void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
     }
 
     assert(!blk->bs);
-    assert(!bs->blk);
     bdrv_ref(bs);
     blk->bs = bs;
+
+    if (bs->blk) {
+        blk_remove_bs(bs->blk);
+    }
+
     bs->blk = blk;
 }
 
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index b6cf5bf..c8b47f7 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -72,6 +72,7 @@ BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 
 BlockDriverState *blk_bs(BlockBackend *blk);
+void blk_remove_bs(BlockBackend *blk);
 void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs);
 
 void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (36 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 37/50] block: Add blk_remove_bs() Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 19:56   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray Max Reitz
                   ` (11 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 qapi/block-core.json | 21 +++++++++++++++++++++
 qmp-commands.hx      | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 106 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index 2f3ccb5..a0b9f17 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1993,6 +1993,54 @@ out:
     aio_context_release(aio_context);
 }
 
+void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
+                            Error **errp)
+{
+    BlockBackend *blk;
+    BlockDriverState *bs;
+    AioContext *aio_context = NULL;
+
+    if (!has_force) {
+        force = false;
+    }
+
+    blk = blk_by_name(device);
+    if (!blk) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    if (!blk_dev_has_removable_media(blk)) {
+        error_setg(errp, "Device '%s' is not removable", device);
+        return;
+    }
+
+    if (blk_dev_is_tray_open(blk)) {
+        return;
+    }
+
+    bs = blk_bs(blk);
+    if (bs) {
+        aio_context = bdrv_get_aio_context(bs);
+        aio_context_acquire(aio_context);
+
+        if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
+            goto out;
+        }
+    }
+
+    if (blk_dev_is_medium_locked(blk)) {
+        blk_dev_eject_request(blk, force);
+    } else {
+        blk_dev_change_media_cb(blk, false);
+    }
+
+out:
+    if (aio_context) {
+        aio_context_release(aio_context);
+    }
+}
+
 /* throttling disk I/O limits */
 void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                                int64_t bps_wr,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index ca9bc32..029f08b 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1718,6 +1718,27 @@
 ##
 { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
 
+##
+# @blockdev-open-tray:
+#
+# Opens a block device's tray. If there is a block driver state tree inserted as
+# a medium, it will become inaccessible to the guest (but it will remain
+# associated to the block device, so closing the tray will make it accessible
+# again).
+#
+# @device: block device name
+#
+# @force:  #optional if false (the default), an eject request will be sent to
+#          the guest if it has locked the tray (and the tray will not be opened
+#          immediately); if true, the tray will be opened regardless of whether
+#          it is locked
+#
+# Since: 2.3
+##
+{ 'command': 'blockdev-open-tray',
+  'data': { 'device': 'str',
+            '*force': 'bool' } }
+
 
 ##
 # @BlockErrorAction
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7576c18..cfa1b98 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3641,6 +3641,43 @@ Example (2):
 EQMP
 
     {
+        .name       = "blockdev-open-tray",
+        .args_type  = "device:s,force:b?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_open_tray,
+    },
+
+SQMP
+blockdev-open-tray
+------------------
+
+Opens a block device's tray. If there is a block driver state tree inserted as a
+medium, it will become inaccessible to the guest (but it will remain associated
+to the block device, so closing the tray will make it accessible again).
+
+Arguments:
+
+- "device": block device name (json-string)
+- "force": if false (the default), an eject request will be sent to the guest if
+           it has locked the tray (and the tray will not be opened immediately);
+           if true, the tray will be opened regardless of whether it is locked
+           (json-bool, optional)
+
+Example (1):
+
+-> { "execute": "blockdev-open-tray",
+     "arguments": { "device": "ide1-cd0" } }
+
+<- { "timestamp": { "seconds": 1418751016,
+                    "microseconds": 716996 },
+     "event": "DEVICE_TRAY_MOVED",
+     "data": { "device": "ide1-cd0",
+               "tray-open": true } }
+
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "query-named-block-nodes",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes,
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (37 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 19:58   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 40/50] blockdev: Add blockdev-remove-medium Max Reitz
                   ` (10 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 22 ++++++++++++++++++++++
 qapi/block-core.json | 14 ++++++++++++++
 qmp-commands.hx      | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index a0b9f17..d6a3fdf 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2041,6 +2041,28 @@ out:
     }
 }
 
+void qmp_blockdev_close_tray(const char *device, Error **errp)
+{
+    BlockBackend *blk;
+
+    blk = blk_by_name(device);
+    if (!blk) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    if (!blk_dev_has_removable_media(blk)) {
+        error_setg(errp, "Device '%s' is not removable", device);
+        return;
+    }
+
+    if (!blk_dev_is_tray_open(blk)) {
+        return;
+    }
+
+    blk_dev_change_media_cb(blk, true);
+}
+
 /* throttling disk I/O limits */
 void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                                int64_t bps_wr,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 029f08b..802734a 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1739,6 +1739,20 @@
   'data': { 'device': 'str',
             '*force': 'bool' } }
 
+##
+# @blockdev-close-tray:
+#
+# Closes a block device's tray. If there is a block driver state tree associated
+# with the block device (which is currently ejected), that tree will be loaded
+# as the medium.
+#
+# @device: block device name
+#
+# Since: 2.3
+##
+{ 'command': 'blockdev-close-tray',
+  'data': { 'device': 'str' } }
+
 
 ##
 # @BlockErrorAction
diff --git a/qmp-commands.hx b/qmp-commands.hx
index cfa1b98..5927507 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3678,6 +3678,39 @@ Example (1):
 EQMP
 
     {
+        .name       = "blockdev-close-tray",
+        .args_type  = "device:s",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_close_tray,
+    },
+
+SQMP
+blockdev-close-tray
+-------------------
+
+Closes a block device's tray. If there is a block driver state tree associated
+with the block device (which is currently ejected), that tree will be loaded as
+the medium.
+
+Arguments:
+
+- "device": block device name (json-string)
+
+Example (1):
+
+-> { "execute": "blockdev-close-tray",
+     "arguments": { "device": "ide1-cd0" } }
+
+<- { "timestamp": { "seconds": 1418751345,
+                    "microseconds": 272147 },
+     "event": "DEVICE_TRAY_MOVED",
+     "data": { "device": "ide1-cd0",
+               "tray-open": false } }
+
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "query-named-block-nodes",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes,
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 40/50] blockdev: Add blockdev-remove-medium
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (38 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 20:11   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium Max Reitz
                   ` (9 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 25 +++++++++++++++++++++++++
 qapi/block-core.json | 13 +++++++++++++
 qmp-commands.hx      | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index d6a3fdf..17785b8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2063,6 +2063,31 @@ void qmp_blockdev_close_tray(const char *device, Error **errp)
     blk_dev_change_media_cb(blk, true);
 }
 
+void qmp_blockdev_remove_medium(const char *device, Error **errp)
+{
+    BlockBackend *blk;
+
+    blk = blk_by_name(device);
+    if (!blk) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    if (!blk_dev_has_removable_media(blk)) {
+        error_setg(errp, "Device '%s' is not removable", device);
+        return;
+    }
+
+    if (!blk_dev_is_tray_open(blk)) {
+        error_setg(errp, "Tray of device '%s' is not open", device);
+        return;
+    }
+
+    if (blk_bs(blk)) {
+        blk_remove_bs(blk);
+    }
+}
+
 /* throttling disk I/O limits */
 void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                                int64_t bps_wr,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 802734a..1ace69d 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1753,6 +1753,19 @@
 { 'command': 'blockdev-close-tray',
   'data': { 'device': 'str' } }
 
+##
+# @blockdev-remove-medium:
+#
+# Removes a medium (a block driver state tree) from a block device. That block
+# device's tray must currently be open.
+#
+# @device: block device name
+#
+# Since: 2.3
+##
+{ 'command': 'blockdev-remove-medium',
+  'data': { 'device': 'str' } }
+
 
 ##
 # @BlockErrorAction
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5927507..3d5c10c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3711,6 +3711,49 @@ Example (1):
 EQMP
 
     {
+        .name       = "blockdev-remove-medium",
+        .args_type  = "device:s",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_remove_medium,
+    },
+
+SQMP
+blockdev-remove-medium
+----------------------
+
+Removes a medium (a block driver state tree) from a block device. That block
+device's tray must currently be open.
+
+Arguments:
+
+- "device": block device name (json-string)
+
+Example (1):
+
+-> { "execute": "blockdev-remove-medium",
+     "arguments": { "device": "ide1-cd0" } }
+
+<- { "error": { "class": "GenericError",
+                "desc": "Tray of device 'ide1-cd0' is not open" } }
+
+-> { "execute": "blockdev-open-tray",
+     "arguments": { "device": "ide1-cd0" } }
+
+<- { "timestamp": { "seconds": 1418751627,
+                    "microseconds": 549958 },
+     "event": "DEVICE_TRAY_MOVED",
+     "data": { "device": "ide1-cd0",
+               "tray-open": true } }
+
+<- { "return": {} }
+
+-> { "execute": "blockdev-remove-medium",
+     "arguments": { "device": "ide1-cd0" } }
+
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "query-named-block-nodes",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes,
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (39 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 40/50] blockdev: Add blockdev-remove-medium Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 20:18   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 42/50] blockdev: Implement eject with basic operations Max Reitz
                   ` (8 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

And a helper function for that which directly takes a pointer to the BDS
to be inserted instead of its node-name (which will be used for
implementing 'change' using blockdev-insert-medium).

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 43 +++++++++++++++++++++++++++++++++++++++++++
 qapi/block-core.json | 17 +++++++++++++++++
 qmp-commands.hx      | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 98 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index 17785b8..e4588b3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2088,6 +2088,49 @@ void qmp_blockdev_remove_medium(const char *device, Error **errp)
     }
 }
 
+static void qmp_blockdev_insert_anon_medium(const char *device,
+                                            BlockDriverState *bs, Error **errp)
+{
+    BlockBackend *blk;
+
+    blk = blk_by_name(device);
+    if (!blk) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    if (!blk_dev_has_removable_media(blk)) {
+        error_setg(errp, "Device '%s' is not removable", device);
+        return;
+    }
+
+    if (!blk_dev_is_tray_open(blk)) {
+        error_setg(errp, "Tray of device '%s' is not open", device);
+        return;
+    }
+
+    if (blk_bs(blk)) {
+        error_setg(errp, "There already is a medium in device '%s'", device);
+        return;
+    }
+
+    blk_insert_bs(blk, bs);
+}
+
+void qmp_blockdev_insert_medium(const char *device, const char *node_name,
+                                Error **errp)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find_node(node_name);
+    if (!bs) {
+        error_setg(errp, "Node '%s' not found", node_name);
+        return;
+    }
+
+    qmp_blockdev_insert_anon_medium(device, bs, errp);
+}
+
 /* throttling disk I/O limits */
 void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                                int64_t bps_wr,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 1ace69d..ba41015 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1766,6 +1766,23 @@
 { 'command': 'blockdev-remove-medium',
   'data': { 'device': 'str' } }
 
+##
+# @blockdev-insert-medium:
+#
+# Inserts a medium (a block driver state tree) into a block device. That block
+# device's tray must currently be open and there must be no medium inserted
+# already.
+#
+# @device:    block device name
+#
+# @node-name: name of a node in the block driver state graph
+#
+# Since: 2.3
+##
+{ 'command': 'blockdev-insert-medium',
+  'data': { 'device': 'str',
+            'node-name': 'str'} }
+
 
 ##
 # @BlockErrorAction
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3d5c10c..604d638 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3754,6 +3754,44 @@ Example (1):
 EQMP
 
     {
+        .name       = "blockdev-insert-medium",
+        .args_type  = "device:s,node-name:s",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_insert_medium,
+    },
+
+SQMP
+blockdev-insert-medium
+----------------------
+
+Inserts a medium (a block driver state tree) into a block device. That block
+device's tray must currently be open and there must be no medium inserted
+already.
+
+Arguments:
+
+- "device": block device name (json-string)
+- "node-name": root node of the BDS tree to insert into the block device
+
+Example (1):
+
+-> { "execute": "blockdev-add",
+     "arguments": { "options": { "id": "backend0",
+                                 "node-name": "node0",
+                                 "driver": "raw",
+                                 "file": { "driver": "file",
+                                           "filename": "fedora.iso" } } } }
+
+<- { "return": {} }
+
+-> { "execute": "blockdev-insert-medium",
+     "arguments": { "device": "ide1-cd0",
+                    "node-name": "node0" } }
+
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "query-named-block-nodes",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes,
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 42/50] blockdev: Implement eject with basic operations
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (40 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 20:26   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 43/50] blockdev: Implement change " Max Reitz
                   ` (7 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Implement 'eject' by calling blockdev-open-tray and
blockdev-remove-medium.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index e4588b3..0b204eb 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1865,15 +1865,15 @@ out:
 
 void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
 {
-    BlockBackend *blk;
+    Error *local_err = NULL;
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+    qmp_blockdev_open_tray(device, has_force, force, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
         return;
     }
 
-    eject_device(blk, force, errp);
+    qmp_blockdev_remove_medium(device, errp);
 }
 
 void qmp_block_passwd(bool has_device, const char *device,
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 43/50] blockdev: Implement change with basic operations
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (41 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 42/50] blockdev: Implement eject with basic operations Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 20:30   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 44/50] block: Inquire tray state before tray-moved events Max Reitz
                   ` (6 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Implement 'change' on block devices by calling blockdev-open-tray,
blockdev-remove-medium, blockdev-insert-medium (a variation of that
which does not need a node-name) and blockdev-close-tray.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c | 191 +++++++++++++++++++++++--------------------------------------
 1 file changed, 72 insertions(+), 119 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 0b204eb..6e440b8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1828,41 +1828,6 @@ exit:
     }
 }
 
-
-static void eject_device(BlockBackend *blk, int force, Error **errp)
-{
-    BlockDriverState *bs = blk_bs(blk);
-    AioContext *aio_context;
-
-    aio_context = blk_get_aio_context(blk);
-    aio_context_acquire(aio_context);
-
-    if (bs && bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
-        goto out;
-    }
-    if (!blk_dev_has_removable_media(blk)) {
-        error_setg(errp, "Device '%s' is not removable",
-                   bdrv_get_device_name(bs));
-        goto out;
-    }
-
-    if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) {
-        blk_dev_eject_request(blk, force);
-        if (!force) {
-            error_setg(errp, "Device '%s' is locked",
-                       bdrv_get_device_name(bs));
-            goto out;
-        }
-    }
-
-    if (bs) {
-        bdrv_close(bs);
-    }
-
-out:
-    aio_context_release(aio_context);
-}
-
 void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
 {
     Error *local_err = NULL;
@@ -1909,90 +1874,6 @@ out:
     aio_context_release(aio_context);
 }
 
-/* Assumes AioContext is held */
-static void qmp_bdrv_open_encrypted(BlockDriverState **pbs,
-                                    const char *filename,
-                                    int bdrv_flags, BlockDriver *drv,
-                                    const char *password, Error **errp)
-{
-    BlockDriverState *bs;
-    Error *local_err = NULL;
-    int ret;
-
-    ret = bdrv_open(pbs, filename, NULL, NULL, bdrv_flags, drv, &local_err);
-    if (ret < 0) {
-        error_propagate(errp, local_err);
-        return;
-    }
-    bs = *pbs;
-
-    if (bdrv_key_required(bs)) {
-        if (password) {
-            if (bdrv_set_key(bs, password) < 0) {
-                error_set(errp, QERR_INVALID_PASSWORD);
-            }
-        } else {
-            error_set(errp, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs),
-                      bdrv_get_encrypted_filename(bs));
-        }
-    } else if (password) {
-        error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
-    }
-}
-
-void qmp_change_blockdev(const char *device, const char *filename,
-                         const char *format, Error **errp)
-{
-    BlockBackend *blk;
-    BlockDriverState *bs;
-    AioContext *aio_context;
-    BlockDriver *drv = NULL;
-    int bdrv_flags;
-    bool new_bs;
-    Error *err = NULL;
-
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
-        return;
-    }
-    bs = blk_bs(blk);
-    new_bs = !bs;
-
-    aio_context = blk_get_aio_context(blk);
-    aio_context_acquire(aio_context);
-
-    if (format) {
-        drv = bdrv_find_whitelisted_format(format, blk_is_read_only(blk));
-        if (!drv) {
-            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
-            goto out;
-        }
-    }
-
-    eject_device(blk, 0, &err);
-    if (err) {
-        error_propagate(errp, err);
-        goto out;
-    }
-
-    bdrv_flags = blk_is_read_only(blk) ? 0 : BDRV_O_RDWR;
-    bdrv_flags |= blk_get_root_state(blk)->open_flags & ~BDRV_O_RDWR;
-
-    qmp_bdrv_open_encrypted(&bs, filename, bdrv_flags, drv, NULL, &err);
-    if (err) {
-        error_propagate(errp, err);
-    } else if (new_bs) {
-        blk_insert_bs(blk, bs);
-        /* Has been sent automatically by bdrv_open() if blk_bs(blk) was not
-         * NULL */
-        blk_dev_change_media_cb(blk, true);
-    }
-
-out:
-    aio_context_release(aio_context);
-}
-
 void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
                             Error **errp)
 {
@@ -2131,6 +2012,78 @@ void qmp_blockdev_insert_medium(const char *device, const char *node_name,
     qmp_blockdev_insert_anon_medium(device, bs, errp);
 }
 
+void qmp_change_blockdev(const char *device, const char *filename,
+                         const char *format, Error **errp)
+{
+    BlockBackend *blk;
+    BlockBackendRootState *blk_rs;
+    BlockDriverState *medium_bs;
+    BlockDriver *drv = NULL;
+    int bdrv_flags, ret;
+    Error *err = NULL;
+
+    blk = blk_by_name(device);
+    if (!blk) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    if (blk_bs(blk)) {
+        blk_update_root_state(blk);
+    }
+
+    blk_rs = blk_get_root_state(blk);
+    bdrv_flags = blk_rs->read_only ? 0 : BDRV_O_RDWR;
+    bdrv_flags |= blk_rs->open_flags & ~BDRV_O_RDWR;
+
+    if (format) {
+        drv = bdrv_find_whitelisted_format(format, bdrv_flags & BDRV_O_RDWR);
+        if (!drv) {
+            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+            return;
+        }
+    }
+
+    medium_bs = NULL;
+    ret = bdrv_open(&medium_bs, filename, NULL, NULL, bdrv_flags, drv, errp);
+    if (ret < 0) {
+        return;
+    }
+
+    medium_bs->detect_zeroes = blk_rs->detect_zeroes;
+    if (blk_rs->io_limits_enabled) {
+        bdrv_io_limits_enable(medium_bs);
+        bdrv_set_io_limits(medium_bs, &blk_rs->throttle_config);
+    }
+
+    if (bdrv_key_required(medium_bs)) {
+        error_set(errp, QERR_DEVICE_ENCRYPTED, device,
+                  bdrv_get_encrypted_filename(medium_bs));
+        bdrv_unref(medium_bs);
+        return;
+    }
+
+    qmp_blockdev_open_tray(device, false, false, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    qmp_blockdev_remove_medium(device, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    qmp_blockdev_insert_anon_medium(device, medium_bs, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    qmp_blockdev_close_tray(device, errp);
+}
+
 /* throttling disk I/O limits */
 void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                                int64_t bps_wr,
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 44/50] block: Inquire tray state before tray-moved events
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (42 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 43/50] blockdev: Implement change " Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 20:37   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium Max Reitz
                   ` (5 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

blk_dev_change_media_cb() is called for all potential tray movements;
however, it is possible to request closing the tray but nothing actually
happening (on a floppy disk drive without a medium).

Thus, the actual tray status should be inquired before sending a
tray-moved event (and an event should be sent whenever the status
changed).

Checking @load is now superfluous; it was necessary because it was
possible to change a medium without having explicitly opened the tray
and closed it again (or it might have been possible, at least). This is
no longer possible, though.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/block-backend.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index d2c1bff..7c18f8d 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -420,18 +420,15 @@ void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
 void blk_dev_change_media_cb(BlockBackend *blk, bool load)
 {
     if (blk->dev_ops && blk->dev_ops->change_media_cb) {
-        bool tray_was_closed = !blk_dev_is_tray_open(blk);
+        bool tray_was_open, tray_is_open;
 
+        tray_was_open = blk_dev_is_tray_open(blk);
         blk->dev_ops->change_media_cb(blk->dev_opaque, load);
-        if (tray_was_closed) {
-            /* tray open */
-            qapi_event_send_device_tray_moved(blk_name(blk),
-                                              true, &error_abort);
-        }
-        if (load) {
-            /* tray close */
-            qapi_event_send_device_tray_moved(blk_name(blk),
-                                              false, &error_abort);
+        tray_is_open = blk_dev_is_tray_open(blk);
+
+        if (tray_was_open != tray_is_open) {
+            qapi_event_send_device_tray_moved(blk_name(blk), tray_is_open,
+                                              &error_abort);
         }
     }
 }
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (43 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 44/50] block: Inquire tray state before tray-moved events Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 21:01   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 46/50] hmp: Use blockdev-change-medium for change command Max Reitz
                   ` (4 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Introduce a new QMP command 'blockdev-change-medium' which is intended
to replace the 'change' command for block devices. The existing function
qmp_change_blockdev() is accordingly renamed to
qmp_blockdev_change_medium().

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c                |  7 ++++---
 include/sysemu/blockdev.h |  2 --
 qapi-schema.json          |  3 ++-
 qapi/block-core.json      | 23 +++++++++++++++++++++++
 qmp-commands.hx           | 31 +++++++++++++++++++++++++++++++
 qmp.c                     |  2 +-
 6 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 6e440b8..2ada2b1 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2012,8 +2012,9 @@ void qmp_blockdev_insert_medium(const char *device, const char *node_name,
     qmp_blockdev_insert_anon_medium(device, bs, errp);
 }
 
-void qmp_change_blockdev(const char *device, const char *filename,
-                         const char *format, Error **errp)
+void qmp_blockdev_change_medium(const char *device, const char *filename,
+                                bool has_format, const char *format,
+                                Error **errp)
 {
     BlockBackend *blk;
     BlockBackendRootState *blk_rs;
@@ -2036,7 +2037,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
     bdrv_flags = blk_rs->read_only ? 0 : BDRV_O_RDWR;
     bdrv_flags |= blk_rs->open_flags & ~BDRV_O_RDWR;
 
-    if (format) {
+    if (has_format) {
         drv = bdrv_find_whitelisted_format(format, bdrv_flags & BDRV_O_RDWR);
         if (!drv) {
             error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 09d1e30..2a34332 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -65,8 +65,6 @@ DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type);
 
 DriveInfo *add_init_drive(const char *opts);
 
-void qmp_change_blockdev(const char *device, const char *filename,
-                         const char *format, Error **errp);
 void do_commit(Monitor *mon, const QDict *qdict);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index e16f8eb..61867e1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1649,7 +1649,8 @@
 #          device between when these calls are executed is undefined.
 #
 # Notes:  It is strongly recommended that this interface is not used especially
-#         for changing block devices.
+#         for changing block devices.  Please use blockdev-change-medium
+#         instead (for VNC, please use change-vnc-password).
 #
 # Since: 0.14.0
 ##
diff --git a/qapi/block-core.json b/qapi/block-core.json
index ba41015..d3c3ca7 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1785,6 +1785,29 @@
 
 
 ##
+# @blockdev-change-medium:
+#
+# Changes the medium inserted into a block device by ejecting the current medium
+# and loading a new image file which is inserted as the new medium (this command
+# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
+# and blockdev-close-tray).
+#
+# @device:      block device name
+#
+# @filename:    filename of the new image to be loaded
+#
+# @format:      #optional, format to open the new image with (defaults to the
+#               probed format)
+#
+# Since: 2.3
+##
+{ 'command': 'blockdev-change-medium',
+  'data': { 'device': 'str',
+            'filename': 'str',
+            '*format': 'str' } }
+
+
+##
 # @BlockErrorAction
 #
 # An enumeration of action that has been taken when a DISK I/O occurs
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 604d638..1987a09 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3854,6 +3854,37 @@ Example:
 EQMP
 
     {
+        .name       = "blockdev-change-medium",
+        .args_type  = "device:B,filename:F,format:s?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_change_medium,
+    },
+
+SQMP
+blockdev-change-medium
+----------------------
+
+Changes the medium inserted into a block device by ejecting the current medium
+and loading a new image file which is inserted as the new medium.
+
+Arguments:
+
+- "device": device name (json-string)
+- "filename": filename of the new image (json-string)
+- "format": format of the new image (json-string, optional)
+
+Examples:
+
+1. Change a removable medium
+
+-> { "execute": "blockdev-change-medium",
+             "arguments": { "device": "ide1-cd0",
+                            "filename": "/srv/images/Fedora-12-x86_64-DVD.iso",
+                            "format": "raw" } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "query-memdev",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_memdev,
diff --git a/qmp.c b/qmp.c
index 635d001..1cfdb74 100644
--- a/qmp.c
+++ b/qmp.c
@@ -417,7 +417,7 @@ void qmp_change(const char *device, const char *target,
     if (strcmp(device, "vnc") == 0) {
         qmp_change_vnc(target, has_arg, arg, errp);
     } else {
-        qmp_change_blockdev(device, target, arg, errp);
+        qmp_blockdev_change_medium(device, target, has_arg, arg, errp);
     }
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 46/50] hmp: Use blockdev-change-medium for change command
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (44 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 21:02   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium Max Reitz
                   ` (3 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Use separate code paths for the two overloaded functions of the 'change'
HMP command, and invoke the 'blockdev-change-medium' QMP command if used
on a block device (by calling qmp_blockdev_change_medium()).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 hmp.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/hmp.c b/hmp.c
index f806387..300e7d8 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1180,22 +1180,25 @@ void hmp_change(Monitor *mon, const QDict *qdict)
     const char *arg = qdict_get_try_str(qdict, "arg");
     Error *err = NULL;
 
-    if (strcmp(device, "vnc") == 0 &&
-            (strcmp(target, "passwd") == 0 ||
-             strcmp(target, "password") == 0)) {
-        if (!arg) {
-            monitor_read_password(mon, hmp_change_read_arg, NULL);
+    if (strcmp(device, "vnc") == 0) {
+        if (strcmp(target, "passwd") == 0 ||
+            strcmp(target, "password") == 0) {
+            if (!arg) {
+                monitor_read_password(mon, hmp_change_read_arg, NULL);
+                return;
+            }
+        }
+        qmp_change("vnc", target, !!arg, arg, &err);
+    } else {
+        qmp_blockdev_change_medium(device, target, !!arg, arg, &err);
+        if (err &&
+            error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
+            error_free(err);
+            monitor_read_block_device_key(mon, device, NULL, NULL);
             return;
         }
     }
 
-    qmp_change(device, target, !!arg, arg, &err);
-    if (err &&
-        error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
-        error_free(err);
-        monitor_read_block_device_key(mon, device, NULL, NULL);
-        return;
-    }
     hmp_handle_error(mon, &err);
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (45 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 46/50] hmp: Use blockdev-change-medium for change command Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 21:08   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command Max Reitz
                   ` (2 subsequent siblings)
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Add an option to qmp_blockdev_change_medium() which allows changing the
read-only status of the block device whose medium is changed.

Some drives do not have a inherently fixed read-only status; for
instance, floppy disks can be set read-only or writable independently of
the drive. Some users may find it useful to be able to therefore change
the read-only status of a block device when changing the medium.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 blockdev.c           | 25 ++++++++++++++++++++++++-
 hmp.c                |  2 +-
 qapi/block-core.json | 24 +++++++++++++++++++++++-
 qmp-commands.hx      | 24 +++++++++++++++++++++++-
 qmp.c                |  3 ++-
 5 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 2ada2b1..8ed2fec 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2014,6 +2014,8 @@ void qmp_blockdev_insert_medium(const char *device, const char *node_name,
 
 void qmp_blockdev_change_medium(const char *device, const char *filename,
                                 bool has_format, const char *format,
+                                bool has_read_only,
+                                BlockdevChangeReadOnlyMode read_only,
                                 Error **errp)
 {
     BlockBackend *blk;
@@ -2034,7 +2036,28 @@ void qmp_blockdev_change_medium(const char *device, const char *filename,
     }
 
     blk_rs = blk_get_root_state(blk);
-    bdrv_flags = blk_rs->read_only ? 0 : BDRV_O_RDWR;
+
+    if (!has_read_only) {
+        read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
+    }
+
+    switch (read_only) {
+    case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN:
+        bdrv_flags = blk_rs->read_only ? 0 : BDRV_O_RDWR;
+        break;
+
+    case BLOCKDEV_CHANGE_READ_ONLY_MODE_RO:
+        bdrv_flags = 0;
+        break;
+
+    case BLOCKDEV_CHANGE_READ_ONLY_MODE_RW:
+        bdrv_flags = BDRV_O_RDWR;
+        break;
+
+    default:
+        abort();
+    }
+
     bdrv_flags |= blk_rs->open_flags & ~BDRV_O_RDWR;
 
     if (has_format) {
diff --git a/hmp.c b/hmp.c
index 300e7d8..dbf0947 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1190,7 +1190,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
         }
         qmp_change("vnc", target, !!arg, arg, &err);
     } else {
-        qmp_blockdev_change_medium(device, target, !!arg, arg, &err);
+        qmp_blockdev_change_medium(device, target, !!arg, arg, false, 0, &err);
         if (err &&
             error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
             error_free(err);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index d3c3ca7..eb2724e 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1785,6 +1785,24 @@
 
 
 ##
+# @BlockdevChangeReadOnlyMode:
+#
+# Specifies the new read-only mode of a block device subject to the
+# @blockdev-change-medium command.
+#
+# @retain:  Retains the current read-only mode
+#
+# @ro:      Makes the device read-only
+#
+# @rw:      Makes the device writable
+#
+# Since: 2.3
+##
+{ 'enum': 'BlockdevChangeReadOnlyMode',
+  'data': ['retain', 'ro', 'rw'] }
+
+
+##
 # @blockdev-change-medium:
 #
 # Changes the medium inserted into a block device by ejecting the current medium
@@ -1799,12 +1817,16 @@
 # @format:      #optional, format to open the new image with (defaults to the
 #               probed format)
 #
+# @read-only:   #optional, change the read-only mode of the device; defaults to
+#               'retain'
+#
 # Since: 2.3
 ##
 { 'command': 'blockdev-change-medium',
   'data': { 'device': 'str',
             'filename': 'str',
-            '*format': 'str' } }
+            '*format': 'str',
+            '*read-only': 'BlockdevChangeReadOnlyMode' } }
 
 
 ##
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 1987a09..f14953a 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3855,7 +3855,7 @@ EQMP
 
     {
         .name       = "blockdev-change-medium",
-        .args_type  = "device:B,filename:F,format:s?",
+        .args_type  = "device:B,filename:F,format:s?,read-only:s?",
         .mhandler.cmd_new = qmp_marshal_input_blockdev_change_medium,
     },
 
@@ -3871,6 +3871,8 @@ Arguments:
 - "device": device name (json-string)
 - "filename": filename of the new image (json-string)
 - "format": format of the new image (json-string, optional)
+- "read-only": new read-only mode (json-string, optional)
+          - Possible values: "retain" (default), "ro", "rw"
 
 Examples:
 
@@ -3882,6 +3884,26 @@ Examples:
                             "format": "raw" } }
 <- { "return": {} }
 
+2. Load a read-only medium into a writable drive
+
+-> { "execute": "blockdev-change-medium",
+             "arguments": { "device": "isa-fd0",
+                            "filename": "/srv/images/ro.img",
+                            "format": "raw",
+                            "read-only": "retain" } }
+
+<- { "error":
+     { "class": "GenericError",
+       "desc": "Could not open '/srv/images/ro.img': Permission denied" } }
+
+-> { "execute": "blockdev-change-medium",
+             "arguments": { "device": "isa-fd0",
+                            "filename": "/srv/images/ro.img",
+                            "format": "raw",
+                            "read-only": "ro" } }
+
+<- { "return": {} }
+
 EQMP
 
     {
diff --git a/qmp.c b/qmp.c
index 1cfdb74..d414118 100644
--- a/qmp.c
+++ b/qmp.c
@@ -417,7 +417,8 @@ void qmp_change(const char *device, const char *target,
     if (strcmp(device, "vnc") == 0) {
         qmp_change_vnc(target, has_arg, arg, errp);
     } else {
-        qmp_blockdev_change_medium(device, target, has_arg, arg, errp);
+        qmp_blockdev_change_medium(device, target, has_arg, arg, false, 0,
+                                   errp);
     }
 }
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (46 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 21:22   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive() Max Reitz
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands Max Reitz
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Expose the new read-only option of 'blockdev-change-medium' for the
'change' HMP command.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 hmp-commands.hx | 20 +++++++++++++++++---
 hmp.c           | 21 ++++++++++++++++++++-
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index e37bc8b..70cb7d7 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -196,8 +196,8 @@ ETEXI
 
     {
         .name       = "change",
-        .args_type  = "device:B,target:F,arg:s?",
-        .params     = "device filename [format]",
+        .args_type  = "device:B,target:F,arg:s?,read-only:s?",
+        .params     = "device filename [format [read-only]]",
         .help       = "change a removable medium, optional format",
         .mhandler.cmd = hmp_change,
     },
@@ -209,7 +209,7 @@ STEXI
 Change the configuration of a device.
 
 @table @option
-@item change @var{diskdevice} @var{filename} [@var{format}]
+@item change @var{diskdevice} @var{filename} [@var{format} [@var{read-only}]]
 Change the medium for a removable disk device to point to @var{filename}. eg
 
 @example
@@ -218,6 +218,20 @@ Change the medium for a removable disk device to point to @var{filename}. eg
 
 @var{format} is optional.
 
+@var{read-only} may be used to change the read-only status of the device. It
+accepts the following values:
+
+@table @var
+@item retain
+Retains the current status; this is the default.
+
+@item ro
+Makes the device read-only.
+
+@item rw
+Makes the device writable.
+@end table
+
 @item change vnc @var{display},@var{options}
 Change the configuration of the VNC server. The valid syntax for @var{display}
 and @var{options} are described at @ref{sec_invocation}. eg
diff --git a/hmp.c b/hmp.c
index dbf0947..8e75771 100644
--- a/hmp.c
+++ b/hmp.c
@@ -24,6 +24,7 @@
 #include "monitor/monitor.h"
 #include "qapi/opts-visitor.h"
 #include "qapi/string-output-visitor.h"
+#include "qapi/util.h"
 #include "qapi-visit.h"
 #include "ui/console.h"
 #include "block/qapi.h"
@@ -1178,9 +1179,15 @@ void hmp_change(Monitor *mon, const QDict *qdict)
     const char *device = qdict_get_str(qdict, "device");
     const char *target = qdict_get_str(qdict, "target");
     const char *arg = qdict_get_try_str(qdict, "arg");
+    const char *read_only = qdict_get_try_str(qdict, "read-only");
+    BlockdevChangeReadOnlyMode read_only_mode = 0;
     Error *err = NULL;
 
     if (strcmp(device, "vnc") == 0) {
+        if (read_only) {
+            monitor_printf(mon, "Parameter 'read-only' is invalid for VNC");
+            return;
+        }
         if (strcmp(target, "passwd") == 0 ||
             strcmp(target, "password") == 0) {
             if (!arg) {
@@ -1190,7 +1197,19 @@ void hmp_change(Monitor *mon, const QDict *qdict)
         }
         qmp_change("vnc", target, !!arg, arg, &err);
     } else {
-        qmp_blockdev_change_medium(device, target, !!arg, arg, false, 0, &err);
+        if (read_only) {
+            read_only_mode =
+                qapi_enum_parse(BlockdevChangeReadOnlyMode_lookup,
+                                read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_MAX,
+                                BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
+            if (err) {
+                hmp_handle_error(mon, &err);
+                return;
+            }
+        }
+
+        qmp_blockdev_change_medium(device, target, !!arg, arg,
+                                   !!read_only, read_only_mode, &err);
         if (err &&
             error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
             error_free(err);
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive()
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (47 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 21:27   ` Eric Blake
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands Max Reitz
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

This patch allows specifying the interface to be used for the drive, and
makes specifying a path optional (if the path is None, the "file" option
will be omitted, thus creating an empty drive).

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 tests/qemu-iotests/iotests.py | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 241b5ee..27b2490 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -94,13 +94,16 @@ class VM(object):
         self._args.append('-monitor')
         self._args.append(args)
 
-    def add_drive(self, path, opts=''):
+    def add_drive(self, path, opts='', interface='virtio'):
         '''Add a virtio-blk drive to the VM'''
-        options = ['if=virtio',
+        options = ['if=%s' % interface,
                    'format=%s' % imgfmt,
                    'cache=%s' % cachemode,
-                   'file=%s' % path,
                    'id=drive%d' % self._num_drives]
+
+        if not path is None:
+            options.append('file=%s' % path)
+
         if opts:
             options.append(opts)
 
-- 
2.1.0

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

* [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands
  2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
                   ` (48 preceding siblings ...)
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive() Max Reitz
@ 2015-01-27 19:46 ` Max Reitz
  2015-01-28 21:57   ` Eric Blake
  49 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-27 19:46 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster, Max Reitz,
	Stefan Hajnoczi, John Snow

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 tests/qemu-iotests/118     | 649 +++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/118.out |   5 +
 tests/qemu-iotests/group   |   1 +
 3 files changed, 655 insertions(+)
 create mode 100755 tests/qemu-iotests/118
 create mode 100644 tests/qemu-iotests/118.out

diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118
new file mode 100755
index 0000000..06140e9
--- /dev/null
+++ b/tests/qemu-iotests/118
@@ -0,0 +1,649 @@
+#!/usr/bin/env python
+#
+# Test case for the QMP 'change' command and all other associated
+# commands
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import stat
+import iotests
+from iotests import qemu_img
+
+old_img = os.path.join(iotests.test_dir, 'test0.img')
+new_img = os.path.join(iotests.test_dir, 'test1.img')
+
+class ChangeBaseClass(iotests.QMPTestCase):
+    has_opened = False
+    has_closed = False
+
+    def process_events(self):
+        for event in self.vm.get_qmp_events(wait=True):
+            if event['event'] == 'DEVICE_TRAY_MOVED' and event['data']['device'] == 'drive0':
+                if event['data']['tray-open'] == False:
+                    self.has_closed = True
+                else:
+                    self.has_opened = True
+
+class GeneralChangeTestsBaseClass(ChangeBaseClass):
+    def test_change(self):
+        result = self.vm.qmp('change', device='drive0', target=new_img,
+                                       arg=iotests.imgfmt)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_blockdev_change_medium(self):
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_eject(self):
+        result = self.vm.qmp('eject', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp_absent(result, 'return[0]/inserted')
+
+    def test_tray_eject_change(self):
+        result = self.vm.qmp('eject', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp_absent(result, 'return[0]/inserted')
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_tray_open_close(self):
+        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        if self.was_empty == True:
+            self.assert_qmp_absent(result, 'return[0]/inserted')
+        else:
+            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        if self.has_real_tray or not self.was_empty:
+            while not self.has_closed:
+                self.process_events()
+
+        result = self.vm.qmp('query-block')
+        if self.has_real_tray or not self.was_empty:
+            self.assert_qmp(result, 'return[0]/tray_open', False)
+        else:
+            self.assert_qmp(result, 'return[0]/tray_open', True)
+        if self.was_empty == True:
+            self.assert_qmp_absent(result, 'return[0]/inserted')
+        else:
+            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+    def test_tray_eject_close(self):
+        result = self.vm.qmp('eject', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp_absent(result, 'return[0]/inserted')
+
+        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        if self.has_real_tray:
+            while not self.has_closed:
+                self.process_events()
+
+        result = self.vm.qmp('query-block')
+        if self.has_real_tray:
+            self.assert_qmp(result, 'return[0]/tray_open', False)
+        else:
+            self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp_absent(result, 'return[0]/inserted')
+
+    def test_tray_open_change(self):
+        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        if self.was_empty == True:
+            self.assert_qmp_absent(result, 'return[0]/inserted')
+        else:
+            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_cycle(self):
+        result = self.vm.qmp('blockdev-add',
+                             options={'node-name': 'new',
+                                      'driver': iotests.imgfmt,
+                                      'file': {'filename': new_img,
+                                               'driver': 'file'}})
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        if self.was_empty == True:
+            self.assert_qmp_absent(result, 'return[0]/inserted')
+        else:
+            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-remove-medium', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp_absent(result, 'return[0]/inserted')
+
+        result = self.vm.qmp('blockdev-insert-medium', device='drive0',
+                                                       node_name='new')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_close_on_closed(self):
+        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        # Should be a no-op
+        self.assert_qmp(result, 'return', {})
+        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
+
+    def test_remove_on_closed(self):
+        if self.has_opened:
+            # Empty floppy drive
+            return
+
+        result = self.vm.qmp('blockdev-remove-medium', device='drive0')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+    def test_insert_on_closed(self):
+        if self.has_opened:
+            # Empty floppy drive
+            return
+
+        result = self.vm.qmp('blockdev-add',
+                             options={'node-name': 'new',
+                                      'driver': iotests.imgfmt,
+                                      'file': {'filename': new_img,
+                                               'driver': 'file'}})
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-insert-medium', device='drive0',
+                                                       node_name='new')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+class TestInitiallyFilled(GeneralChangeTestsBaseClass):
+    was_empty = False
+
+    def setUp(self, media, interface):
+        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
+        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
+        self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(old_img)
+        os.remove(new_img)
+
+    def test_insert_on_filled(self):
+        result = self.vm.qmp('blockdev-add',
+                             options={'node-name': 'new',
+                                      'driver': iotests.imgfmt,
+                                      'file': {'filename': new_img,
+                                               'driver': 'file'}})
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-open-tray', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('blockdev-insert-medium', device='drive0',
+                                                       node_name='new')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
+    was_empty = True
+
+    def setUp(self, media, interface):
+        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
+        self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(new_img)
+
+    def test_remove_on_empty(self):
+        result = self.vm.qmp('blockdev-open-tray', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('blockdev-remove-medium', device='drive0')
+        # Should be a no-op
+        self.assert_qmp(result, 'return', {})
+
+class TestCDInitiallyFilled(TestInitiallyFilled):
+    TestInitiallyFilled = TestInitiallyFilled
+    has_real_tray = True
+
+    def setUp(self):
+        self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
+
+class TestCDInitiallyEmpty(TestInitiallyEmpty):
+    TestInitiallyEmpty = TestInitiallyEmpty
+    has_real_tray = True
+
+    def setUp(self):
+        self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
+
+class TestFloppyInitiallyFilled(TestInitiallyFilled):
+    TestInitiallyFilled = TestInitiallyFilled
+    has_real_tray = False
+
+    def setUp(self):
+        self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
+
+class TestFloppyInitiallyEmpty(TestInitiallyEmpty):
+    TestInitiallyEmpty = TestInitiallyEmpty
+    has_real_tray = False
+
+    def setUp(self):
+        self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
+        # FDDs not having a real tray and there not being a medium inside the
+        # tray at startup means the tray will be considered open
+        self.has_opened = True
+
+class TestChangeReadOnly(ChangeBaseClass):
+    def setUp(self):
+        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
+        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
+        self.vm = iotests.VM()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.chmod(old_img, 0666)
+        os.chmod(new_img, 0666)
+        os.remove(old_img)
+        os.remove(new_img)
+
+    def test_ro_ro_retain(self):
+        os.chmod(old_img, 0444)
+        os.chmod(new_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='retain')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_ro_rw_retain(self):
+        os.chmod(old_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='retain')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_rw_ro_retain(self):
+        os.chmod(new_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='retain')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+    def test_ro_rw(self):
+        os.chmod(old_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='rw')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_rw_ro(self):
+        os.chmod(new_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='ro')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_make_rw_ro(self):
+        self.vm.add_drive(old_img, 'media=disk', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='ro')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_make_ro_rw(self):
+        os.chmod(new_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='rw')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+    def test_make_rw_ro_by_retain(self):
+        os.chmod(old_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='retain')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+    def test_make_ro_rw_by_retain(self):
+        os.chmod(new_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                                       filename=new_img,
+                                                       format=iotests.imgfmt,
+                                                       read_only='retain')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+    def test_rw_ro_cycle(self):
+        os.chmod(new_img, 0444)
+        self.vm.add_drive(old_img, 'media=disk', 'floppy')
+        self.vm.launch()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-add',
+                             options={'node-name': 'new',
+                                      'driver': iotests.imgfmt,
+                                      'read-only': True,
+                                      'file': {'filename': new_img,
+                                               'driver': 'file'}})
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_opened:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp(result, 'return[0]/inserted/ro', False)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+        result = self.vm.qmp('blockdev-remove-medium', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp_absent(result, 'return[0]/inserted')
+
+        result = self.vm.qmp('blockdev-insert-medium', device='drive0',
+                                                       node_name='new')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', True)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        while not self.has_closed:
+            self.process_events()
+
+        result = self.vm.qmp('query-block')
+        self.assert_qmp(result, 'return[0]/tray_open', False)
+        self.assert_qmp(result, 'return[0]/inserted/ro', True)
+        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+GeneralChangeTestsBaseClass = None
+TestInitiallyFilled = None
+TestInitiallyEmpty = None
+
+if __name__ == '__main__':
+    iotests.main()
diff --git a/tests/qemu-iotests/118.out b/tests/qemu-iotests/118.out
new file mode 100644
index 0000000..7d4a8ca
--- /dev/null
+++ b/tests/qemu-iotests/118.out
@@ -0,0 +1,5 @@
+..........................................................
+----------------------------------------------------------------------
+Ran 58 tests
+
+OK
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ddfedb5..0b3722e 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -116,3 +116,4 @@
 113 rw auto quick
 114 rw auto quick
 116 rw auto quick
+118 rw auto
-- 
2.1.0

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

* Re: [Qemu-devel] [PATCH RESEND 11/50] block: Move BlockAcctStats into BlockBackend
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 11/50] block: Move BlockAcctStats into BlockBackend Max Reitz
@ 2015-01-27 20:31   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 20:31 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

[replies to earlier patches in the other thread; moving the rest of my
review here for the sake of improved cc]

On 01/27/2015 12:45 PM, Max Reitz wrote:
> As the comment above bdrv_get_stats() says, BlockAcctStats is something
> which belongs to the device instead of each BlockDriverState. This patch
> therefore moves it into the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block.c                   | 11 -----------
>  block/block-backend.c     |  5 ++++-
>  block/qapi.c              | 20 ++++++++++++--------
>  include/block/block.h     |  2 --
>  include/block/block_int.h |  3 ---
>  5 files changed, 16 insertions(+), 25 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

(I spent some time hunting to ensure that 0-initialized stats make sense
when there is no BB - libvirt returns -1 rather than 0 for some stats,
but it's always a pain to remember which stats have the special treatment)

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 12/50] block: Move I/O status and error actions into BB
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 12/50] block: Move I/O status and error actions into BB Max Reitz
@ 2015-01-27 20:51   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 20:51 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> These options are only relevant for the user of a whole BDS tree (like a
> guest device or a block job) and should thus be moved into the
> BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block.c                        | 125 -----------------------------------------
>  block/backup.c                 |  17 ++++--
>  block/block-backend.c          | 116 ++++++++++++++++++++++++++++++++++++--
>  block/commit.c                 |   3 +-
>  block/mirror.c                 |  17 ++++--
>  block/qapi.c                   |   4 +-
>  block/stream.c                 |   3 +-
>  blockdev.c                     |   6 +-
>  blockjob.c                     |   5 +-
>  include/block/block.h          |  11 ----
>  include/block/block_int.h      |   6 --
>  include/sysemu/block-backend.h |   7 +++
>  qmp.c                          |   6 +-
>  13 files changed, 158 insertions(+), 168 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 13/50] block: Add BlockBackendRootState
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 13/50] block: Add BlockBackendRootState Max Reitz
@ 2015-01-27 21:03   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:03 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> This structure will store some of the state of the root BDS if the BDS
> tree is removed, so that state can be restored once a new BDS tree is
> inserted.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c          | 26 ++++++++++++++++++++++++++
>  include/block/block_int.h      |  9 +++++++++
>  include/qemu/typedefs.h        |  1 +
>  include/sysemu/block-backend.h |  2 ++
>  4 files changed, 38 insertions(+)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 14/50] block: Make some BB functions fall back to BBRS
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 14/50] block: Make some BB functions fall back to BBRS Max Reitz
@ 2015-01-27 21:15   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:15 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> If there is no BDS tree attached to a BlockBackend, functions that can
> do so should fall back to the BlockBackendRootState structure (which are
> blk_is_read_only() and blk_get_flags(), because the read-only status and
> the "open flags" are part of the BBRS).
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 15/50] block: Fail requests to empty BlockBackend
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 15/50] block: Fail requests to empty BlockBackend Max Reitz
@ 2015-01-27 21:24   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:24 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> If there is no BlockDriverState in a BlockBackend or if the tray of the
> guest device is open, fail all requests (where that is possible) with
> -ENOMEDIUM.
> 
> The reason the status of the guest device is taken into account is
> because once the guest device's tray is opened, any request on the same
> BlockBackend as the guest uses should fail. If the BDS tree is supposed
> to be usable even after ejecting it from the guest, a different
> BlockBackend must be used.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
> 

> @@ -635,6 +635,10 @@ int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count)
>  
>  int64_t blk_getlength(BlockBackend *blk)
>  {
> +    if (!blk_is_available(blk)) {
> +        return -ENOMEDIUM;
> +    }
> +
>      return bdrv_getlength(blk->bs);
>  }

If you add blk_nb_sectors, it will probably need the same treatment.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS Max Reitz
@ 2015-01-27 21:36   ` Eric Blake
  2015-01-27 21:39     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:36 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> There are several BlockBackend functions which, in theory, cannot fail.
> This patch makes them cope with the BlockDriverState pointer being NULL
> by making them fall back to some default action like ignoring the value
> in setters and returning the default in getters.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c | 70 ++++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 55 insertions(+), 15 deletions(-)
> 

> @@ -926,22 +944,32 @@ void *blk_blockalign(BlockBackend *blk, size_t size)
>  
>  bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
>  {
> +    if (!blk->bs) {
> +        return false;
> +    }
> +
>      return bdrv_op_is_blocked(blk->bs, op, errp);
>  }

I don't know if this is correct - maybe a no-medium drive should block
actions like commit by default?

If my design question gets answered satisfactorily that you went with
the right default, then

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS
  2015-01-27 21:36   ` Eric Blake
@ 2015-01-27 21:39     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 21:39 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-27 at 16:36, Eric Blake wrote:
> On 01/27/2015 12:45 PM, Max Reitz wrote:
>> There are several BlockBackend functions which, in theory, cannot fail.
>> This patch makes them cope with the BlockDriverState pointer being NULL
>> by making them fall back to some default action like ignoring the value
>> in setters and returning the default in getters.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   block/block-backend.c | 70 ++++++++++++++++++++++++++++++++++++++++-----------
>>   1 file changed, 55 insertions(+), 15 deletions(-)
>>
>> @@ -926,22 +944,32 @@ void *blk_blockalign(BlockBackend *blk, size_t size)
>>   
>>   bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
>>   {
>> +    if (!blk->bs) {
>> +        return false;
>> +    }
>> +
>>       return bdrv_op_is_blocked(blk->bs, op, errp);
>>   }
> I don't know if this is correct - maybe a no-medium drive should block
> actions like commit by default?

Somehow I don't think they should be blocked. For instance, commit will 
fail the instant you actually try to commit something (that is, read 
some data or access the backing hierarchy).

Generally, I think we don't need to block operations on an empty 
BlockBackend due to the fact that any operation will fail anyway.

Max

> If my design question gets answered satisfactorily that you went with
> the right default, then
>
> Reviewed-by: Eric Blake <eblake@redhat.com>
>

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

* Re: [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs()
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs() Max Reitz
@ 2015-01-27 21:56   ` Eric Blake
  2015-01-28 18:31   ` John Snow
  1 sibling, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:56 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> blk_by_name() may return a BlockBackend for which blk_bs() returns NULL.
> In this case, an error should be returned (instead of just returning
> NULL without modifying *errp).
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 18/50] block: Respect empty BB in bdrv_query_info()
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 18/50] block: Respect empty BB in bdrv_query_info() Max Reitz
@ 2015-01-27 21:57   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:57 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/qapi.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA Max Reitz
@ 2015-01-27 21:59   ` Eric Blake
  2015-01-27 22:13     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-27 21:59 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> When preparing a blockdev-backup transaction, the BlockBackend should be
> used because there may be no medium associated to the BB (which would
> make bdrv_find() fail, whereas blk_by_name() does not).
> 
> This does not make a real difference because blockdev-backup will fail
> without a medium anyway; however, it will have an impact on the error
> returned ("device not found" vs. "no medium").
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 17 ++++++++++-------
>  1 file changed, 10 insertions(+), 7 deletions(-)

And no tests changed output as a result?  Might be worth adding a test
for the error message.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 20/50] blockdev: Check blk_is_available() in sn-del-int-sync
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 20/50] blockdev: Check blk_is_available() in sn-del-int-sync Max Reitz
@ 2015-01-27 22:10   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 22:10 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Check whether the BlockBackend is actually available at the start of
> snapshot-delete-internal-sync.

Cute abbreviation in the subject line.

> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 18 +++++++++++++-----
>  1 file changed, 13 insertions(+), 5 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA
  2015-01-27 21:59   ` Eric Blake
@ 2015-01-27 22:13     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-27 22:13 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-27 at 16:59, Eric Blake wrote:
> On 01/27/2015 12:45 PM, Max Reitz wrote:
>> When preparing a blockdev-backup transaction, the BlockBackend should be
>> used because there may be no medium associated to the BB (which would
>> make bdrv_find() fail, whereas blk_by_name() does not).
>>
>> This does not make a real difference because blockdev-backup will fail
>> without a medium anyway; however, it will have an impact on the error
>> returned ("device not found" vs. "no medium").
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c | 17 ++++++++++-------
>>   1 file changed, 10 insertions(+), 7 deletions(-)
> And no tests changed output as a result?  Might be worth adding a test
> for the error message.

Actually, it's preventing a test output change: At this point, a BB 
always has a BDS, thus there is no change (if blk_by_name() works, 
bdrv_find() will work, too). This will change only later (patches 34 and 
40), at which point the message would change to "device not found" 
without this patch (and as far as I remember, qemu-iotest 055 tests the 
error type).

Max

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

* Re: [Qemu-devel] [PATCH RESEND 21/50] blockdev: Check BB validity in internal snapshot TA
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 21/50] blockdev: Check BB validity in internal snapshot TA Max Reitz
@ 2015-01-27 23:02   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-27 23:02 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA Max Reitz
@ 2015-01-27 23:44   ` Eric Blake
  2015-01-28 16:27     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-27 23:44 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> In the drive-backup transaction, call blk_is_available() before using
> blk_bs() to obtain the root BlockDriverState behind the BlockBackend.

Took me a while to figure that TA meant transaction in the subject.
Either spell it out, or just drop 'TA' entirely (the shorter subject
would still make sense).  (21/50 as well).

> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 23/50] blockdev: Catch NULL BDS in block_set_io_throttle
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 23/50] blockdev: Catch NULL BDS in block_set_io_throttle Max Reitz
@ 2015-01-28 15:26   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 15:26 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Split bdrv_find() into blk_by_name() and blk_bs() to separate the
> "no medium inserted" case from the "device not found" case.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 20 ++++++++++++++------
>  1 file changed, 14 insertions(+), 6 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 24/50] blockdev: Check BB validity in block-stream
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 24/50] blockdev: Check BB validity in block-stream Max Reitz
@ 2015-01-28 15:28   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 15:28 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 25/50] blockdev: Check BB validity in block-commit
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 25/50] blockdev: Check BB validity in block-commit Max Reitz
@ 2015-01-28 16:09   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:09 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 26/50] blockdev: Check BB validity in drive-backup
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 26/50] blockdev: Check BB validity in drive-backup Max Reitz
@ 2015-01-28 16:20   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:20 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:45 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend (instead of calling
> bdrv_is_inserted() after bdrv_find()).
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA
  2015-01-27 23:44   ` Eric Blake
@ 2015-01-28 16:27     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 16:27 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-27 at 18:44, Eric Blake wrote:
> On 01/27/2015 12:45 PM, Max Reitz wrote:
>> In the drive-backup transaction, call blk_is_available() before using
>> blk_bs() to obtain the root BlockDriverState behind the BlockBackend.
> Took me a while to figure that TA meant transaction in the subject.
> Either spell it out, or just drop 'TA' entirely (the shorter subject
> would still make sense).  (21/50 as well).

Well, the subject would then be the same as for 26. drive-backup is 
something different than the drive-backup transaction.

I don't really have a problem with using longer subjects lines, but vim 
tells me not to. :-( However, vim hasn't passed the turing test, so if 
you tell me to I'll ignore it.

Max

>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c | 15 ++++++++++-----
>>   1 file changed, 10 insertions(+), 5 deletions(-)
> Reviewed-by: Eric Blake <eblake@redhat.com>
>

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

* Re: [Qemu-devel] [PATCH RESEND 27/50] blockdev: Check BB validity in blockdev-backup
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 27/50] blockdev: Check BB validity in blockdev-backup Max Reitz
@ 2015-01-28 16:42   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:42 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 28/50] blockdev: Check BB validity in drive-mirror
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 28/50] blockdev: Check BB validity in drive-mirror Max Reitz
@ 2015-01-28 16:43   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:43 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 29/50] blockdev: Check BB validity in find_block_job()
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 29/50] blockdev: Check BB validity in find_block_job() Max Reitz
@ 2015-01-28 16:44   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:44 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 30/50] blockdev: Check BB validity in change-backing-file
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 30/50] blockdev: Check BB validity in change-backing-file Max Reitz
@ 2015-01-28 16:50   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:50 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Call blk_is_available() before using blk_bs() to obtain the root
> BlockDriverState behind the BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs()
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs() Max Reitz
@ 2015-01-28 16:52   ` Eric Blake
  2015-01-28 16:58     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 16:52 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> This function associates the given BlockDriverState with the given
> BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c          | 16 ++++++++++++++++
>  include/sysemu/block-backend.h |  1 +
>  2 files changed, 17 insertions(+)
> 
> diff --git a/block/block-backend.c b/block/block-backend.c
> index 760558f..656ebfc 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -312,6 +312,22 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
>  }
>  
>  /*
> + * Associates a new BlockDriverState with @blk.
> + */
> +void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
> +{
> +    if (bs->blk == blk) {
> +        return;
> +    }
> +
> +    assert(!blk->bs);

I guess this interesting code allows for idempotent use of blk_insert_bs
more than once?  What situations require that usage pattern?

At any rate, the new function looks fine.
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs()
  2015-01-28 16:52   ` Eric Blake
@ 2015-01-28 16:58     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 16:58 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 11:52, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> This function associates the given BlockDriverState with the given
>> BlockBackend.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   block/block-backend.c          | 16 ++++++++++++++++
>>   include/sysemu/block-backend.h |  1 +
>>   2 files changed, 17 insertions(+)
>>
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index 760558f..656ebfc 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -312,6 +312,22 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
>>   }
>>   
>>   /*
>> + * Associates a new BlockDriverState with @blk.
>> + */
>> +void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
>> +{
>> +    if (bs->blk == blk) {
>> +        return;
>> +    }
>> +
>> +    assert(!blk->bs);
> I guess this interesting code allows for idempotent use of blk_insert_bs
> more than once?  What situations require that usage pattern?

Well, to be honest, there is no such requirement. I could (probably) 
have just omitted the condition before the assertion; but I just felt 
like it would be perfectly valid for this function to be idempotent 
which is why the condition is there.

> At any rate, the new function looks fine.
> Reviewed-by: Eric Blake <eblake@redhat.com>

Once again, thank you!

Max

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

* Re: [Qemu-devel] [PATCH RESEND 32/50] blockdev: Check BB validity in eject and change
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 32/50] blockdev: Check BB validity in eject and change Max Reitz
@ 2015-01-28 17:42   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 17:42 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Both commands will be reimplemented in a follow-up to this patch so this
> does not need to be nice, it just has to work.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 35 +++++++++++++++++++++++++----------
>  1 file changed, 25 insertions(+), 10 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 33/50] blockdev: Respect NULL BDS in do_drive_del()
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 33/50] blockdev: Respect NULL BDS in do_drive_del() Max Reitz
@ 2015-01-28 17:45   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 17:45 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 34/50] blockdev: Do not create BDS for empty drive
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 34/50] blockdev: Do not create BDS for empty drive Max Reitz
@ 2015-01-28 17:50   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 17:50 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Do not use "rudimentary" BDSs for empty drives any longer (for
> freshly created drives).
> 
> With this change, bdrv_close_all() has no effect on empty drives (whose
> media were not changed) any longer. This breaks some test outputs, fix
> them.
> 
> After a follow-up patch, empty drives will generally use a NULL BDS, not
> only the freshly created drives.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c                 | 68 ++++++++++++++++++++++++++--------------------
>  tests/qemu-iotests/067.out | 44 ------------------------------
>  tests/qemu-iotests/071.out |  2 --
>  tests/qemu-iotests/081.out |  1 -
>  tests/qemu-iotests/087.out |  5 ----
>  5 files changed, 38 insertions(+), 82 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs()
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs() Max Reitz
  2015-01-27 21:56   ` Eric Blake
@ 2015-01-28 18:31   ` John Snow
  2015-01-28 18:35     ` Max Reitz
  1 sibling, 1 reply; 107+ messages in thread
From: John Snow @ 2015-01-28 18:31 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Jeff Cody, Fam Zheng, Markus Armbruster, Stefan Hajnoczi



On 01/27/2015 02:45 PM, Max Reitz wrote:
> blk_by_name() may return a BlockBackend for which blk_bs() returns NULL.
> In this case, an error should be returned (instead of just returning
> NULL without modifying *errp).
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>   block.c | 5 +++++
>   1 file changed, 5 insertions(+)
>
> diff --git a/block.c b/block.c
> index 9a0a510..b7e631c 100644
> --- a/block.c
> +++ b/block.c
> @@ -3718,6 +3718,11 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
>           blk = blk_by_name(device);
>
>           if (blk) {
> +            if (!blk_bs(blk)) {
> +                error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
> +                return NULL;
> +            }
> +
>               return blk_bs(blk);
>           }
>       }
>

Do we have a consensus on The One True And Proper Way to report errors? 
I know Markus usually campaigns against error_set() in favor of 
error_setg().

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

* Re: [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs()
  2015-01-28 18:31   ` John Snow
@ 2015-01-28 18:35     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 18:35 UTC (permalink / raw)
  To: John Snow, qemu-devel
  Cc: Kevin Wolf, Jeff Cody, Fam Zheng, Markus Armbruster, Stefan Hajnoczi

On 2015-01-28 at 13:31, John Snow wrote:
>
>
> On 01/27/2015 02:45 PM, Max Reitz wrote:
>> blk_by_name() may return a BlockBackend for which blk_bs() returns NULL.
>> In this case, an error should be returned (instead of just returning
>> NULL without modifying *errp).
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   block.c | 5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/block.c b/block.c
>> index 9a0a510..b7e631c 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -3718,6 +3718,11 @@ BlockDriverState *bdrv_lookup_bs(const char 
>> *device,
>>           blk = blk_by_name(device);
>>
>>           if (blk) {
>> +            if (!blk_bs(blk)) {
>> +                error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
>> +                return NULL;
>> +            }
>> +
>>               return blk_bs(blk);
>>           }
>>       }
>>
>
> Do we have a consensus on The One True And Proper Way to report 
> errors? I know Markus usually campaigns against error_set() in favor 
> of error_setg().

The wiki says to use error_setg(). However, QERR_DEVICE_HAS_NO_MEDIUM is 
at least a generic error (ERROR_CLASS_GENERIC_ERROR) and I somehow like 
using a macro for such commonplace errors more.

I don't know the real problem with error_set() with macro, though. I can 
only imagine that if we use macros, people may start to rely on the 
human-readable error string whereas they should not. If I would not use 
a macro here, I would've written my own error message which might have 
differed from QERR_DEVICE_HAS_NO_MEDIUM and thus increased diversity. 
But I don't feel like that's enough of a reason... I'm most probably 
just missing something about the evilness of error_set() with macros.

Max

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

* Re: [Qemu-devel] [PATCH RESEND 35/50] blockdev: Pull out blockdev option extraction
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 35/50] blockdev: Pull out blockdev option extraction Max Reitz
@ 2015-01-28 19:23   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 19:23 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Extract some of the blockdev option extraction code from blockdev_init()
> into an own function. This simplifies blockdev_init() and will allow

s/an/its/

> reusing the code in a different function added in a follow-up patch.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 201 +++++++++++++++++++++++++++++++++----------------------------
>  1 file changed, 108 insertions(+), 93 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 36/50] blockdev: Allow more options for BB-less BDS tree
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 36/50] blockdev: Allow more options for BB-less BDS tree Max Reitz
@ 2015-01-28 19:26   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 19:26 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Most of the options which blockdev_init() parses for both the
> BlockBackend and the root BDS are valid for just the root BDS as well
> (e.g. read-only). This patch allows specifying these options even if not
> creating a BlockBackend.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 150 insertions(+), 6 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 37/50] block: Add blk_remove_bs()
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 37/50] block: Add blk_remove_bs() Max Reitz
@ 2015-01-28 19:49   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 19:49 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> This function removes the BlockDriverState associated with the given
> BlockBackend from that BB and sets the BDS pointer in the BB to NULL.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c          | 22 +++++++++++++++++++++-
>  include/sysemu/block-backend.h |  1 +
>  2 files changed, 22 insertions(+), 1 deletion(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray Max Reitz
@ 2015-01-28 19:56   ` Eric Blake
  2015-01-28 19:59     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 19:56 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  qapi/block-core.json | 21 +++++++++++++++++++++
>  qmp-commands.hx      | 37 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 106 insertions(+)
> 

> +Example (1):
> +

With only one example, the (1) doesn't add much.  Minor whether you
leave it in or take it out.

> +-> { "execute": "blockdev-open-tray",
> +     "arguments": { "device": "ide1-cd0" } }
> +
> +<- { "timestamp": { "seconds": 1418751016,
> +                    "microseconds": 716996 },
> +     "event": "DEVICE_TRAY_MOVED",
> +     "data": { "device": "ide1-cd0",
> +               "tray-open": true } }
> +
> +<- { "return": {} }

Nice inclusion of the event alongside the return code!

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray Max Reitz
@ 2015-01-28 19:58   ` Eric Blake
  2015-01-28 20:00     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 19:58 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c           | 22 ++++++++++++++++++++++
>  qapi/block-core.json | 14 ++++++++++++++
>  qmp-commands.hx      | 33 +++++++++++++++++++++++++++++++++
>  3 files changed, 69 insertions(+)
> 

> +void qmp_blockdev_close_tray(const char *device, Error **errp)
> +{
> +    BlockBackend *blk;
> +
> +    blk = blk_by_name(device);
> +    if (!blk) {
> +        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
> +        return;
> +    }
> +
> +    if (!blk_dev_has_removable_media(blk)) {
> +        error_setg(errp, "Device '%s' is not removable", device);
> +        return;
> +    }
> +
> +    if (!blk_dev_is_tray_open(blk)) {
> +        return;
> +    }

Is it worth documenting that this (and the one in 38/50) are intentional
no-ops if the tray is already in the desired state?

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray
  2015-01-28 19:56   ` Eric Blake
@ 2015-01-28 19:59     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 19:59 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 14:56, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   qapi/block-core.json | 21 +++++++++++++++++++++
>>   qmp-commands.hx      | 37 +++++++++++++++++++++++++++++++++++++
>>   3 files changed, 106 insertions(+)
>>
>> +Example (1):
>> +
> With only one example, the (1) doesn't add much.  Minor whether you
> leave it in or take it out.

I'll remove it.

Max

>> +-> { "execute": "blockdev-open-tray",
>> +     "arguments": { "device": "ide1-cd0" } }
>> +
>> +<- { "timestamp": { "seconds": 1418751016,
>> +                    "microseconds": 716996 },
>> +     "event": "DEVICE_TRAY_MOVED",
>> +     "data": { "device": "ide1-cd0",
>> +               "tray-open": true } }
>> +
>> +<- { "return": {} }
> Nice inclusion of the event alongside the return code!
>
> Reviewed-by: Eric Blake <eblake@redhat.com>
>

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

* Re: [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray
  2015-01-28 19:58   ` Eric Blake
@ 2015-01-28 20:00     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 20:00 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 14:58, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c           | 22 ++++++++++++++++++++++
>>   qapi/block-core.json | 14 ++++++++++++++
>>   qmp-commands.hx      | 33 +++++++++++++++++++++++++++++++++
>>   3 files changed, 69 insertions(+)
>>
>> +void qmp_blockdev_close_tray(const char *device, Error **errp)
>> +{
>> +    BlockBackend *blk;
>> +
>> +    blk = blk_by_name(device);
>> +    if (!blk) {
>> +        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>> +        return;
>> +    }
>> +
>> +    if (!blk_dev_has_removable_media(blk)) {
>> +        error_setg(errp, "Device '%s' is not removable", device);
>> +        return;
>> +    }
>> +
>> +    if (!blk_dev_is_tray_open(blk)) {
>> +        return;
>> +    }
> Is it worth documenting that this (and the one in 38/50) are intentional
> no-ops if the tray is already in the desired state?

There's certainly no harm in documenting it, so I might as well just do it.

Max

> Reviewed-by: Eric Blake <eblake@redhat.com>

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

* Re: [Qemu-devel] [PATCH RESEND 40/50] blockdev: Add blockdev-remove-medium
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 40/50] blockdev: Add blockdev-remove-medium Max Reitz
@ 2015-01-28 20:11   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 20:11 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c           | 25 +++++++++++++++++++++++++
>  qapi/block-core.json | 13 +++++++++++++
>  qmp-commands.hx      | 43 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 81 insertions(+)
> 

>  
> +void qmp_blockdev_remove_medium(const char *device, Error **errp)
> +{

> +    if (!blk_dev_is_tray_open(blk)) {
> +        error_setg(errp, "Tray of device '%s' is not open", device);
> +        return;
> +    }
> +
> +    if (blk_bs(blk)) {
> +        blk_remove_bs(blk);

Another intentional no-op if there is already no medium; worth
documenting alongside the other touchups.

>  
> +##
> +# @blockdev-remove-medium:
> +#
> +# Removes a medium (a block driver state tree) from a block device. That block
> +# device's tray must currently be open.
> +#
> +# @device: block device name
> +#
> +# Since: 2.3
> +##
> +{ 'command': 'blockdev-remove-medium',
> +  'data': { 'device': 'str' } }

Just thinking aloud - obviously, this is a device operation.  But do we
want to allow specifying the device by the node-name of the BDS being
removed?  (I suppose the same applies to 38 [open a tray by the name of
the BDS in the tray] and 39 [close a tray that has the given BDS
inserted]).  But I'm fine with naming the parameter 'device', even if we
allow for a BDS->BB lookup when actually resolving the user's input,
since that would only be a convenience (and not like other block API
that specifically operate on nodes of a BDS tree rather than a device).

Furthermore, the counterpart command for inserting a medium (later in
this series) is one case where we CAN'T do the BDS->BB lookup
(generally, insertion will fail if a BDS node is already in the BB
device, unless you implement swap semantics, but that would make it
confusing to insert one BDS into the device referenced by another
BDS->BB lookup); and symmetry argues that if that command supports ONLY
a BB name, then all of the related commands are just fine using 'device'
as their parameter name to imply BB name.

So I'm fine with the naming you've used so far.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium Max Reitz
@ 2015-01-28 20:18   ` Eric Blake
  2015-01-28 20:20     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 20:18 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> And a helper function for that which directly takes a pointer to the BDS
> to be inserted instead of its node-name (which will be used for
> implementing 'change' using blockdev-insert-medium).
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c           | 43 +++++++++++++++++++++++++++++++++++++++++++
>  qapi/block-core.json | 17 +++++++++++++++++
>  qmp-commands.hx      | 38 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 98 insertions(+)
> 

> +static void qmp_blockdev_insert_anon_medium(const char *device,
> +                                            BlockDriverState *bs, Error **errp)
> +{
> +    BlockBackend *blk;
> +
> +    blk = blk_by_name(device);
> +    if (!blk) {
> +        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
> +        return;
> +    }
> +
> +    if (!blk_dev_has_removable_media(blk)) {
> +        error_setg(errp, "Device '%s' is not removable", device);
> +        return;
> +    }
> +
> +    if (!blk_dev_is_tray_open(blk)) {
> +        error_setg(errp, "Tray of device '%s' is not open", device);
> +        return;
> +    }
> +
> +    if (blk_bs(blk)) {
> +        error_setg(errp, "There already is a medium in device '%s'", device);
> +        return;
> +    }

Good, you didn't implement hot-swap semantics of replacing an existing
medium (that gets too confusing; so I _like_ that you force the user to
consider all the steps through multiple low-level commands).


> +
> +Example (1):

I'll quit pointing it out; but if you clean up the useless (1) in one
patch, do it across the series.

> +
> +-> { "execute": "blockdev-add",
> +     "arguments": { "options": { "id": "backend0",
> +                                 "node-name": "node0",

Why is 'id' needed?  Isn't the point of this command sequence to create
a BDS tree that is NOT tied to a BB, and then use insert-medium to make
the association after the fact?  We don't need to create a BB named
'backend0' if we are immediately going to reuse 'node0' in a different
BB (true, we have somewhat anticipated the idea of sharing BDS tree
among multiple BB, but haven't quite turned that on before now).

> +                                 "driver": "raw",
> +                                 "file": { "driver": "file",
> +                                           "filename": "fedora.iso" } } } }
> +
> +<- { "return": {} }
> +
> +-> { "execute": "blockdev-insert-medium",
> +     "arguments": { "device": "ide1-cd0",
> +                    "node-name": "node0" } }
> +
> +<- { "return": {} }

If you can either explain why you used 'id' in the example, or remove
that parameter, you can add:
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium
  2015-01-28 20:18   ` Eric Blake
@ 2015-01-28 20:20     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 20:20 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 15:18, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> And a helper function for that which directly takes a pointer to the BDS
>> to be inserted instead of its node-name (which will be used for
>> implementing 'change' using blockdev-insert-medium).
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c           | 43 +++++++++++++++++++++++++++++++++++++++++++
>>   qapi/block-core.json | 17 +++++++++++++++++
>>   qmp-commands.hx      | 38 ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 98 insertions(+)
>>
>> +static void qmp_blockdev_insert_anon_medium(const char *device,
>> +                                            BlockDriverState *bs, Error **errp)
>> +{
>> +    BlockBackend *blk;
>> +
>> +    blk = blk_by_name(device);
>> +    if (!blk) {
>> +        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>> +        return;
>> +    }
>> +
>> +    if (!blk_dev_has_removable_media(blk)) {
>> +        error_setg(errp, "Device '%s' is not removable", device);
>> +        return;
>> +    }
>> +
>> +    if (!blk_dev_is_tray_open(blk)) {
>> +        error_setg(errp, "Tray of device '%s' is not open", device);
>> +        return;
>> +    }
>> +
>> +    if (blk_bs(blk)) {
>> +        error_setg(errp, "There already is a medium in device '%s'", device);
>> +        return;
>> +    }
> Good, you didn't implement hot-swap semantics of replacing an existing
> medium (that gets too confusing; so I _like_ that you force the user to
> consider all the steps through multiple low-level commands).
>
>
>> +
>> +Example (1):
> I'll quit pointing it out; but if you clean up the useless (1) in one
> patch, do it across the series.

Yes, will do.

>> +
>> +-> { "execute": "blockdev-add",
>> +     "arguments": { "options": { "id": "backend0",
>> +                                 "node-name": "node0",
> Why is 'id' needed?

Oops, because I forgot removing it after I added the functionality for 
creating a BDS tree without a BB. I'll remove it, thanks for catching it.

Max

> Isn't the point of this command sequence to create
> a BDS tree that is NOT tied to a BB, and then use insert-medium to make
> the association after the fact?  We don't need to create a BB named
> 'backend0' if we are immediately going to reuse 'node0' in a different
> BB (true, we have somewhat anticipated the idea of sharing BDS tree
> among multiple BB, but haven't quite turned that on before now).
>
>> +                                 "driver": "raw",
>> +                                 "file": { "driver": "file",
>> +                                           "filename": "fedora.iso" } } } }
>> +
>> +<- { "return": {} }
>> +
>> +-> { "execute": "blockdev-insert-medium",
>> +     "arguments": { "device": "ide1-cd0",
>> +                    "node-name": "node0" } }
>> +
>> +<- { "return": {} }
> If you can either explain why you used 'id' in the example, or remove
> that parameter, you can add:
> Reviewed-by: Eric Blake <eblake@redhat.com>
>

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

* Re: [Qemu-devel] [PATCH RESEND 42/50] blockdev: Implement eject with basic operations
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 42/50] blockdev: Implement eject with basic operations Max Reitz
@ 2015-01-28 20:26   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 20:26 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Implement 'eject' by calling blockdev-open-tray and
> blockdev-remove-medium.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)

Hmm. If you decide to enforce node-name only on the low-level command,
but still want this high-level command to support BDS->BB lookup for
convenience, you might need additional code here.  I don't know if that
is an argument in favor or against supporting BDS->BB as convenience at
the low level.  I don't have a strong enough opinion towards either
decision, so I'll let others chime in or let your original choice be
good enough.  Therefore:

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 43/50] blockdev: Implement change with basic operations
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 43/50] blockdev: Implement change " Max Reitz
@ 2015-01-28 20:30   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 20:30 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Implement 'change' on block devices by calling blockdev-open-tray,
> blockdev-remove-medium, blockdev-insert-medium (a variation of that
> which does not need a node-name) and blockdev-close-tray.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c | 191 +++++++++++++++++++++++--------------------------------------
>  1 file changed, 72 insertions(+), 119 deletions(-)
> 

> +
> +    qmp_blockdev_open_tray(device, false, false, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    qmp_blockdev_remove_medium(device, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    qmp_blockdev_insert_anon_medium(device, medium_bs, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    qmp_blockdev_close_tray(device, errp);

So if we fail anywhere in the middle, the device is left in an
unspecified state, and a followup query-block would be needed to learn
where we failed.  I guess that's life when you use a high-level command
instead of chaining low-level ones yourself.  I can live with it.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 44/50] block: Inquire tray state before tray-moved events
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 44/50] block: Inquire tray state before tray-moved events Max Reitz
@ 2015-01-28 20:37   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 20:37 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> blk_dev_change_media_cb() is called for all potential tray movements;
> however, it is possible to request closing the tray but nothing actually
> happening (on a floppy disk drive without a medium).
> 
> Thus, the actual tray status should be inquired before sending a
> tray-moved event (and an event should be sent whenever the status
> changed).
> 
> Checking @load is now superfluous; it was necessary because it was
> possible to change a medium without having explicitly opened the tray
> and closed it again (or it might have been possible, at least). This is
> no longer possible, though.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  block/block-backend.c | 17 +++++++----------
>  1 file changed, 7 insertions(+), 10 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium Max Reitz
@ 2015-01-28 21:01   ` Eric Blake
  2015-01-28 21:19     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:01 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Introduce a new QMP command 'blockdev-change-medium' which is intended
> to replace the 'change' command for block devices. The existing function
> qmp_change_blockdev() is accordingly renamed to
> qmp_blockdev_change_medium().
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c                |  7 ++++---
>  include/sysemu/blockdev.h |  2 --
>  qapi-schema.json          |  3 ++-
>  qapi/block-core.json      | 23 +++++++++++++++++++++++
>  qmp-commands.hx           | 31 +++++++++++++++++++++++++++++++
>  qmp.c                     |  2 +-
>  6 files changed, 61 insertions(+), 7 deletions(-)
> 

> +++ b/qapi-schema.json
> @@ -1649,7 +1649,8 @@
>  #          device between when these calls are executed is undefined.
>  #
>  # Notes:  It is strongly recommended that this interface is not used especially
> -#         for changing block devices.
> +#         for changing block devices.  Please use blockdev-change-medium
> +#         instead (for VNC, please use change-vnc-password).

Not grammatically wrong, but still feels a bit awkward.  Maybe better
worded as:

This interface is deprecated, and it is strongly recommended that you
avoid using it.  For changing block devices, use blockdev-change-medium;
for changing VNC parameters, use change-vnc-password.


>  ##
> +# @blockdev-change-medium:
> +#
> +# Changes the medium inserted into a block device by ejecting the current medium
> +# and loading a new image file which is inserted as the new medium (this command
> +# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
> +# and blockdev-close-tray).
> +#
> +# @device:      block device name
> +#
> +# @filename:    filename of the new image to be loaded
> +#
> +# @format:      #optional, format to open the new image with (defaults to the
> +#               probed format)
> +#
> +# Since: 2.3
> +##
> +{ 'command': 'blockdev-change-medium',
> +  'data': { 'device': 'str',
> +            'filename': 'str',
> +            '*format': 'str' } }

Intentional that there is no way to specify 'force'?  I can live with
that (force is a sledgehammer; and someone that can justify using it can
just use the lower-level functions themselves.  No need to bloat the
nice wrapper interface with something that is usually not needed).

I'm unclear on whether this command will wait for the tray open to
happen, or if it fails in the middle if the tray was locked and a
request sent to the guest but the guest did not act fast enough to
unlock things.  As such, I'm not quite sure if this interface is missing
any parameters.


> +Examples:
> +
> +1. Change a removable medium
> +
> +-> { "execute": "blockdev-change-medium",
> +             "arguments": { "device": "ide1-cd0",
> +                            "filename": "/srv/images/Fedora-12-x86_64-DVD.iso",

Wow - you're still testing a Fedora 12 image?

I'm a bit reluctant to mark this one reviewed, without more discussion.

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 46/50] hmp: Use blockdev-change-medium for change command
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 46/50] hmp: Use blockdev-change-medium for change command Max Reitz
@ 2015-01-28 21:02   ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:02 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Use separate code paths for the two overloaded functions of the 'change'
> HMP command, and invoke the 'blockdev-change-medium' QMP command if used
> on a block device (by calling qmp_blockdev_change_medium()).
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
>  hmp.c | 27 +++++++++++++++------------
>  1 file changed, 15 insertions(+), 12 deletions(-)

Oh wow - this one survived untouched from an earlier posting :)

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium Max Reitz
@ 2015-01-28 21:08   ` Eric Blake
  2015-01-28 21:22     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:08 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Add an option to qmp_blockdev_change_medium() which allows changing the
> read-only status of the block device whose medium is changed.
> 
> Some drives do not have a inherently fixed read-only status; for
> instance, floppy disks can be set read-only or writable independently of
> the drive. Some users may find it useful to be able to therefore change
> the read-only status of a block device when changing the medium.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  blockdev.c           | 25 ++++++++++++++++++++++++-
>  hmp.c                |  2 +-
>  qapi/block-core.json | 24 +++++++++++++++++++++++-
>  qmp-commands.hx      | 24 +++++++++++++++++++++++-
>  qmp.c                |  3 ++-
>  5 files changed, 73 insertions(+), 5 deletions(-)
> 

>  
>  ##
> +# @BlockdevChangeReadOnlyMode:
> +#
> +# Specifies the new read-only mode of a block device subject to the
> +# @blockdev-change-medium command.
> +#
> +# @retain:  Retains the current read-only mode
> +#
> +# @ro:      Makes the device read-only
> +#
> +# @rw:      Makes the device writable
> +#
> +# Since: 2.3
> +##
> +{ 'enum': 'BlockdevChangeReadOnlyMode',
> +  'data': ['retain', 'ro', 'rw'] }

Bike-shedding; would 'read-only' and 'read-write' look any better than
abbreviations?  Doesn't affect functionality, though.

> +
> +
> +##
>  # @blockdev-change-medium:
>  #
>  # Changes the medium inserted into a block device by ejecting the current medium
> @@ -1799,12 +1817,16 @@
>  # @format:      #optional, format to open the new image with (defaults to the
>  #               probed format)
>  #
> +# @read-only:   #optional, change the read-only mode of the device; defaults to
> +#               'retain'

"read-only":"rw" looks weird.  Maybe naming this "read-mode" instead of
"read-only" would help.  Again, bikeshedding that doesn't affect
functionality, but worth considering for the interface cleanliness.

So functionally, if nothing changes, you can add:
Reviewed-by: Eric Blake <eblake@redhat.com>

But if you change the interface on a respin, drop my R-b to make sure I
check and still like the new naming conventions.

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium
  2015-01-28 21:01   ` Eric Blake
@ 2015-01-28 21:19     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 21:19 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 16:01, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> Introduce a new QMP command 'blockdev-change-medium' which is intended
>> to replace the 'change' command for block devices. The existing function
>> qmp_change_blockdev() is accordingly renamed to
>> qmp_blockdev_change_medium().
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c                |  7 ++++---
>>   include/sysemu/blockdev.h |  2 --
>>   qapi-schema.json          |  3 ++-
>>   qapi/block-core.json      | 23 +++++++++++++++++++++++
>>   qmp-commands.hx           | 31 +++++++++++++++++++++++++++++++
>>   qmp.c                     |  2 +-
>>   6 files changed, 61 insertions(+), 7 deletions(-)
>>
>> +++ b/qapi-schema.json
>> @@ -1649,7 +1649,8 @@
>>   #          device between when these calls are executed is undefined.
>>   #
>>   # Notes:  It is strongly recommended that this interface is not used especially
>> -#         for changing block devices.
>> +#         for changing block devices.  Please use blockdev-change-medium
>> +#         instead (for VNC, please use change-vnc-password).
> Not grammatically wrong, but still feels a bit awkward.  Maybe better
> worded as:
>
> This interface is deprecated, and it is strongly recommended that you
> avoid using it.  For changing block devices, use blockdev-change-medium;
> for changing VNC parameters, use change-vnc-password.

Thanks, I'll change it.

>>   ##
>> +# @blockdev-change-medium:
>> +#
>> +# Changes the medium inserted into a block device by ejecting the current medium
>> +# and loading a new image file which is inserted as the new medium (this command
>> +# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
>> +# and blockdev-close-tray).
>> +#
>> +# @device:      block device name
>> +#
>> +# @filename:    filename of the new image to be loaded
>> +#
>> +# @format:      #optional, format to open the new image with (defaults to the
>> +#               probed format)
>> +#
>> +# Since: 2.3
>> +##
>> +{ 'command': 'blockdev-change-medium',
>> +  'data': { 'device': 'str',
>> +            'filename': 'str',
>> +            '*format': 'str' } }
> Intentional that there is no way to specify 'force'?  I can live with
> that (force is a sledgehammer; and someone that can justify using it can
> just use the lower-level functions themselves.  No need to bloat the
> nice wrapper interface with something that is usually not needed).

Yes, I'd rather drop 'force' here.

> I'm unclear on whether this command will wait for the tray open to
> happen, or if it fails in the middle if the tray was locked and a
> request sent to the guest but the guest did not act fast enough to
> unlock things.  As such, I'm not quite sure if this interface is missing
> any parameters.

Well, I'd rather call this interface deprecated from the start (it's 
basically as deprecated as 'change' is, only that 'change' is even worse 
because it unites multiple different commands) than making it suitable 
for any situation.

There are two points from my perspective: First, this is mainly a 
replacement for 'change'. Since 'change' did not have a 'force' 
parameter, I don't see the need to have one here either. Second, we can 
always add additional parameters later (without breaking compatibility); 
for instance, in this series still the read-only mode parameter will be 
added.

>> +Examples:
>> +
>> +1. Change a removable medium
>> +
>> +-> { "execute": "blockdev-change-medium",
>> +             "arguments": { "device": "ide1-cd0",
>> +                            "filename": "/srv/images/Fedora-12-x86_64-DVD.iso",
> Wow - you're still testing a Fedora 12 image?

No, I got that file name from the 'change' example. :-)

> I'm a bit reluctant to mark this one reviewed, without more discussion.

No problem. I'll have to send a v2 anyway.

Max

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

* Re: [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium
  2015-01-28 21:08   ` Eric Blake
@ 2015-01-28 21:22     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 21:22 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 16:08, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> Add an option to qmp_blockdev_change_medium() which allows changing the
>> read-only status of the block device whose medium is changed.
>>
>> Some drives do not have a inherently fixed read-only status; for
>> instance, floppy disks can be set read-only or writable independently of
>> the drive. Some users may find it useful to be able to therefore change
>> the read-only status of a block device when changing the medium.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   blockdev.c           | 25 ++++++++++++++++++++++++-
>>   hmp.c                |  2 +-
>>   qapi/block-core.json | 24 +++++++++++++++++++++++-
>>   qmp-commands.hx      | 24 +++++++++++++++++++++++-
>>   qmp.c                |  3 ++-
>>   5 files changed, 73 insertions(+), 5 deletions(-)
>>
>>   
>>   ##
>> +# @BlockdevChangeReadOnlyMode:
>> +#
>> +# Specifies the new read-only mode of a block device subject to the
>> +# @blockdev-change-medium command.
>> +#
>> +# @retain:  Retains the current read-only mode
>> +#
>> +# @ro:      Makes the device read-only
>> +#
>> +# @rw:      Makes the device writable
>> +#
>> +# Since: 2.3
>> +##
>> +{ 'enum': 'BlockdevChangeReadOnlyMode',
>> +  'data': ['retain', 'ro', 'rw'] }
> Bike-shedding; would 'read-only' and 'read-write' look any better than
> abbreviations?  Doesn't affect functionality, though.

I don't mind either way.

>> +
>> +
>> +##
>>   # @blockdev-change-medium:
>>   #
>>   # Changes the medium inserted into a block device by ejecting the current medium
>> @@ -1799,12 +1817,16 @@
>>   # @format:      #optional, format to open the new image with (defaults to the
>>   #               probed format)
>>   #
>> +# @read-only:   #optional, change the read-only mode of the device; defaults to
>> +#               'retain'
> "read-only":"rw" looks weird.  Maybe naming this "read-mode" instead of
> "read-only" would help.  Again, bikeshedding that doesn't affect
> functionality, but worth considering for the interface cleanliness.

Well, actually it's write-mode, because reading will always be possible. :-)

"access" would be another possibility, or "read-only-mode".

> So functionally, if nothing changes, you can add:
> Reviewed-by: Eric Blake <eblake@redhat.com>
>
> But if you change the interface on a respin, drop my R-b to make sure I
> check and still like the new naming conventions.

Understood.

Max

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

* Re: [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command Max Reitz
@ 2015-01-28 21:22   ` Eric Blake
  2015-01-28 21:26     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:22 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Expose the new read-only option of 'blockdev-change-medium' for the
> 'change' HMP command.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
>  hmp-commands.hx | 20 +++++++++++++++++---
>  hmp.c           | 21 ++++++++++++++++++++-
>  2 files changed, 37 insertions(+), 4 deletions(-)
> 

Already reviewed...

>  
> +@var{read-only} may be used to change the read-only status of the device. It
> +accepts the following values:
> +
> +@table @var
> +@item retain
> +Retains the current status; this is the default.
> +
> +@item ro
> +Makes the device read-only.
> +
> +@item rw
> +Makes the device writable.

Hmm.  I suggested in 47/50 to rename the QMP enum values to something
longer, which would affect this on a rebase.  On the other hand, it
would be nice to make the HMP counterpart support BOTH spellings for
convenience ('read-write' for legibility, 'rw' for brevity in typing);
and I have no clue if tab completion starts to play a role either.  Up
to you if you want to add complexity or leave things simple and stupid
(the choices we make in HMP for user-friendliness have no bearing on
what libvirt will want to do, so I really have no strong preference).

...so my review still stands if nothing changes, and is probably worth
dropping if you respin to add user-friendly complexity.


>      const char *arg = qdict_get_try_str(qdict, "arg");
> +    const char *read_only = qdict_get_try_str(qdict, "read-only");
> +    BlockdevChangeReadOnlyMode read_only_mode = 0;
>      Error *err = NULL;
>  
>      if (strcmp(device, "vnc") == 0) {
> +        if (read_only) {
> +            monitor_printf(mon, "Parameter 'read-only' is invalid for VNC");

Hmm. In HMP, you don't type the parameter name (it is implicit based on
the rules for converting positional HMP arguments into dictionary
entries for use in the rest of the code).  In particular, that means
that if I type 'change vnc password rw', that means that 'rw' will be in
the "read-only" parameter position, even though it has nothing to do
with read-only.  [hmm - how did 'change vnc password XXX' work anyways,
since the .params for 'change' didn't allow a third argument before your
patch?]

At any rate, the idea I mentioned in the QMP patch about naming the
parameter 'read-mode' instead of 'read-only' might make for nicer error
messages.

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command
  2015-01-28 21:22   ` Eric Blake
@ 2015-01-28 21:26     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 21:26 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 16:22, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> Expose the new read-only option of 'blockdev-change-medium' for the
>> 'change' HMP command.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>> ---
>>   hmp-commands.hx | 20 +++++++++++++++++---
>>   hmp.c           | 21 ++++++++++++++++++++-
>>   2 files changed, 37 insertions(+), 4 deletions(-)
>>
> Already reviewed...
>
>>   
>> +@var{read-only} may be used to change the read-only status of the device. It
>> +accepts the following values:
>> +
>> +@table @var
>> +@item retain
>> +Retains the current status; this is the default.
>> +
>> +@item ro
>> +Makes the device read-only.
>> +
>> +@item rw
>> +Makes the device writable.
> Hmm.  I suggested in 47/50 to rename the QMP enum values to something
> longer, which would affect this on a rebase.  On the other hand, it
> would be nice to make the HMP counterpart support BOTH spellings for
> convenience ('read-write' for legibility, 'rw' for brevity in typing);
> and I have no clue if tab completion starts to play a role either.  Up
> to you if you want to add complexity or leave things simple and stupid
> (the choices we make in HMP for user-friendliness have no bearing on
> what libvirt will want to do, so I really have no strong preference).
>
> ...so my review still stands if nothing changes, and is probably worth
> dropping if you respin to add user-friendly complexity.

I probably won't care for brevity too much. Again, if we want to allow 
shortcuts later on, it won't break compatibility so we don't really need 
to worry about it now (although I guess if we don't add it now, we won't 
add it ever).

>>       const char *arg = qdict_get_try_str(qdict, "arg");
>> +    const char *read_only = qdict_get_try_str(qdict, "read-only");
>> +    BlockdevChangeReadOnlyMode read_only_mode = 0;
>>       Error *err = NULL;
>>   
>>       if (strcmp(device, "vnc") == 0) {
>> +        if (read_only) {
>> +            monitor_printf(mon, "Parameter 'read-only' is invalid for VNC");
> Hmm. In HMP, you don't type the parameter name (it is implicit based on
> the rules for converting positional HMP arguments into dictionary
> entries for use in the rest of the code).  In particular, that means
> that if I type 'change vnc password rw', that means that 'rw' will be in
> the "read-only" parameter position, even though it has nothing to do
> with read-only.  [hmm - how did 'change vnc password XXX' work anyways,
> since the .params for 'change' didn't allow a third argument before your
> patch?]

Well, "help change" will tell you that that parameter is named 
"read-only", so I think mentioning the parameter name (instead of 
"garbage at the end of line" or something like that) is fine.

Max

> At any rate, the idea I mentioned in the QMP patch about naming the
> parameter 'read-mode' instead of 'read-only' might make for nicer error
> messages.

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

* Re: [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive()
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive() Max Reitz
@ 2015-01-28 21:27   ` Eric Blake
  2015-01-28 21:28     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:27 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> This patch allows specifying the interface to be used for the drive, and
> makes specifying a path optional (if the path is None, the "file" option
> will be omitted, thus creating an empty drive).
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  tests/qemu-iotests/iotests.py | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 

> +
> +        if not path is None:
> +            options.append('file=%s' % path)

Works, but it is more idiomatic to use 'if path is not None:', based on
a grep of the source tree.

With that minor switch,
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive()
  2015-01-28 21:27   ` Eric Blake
@ 2015-01-28 21:28     ` Max Reitz
  2015-01-28 21:58       ` Eric Blake
  0 siblings, 1 reply; 107+ messages in thread
From: Max Reitz @ 2015-01-28 21:28 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 16:27, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> This patch allows specifying the interface to be used for the drive, and
>> makes specifying a path optional (if the path is None, the "file" option
>> will be omitted, thus creating an empty drive).
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   tests/qemu-iotests/iotests.py | 9 ++++++---
>>   1 file changed, 6 insertions(+), 3 deletions(-)
>>
>> +
>> +        if not path is None:
>> +            options.append('file=%s' % path)
> Works, but it is more idiomatic to use 'if path is not None:', based on
> a grep of the source tree.

Did I ever mention I don't know Python very well?

That sounds a lot better, will do, thanks.

> With that minor switch,
> Reviewed-by: Eric Blake <eblake@redhat.com>

On to the last patch! :-)

Max

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

* Re: [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands
  2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands Max Reitz
@ 2015-01-28 21:57   ` Eric Blake
  2015-01-28 22:02     ` Max Reitz
  0 siblings, 1 reply; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:57 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/27/2015 12:46 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  tests/qemu-iotests/118     | 649 +++++++++++++++++++++++++++++++++++++++++++++
>  tests/qemu-iotests/118.out |   5 +
>  tests/qemu-iotests/group   |   1 +
>  3 files changed, 655 insertions(+)
>  create mode 100755 tests/qemu-iotests/118
>  create mode 100644 tests/qemu-iotests/118.out
> 

Looks like lots of useful tests and good coverage, including things like
no-op open of an already open tray.  I didn't spot any obvious flaws
(but my python is weak), or think of any obvious missing tests, so feel
free to add:

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive()
  2015-01-28 21:28     ` Max Reitz
@ 2015-01-28 21:58       ` Eric Blake
  0 siblings, 0 replies; 107+ messages in thread
From: Eric Blake @ 2015-01-28 21:58 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

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

On 01/28/2015 02:28 PM, Max Reitz wrote:
> On 2015-01-28 at 16:27, Eric Blake wrote:
>> On 01/27/2015 12:46 PM, Max Reitz wrote:
>>> This patch allows specifying the interface to be used for the drive, and
>>> makes specifying a path optional (if the path is None, the "file" option
>>> will be omitted, thus creating an empty drive).
>>>
>>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>>> ---
>>>   tests/qemu-iotests/iotests.py | 9 ++++++---
>>>   1 file changed, 6 insertions(+), 3 deletions(-)
>>>
>>> +
>>> +        if not path is None:
>>> +            options.append('file=%s' % path)
>> Works, but it is more idiomatic to use 'if path is not None:', based on
>> a grep of the source tree.
> 
> Did I ever mention I don't know Python very well?

The feeling is mutual.  So it's the blind leading the blind :)

> 
> That sounds a lot better, will do, thanks.
> 
>> With that minor switch,
>> Reviewed-by: Eric Blake <eblake@redhat.com>
> 
> On to the last patch! :-)
> 
> Max
> 
> 

-- 
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] 107+ messages in thread

* Re: [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands
  2015-01-28 21:57   ` Eric Blake
@ 2015-01-28 22:02     ` Max Reitz
  0 siblings, 0 replies; 107+ messages in thread
From: Max Reitz @ 2015-01-28 22:02 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, Jeff Cody, Markus Armbruster,
	Stefan Hajnoczi, John Snow

On 2015-01-28 at 16:57, Eric Blake wrote:
> On 01/27/2015 12:46 PM, Max Reitz wrote:
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   tests/qemu-iotests/118     | 649 +++++++++++++++++++++++++++++++++++++++++++++
>>   tests/qemu-iotests/118.out |   5 +
>>   tests/qemu-iotests/group   |   1 +
>>   3 files changed, 655 insertions(+)
>>   create mode 100755 tests/qemu-iotests/118
>>   create mode 100644 tests/qemu-iotests/118.out
>>
> Looks like lots of useful tests and good coverage, including things like
> no-op open of an already open tray.  I didn't spot any obvious flaws
> (but my python is weak), or think of any obvious missing tests, so feel
> free to add:
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thank you very much for reviewing this series! I really did not think 
someone would jump on this so fast. :-)

Max

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

* Re: [Qemu-devel] [PATCH RESEND 03/50] hw/block/fdc: Implement tray status
  2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 03/50] hw/block/fdc: Implement tray status Max Reitz
@ 2015-01-30 21:04   ` John Snow
  0 siblings, 0 replies; 107+ messages in thread
From: John Snow @ 2015-01-30 21:04 UTC (permalink / raw)
  To: Max Reitz, qemu-devel
  Cc: Kevin Wolf, Jeff Cody, Fam Zheng, Markus Armbruster, Stefan Hajnoczi



On 01/27/2015 02:45 PM, Max Reitz wrote:
> The tray of an FDD is open iff there is no medium inserted (there are
> only two states for an FDD: "medium inserted" or "no medium inserted").
>
> This results in the tray being reported as open if qemu has been started
> with the default floppy drive, which breaks some tests. Fix them.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>   hw/block/fdc.c             | 20 +++++++++++++---
>   tests/fdc-test.c           |  4 +---
>   tests/qemu-iotests/067.out | 60 +++++++---------------------------------------
>   tests/qemu-iotests/071.out |  2 --
>   tests/qemu-iotests/081.out |  1 -
>   tests/qemu-iotests/087.out |  5 ----
>   6 files changed, 26 insertions(+), 66 deletions(-)
>
> diff --git a/hw/block/fdc.c b/hw/block/fdc.c
> index 2bf87c9..0c5a6b4 100644
> --- a/hw/block/fdc.c
> +++ b/hw/block/fdc.c
> @@ -192,6 +192,8 @@ typedef struct FDrive {
>       uint8_t ro;               /* Is read-only           */
>       uint8_t media_changed;    /* Is media changed       */
>       uint8_t media_rate;       /* Data rate of medium    */
> +
> +    bool media_inserted;      /* Is there a medium in the tray */
>   } FDrive;
>
>   static void fd_init(FDrive *drv)
> @@ -261,7 +263,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
>   #endif
>           drv->head = head;
>           if (drv->track != track) {
> -            if (drv->blk != NULL && blk_is_inserted(drv->blk)) {
> +            if (drv->media_inserted) {
>                   drv->media_changed = 0;
>               }
>               ret = 1;
> @@ -270,7 +272,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
>           drv->sect = sect;
>       }
>
> -    if (drv->blk == NULL || !blk_is_inserted(drv->blk)) {
> +    if (!drv->media_inserted) {
>           ret = 2;
>       }
>
> @@ -296,7 +298,7 @@ static void fd_revalidate(FDrive *drv)
>           ro = blk_is_read_only(drv->blk);
>           pick_geometry(drv->blk, &nb_heads, &max_track,
>                         &last_sect, drv->drive, &drive, &rate);
> -        if (!blk_is_inserted(drv->blk)) {
> +        if (!drv->media_inserted) {
>               FLOPPY_DPRINTF("No disk in drive\n");
>           } else {
>               FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
> @@ -2062,12 +2064,21 @@ static void fdctrl_change_cb(void *opaque, bool load)
>   {
>       FDrive *drive = opaque;
>
> +    drive->media_inserted = load && drive->blk && blk_is_inserted(drive->blk);
> +
>       drive->media_changed = 1;
>       fd_revalidate(drive);
>   }
>
> +static bool fdctrl_is_tray_open(void *opaque)
> +{
> +    FDrive *drive = opaque;
> +    return !drive->media_inserted;
> +}
> +
>   static const BlockDevOps fdctrl_block_ops = {
>       .change_media_cb = fdctrl_change_cb,
> +    .is_tray_open = fdctrl_is_tray_open,
>   };
>
>   /* Init functions */
> @@ -2095,6 +2106,9 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
>           fdctrl_change_cb(drive, 0);
>           if (drive->blk) {
>               blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive);
> +            if (blk_is_inserted(drive->blk)) {
> +                drive->media_inserted = true;
> +            }
>           }
>       }
>   }
> diff --git a/tests/fdc-test.c b/tests/fdc-test.c
> index 3c6c83c..f287c10 100644
> --- a/tests/fdc-test.c
> +++ b/tests/fdc-test.c
> @@ -293,9 +293,7 @@ static void test_media_insert(void)
>       qmp_discard_response("{'execute':'change', 'arguments':{"
>                            " 'device':'floppy0', 'target': %s, 'arg': 'raw' }}",
>                            test_image);
> -    qmp_discard_response(""); /* ignore event
> -                                 (FIXME open -> open transition?!) */
> -    qmp_discard_response(""); /* ignore event */
> +    qmp_discard_response(""); /* ignore event (open -> close) */
>
>       dir = inb(FLOPPY_BASE + reg_dir);
>       assert_bit_set(dir, DSKCHG);
> diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
> index 00b3eae..42bae32 100644
> --- a/tests/qemu-iotests/067.out
> +++ b/tests/qemu-iotests/067.out
> @@ -69,7 +69,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -131,7 +131,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -165,17 +165,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
>           "tray-open": true
>       }
>   }
> -{
> -    "timestamp": {
> -        "seconds":  TIMESTAMP,
> -        "microseconds":  TIMESTAMP
> -    },
> -    "event": "DEVICE_TRAY_MOVED",
> -    "data": {
> -        "device": "floppy0",
> -        "tray-open": true
> -    }
> -}
>
>
>   === -drive/device_add and device_del ===
> @@ -246,7 +235,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -312,7 +301,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -346,17 +335,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
>           "tray-open": true
>       }
>   }
> -{
> -    "timestamp": {
> -        "seconds":  TIMESTAMP,
> -        "microseconds":  TIMESTAMP
> -    },
> -    "event": "DEVICE_TRAY_MOVED",
> -    "data": {
> -        "device": "floppy0",
> -        "tray-open": true
> -    }
> -}
>
>
>   === drive_add/device_add and device_del ===
> @@ -386,7 +364,7 @@ Testing:
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -496,7 +474,7 @@ Testing:
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -530,17 +508,6 @@ Testing:
>           "tray-open": true
>       }
>   }
> -{
> -    "timestamp": {
> -        "seconds":  TIMESTAMP,
> -        "microseconds":  TIMESTAMP
> -    },
> -    "event": "DEVICE_TRAY_MOVED",
> -    "data": {
> -        "device": "floppy0",
> -        "tray-open": true
> -    }
> -}
>
>
>   === blockdev_add/device_add and device_del ===
> @@ -571,7 +538,7 @@ Testing:
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -681,7 +648,7 @@ Testing:
>               "device": "floppy0",
>               "locked": false,
>               "removable": true,
> -            "tray_open": false,
> +            "tray_open": true,
>               "type": "unknown"
>           },
>           {
> @@ -760,16 +727,5 @@ Testing:
>           "tray-open": true
>       }
>   }
> -{
> -    "timestamp": {
> -        "seconds":  TIMESTAMP,
> -        "microseconds":  TIMESTAMP
> -    },
> -    "event": "DEVICE_TRAY_MOVED",
> -    "data": {
> -        "device": "floppy0",
> -        "tray-open": true
> -    }
> -}
>
>   *** done
> diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
> index c8ecfaf..904ce15 100644
> --- a/tests/qemu-iotests/071.out
> +++ b/tests/qemu-iotests/071.out
> @@ -52,7 +52,6 @@ read failed: Input/output error
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>   QEMU_PROG: Failed to flush the L2 table cache: Input/output error
>   QEMU_PROG: Failed to flush the refcount block cache: Input/output error
>
> @@ -95,7 +94,6 @@ read failed: Input/output error
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>   QEMU_PROG: Failed to flush the L2 table cache: Input/output error
>   QEMU_PROG: Failed to flush the refcount block cache: Input/output error
>
> diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
> index 2375916..b1e4909 100644
> --- a/tests/qemu-iotests/081.out
> +++ b/tests/qemu-iotests/081.out
> @@ -38,7 +38,6 @@ read 10485760/10485760 bytes at offset 0
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>
>
>   == using quorum rewrite corrupted mode ==
> diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
> index 681ef93..033cc3b 100644
> --- a/tests/qemu-iotests/087.out
> +++ b/tests/qemu-iotests/087.out
> @@ -15,7 +15,6 @@ QMP_VERSION
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>
>
>   === aio=native without O_DIRECT ===
> @@ -27,7 +26,6 @@ QMP_VERSION
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>
>
>   === Encrypted image ===
> @@ -40,7 +38,6 @@ QMP_VERSION
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>
>   Testing:
>   QMP_VERSION
> @@ -49,7 +46,6 @@ QMP_VERSION
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>
>
>   === Missing driver ===
> @@ -62,6 +58,5 @@ QMP_VERSION
>   {"return": {}}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
>   {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
>
>   *** done
>

Since I am fated to care more about floppy disks than I have in the past:

Reviewed-by: John Snow <jsnow@redhat.com>

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

end of thread, other threads:[~2015-01-30 21:05 UTC | newest]

Thread overview: 107+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-27 19:45 [Qemu-devel] [PATCH RESEND 00/50] blockdev: BlockBackend and media Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 01/50] blockdev: Allow creation of BDS trees without BB Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 02/50] iotests: Only create BB if necessary Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 03/50] hw/block/fdc: Implement tray status Max Reitz
2015-01-30 21:04   ` John Snow
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 04/50] hw/usb-storage: Check whether BB is inserted Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 05/50] block: Fix BB AIOCB AioContext without BDS Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 06/50] block: Add blk_is_available() Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 07/50] block: Make bdrv_is_inserted() recursive Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 08/50] block/quorum: Implement bdrv_is_inserted() Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 09/50] block: Move guest_block_size into BlockBackend Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 10/50] block: Remove wr_highest_offset from BlockAcctStats Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 11/50] block: Move BlockAcctStats into BlockBackend Max Reitz
2015-01-27 20:31   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 12/50] block: Move I/O status and error actions into BB Max Reitz
2015-01-27 20:51   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 13/50] block: Add BlockBackendRootState Max Reitz
2015-01-27 21:03   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 14/50] block: Make some BB functions fall back to BBRS Max Reitz
2015-01-27 21:15   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 15/50] block: Fail requests to empty BlockBackend Max Reitz
2015-01-27 21:24   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 16/50] block: Prepare remaining BB functions for NULL BDS Max Reitz
2015-01-27 21:36   ` Eric Blake
2015-01-27 21:39     ` Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 17/50] block: Respect empty BB in bdrv_lookup_bs() Max Reitz
2015-01-27 21:56   ` Eric Blake
2015-01-28 18:31   ` John Snow
2015-01-28 18:35     ` Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 18/50] block: Respect empty BB in bdrv_query_info() Max Reitz
2015-01-27 21:57   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 19/50] blockdev: Use BlockBackend for blockdev-backup TA Max Reitz
2015-01-27 21:59   ` Eric Blake
2015-01-27 22:13     ` Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 20/50] blockdev: Check blk_is_available() in sn-del-int-sync Max Reitz
2015-01-27 22:10   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 21/50] blockdev: Check BB validity in internal snapshot TA Max Reitz
2015-01-27 23:02   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 22/50] blockdev: Check BB validity in drive-backup TA Max Reitz
2015-01-27 23:44   ` Eric Blake
2015-01-28 16:27     ` Max Reitz
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 23/50] blockdev: Catch NULL BDS in block_set_io_throttle Max Reitz
2015-01-28 15:26   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 24/50] blockdev: Check BB validity in block-stream Max Reitz
2015-01-28 15:28   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 25/50] blockdev: Check BB validity in block-commit Max Reitz
2015-01-28 16:09   ` Eric Blake
2015-01-27 19:45 ` [Qemu-devel] [PATCH RESEND 26/50] blockdev: Check BB validity in drive-backup Max Reitz
2015-01-28 16:20   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 27/50] blockdev: Check BB validity in blockdev-backup Max Reitz
2015-01-28 16:42   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 28/50] blockdev: Check BB validity in drive-mirror Max Reitz
2015-01-28 16:43   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 29/50] blockdev: Check BB validity in find_block_job() Max Reitz
2015-01-28 16:44   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 30/50] blockdev: Check BB validity in change-backing-file Max Reitz
2015-01-28 16:50   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 31/50] block: Add blk_insert_bs() Max Reitz
2015-01-28 16:52   ` Eric Blake
2015-01-28 16:58     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 32/50] blockdev: Check BB validity in eject and change Max Reitz
2015-01-28 17:42   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 33/50] blockdev: Respect NULL BDS in do_drive_del() Max Reitz
2015-01-28 17:45   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 34/50] blockdev: Do not create BDS for empty drive Max Reitz
2015-01-28 17:50   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 35/50] blockdev: Pull out blockdev option extraction Max Reitz
2015-01-28 19:23   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 36/50] blockdev: Allow more options for BB-less BDS tree Max Reitz
2015-01-28 19:26   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 37/50] block: Add blk_remove_bs() Max Reitz
2015-01-28 19:49   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 38/50] blockdev: Add blockdev-open-tray Max Reitz
2015-01-28 19:56   ` Eric Blake
2015-01-28 19:59     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 39/50] blockdev: Add blockdev-close-tray Max Reitz
2015-01-28 19:58   ` Eric Blake
2015-01-28 20:00     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 40/50] blockdev: Add blockdev-remove-medium Max Reitz
2015-01-28 20:11   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 41/50] blockdev: Add blockdev-insert-medium Max Reitz
2015-01-28 20:18   ` Eric Blake
2015-01-28 20:20     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 42/50] blockdev: Implement eject with basic operations Max Reitz
2015-01-28 20:26   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 43/50] blockdev: Implement change " Max Reitz
2015-01-28 20:30   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 44/50] block: Inquire tray state before tray-moved events Max Reitz
2015-01-28 20:37   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 45/50] qmp: Introduce blockdev-change-medium Max Reitz
2015-01-28 21:01   ` Eric Blake
2015-01-28 21:19     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 46/50] hmp: Use blockdev-change-medium for change command Max Reitz
2015-01-28 21:02   ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 47/50] blockdev: Add read-only option to blockdev-change-medium Max Reitz
2015-01-28 21:08   ` Eric Blake
2015-01-28 21:22     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 48/50] hmp: Add read-only option to change command Max Reitz
2015-01-28 21:22   ` Eric Blake
2015-01-28 21:26     ` Max Reitz
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 49/50] iotests: More options for VM.add_drive() Max Reitz
2015-01-28 21:27   ` Eric Blake
2015-01-28 21:28     ` Max Reitz
2015-01-28 21:58       ` Eric Blake
2015-01-27 19:46 ` [Qemu-devel] [PATCH RESEND 50/50] iotests: Add test for change-related QMP commands Max Reitz
2015-01-28 21:57   ` Eric Blake
2015-01-28 22:02     ` Max Reitz

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.