diff options
Diffstat (limited to 'hw/core/qdev-properties-system.c')
| -rw-r--r-- | hw/core/qdev-properties-system.c | 151 |
1 files changed, 86 insertions, 65 deletions
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 70bfd4809b..38b0c9f09b 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -25,29 +25,67 @@ #include "sysemu/iothread.h" #include "sysemu/tpm_backend.h" -static void get_pointer(Object *obj, Visitor *v, Property *prop, - char *(*print)(void *ptr), - const char *name, Error **errp) +static bool check_prop_still_unset(DeviceState *dev, const char *name, + const void *old_val, const char *new_val, + Error **errp) +{ + const GlobalProperty *prop = qdev_find_global_prop(dev, name); + + if (!old_val) { + return true; + } + + if (prop) { + error_setg(errp, "-global %s.%s=... conflicts with %s=%s", + prop->driver, prop->property, name, new_val); + } else { + /* Error message is vague, but a better one would be hard */ + error_setg(errp, "%s=%s conflicts, and override is not implemented", + name, new_val); + } + return false; +} + + +/* --- drive --- */ + +static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) { DeviceState *dev = DEVICE(obj); + Property *prop = opaque; void **ptr = qdev_get_prop_ptr(dev, prop); + const char *value; char *p; - p = *ptr ? print(*ptr) : g_strdup(""); + if (*ptr) { + value = blk_name(*ptr); + if (!*value) { + BlockDriverState *bs = blk_bs(*ptr); + if (bs) { + value = bdrv_get_node_name(bs); + } + } + } else { + value = ""; + } + + p = g_strdup(value); visit_type_str(v, name, &p, errp); g_free(p); } -static void set_pointer(Object *obj, Visitor *v, Property *prop, - void (*parse)(DeviceState *dev, const char *str, - void **ptr, const char *propname, - Error **errp), - const char *name, Error **errp) +static void set_drive_helper(Object *obj, Visitor *v, const char *name, + void *opaque, bool iothread, Error **errp) { DeviceState *dev = DEVICE(obj); + Property *prop = opaque; Error *local_err = NULL; void **ptr = qdev_get_prop_ptr(dev, prop); char *str; + BlockBackend *blk; + bool blk_created = false; + int ret; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); @@ -59,23 +97,20 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop, error_propagate(errp, local_err); return; } + + /* + * TODO Should this really be an error? If no, the old value + * needs to be released before we store the new one. + */ + if (!check_prop_still_unset(dev, name, *ptr, str, errp)) { + return; + } + if (!*str) { g_free(str); *ptr = NULL; return; } - parse(dev, str, ptr, prop->name, errp); - g_free(str); -} - -/* --- drive --- */ - -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; - int ret; blk = blk_by_name(str); if (!blk) { @@ -101,7 +136,7 @@ static void do_parse_drive(DeviceState *dev, const char *str, void **ptr, } if (!blk) { error_setg(errp, "Property '%s.%s' can't find value '%s'", - object_get_typename(OBJECT(dev)), propname, str); + object_get_typename(OBJECT(dev)), prop->name, str); goto fail; } if (blk_attach_dev(blk, dev) < 0) { @@ -126,18 +161,20 @@ fail: /* If we need to keep a reference, blk_attach_dev() took it */ blk_unref(blk); } + + g_free(str); } -static void parse_drive(DeviceState *dev, const char *str, void **ptr, - const char *propname, Error **errp) +static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) { - do_parse_drive(dev, str, ptr, propname, false, errp); + set_drive_helper(obj, v, name, opaque, false, errp); } -static void parse_drive_iothread(DeviceState *dev, const char *str, void **ptr, - const char *propname, Error **errp) +static void set_drive_iothread(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { - do_parse_drive(dev, str, ptr, propname, true, errp); + set_drive_helper(obj, v, name, opaque, true, errp); } static void release_drive(Object *obj, const char *name, void *opaque) @@ -156,38 +193,6 @@ static void release_drive(Object *obj, const char *name, void *opaque) } } -static char *print_drive(void *ptr) -{ - const char *name; - - name = blk_name(ptr); - if (!*name) { - BlockDriverState *bs = blk_bs(ptr); - if (bs) { - name = bdrv_get_node_name(bs); - } - } - return g_strdup(name); -} - -static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - get_pointer(obj, v, opaque, print_drive, name, errp); -} - -static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - 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", @@ -239,6 +244,14 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, return; } + /* + * TODO Should this really be an error? If no, the old value + * needs to be released before we store the new one. + */ + if (!check_prop_still_unset(dev, name, be->chr, str, errp)) { + return; + } + if (!*str) { g_free(str); be->chr = NULL; @@ -324,14 +337,16 @@ static void set_netdev(Object *obj, Visitor *v, const char *name, } for (i = 0; i < queues; i++) { - if (peers[i]->peer) { err = -EEXIST; goto out; } - if (ncs[i]) { - err = -EINVAL; + /* + * TODO Should this really be an error? If no, the old value + * needs to be released before we store the new one. + */ + if (!check_prop_still_unset(dev, name, ncs[i], str, errp)) { goto out; } @@ -410,8 +425,8 @@ const PropertyInfo qdev_prop_audiodev = { .set = set_audiodev, }; -void qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockBackend *value, Error **errp) +void qdev_prop_set_drive_err(DeviceState *dev, const char *name, + BlockBackend *value, Error **errp) { const char *ref = ""; @@ -428,6 +443,12 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name, object_property_set_str(OBJECT(dev), ref, name, errp); } +void qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value) +{ + qdev_prop_set_drive_err(dev, name, value, &error_abort); +} + void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value) { |