ae23c9
From 7ec94ee16262eb0da7fb7788347a65162845b1c2 Mon Sep 17 00:00:00 2001
ae23c9
From: Kevin Wolf <kwolf@redhat.com>
ae23c9
Date: Wed, 10 Oct 2018 13:19:57 +0100
ae23c9
Subject: [PATCH 3/5] mirror: Fail gracefully for source == target
ae23c9
ae23c9
RH-Author: Kevin Wolf <kwolf@redhat.com>
ae23c9
Message-id: <20181010131957.23198-2-kwolf@redhat.com>
ae23c9
Patchwork-id: 82564
ae23c9
O-Subject: [RHEL-8 qemu-kvm PATCH 1/1] mirror: Fail gracefully for source == target
ae23c9
Bugzilla: 1637963
ae23c9
RH-Acked-by: John Snow <jsnow@redhat.com>
ae23c9
RH-Acked-by: Fam Zheng <famz@redhat.com>
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
ae23c9
blockdev-mirror with the same node for source and target segfaults
ae23c9
today: A node is in its own backing chain, so mirror_start_job() decides
ae23c9
that this is an active commit. When adding the intermediate nodes with
ae23c9
block_job_add_bdrv(), it starts the iteration through the subchain with
ae23c9
the backing file of source, though, so it never reaches target and
ae23c9
instead runs into NULL at the base.
ae23c9
ae23c9
While we could fix that by starting with source itself, there is no
ae23c9
point in allowing mirroring a node into itself and I wouldn't be
ae23c9
surprised if this caused more problems later.
ae23c9
ae23c9
So just check for this scenario and error out.
ae23c9
ae23c9
Cc: qemu-stable@nongnu.org
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Reviewed-by: Eric Blake <eblake@redhat.com>
ae23c9
(cherry picked from commit 86fae10c64d642256cf019e6829929fa0d259c7a)
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 block/mirror.c             | 5 +++++
ae23c9
 tests/qemu-iotests/041     | 6 ++++++
ae23c9
 tests/qemu-iotests/041.out | 4 ++--
ae23c9
 3 files changed, 13 insertions(+), 2 deletions(-)
ae23c9
ae23c9
diff --git a/block/mirror.c b/block/mirror.c
ae23c9
index 163b1d4..313e6e9 100644
ae23c9
--- a/block/mirror.c
ae23c9
+++ b/block/mirror.c
ae23c9
@@ -1149,6 +1149,11 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
ae23c9
         buf_size = DEFAULT_MIRROR_BUF_SIZE;
ae23c9
     }
ae23c9
 
ae23c9
+    if (bs == target) {
ae23c9
+        error_setg(errp, "Can't mirror node into itself");
ae23c9
+        return;
ae23c9
+    }
ae23c9
+
ae23c9
     /* In the case of active commit, add dummy driver to provide consistent
ae23c9
      * reads on the top, while disabling it in the intermediate nodes, and make
ae23c9
      * the backing chain writable. */
ae23c9
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
ae23c9
index c20ac7d..9336ab6 100755
ae23c9
--- a/tests/qemu-iotests/041
ae23c9
+++ b/tests/qemu-iotests/041
ae23c9
@@ -234,6 +234,12 @@ class TestSingleBlockdev(TestSingleDrive):
ae23c9
         result = self.vm.qmp("blockdev-add", **args)
ae23c9
         self.assert_qmp(result, 'return', {})
ae23c9
 
ae23c9
+    def test_mirror_to_self(self):
ae23c9
+        result = self.vm.qmp(self.qmp_cmd, job_id='job0',
ae23c9
+                             device=self.qmp_target, sync='full',
ae23c9
+                             target=self.qmp_target)
ae23c9
+        self.assert_qmp(result, 'error/class', 'GenericError')
ae23c9
+
ae23c9
     test_large_cluster = None
ae23c9
     test_image_not_found = None
ae23c9
     test_small_buffer2 = None
ae23c9
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
ae23c9
index c28b392..e071d0b 100644
ae23c9
--- a/tests/qemu-iotests/041.out
ae23c9
+++ b/tests/qemu-iotests/041.out
ae23c9
@@ -1,5 +1,5 @@
ae23c9
-.....................................................................................
ae23c9
+........................................................................................
ae23c9
 ----------------------------------------------------------------------
ae23c9
-Ran 85 tests
ae23c9
+Ran 88 tests
ae23c9
 
ae23c9
 OK
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9