All of lore.kernel.org
 help / color / mirror / Atom feed
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, berrange@redhat.com,
	ehabkost@redhat.com, qemu-devel@nongnu.org, mreitz@redhat.com,
	pbonzini@redhat.com, den@virtuozzo.com
Subject: [PATCH v0 2/2] block: allow to set 'drive' property on a realized block device
Date: Sun, 10 Nov 2019 22:03:10 +0300	[thread overview]
Message-ID: <20191110190310.19799-3-dplotnikov@virtuozzo.com> (raw)
In-Reply-To: <20191110190310.19799-1-dplotnikov@virtuozzo.com>

This allows to change (replace) the file on a block device and is useful
to workaround exclusive file access restrictions, e.g. to implement VM
migration with a shared disk stored on some storage with the exclusive
file opening model: a destination VM is started waiting for incomming
migration with a fake image drive, and later, on the last migration
phase, the fake image file is replaced with the real one.

Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
---
 hw/core/qdev-properties-system.c | 89 +++++++++++++++++++++++++++-----
 1 file changed, 77 insertions(+), 12 deletions(-)

diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index c534590dcd..aaab1370a4 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -79,8 +79,55 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
 
 /* --- drive --- */
 
-static void do_parse_drive(DeviceState *dev, const char *str, void **ptr,
-                           const char *propname, bool iothread, Error **errp)
+static void do_parse_drive_realized(DeviceState *dev, const char *str,
+                                    void **ptr, const char *propname,
+                                    bool iothread, Error **errp)
+{
+    BlockBackend *blk = *ptr;
+    BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
+    int ret;
+    bool blk_created = false;
+
+    if (!bs) {
+        error_setg(errp, "Can't find blockdev '%s'", str);
+        return;
+    }
+
+    if (!blk) {
+        AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
+                                     qemu_get_aio_context();
+        blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
+        blk_created = true;
+    } else {
+        if (blk_bs(blk)) {
+            blk_remove_bs(blk);
+        }
+    }
+
+    ret = blk_insert_bs(blk, bs, errp);
+
+    if (!ret && blk_created) {
+        if (blk_attach_dev(blk, dev) < 0) {
+            /*
+             * Shouldn't be any errors here since we just created
+             * the new blk because the device doesn't have any.
+             * Leave the message here in case blk_attach_dev is changed
+             */
+             error_setg(errp, "Can't attach drive '%s' to device '%s'",
+                        str, object_get_typename(OBJECT(dev)));
+        } else {
+            *ptr = blk;
+        }
+    }
+
+    if (blk_created) {
+        blk_unref(blk);
+    }
+}
+
+static void do_parse_drive_unrealized(DeviceState *dev, const char *str,
+                                      void **ptr, const char *propname,
+                                      bool iothread, Error **errp)
 {
     BlockBackend *blk;
     bool blk_created = false;
@@ -137,18 +184,34 @@ fail:
     }
 }
 
-static void parse_drive(DeviceState *dev, const char *str, void **ptr,
-                        const char *propname, Error **errp)
-{
-    do_parse_drive(dev, str, ptr, propname, false, errp);
-}
-
-static void parse_drive_iothread(DeviceState *dev, const char *str, void **ptr,
+static void parse_drive_realized(DeviceState *dev, const char *str, void **ptr,
                                  const char *propname, Error **errp)
 {
-    do_parse_drive(dev, str, ptr, propname, true, errp);
+    do_parse_drive_realized(dev, str, ptr, propname, false, errp);
 }
 
+static void parse_drive_realized_iothread(DeviceState *dev, const char *str,
+                                          void **ptr, const char *propname,
+                                          Error **errp)
+{
+    do_parse_drive_realized(dev, str, ptr, propname, true, errp);
+}
+
+static void parse_drive_unrealized(DeviceState *dev, const char *str,
+                                   void **ptr, const char *propname,
+                                   Error **errp)
+{
+    do_parse_drive_unrealized(dev, str, ptr, propname, false, errp);
+}
+
+static void parse_drive_unrealized_iothread(DeviceState *dev, const char *str,
+                                            void **ptr, const char *propname,
+                                            Error **errp)
+{
+    do_parse_drive_unrealized(dev, str, ptr, propname, true, errp);
+}
+
+
 static void release_drive(Object *obj, const char *name, void *opaque)
 {
     DeviceState *dev = DEVICE(obj);
@@ -188,13 +251,15 @@ static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque,
 static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
                       Error **errp)
 {
-    set_pointer(obj, v, opaque, NULL, parse_drive, name, errp);
+    set_pointer(obj, v, opaque, parse_drive_realized, parse_drive_unrealized,
+                name, errp);
 }
 
 static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
                                void *opaque, Error **errp)
 {
-    set_pointer(obj, v, opaque, NULL, parse_drive_iothread, name, errp);
+    set_pointer(obj, v, opaque, parse_drive_realized_iothread,
+                parse_drive_unrealized_iothread, name, errp);
 }
 
 const PropertyInfo qdev_prop_drive = {
-- 
2.17.0



  parent reply	other threads:[~2019-11-10 19:05 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-10 19:03 [PATCH v0 0/2] allow to set 'drive' property on a realized block device Denis Plotnikov
2019-11-10 19:03 ` [PATCH v0 1/2] qdev-properties-system: extend set_pionter for unrealized devices Denis Plotnikov
2019-11-18 18:54   ` Eduardo Habkost
2019-11-22 11:36     ` Denis Plotnikov
2019-11-25 15:30       ` Eduardo Habkost
2019-11-26  6:49         ` Denis Plotnikov
2019-11-26 16:38           ` Kevin Wolf
2019-11-10 19:03 ` Denis Plotnikov [this message]
2019-11-10 19:08   ` [PATCH v0 2/2] block: allow to set 'drive' property on a realized block device Denis Plotnikov
2019-11-18 10:50     ` Denis Plotnikov
2019-12-13  7:30       ` [PING]Re: " Denis Plotnikov
2019-12-13 10:32       ` Kevin Wolf
2019-12-16 14:51         ` Denis Plotnikov
2019-12-16 15:38           ` Kevin Wolf
2019-12-16 15:58             ` Denis Plotnikov
2019-11-18 10:30 ` [PATCH v0 0/2] " Denis Plotnikov
2020-03-02 13:38 ` Kevin Wolf
2020-03-02 13:55   ` Denis Plotnikov
2020-03-02 15:39     ` Kevin Wolf
2020-03-03  7:43       ` Vladimir Sementsov-Ogievskiy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191110190310.19799-3-dplotnikov@virtuozzo.com \
    --to=dplotnikov@virtuozzo.com \
    --cc=berrange@redhat.com \
    --cc=den@virtuozzo.com \
    --cc=ehabkost@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=vsementsov@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.