All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RFC] mirror: allow mirroring an intermediate image
@ 2015-04-09 14:33 Alberto Garcia
  0 siblings, 0 replies; only message in thread
From: Alberto Garcia @ 2015-04-09 14:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Alberto Garcia, qemu-block, Stefan Hajnoczi

This extends the drive-mirror command by allowing it to operate on
intermediate images. The device parameter can now take the node name
of the image to be mirrored. After the operation its overlay image
will point to the new one.

Signed-off-by: Alberto Garcia <berto@igalia.com>
---
 block.c              |  2 ++
 block/mirror.c       | 38 ++++++++++++++++++++++++++++++++++++--
 blockdev.c           |  7 ++-----
 qapi/block-core.json |  2 +-
 qmp-commands.hx      |  2 +-
 5 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/block.c b/block.c
index e892cb4..7bbae5a 100644
--- a/block.c
+++ b/block.c
@@ -1245,6 +1245,8 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
                     bs->backing_blocker);
     bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_STREAM,
                     bs->backing_blocker);
+    bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_MIRROR,
+                    bs->backing_blocker);
 out:
     bdrv_refresh_limits(bs, NULL);
 }
diff --git a/block/mirror.c b/block/mirror.c
index 189e8f8..c05598f 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -340,6 +340,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
     }
 
     if (s->should_complete && data->ret == 0) {
+        BlockDriverState *bdrv;
         BlockDriverState *to_replace = s->common.bs;
         if (s->to_replace) {
             to_replace = s->to_replace;
@@ -355,6 +356,39 @@ static void mirror_exit(BlockJob *job, void *opaque)
             bdrv_set_backing_hd(s->base, NULL);
             bdrv_unref(p);
         }
+
+        /* If a BlockDriverState was pointing to the image that we
+         * have just replaced, it must point now to the new one. */
+        for (bdrv = bdrv_next(NULL); bdrv; bdrv = bdrv_next(bdrv)) {
+            BlockDriverState *overlay;
+            AioContext *aio_context = bdrv_get_aio_context(bdrv);
+            aio_context_acquire(aio_context);
+            overlay = bdrv_find_overlay(bdrv, to_replace);
+            if (overlay) {
+                int ret, flags;
+                const char *filename, *format;
+
+                /* Change backing file in the header of the overlay image */
+                filename = to_replace->filename;
+                format = to_replace->drv ? to_replace->drv->format_name : "";
+                flags = bdrv_get_flags(overlay);
+                if (!(flags & BDRV_O_RDWR)) {
+                    bdrv_reopen(overlay, flags | BDRV_O_RDWR, NULL);
+                }
+                ret = bdrv_change_backing_file(overlay, filename, format);
+                if (!(flags & BDRV_O_RDWR)) {
+                    bdrv_reopen(overlay, flags, NULL);
+                }
+
+                /* If everything went well, update the BlockDriverState */
+                if (ret == 0) {
+                    bdrv_set_backing_hd(overlay, to_replace);
+                } else {
+                    data->ret = ret;
+                }
+            }
+            aio_context_release(aio_context);
+        }
     }
     if (s->to_replace) {
         bdrv_op_unblock_all(s->to_replace, s->replace_blocker);
@@ -608,8 +642,8 @@ static void mirror_complete(BlockJob *job, Error **errp)
     }
     if (!s->synced) {
         error_setg(errp,
-                   "The active block job for device '%s' cannot be completed",
-                   bdrv_get_device_name(job->bs));
+                   "The active block job for node '%s' cannot be completed",
+                   bdrv_get_device_or_node_name(job->bs));
         return;
     }
 
diff --git a/blockdev.c b/blockdev.c
index f24cf2d..eb2e5c1 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2464,7 +2464,6 @@ 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;
@@ -2504,12 +2503,10 @@ void qmp_drive_mirror(const char *device, const char *target,
         return;
     }
 
-    blk = blk_by_name(device);
-    if (!blk) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+    bs = bdrv_lookup_bs(device, device, errp);
+    if (!bs) {
         return;
     }
-    bs = blk_bs(blk);
 
     aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 60b9664..3c10f89 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -903,7 +903,7 @@
 #
 # Start mirroring a block device's writes to a new destination.
 #
-# @device:  the name of the device whose writes should be mirrored.
+# @device: the device or node name of the image whose writes should be mirrored.
 #
 # @target: the target of the new image. If the file exists, or if it
 #          is a device, the existing file/device will be used as the new
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3a42ad0..91902a1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1397,7 +1397,7 @@ of the source.
 
 Arguments:
 
-- "device": device name to operate on (json-string)
+- "device": device or node name to operate on (json-string)
 - "target": name of new image file (json-string)
 - "format": format of new image (json-string, optional)
 - "node-name": the name of the new block driver state in the node graph
-- 
2.1.4

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-04-09 14:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-09 14:33 [Qemu-devel] [PATCH RFC] mirror: allow mirroring an intermediate image Alberto Garcia

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.