All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony PERARD <anthony.perard@citrix.com>
To: qemu-devel@nongnu.org
Cc: xen-devel@lists.xenproject.org,
	Peter Maydell <peter.maydell@linaro.org>,
	Anthony PERARD <anthony.perard@citrix.com>
Subject: [Qemu-devel] [PULL 18/25] xen: automatically create XenBlockDevice-s
Date: Mon, 14 Jan 2019 13:51:47 +0000	[thread overview]
Message-ID: <20190114135154.16826-19-anthony.perard@citrix.com> (raw)
In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com>

From: Paul Durrant <paul.durrant@citrix.com>

This patch adds create and destroy function for XenBlockDevice-s so that
they can be created automatically when the Xen toolstack instantiates a new
PV backend via xenstore. When the XenBlockDevice is created this way it is
also necessary to create a 'drive' which matches the configuration that the
Xen toolstack has written into xenstore. This is done by formulating the
parameters necessary for each 'blockdev' layer of the drive and then using
qmp_blockdev_add() to create the layers. Also, for compatibility with the
legacy 'xen_disk' implementation, an iothread is automatically created for
the new XenBlockDevice. This, like the driver layers, will be destroyed
after the XenBlockDevice is unrealized.

The legacy backend scan for 'qdisk' is removed by this patch, which makes
the 'xen_disk' code is redundant. The code will be removed by a subsequent
patch.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 hw/block/trace-events       |   4 +
 hw/block/xen-block.c        | 375 ++++++++++++++++++++++++++++++++++++
 hw/xen/xen-legacy-backend.c |   1 -
 include/hw/xen/xen-block.h  |  12 ++
 4 files changed, 391 insertions(+), 1 deletion(-)

diff --git a/hw/block/trace-events b/hw/block/trace-events
index 89e258319c..55e5a5500c 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -137,3 +137,7 @@ xen_disk_realize(void) ""
 xen_disk_unrealize(void) ""
 xen_cdrom_realize(void) ""
 xen_cdrom_unrealize(void) ""
+xen_block_blockdev_add(char *str) "%s"
+xen_block_blockdev_del(const char *node_name) "%s"
+xen_block_device_create(unsigned int number) "%u"
+xen_block_device_destroy(unsigned int number) "%u"
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index a7c37c185a..be28b63442 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -7,12 +7,20 @@
 
 #include "qemu/osdep.h"
 #include "qemu/cutils.h"
+#include "qemu/option.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-visit-block-core.h"
+#include "qapi/qobject-input-visitor.h"
 #include "qapi/visitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
 #include "hw/hw.h"
 #include "hw/xen/xen_common.h"
 #include "hw/block/xen_blkif.h"
 #include "hw/xen/xen-block.h"
+#include "hw/xen/xen-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/iothread.h"
@@ -474,6 +482,7 @@ static void xen_block_class_init(ObjectClass *class, void *data)
     DeviceClass *dev_class = DEVICE_CLASS(class);
     XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class);
 
+    xendev_class->backend = "qdisk";
     xendev_class->device = "vbd";
     xendev_class->get_name = xen_block_get_name;
     xendev_class->realize = xen_block_realize;
@@ -586,3 +595,369 @@ static void xen_block_register_types(void)
 }
 
 type_init(xen_block_register_types)
+
+static void xen_block_blockdev_del(const char *node_name, Error **errp)
+{
+    trace_xen_block_blockdev_del(node_name);
+
+    qmp_blockdev_del(node_name, errp);
+}
+
+static char *xen_block_blockdev_add(const char *id, QDict *qdict,
+                                    Error **errp)
+{
+    const char *driver = qdict_get_try_str(qdict, "driver");
+    BlockdevOptions *options = NULL;
+    Error *local_err = NULL;
+    char *node_name;
+    Visitor *v;
+
+    if (!driver) {
+        error_setg(errp, "no 'driver' parameter");
+        return NULL;
+    }
+
+    node_name = g_strdup_printf("%s-%s", id, driver);
+    qdict_put_str(qdict, "node-name", node_name);
+
+    trace_xen_block_blockdev_add(node_name);
+
+    v = qobject_input_visitor_new(QOBJECT(qdict));
+    visit_type_BlockdevOptions(v, NULL, &options, &local_err);
+    visit_free(v);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+    qmp_blockdev_add(options, &local_err);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+    qapi_free_BlockdevOptions(options);
+
+    return node_name;
+
+fail:
+    if (options) {
+        qapi_free_BlockdevOptions(options);
+    }
+    g_free(node_name);
+
+    return NULL;
+}
+
+static void xen_block_drive_destroy(XenBlockDrive *drive, Error **errp)
+{
+    char *node_name = drive->node_name;
+
+    if (node_name) {
+        Error *local_err = NULL;
+
+        xen_block_blockdev_del(node_name, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+        g_free(node_name);
+        drive->node_name = NULL;
+    }
+    g_free(drive->id);
+    g_free(drive);
+}
+
+static XenBlockDrive *xen_block_drive_create(const char *id,
+                                             const char *device_type,
+                                             QDict *opts, Error **errp)
+{
+    const char *params = qdict_get_try_str(opts, "params");
+    const char *mode = qdict_get_try_str(opts, "mode");
+    const char *direct_io_safe = qdict_get_try_str(opts, "direct-io-safe");
+    const char *discard_enable = qdict_get_try_str(opts, "discard-enable");
+    char *driver = NULL;
+    char *filename = NULL;
+    XenBlockDrive *drive = NULL;
+    Error *local_err = NULL;
+    QDict *file_layer;
+    QDict *driver_layer;
+
+    if (params) {
+        char **v = g_strsplit(params, ":", 2);
+
+        if (v[1] == NULL) {
+            filename = g_strdup(v[0]);
+            driver = g_strdup("raw");
+        } else {
+            if (strcmp(v[0], "aio") == 0) {
+                driver = g_strdup("raw");
+            } else if (strcmp(v[0], "vhd") == 0) {
+                driver = g_strdup("vpc");
+            } else {
+                driver = g_strdup(v[0]);
+            }
+            filename = g_strdup(v[1]);
+        }
+
+        g_strfreev(v);
+    }
+
+    if (!filename) {
+        error_setg(errp, "no filename");
+        goto done;
+    }
+    assert(driver);
+
+    drive = g_new0(XenBlockDrive, 1);
+    drive->id = g_strdup(id);
+
+    file_layer = qdict_new();
+
+    qdict_put_str(file_layer, "driver", "file");
+    qdict_put_str(file_layer, "filename", filename);
+
+    if (mode && *mode != 'w') {
+        qdict_put_bool(file_layer, "read-only", true);
+    }
+
+    if (direct_io_safe) {
+        unsigned long value;
+
+        if (!qemu_strtoul(direct_io_safe, NULL, 2, &value) && !!value) {
+            QDict *cache_qdict = qdict_new();
+
+            qdict_put_bool(cache_qdict, "direct", true);
+            qdict_put_obj(file_layer, "cache", QOBJECT(cache_qdict));
+
+            qdict_put_str(file_layer, "aio", "native");
+        }
+    }
+
+    if (discard_enable) {
+        unsigned long value;
+
+        if (!qemu_strtoul(discard_enable, NULL, 2, &value) && !!value) {
+            qdict_put_str(file_layer, "discard", "unmap");
+        }
+    }
+
+    /*
+     * It is necessary to turn file locking off as an emulated device
+     * may have already opened the same image file.
+     */
+    qdict_put_str(file_layer, "locking", "off");
+
+    driver_layer = qdict_new();
+
+    qdict_put_str(driver_layer, "driver", driver);
+    qdict_put_obj(driver_layer, "file", QOBJECT(file_layer));
+
+    g_assert(!drive->node_name);
+    drive->node_name = xen_block_blockdev_add(drive->id, driver_layer,
+                                              &local_err);
+
+done:
+    g_free(driver);
+    g_free(filename);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        xen_block_drive_destroy(drive, NULL);
+        return NULL;
+    }
+
+    return drive;
+}
+
+static const char *xen_block_drive_get_node_name(XenBlockDrive *drive)
+{
+    return drive->node_name ? drive->node_name : "";
+}
+
+static void xen_block_iothread_destroy(XenBlockIOThread *iothread,
+                                       Error **errp)
+{
+    qmp_object_del(iothread->id, errp);
+
+    g_free(iothread->id);
+    g_free(iothread);
+}
+
+static XenBlockIOThread *xen_block_iothread_create(const char *id,
+                                                   Error **errp)
+{
+    XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1);
+    Error *local_err = NULL;
+
+    iothread->id = g_strdup(id);
+
+    qmp_object_add(TYPE_IOTHREAD, id, false, NULL, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+
+        g_free(iothread->id);
+        g_free(iothread);
+        return NULL;
+    }
+
+    return iothread;
+}
+
+static void xen_block_device_create(XenBackendInstance *backend,
+                                    QDict *opts, Error **errp)
+{
+    XenBus *xenbus = xen_backend_get_bus(backend);
+    const char *name = xen_backend_get_name(backend);
+    unsigned long number;
+    const char *vdev, *device_type;
+    XenBlockDrive *drive = NULL;
+    XenBlockIOThread *iothread = NULL;
+    XenDevice *xendev = NULL;
+    Error *local_err = NULL;
+    const char *type;
+    XenBlockDevice *blockdev;
+
+    if (qemu_strtoul(name, NULL, 10, &number)) {
+        error_setg(errp, "failed to parse name '%s'", name);
+        goto fail;
+    }
+
+    trace_xen_block_device_create(number);
+
+    vdev = qdict_get_try_str(opts, "dev");
+    if (!vdev) {
+        error_setg(errp, "no dev parameter");
+        goto fail;
+    }
+
+    device_type = qdict_get_try_str(opts, "device-type");
+    if (!device_type) {
+        error_setg(errp, "no device-type parameter");
+        goto fail;
+    }
+
+    if (!strcmp(device_type, "disk")) {
+        type = TYPE_XEN_DISK_DEVICE;
+    } else if (!strcmp(device_type, "cdrom")) {
+        type = TYPE_XEN_CDROM_DEVICE;
+    } else {
+        error_setg(errp, "invalid device-type parameter '%s'", device_type);
+        goto fail;
+    }
+
+    drive = xen_block_drive_create(vdev, device_type, opts, &local_err);
+    if (!drive) {
+        error_propagate_prepend(errp, local_err, "failed to create drive: ");
+        goto fail;
+    }
+
+    iothread = xen_block_iothread_create(vdev, &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err,
+                                "failed to create iothread: ");
+        goto fail;
+    }
+
+    xendev = XEN_DEVICE(qdev_create(BUS(xenbus), type));
+    blockdev = XEN_BLOCK_DEVICE(xendev);
+
+    object_property_set_str(OBJECT(xendev), vdev, "vdev", &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err, "failed to set 'vdev': ");
+        goto fail;
+    }
+
+    object_property_set_str(OBJECT(xendev),
+                            xen_block_drive_get_node_name(drive), "drive",
+                            &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err, "failed to set 'drive': ");
+        goto fail;
+    }
+
+    object_property_set_str(OBJECT(xendev), iothread->id, "iothread",
+                            &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err,
+                                "failed to set 'iothread': ");
+        goto fail;
+    }
+
+    blockdev->iothread = iothread;
+    blockdev->drive = drive;
+
+    object_property_set_bool(OBJECT(xendev), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err,
+                                "realization of device %s failed: ",
+                                type);
+        goto fail;
+    }
+
+    xen_backend_set_device(backend, xendev);
+    return;
+
+fail:
+    if (xendev) {
+        object_unparent(OBJECT(xendev));
+    }
+
+    if (iothread) {
+        xen_block_iothread_destroy(iothread, NULL);
+    }
+
+    if (drive) {
+        xen_block_drive_destroy(drive, NULL);
+    }
+}
+
+static void xen_block_device_destroy(XenBackendInstance *backend,
+                                     Error **errp)
+{
+    XenDevice *xendev = xen_backend_get_device(backend);
+    XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev);
+    XenBlockVdev *vdev = &blockdev->props.vdev;
+    XenBlockDrive *drive = blockdev->drive;
+    XenBlockIOThread *iothread = blockdev->iothread;
+
+    trace_xen_block_device_destroy(vdev->number);
+
+    object_unparent(OBJECT(xendev));
+
+    if (iothread) {
+        Error *local_err = NULL;
+
+        xen_block_iothread_destroy(iothread, &local_err);
+        if (local_err) {
+            error_propagate_prepend(errp, local_err,
+                                "failed to destroy iothread: ");
+            return;
+        }
+    }
+
+    if (drive) {
+        Error *local_err = NULL;
+
+        xen_block_drive_destroy(drive, &local_err);
+        if (local_err) {
+            error_propagate_prepend(errp, local_err,
+                                "failed to destroy drive: ");
+        }
+    }
+}
+
+static const XenBackendInfo xen_block_backend_info = {
+    .type = "qdisk",
+    .create = xen_block_device_create,
+    .destroy = xen_block_device_destroy,
+};
+
+static void xen_block_register_backend(void)
+{
+    xen_backend_register(&xen_block_backend_info);
+}
+
+xen_backend_init(xen_block_register_backend);
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 41419763c8..36fd1e9b09 100644
--- a/hw/xen/xen-legacy-backend.c
+++ b/hw/xen/xen-legacy-backend.c
@@ -753,7 +753,6 @@ void xen_be_register_common(void)
 
     xen_be_register("console", &xen_console_ops);
     xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
 #ifdef CONFIG_VIRTFS
     xen_be_register("9pfs", &xen_9pfs_ops);
 #endif
diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h
index c4223f9be1..11d351b4b3 100644
--- a/include/hw/xen/xen-block.h
+++ b/include/hw/xen/xen-block.h
@@ -29,6 +29,7 @@ typedef struct XenBlockVdev {
     unsigned long number;
 } XenBlockVdev;
 
+
 typedef struct XenBlockProperties {
     XenBlockVdev vdev;
     BlockConf conf;
@@ -36,12 +37,23 @@ typedef struct XenBlockProperties {
     IOThread *iothread;
 } XenBlockProperties;
 
+typedef struct XenBlockDrive {
+    char *id;
+    char *node_name;
+} XenBlockDrive;
+
+typedef struct XenBlockIOThread {
+    char *id;
+} XenBlockIOThread;
+
 typedef struct XenBlockDevice {
     XenDevice xendev;
     XenBlockProperties props;
     const char *device_type;
     unsigned int info;
     XenBlockDataPlane *dataplane;
+    XenBlockDrive *drive;
+    XenBlockIOThread *iothread;
 } XenBlockDevice;
 
 typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp);
-- 
Anthony PERARD

WARNING: multiple messages have this Message-ID (diff)
From: Anthony PERARD <anthony.perard@citrix.com>
To: qemu-devel@nongnu.org
Cc: Anthony PERARD <anthony.perard@citrix.com>,
	xen-devel@lists.xenproject.org,
	Peter Maydell <peter.maydell@linaro.org>
Subject: [PULL 18/25] xen: automatically create XenBlockDevice-s
Date: Mon, 14 Jan 2019 13:51:47 +0000	[thread overview]
Message-ID: <20190114135154.16826-19-anthony.perard@citrix.com> (raw)
In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com>

From: Paul Durrant <paul.durrant@citrix.com>

This patch adds create and destroy function for XenBlockDevice-s so that
they can be created automatically when the Xen toolstack instantiates a new
PV backend via xenstore. When the XenBlockDevice is created this way it is
also necessary to create a 'drive' which matches the configuration that the
Xen toolstack has written into xenstore. This is done by formulating the
parameters necessary for each 'blockdev' layer of the drive and then using
qmp_blockdev_add() to create the layers. Also, for compatibility with the
legacy 'xen_disk' implementation, an iothread is automatically created for
the new XenBlockDevice. This, like the driver layers, will be destroyed
after the XenBlockDevice is unrealized.

The legacy backend scan for 'qdisk' is removed by this patch, which makes
the 'xen_disk' code is redundant. The code will be removed by a subsequent
patch.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 hw/block/trace-events       |   4 +
 hw/block/xen-block.c        | 375 ++++++++++++++++++++++++++++++++++++
 hw/xen/xen-legacy-backend.c |   1 -
 include/hw/xen/xen-block.h  |  12 ++
 4 files changed, 391 insertions(+), 1 deletion(-)

diff --git a/hw/block/trace-events b/hw/block/trace-events
index 89e258319c..55e5a5500c 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -137,3 +137,7 @@ xen_disk_realize(void) ""
 xen_disk_unrealize(void) ""
 xen_cdrom_realize(void) ""
 xen_cdrom_unrealize(void) ""
+xen_block_blockdev_add(char *str) "%s"
+xen_block_blockdev_del(const char *node_name) "%s"
+xen_block_device_create(unsigned int number) "%u"
+xen_block_device_destroy(unsigned int number) "%u"
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index a7c37c185a..be28b63442 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -7,12 +7,20 @@
 
 #include "qemu/osdep.h"
 #include "qemu/cutils.h"
+#include "qemu/option.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-visit-block-core.h"
+#include "qapi/qobject-input-visitor.h"
 #include "qapi/visitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
 #include "hw/hw.h"
 #include "hw/xen/xen_common.h"
 #include "hw/block/xen_blkif.h"
 #include "hw/xen/xen-block.h"
+#include "hw/xen/xen-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/iothread.h"
@@ -474,6 +482,7 @@ static void xen_block_class_init(ObjectClass *class, void *data)
     DeviceClass *dev_class = DEVICE_CLASS(class);
     XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class);
 
+    xendev_class->backend = "qdisk";
     xendev_class->device = "vbd";
     xendev_class->get_name = xen_block_get_name;
     xendev_class->realize = xen_block_realize;
@@ -586,3 +595,369 @@ static void xen_block_register_types(void)
 }
 
 type_init(xen_block_register_types)
+
+static void xen_block_blockdev_del(const char *node_name, Error **errp)
+{
+    trace_xen_block_blockdev_del(node_name);
+
+    qmp_blockdev_del(node_name, errp);
+}
+
+static char *xen_block_blockdev_add(const char *id, QDict *qdict,
+                                    Error **errp)
+{
+    const char *driver = qdict_get_try_str(qdict, "driver");
+    BlockdevOptions *options = NULL;
+    Error *local_err = NULL;
+    char *node_name;
+    Visitor *v;
+
+    if (!driver) {
+        error_setg(errp, "no 'driver' parameter");
+        return NULL;
+    }
+
+    node_name = g_strdup_printf("%s-%s", id, driver);
+    qdict_put_str(qdict, "node-name", node_name);
+
+    trace_xen_block_blockdev_add(node_name);
+
+    v = qobject_input_visitor_new(QOBJECT(qdict));
+    visit_type_BlockdevOptions(v, NULL, &options, &local_err);
+    visit_free(v);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+    qmp_blockdev_add(options, &local_err);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+    qapi_free_BlockdevOptions(options);
+
+    return node_name;
+
+fail:
+    if (options) {
+        qapi_free_BlockdevOptions(options);
+    }
+    g_free(node_name);
+
+    return NULL;
+}
+
+static void xen_block_drive_destroy(XenBlockDrive *drive, Error **errp)
+{
+    char *node_name = drive->node_name;
+
+    if (node_name) {
+        Error *local_err = NULL;
+
+        xen_block_blockdev_del(node_name, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+        g_free(node_name);
+        drive->node_name = NULL;
+    }
+    g_free(drive->id);
+    g_free(drive);
+}
+
+static XenBlockDrive *xen_block_drive_create(const char *id,
+                                             const char *device_type,
+                                             QDict *opts, Error **errp)
+{
+    const char *params = qdict_get_try_str(opts, "params");
+    const char *mode = qdict_get_try_str(opts, "mode");
+    const char *direct_io_safe = qdict_get_try_str(opts, "direct-io-safe");
+    const char *discard_enable = qdict_get_try_str(opts, "discard-enable");
+    char *driver = NULL;
+    char *filename = NULL;
+    XenBlockDrive *drive = NULL;
+    Error *local_err = NULL;
+    QDict *file_layer;
+    QDict *driver_layer;
+
+    if (params) {
+        char **v = g_strsplit(params, ":", 2);
+
+        if (v[1] == NULL) {
+            filename = g_strdup(v[0]);
+            driver = g_strdup("raw");
+        } else {
+            if (strcmp(v[0], "aio") == 0) {
+                driver = g_strdup("raw");
+            } else if (strcmp(v[0], "vhd") == 0) {
+                driver = g_strdup("vpc");
+            } else {
+                driver = g_strdup(v[0]);
+            }
+            filename = g_strdup(v[1]);
+        }
+
+        g_strfreev(v);
+    }
+
+    if (!filename) {
+        error_setg(errp, "no filename");
+        goto done;
+    }
+    assert(driver);
+
+    drive = g_new0(XenBlockDrive, 1);
+    drive->id = g_strdup(id);
+
+    file_layer = qdict_new();
+
+    qdict_put_str(file_layer, "driver", "file");
+    qdict_put_str(file_layer, "filename", filename);
+
+    if (mode && *mode != 'w') {
+        qdict_put_bool(file_layer, "read-only", true);
+    }
+
+    if (direct_io_safe) {
+        unsigned long value;
+
+        if (!qemu_strtoul(direct_io_safe, NULL, 2, &value) && !!value) {
+            QDict *cache_qdict = qdict_new();
+
+            qdict_put_bool(cache_qdict, "direct", true);
+            qdict_put_obj(file_layer, "cache", QOBJECT(cache_qdict));
+
+            qdict_put_str(file_layer, "aio", "native");
+        }
+    }
+
+    if (discard_enable) {
+        unsigned long value;
+
+        if (!qemu_strtoul(discard_enable, NULL, 2, &value) && !!value) {
+            qdict_put_str(file_layer, "discard", "unmap");
+        }
+    }
+
+    /*
+     * It is necessary to turn file locking off as an emulated device
+     * may have already opened the same image file.
+     */
+    qdict_put_str(file_layer, "locking", "off");
+
+    driver_layer = qdict_new();
+
+    qdict_put_str(driver_layer, "driver", driver);
+    qdict_put_obj(driver_layer, "file", QOBJECT(file_layer));
+
+    g_assert(!drive->node_name);
+    drive->node_name = xen_block_blockdev_add(drive->id, driver_layer,
+                                              &local_err);
+
+done:
+    g_free(driver);
+    g_free(filename);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        xen_block_drive_destroy(drive, NULL);
+        return NULL;
+    }
+
+    return drive;
+}
+
+static const char *xen_block_drive_get_node_name(XenBlockDrive *drive)
+{
+    return drive->node_name ? drive->node_name : "";
+}
+
+static void xen_block_iothread_destroy(XenBlockIOThread *iothread,
+                                       Error **errp)
+{
+    qmp_object_del(iothread->id, errp);
+
+    g_free(iothread->id);
+    g_free(iothread);
+}
+
+static XenBlockIOThread *xen_block_iothread_create(const char *id,
+                                                   Error **errp)
+{
+    XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1);
+    Error *local_err = NULL;
+
+    iothread->id = g_strdup(id);
+
+    qmp_object_add(TYPE_IOTHREAD, id, false, NULL, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+
+        g_free(iothread->id);
+        g_free(iothread);
+        return NULL;
+    }
+
+    return iothread;
+}
+
+static void xen_block_device_create(XenBackendInstance *backend,
+                                    QDict *opts, Error **errp)
+{
+    XenBus *xenbus = xen_backend_get_bus(backend);
+    const char *name = xen_backend_get_name(backend);
+    unsigned long number;
+    const char *vdev, *device_type;
+    XenBlockDrive *drive = NULL;
+    XenBlockIOThread *iothread = NULL;
+    XenDevice *xendev = NULL;
+    Error *local_err = NULL;
+    const char *type;
+    XenBlockDevice *blockdev;
+
+    if (qemu_strtoul(name, NULL, 10, &number)) {
+        error_setg(errp, "failed to parse name '%s'", name);
+        goto fail;
+    }
+
+    trace_xen_block_device_create(number);
+
+    vdev = qdict_get_try_str(opts, "dev");
+    if (!vdev) {
+        error_setg(errp, "no dev parameter");
+        goto fail;
+    }
+
+    device_type = qdict_get_try_str(opts, "device-type");
+    if (!device_type) {
+        error_setg(errp, "no device-type parameter");
+        goto fail;
+    }
+
+    if (!strcmp(device_type, "disk")) {
+        type = TYPE_XEN_DISK_DEVICE;
+    } else if (!strcmp(device_type, "cdrom")) {
+        type = TYPE_XEN_CDROM_DEVICE;
+    } else {
+        error_setg(errp, "invalid device-type parameter '%s'", device_type);
+        goto fail;
+    }
+
+    drive = xen_block_drive_create(vdev, device_type, opts, &local_err);
+    if (!drive) {
+        error_propagate_prepend(errp, local_err, "failed to create drive: ");
+        goto fail;
+    }
+
+    iothread = xen_block_iothread_create(vdev, &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err,
+                                "failed to create iothread: ");
+        goto fail;
+    }
+
+    xendev = XEN_DEVICE(qdev_create(BUS(xenbus), type));
+    blockdev = XEN_BLOCK_DEVICE(xendev);
+
+    object_property_set_str(OBJECT(xendev), vdev, "vdev", &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err, "failed to set 'vdev': ");
+        goto fail;
+    }
+
+    object_property_set_str(OBJECT(xendev),
+                            xen_block_drive_get_node_name(drive), "drive",
+                            &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err, "failed to set 'drive': ");
+        goto fail;
+    }
+
+    object_property_set_str(OBJECT(xendev), iothread->id, "iothread",
+                            &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err,
+                                "failed to set 'iothread': ");
+        goto fail;
+    }
+
+    blockdev->iothread = iothread;
+    blockdev->drive = drive;
+
+    object_property_set_bool(OBJECT(xendev), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate_prepend(errp, local_err,
+                                "realization of device %s failed: ",
+                                type);
+        goto fail;
+    }
+
+    xen_backend_set_device(backend, xendev);
+    return;
+
+fail:
+    if (xendev) {
+        object_unparent(OBJECT(xendev));
+    }
+
+    if (iothread) {
+        xen_block_iothread_destroy(iothread, NULL);
+    }
+
+    if (drive) {
+        xen_block_drive_destroy(drive, NULL);
+    }
+}
+
+static void xen_block_device_destroy(XenBackendInstance *backend,
+                                     Error **errp)
+{
+    XenDevice *xendev = xen_backend_get_device(backend);
+    XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev);
+    XenBlockVdev *vdev = &blockdev->props.vdev;
+    XenBlockDrive *drive = blockdev->drive;
+    XenBlockIOThread *iothread = blockdev->iothread;
+
+    trace_xen_block_device_destroy(vdev->number);
+
+    object_unparent(OBJECT(xendev));
+
+    if (iothread) {
+        Error *local_err = NULL;
+
+        xen_block_iothread_destroy(iothread, &local_err);
+        if (local_err) {
+            error_propagate_prepend(errp, local_err,
+                                "failed to destroy iothread: ");
+            return;
+        }
+    }
+
+    if (drive) {
+        Error *local_err = NULL;
+
+        xen_block_drive_destroy(drive, &local_err);
+        if (local_err) {
+            error_propagate_prepend(errp, local_err,
+                                "failed to destroy drive: ");
+        }
+    }
+}
+
+static const XenBackendInfo xen_block_backend_info = {
+    .type = "qdisk",
+    .create = xen_block_device_create,
+    .destroy = xen_block_device_destroy,
+};
+
+static void xen_block_register_backend(void)
+{
+    xen_backend_register(&xen_block_backend_info);
+}
+
+xen_backend_init(xen_block_register_backend);
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 41419763c8..36fd1e9b09 100644
--- a/hw/xen/xen-legacy-backend.c
+++ b/hw/xen/xen-legacy-backend.c
@@ -753,7 +753,6 @@ void xen_be_register_common(void)
 
     xen_be_register("console", &xen_console_ops);
     xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
 #ifdef CONFIG_VIRTFS
     xen_be_register("9pfs", &xen_9pfs_ops);
 #endif
diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h
index c4223f9be1..11d351b4b3 100644
--- a/include/hw/xen/xen-block.h
+++ b/include/hw/xen/xen-block.h
@@ -29,6 +29,7 @@ typedef struct XenBlockVdev {
     unsigned long number;
 } XenBlockVdev;
 
+
 typedef struct XenBlockProperties {
     XenBlockVdev vdev;
     BlockConf conf;
@@ -36,12 +37,23 @@ typedef struct XenBlockProperties {
     IOThread *iothread;
 } XenBlockProperties;
 
+typedef struct XenBlockDrive {
+    char *id;
+    char *node_name;
+} XenBlockDrive;
+
+typedef struct XenBlockIOThread {
+    char *id;
+} XenBlockIOThread;
+
 typedef struct XenBlockDevice {
     XenDevice xendev;
     XenBlockProperties props;
     const char *device_type;
     unsigned int info;
     XenBlockDataPlane *dataplane;
+    XenBlockDrive *drive;
+    XenBlockIOThread *iothread;
 } XenBlockDevice;
 
 typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp);
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2019-01-14 13:59 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-14 13:51 [Qemu-devel] [PULL 00/25] Xen queue v2 Anthony PERARD
2019-01-14 13:51 ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 01/25] hw/xen/xen_pt_graphics: Don't trust the BIOS ROM contents so much Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 02/25] xen/pt: allow passthrough of devices with bogus interrupt pin Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 03/25] xen: re-name XenDevice to XenLegacyDevice Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 04/25] xen: introduce new 'XenBus' and 'XenDevice' object hierarchy Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 05/25] xen: introduce 'xen-block', 'xen-disk' and 'xen-cdrom' Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 06/25] xen: create xenstore areas for XenDevice-s Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2020-04-01 16:14   ` [Qemu-devel] " Philippe Mathieu-Daudé
2020-04-02  9:49     ` Paul Durrant
2020-04-02 12:07       ` Philippe Mathieu-Daudé
2019-01-14 13:51 ` [Qemu-devel] [PULL 07/25] xen: add xenstore watcher infrastructure Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 08/25] xen: add grant table interface for XenDevice-s Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 09/25] xen: add event channel " Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 10/25] xen: duplicate xen_disk.c as basis of dataplane/xen-block.c Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 11/25] xen: remove unnecessary code from dataplane/xen-block.c Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 12/25] xen: add header and build dataplane/xen-block.c Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 13/25] xen: remove 'XenBlkDev' and 'blkdev' names from dataplane/xen-block Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 14/25] xen: remove 'ioreq' struct/varable/field names from dataplane/xen-block.c Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 15/25] xen: purge 'blk' and 'ioreq' from function names in dataplane/xen-block.c Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 16/25] xen: add implementations of xen-block connect and disconnect functions Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 17/25] xen: add a mechanism to automatically create XenDevice-s Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` Anthony PERARD [this message]
2019-01-14 13:51   ` [PULL 18/25] xen: automatically create XenBlockDevice-s Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 19/25] MAINTAINERS: add myself as a Xen maintainer Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 20/25] xen: remove the legacy 'xen_disk' backend Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 21/25] Remove broken Xen PV domain builder Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 22/25] xen: Replace few mentions of xend by libxl Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 23/25] xen-block: improve batching behaviour Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 24/25] xen-block: improve response latency Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 13:51 ` [Qemu-devel] [PULL 25/25] xen-block: avoid repeated memory allocation Anthony PERARD
2019-01-14 13:51   ` Anthony PERARD
2019-01-14 17:34 ` [Qemu-devel] [PULL 00/25] Xen queue v2 Peter Maydell
2019-01-14 17:34   ` Peter Maydell
  -- strict thread matches above, loose matches on Subject: below --
2019-01-10 13:48 [Qemu-devel] [PULL 00/25] xen queue Anthony PERARD
2019-01-10 13:49 ` [Qemu-devel] [PULL 18/25] xen: automatically create XenBlockDevice-s Anthony PERARD

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=20190114135154.16826-19-anthony.perard@citrix.com \
    --to=anthony.perard@citrix.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=xen-devel@lists.xenproject.org \
    /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.