From ebf4cfdb6b33d07e53ceb0c883ca9a2a90f37eef Mon Sep 17 00:00:00 2001
Message-Id: <ebf4cfdb6b33d07e53ceb0c883ca9a2a90f37eef.1342518105.git.minovotn@redhat.com>
In-Reply-To: <27a73856ecc481c66c7afac8171f753887f32e31.1342518105.git.minovotn@redhat.com>
References: <27a73856ecc481c66c7afac8171f753887f32e31.1342518105.git.minovotn@redhat.com>
From: Jeffrey Cody <jcody@redhat.com>
Date: Wed, 30 May 2012 20:56:50 +0200
Subject: [PATCH 05/41] block: don't create mirror block job if the target
 bdrv_open() fails

RH-Author: Jeffrey Cody <jcody@redhat.com>
Message-id: <42d29a954aec142354dbf88ddfcf6f8e4dc2fe62.1338408171.git.jcody@redhat.com>
Patchwork-id: 39862
O-Subject: [RHEL6.4 qemu-kvm PATCH] block: don't create mirror block job if the target bdrv_open() fails
Bugzilla: 814102
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Luiz Capitulino <lcapitulino@redhat.com>

The function mirror_start() creates a block job, and then
opens the BDS.  It returns on error from bdrv_open(), which leaves
the block job orphaned, and the BDS 'in use'.

This patch makes sure that we don't create the block job at all if
the bdrv_open() fails - so the bdrv_open() is attempted
first, and then the block job is created if bdrv_open() was successful.

BZ: 814102
Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=4464544
Upstream: block-mirror is not upstream yet, but I replied to the
          relevant patch from Paolo upstream with the same code
          that is in the patch below.  Since downstream is already
          divergent w.r.t mirroring, I am going ahead and submitting
          this fix for RHEL 6.4.

Signed-off-by: Jeff Cody <jcody@redhat.com>
---
 block/mirror.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 block/mirror.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index ee546db..49649b4 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -263,28 +263,34 @@ int mirror_start(BlockDriverState *bs,
                  void *opaque, bool full)
 {
     MirrorBlockJob *s;
-    int ret;
+    BlockDriverState *target_bs;
+    int ret = 0;
 
-    s = block_job_create(&mirror_job_type, bs, speed, cb, opaque);
-    if (!s) {
-        return -EBUSY; /* bs must already be in use */
-    }
 
-    s->target = bdrv_new("");
-    ret = bdrv_open(s->target, target,
+    target_bs = bdrv_new("");
+    ret = bdrv_open(target_bs, target,
                     flags | BDRV_O_NO_BACKING | BDRV_O_NO_FLUSH | BDRV_O_CACHE_WB,
                     drv);
 
     if (ret < 0) {
-        bdrv_delete(s->target);
-        return ret;
+        bdrv_delete(target_bs);
+        goto exit;
     }
 
+    s = block_job_create(&mirror_job_type, bs, speed, cb, opaque);
+    if (!s) {
+        bdrv_delete(target_bs);
+        ret = -EBUSY; /* bs must already be in use */
+        goto exit;
+    }
+
+    s->target = target_bs;
     s->full = full;
     bdrv_set_dirty_tracking(bs, true);
     s->common.co = qemu_coroutine_create(mirror_run);
     trace_mirror_start(bs, s, s->common.co, opaque);
-    return 0;
+exit:
+    return ret;
 }
 
 void mirror_abort(BlockDriverState *bs)
-- 
1.7.10.4

