summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/core/qdev-properties-system.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 42e048f190..ba412dd2ca 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -69,8 +69,8 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
/* --- drive --- */
-static void parse_drive(DeviceState *dev, const char *str, void **ptr,
- const char *propname, Error **errp)
+static void do_parse_drive(DeviceState *dev, const char *str, void **ptr,
+ const char *propname, bool iothread, Error **errp)
{
BlockBackend *blk;
bool blk_created = false;
@@ -80,9 +80,16 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
if (!blk) {
BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
if (bs) {
- /* BlockBackends of devices start in the main context and are only
- * later moved into another context if the device supports that. */
- blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
+ /*
+ * If the device supports iothreads, it will make sure to move the
+ * block node to the right AioContext if necessary (or fail if this
+ * isn't possible because of other users). Devices that are not
+ * aware of iothreads require their BlockBackends to be in the main
+ * AioContext.
+ */
+ AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
+ qemu_get_aio_context();
+ blk = blk_new(ctx, 0, BLK_PERM_ALL);
blk_created = true;
ret = blk_insert_bs(blk, bs, errp);
@@ -120,6 +127,18 @@ 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,
+ const char *propname, Error **errp)
+{
+ do_parse_drive(dev, str, ptr, propname, true, errp);
+}
+
static void release_drive(Object *obj, const char *name, void *opaque)
{
DeviceState *dev = DEVICE(obj);
@@ -162,6 +181,12 @@ static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
set_pointer(obj, v, opaque, parse_drive, name, errp);
}
+static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ set_pointer(obj, v, opaque, parse_drive_iothread, name, errp);
+}
+
const PropertyInfo qdev_prop_drive = {
.name = "str",
.description = "Node name or ID of a block device to use as a backend",
@@ -170,6 +195,14 @@ const PropertyInfo qdev_prop_drive = {
.release = release_drive,
};
+const PropertyInfo qdev_prop_drive_iothread = {
+ .name = "str",
+ .description = "Node name or ID of a block device to use as a backend",
+ .get = get_drive,
+ .set = set_drive_iothread,
+ .release = release_drive,
+};
+
/* --- character device --- */
static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,