From: Paul Durrant <paul.durrant@citrix.com>
To: qemu-devel@nongnu.org, qemu-block@nongnu.org,
xen-devel@lists.xenproject.org
Cc: Paul Durrant <paul.durrant@citrix.com>,
Kevin Wolf <kwolf@redhat.com>, Max Reitz <mreitz@redhat.com>,
Stefano Stabellini <sstabellini@kernel.org>
Subject: [Qemu-devel] [PATCH v3 16/18] xen: automatically create XenBlockDevice-s
Date: Tue, 11 Dec 2018 10:47:16 +0000 [thread overview]
Message-ID: <1544525238-3527-17-git-send-email-paul.durrant@citrix.com> (raw)
In-Reply-To: <1544525238-3527-1-git-send-email-paul.durrant@citrix.com>
This patch adds a creator function for XenBlockDevice-s so that they can
be created automatically when the Xen toolstack instantiates a new
PV backend. 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 drive is marked 'auto_del' so
that it will be removed when the XenBlockDevice is destroyed. Also, for
compatibility with the legacy 'xen_disk' implementation, an iothread
is automatically created for the new XenBlockDevice. This will also be
removed when the XenBlockDevice is destroyed.
Correspondingly the legacy backend scan for 'qdisk' is removed.
After this patch is applied the legacy 'xen_disk' code is redundant. It
will be removed by a subsequent patch.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Anthony Perard <anthony.perard@citrix.com>
---
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
v2:
- Get rid of error_abort
- Don't use qdev_init_nofail
- Explain why file locking needs to be off
---
hw/block/trace-events | 1 +
hw/block/xen-block.c | 261 +++++++++++++++++++++++++++++++++++++++++++-
hw/xen/xen-legacy-backend.c | 1 -
include/hw/xen/xen-block.h | 1 +
4 files changed, 262 insertions(+), 2 deletions(-)
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 89e2583..a89c8a6 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -137,3 +137,4 @@ xen_disk_realize(void) ""
xen_disk_unrealize(void) ""
xen_cdrom_realize(void) ""
xen_cdrom_unrealize(void) ""
+xen_block_device_create(const char *name) "name: %s"
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index f3d21c6..0d1616d 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -7,12 +7,15 @@
#include "qemu/osdep.h"
#include "qemu/cutils.h"
+#include "qemu/option.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
+#include "qapi/qmp/qdict.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"
@@ -131,6 +134,11 @@ static void xen_block_unrealize(XenDevice *xendev, Error **errp)
xen_block_dataplane_destroy(blockdev->dataplane);
blockdev->dataplane = NULL;
+ if (blockdev->auto_iothread) {
+ iothread_destroy(blockdev->auto_iothread);
+ blockdev->auto_iothread = NULL;
+ }
+
if (blockdev_class->unrealize) {
blockdev_class->unrealize(blockdev, errp);
}
@@ -145,6 +153,8 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
XenBlockVdev *vdev = &blockdev->vdev;
Error *local_err = NULL;
BlockConf *conf = &blockdev->conf;
+ IOThread *iothread = blockdev->auto_iothread ?
+ blockdev->auto_iothread : blockdev->iothread;
if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) {
error_setg(errp, "vdev property not set");
@@ -212,7 +222,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
conf->logical_block_size);
blockdev->dataplane = xen_block_dataplane_create(xendev, conf,
- blockdev->iothread);
+ iothread);
}
static void xen_block_frontend_changed(XenDevice *xendev,
@@ -474,6 +484,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 +597,251 @@ static void xen_block_register_types(void)
}
type_init(xen_block_register_types)
+
+static void 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 *format = NULL;
+ char *file = NULL;
+ char *drive_optstr = NULL;
+ QemuOpts *drive_opts;
+ Error *local_err = NULL;
+
+ if (params) {
+ char **v = g_strsplit(params, ":", 2);
+
+ if (v[1] == NULL) {
+ file = g_strdup(v[0]);
+ } else {
+ if (strcmp(v[0], "aio") == 0) {
+ format = g_strdup("raw");
+ } else if (strcmp(v[0], "vhd") == 0) {
+ format = g_strdup("vpc");
+ } else {
+ format = g_strdup(v[0]);
+ }
+ file = g_strdup(v[1]);
+ }
+
+ g_strfreev(v);
+ }
+
+ if (!file) {
+ error_setg(errp, "no file parameter");
+ return;
+ }
+
+ drive_optstr = g_strdup_printf("id=%s", id);
+ drive_opts = drive_def(drive_optstr);
+ if (!drive_opts) {
+ error_setg(errp, "failed to create drive options");
+ goto done;
+ }
+
+ qemu_opt_set(drive_opts, "file", file, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err, "failed to set 'file': ");
+ goto done;
+ }
+
+ qemu_opt_set(drive_opts, "media", device_type, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to set 'media': ");
+ goto done;
+ }
+
+ if (format) {
+ qemu_opt_set(drive_opts, "format", format, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to set 'format': ");
+ goto done;
+ }
+ }
+
+ if (mode && *mode != 'w') {
+ qemu_opt_set_bool(drive_opts, BDRV_OPT_READ_ONLY, true, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err, "failed to set '%s': ",
+ BDRV_OPT_READ_ONLY);
+ goto done;
+ }
+ }
+
+ /*
+ * It is necessary to turn file locking off as an emulated device
+ * my have already opened the same image file.
+ */
+ qemu_opt_set(drive_opts, "file.locking", "off", &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to set 'file.locking': ");
+ goto done;
+ }
+
+ qemu_opt_set_bool(drive_opts, BDRV_OPT_CACHE_WB, true, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err, "failed to set '%s': ",
+ BDRV_OPT_CACHE_WB);
+ goto done;
+ }
+
+ if (direct_io_safe) {
+ qemu_opt_set_bool(drive_opts, BDRV_OPT_CACHE_DIRECT, true,
+ &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err, "failed to set '%s': ",
+ BDRV_OPT_CACHE_DIRECT);
+ goto done;
+ }
+
+ qemu_opt_set(drive_opts, "aio", "native", &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to set 'aio': ");
+ goto done;
+ }
+ }
+
+ if (discard_enable) {
+ unsigned long value;
+
+ if (!qemu_strtoul(discard_enable, NULL, 2, &value)) {
+ qemu_opt_set_bool(drive_opts, BDRV_OPT_DISCARD, !!value,
+ &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to set '%s': ",
+ BDRV_OPT_DISCARD);
+ goto done;
+ }
+ }
+ }
+
+ drive_new(drive_opts, IF_NONE, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to create drive: ");
+ goto done;
+ }
+
+done:
+ g_free(drive_optstr);
+ g_free(format);
+ g_free(file);
+}
+
+static void xen_block_device_create(BusState *bus, const char *name,
+ QDict *opts, Error **errp)
+{
+ unsigned long number;
+ const char *vdev, *device_type;
+ BlockBackend *blk = NULL;
+ IOThread *iothread = NULL;
+ DeviceState *dev = NULL;
+ Error *local_err = NULL;
+ const char *type;
+ XenBlockDevice *blockdev;
+
+ trace_xen_block_device_create(name);
+
+ if (qemu_strtoul(name, NULL, 10, &number)) {
+ error_setg(errp, "failed to parse name '%s'", name);
+ return;
+ }
+
+ vdev = qdict_get_try_str(opts, "dev");
+ if (!vdev) {
+ error_setg(errp, "no dev parameter");
+ return;
+ }
+
+ device_type = qdict_get_try_str(opts, "device-type");
+ if (!device_type) {
+ error_setg(errp, "no device-type parameter");
+ return;
+ }
+
+ 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);
+ return;
+ }
+
+ xen_block_drive_create(vdev, device_type, opts, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ blk = blk_by_name(vdev);
+ g_assert(blk);
+
+ iothread = iothread_create(vdev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ goto unref;
+ }
+
+ dev = qdev_create(bus, type);
+ blockdev = XEN_BLOCK_DEVICE(dev);
+
+ qdev_prop_set_string(dev, "vdev", vdev);
+ if (blockdev->vdev.number != number) {
+ error_setg(errp, "invalid dev parameter '%s'", vdev);
+ goto unref;
+ }
+
+ qdev_prop_set_drive(dev, "drive", blk, &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err, "failed to set 'drive': ");
+ goto unref;
+ }
+
+ blockdev->auto_iothread = iothread;
+
+ object_property_set_bool(OBJECT(dev), true, "realized", &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "initialization of device %s failed: ",
+ type);
+ goto unref;
+ }
+
+ blockdev_mark_auto_del(blk);
+ return;
+
+unref:
+ if (dev) {
+ object_unparent(OBJECT(dev));
+ }
+
+ if (iothread) {
+ iothread_destroy(iothread);
+ }
+
+ if (blk) {
+ monitor_remove_blk(blk);
+ blk_unref(blk);
+ }
+}
+
+static const XenBackendInfo xen_block_backend_info = {
+ .type = "qdisk",
+ .create = xen_block_device_create,
+};
+
+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 0c26023..fb227de 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 37ed8a6..5bced60 100644
--- a/include/hw/xen/xen-block.h
+++ b/include/hw/xen/xen-block.h
@@ -37,6 +37,7 @@ typedef struct XenBlockDevice {
unsigned int info;
unsigned int max_ring_page_order;
IOThread *iothread;
+ IOThread *auto_iothread;
XenBlockDataPlane *dataplane;
} XenBlockDevice;
--
2.1.4
next prev parent reply other threads:[~2018-12-11 10:59 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-11 10:47 [Qemu-devel] [PATCH v3 00/18] Xen PV backend 'qdevification' Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 01/18] xen: re-name XenDevice to XenLegacyDevice Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 02/18] xen: introduce new 'XenBus' and 'XenDevice' object hierarchy Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 03/18] xen: introduce 'xen-block', 'xen-disk' and 'xen-cdrom' Paul Durrant
2018-12-11 15:16 ` Anthony PERARD
2018-12-11 15:40 ` Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 04/18] xen: create xenstore areas for XenDevice-s Paul Durrant
2018-12-11 15:19 ` Anthony PERARD
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 05/18] xen: add xenstore watcher infrastructure Paul Durrant
2018-12-11 15:21 ` Anthony PERARD
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 06/18] xen: add grant table interface for XenDevice-s Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 07/18] xen: add event channel " Paul Durrant
2018-12-11 15:24 ` Anthony PERARD
2018-12-11 15:43 ` Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 08/18] xen: duplicate xen_disk.c as basis of dataplane/xen-block.c Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 09/18] xen: remove unnecessary code from dataplane/xen-block.c Paul Durrant
2018-12-11 15:30 ` [Qemu-devel] [Xen-devel] " Anthony PERARD
2018-12-11 15:38 ` Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 10/18] xen: add header and build dataplane/xen-block.c Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 11/18] xen: remove 'XenBlkDev' and 'blkdev' names from dataplane/xen-block Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 12/18] xen: remove 'ioreq' struct/varable/field names from dataplane/xen-block.c Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 13/18] xen: purge 'blk' and 'ioreq' from function names in dataplane/xen-block.c Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 14/18] xen: add implementations of xen-block connect and disconnect functions Paul Durrant
2018-12-11 16:17 ` Anthony PERARD
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 15/18] xen: add a mechanism to automatically create XenDevice-s Paul Durrant
2018-12-11 10:47 ` Paul Durrant [this message]
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 17/18] MAINTAINERS: add myself as a Xen maintainer Paul Durrant
2018-12-11 10:47 ` [Qemu-devel] [PATCH v3 18/18] xen: remove the legacy 'xen_disk' backend Paul Durrant
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=1544525238-3527-17-git-send-email-paul.durrant@citrix.com \
--to=paul.durrant@citrix.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=sstabellini@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).