The mirror block job currently only operates on a root block node. It
might be desired to use a throttle node as the root node for limiting
the guest IO, without also limiting mirror operations.

There is no obvious reason why mirror should only be able to operate
on a root block node.

When there is no explicit @replaces argument, implicit filters on top
are skipped. Allowing mirror to operate on non-root nodes does not
change that fact and keeps the behavior consistent with the
documentation for @replaces.

Signed-off-by: Fiona Ebner <[email protected]>
---

Changes in v2:
* Update QAPI description.

 blockdev.c           | 20 +++++++++++++++++---
 qapi/block-core.json |  4 ++--
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 6e86c6262f..0f70973326 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2987,13 +2987,19 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
     bool target_is_zero;
     int ret;
 
-    bs = qmp_get_root_bs(arg->device, errp);
+    bdrv_graph_rdlock_main_loop();
+    bs = bdrv_lookup_bs(arg->device, arg->device, errp);
     if (!bs) {
+        bdrv_graph_rdunlock_main_loop();
+        return;
+    }
+    if (!bdrv_is_inserted(bs)) {
+        error_setg(errp, "Device has no medium");
+        bdrv_graph_rdunlock_main_loop();
         return;
     }
 
     /* Early check to avoid creating target */
-    bdrv_graph_rdlock_main_loop();
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
         bdrv_graph_rdunlock_main_loop();
         return;
@@ -3150,10 +3156,18 @@ void qmp_blockdev_mirror(const char *job_id,
     BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
     int ret;
 
-    bs = qmp_get_root_bs(device, errp);
+    bdrv_graph_rdlock_main_loop();
+    bs = bdrv_lookup_bs(device, device, errp);
     if (!bs) {
+        bdrv_graph_rdunlock_main_loop();
         return;
     }
+    if (!bdrv_is_inserted(bs)) {
+        error_setg(errp, "Device has no medium");
+        bdrv_graph_rdunlock_main_loop();
+        return;
+    }
+    bdrv_graph_rdunlock_main_loop();
 
     target_bs = bdrv_lookup_bs(target, target, errp);
     if (!target_bs) {
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 741c8165c0..469297ea70 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2250,7 +2250,7 @@
 # @job-id: identifier for the newly-created block job.  If omitted,
 #     the device name will be used.  (Since 2.7)
 #
-# @device: the device name or node-name of a root node whose writes
+# @device: the device name or node-name of a block node whose writes
 #     should be mirrored.
 #
 # @target: the target of the new image.  If the file exists, or if it
@@ -2573,7 +2573,7 @@
 # @job-id: identifier for the newly-created block job.  If omitted,
 #     the device name will be used.  (Since 2.7)
 #
-# @device: The device name or node-name of a root node whose writes
+# @device: The device name or node-name of a block node whose writes
 #     should be mirrored.
 #
 # @target: the id or node-name of the block device to mirror to.  This
-- 
2.47.3



Reply via email to