X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=qdev-monitor.c;h=8fd6df93d2d28cec64c4a09646ba59b9da2ae76f;hb=eb578a2394c55f7d598f60796c8318e40b1c0241;hp=5f2fcdfc455113bb8076dfe75ec2e8b177e60ca3;hpb=54639aed97bc1faa2f3a5dc4ea69fd7b527fe573;p=mirror_qemu.git diff --git a/qdev-monitor.c b/qdev-monitor.c index 5f2fcdfc45..8fd6df93d2 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -29,6 +29,7 @@ #include "qemu/error-report.h" #include "qemu/help_option.h" #include "sysemu/block-backend.h" +#include "migration/misc.h" /* * Aliases were a bad idea from the start. Let's keep them @@ -113,7 +114,7 @@ static void qdev_print_devinfo(DeviceClass *dc) if (dc->desc) { error_printf(", desc \"%s\"", dc->desc); } - if (dc->cannot_instantiate_with_device_add_yet) { + if (!dc->user_creatable) { error_printf(", no-user"); } error_printf("\n"); @@ -155,7 +156,7 @@ static void qdev_print_devinfos(bool show_no_user) ? !test_bit(i, dc->categories) : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX)) || (!show_no_user - && dc->cannot_instantiate_with_device_add_yet)) { + && !dc->user_creatable)) { continue; } if (!cat_printed) { @@ -240,7 +241,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) } dc = DEVICE_CLASS(oc); - if (dc->cannot_instantiate_with_device_add_yet || + if (!dc->user_creatable || (qdev_hotplug && !dc->hotpluggable)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver", "pluggable device type"); @@ -603,6 +604,11 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) return NULL; } + if (!migration_is_idle()) { + error_setg(errp, "device_add not allowed while migrating"); + return NULL; + } + /* create device */ dev = DEVICE(object_new(driver)); @@ -836,6 +842,45 @@ static DeviceState *find_device_state(const char *id, Error **errp) return DEVICE(obj); } +void qdev_unplug(DeviceState *dev, Error **errp) +{ + DeviceClass *dc = DEVICE_GET_CLASS(dev); + HotplugHandler *hotplug_ctrl; + HotplugHandlerClass *hdc; + + if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) { + error_setg(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); + return; + } + + if (!dc->hotpluggable) { + error_setg(errp, QERR_DEVICE_NO_HOTPLUG, + object_get_typename(OBJECT(dev))); + return; + } + + if (!migration_is_idle()) { + error_setg(errp, "device_del not allowed while migrating"); + return; + } + + qdev_hot_removed = true; + + hotplug_ctrl = qdev_get_hotplug_handler(dev); + /* hotpluggable device MUST have HotplugHandler, if it doesn't + * then something is very wrong with it */ + g_assert(hotplug_ctrl); + + /* If device supports async unplug just request it to be done, + * otherwise just remove it synchronously */ + hdc = HOTPLUG_HANDLER_GET_CLASS(hotplug_ctrl); + if (hdc->unplug_request) { + hotplug_handler_unplug_request(hotplug_ctrl, dev, errp); + } else { + hotplug_handler_unplug(hotplug_ctrl, dev, errp); + } +} + void qmp_device_del(const char *id, Error **errp) { DeviceState *dev = find_device_state(id, errp);