The qdev_free() function name is misleading since all the function does
is unlink the device from its parent. The device is not necessarily
freed.
The device will be freed when its QObject refcount reaches zero. It is
usual for the parent (bus) to hold the final reference but there are
cases where something else holds a reference so "free" is a misleading
name.
Call object_unparent(obj) directly instead of having a qdev wrapper
function.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
15 files changed:
if (pc->no_hotplug) {
slot_free = false;
} else {
if (pc->no_hotplug) {
slot_free = false;
} else {
+ object_unparent(OBJECT(qdev));
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
+ object_unparent(OBJECT(dev));
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
+ object_unparent(OBJECT(dev));
-/* Unlink device from bus and free the structure. */
-void qdev_free(DeviceState *dev)
-{
- object_unparent(OBJECT(dev));
-}
-
void qdev_machine_creation_done(void)
{
/*
void qdev_machine_creation_done(void)
{
/*
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
DeviceState *dev = kid->child;
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
DeviceState *dev = kid->child;
+ object_unparent(OBJECT(dev));
}
if (bus->parent) {
QLIST_REMOVE(bus, sibling);
}
if (bus->parent) {
QLIST_REMOVE(bus, sibling);
}
dev = pci_create(bus, devfn, "virtio-blk-pci");
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
}
dev = pci_create(bus, devfn, "virtio-blk-pci");
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+ object_unparent(OBJECT(dev));
pci_bridge_region_cleanup(s, s->windows);
memory_region_destroy(&s->address_space_mem);
memory_region_destroy(&s->address_space_io);
pci_bridge_region_cleanup(s, s->windows);
memory_region_destroy(&s->address_space_mem);
memory_region_destroy(&s->address_space_io);
- /* qbus_free() is called automatically by qdev_free() */
+ /* qbus_free() is called automatically during device deletion */
PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
} else {
PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
} else {
- qdev_free(&pci_dev->qdev);
+ object_unparent(OBJECT(pci_dev));
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
++devfn) {
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
if (affected_dev) {
++devfn) {
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
if (affected_dev) {
- qdev_free(&affected_dev->qdev);
+ object_unparent(OBJECT(affected_dev));
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
+ object_unparent(OBJECT(dev));
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
assert(d);
if (d->lun == dev->lun && dev != d) {
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
assert(d);
if (d->lun == dev->lun && dev != d) {
+ object_unparent(OBJECT(d));
}
if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
error_setg(errp, "Setting drive property failed");
}
if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
error_setg(errp, "Setting drive property failed");
+ object_unparent(OBJECT(dev));
return NULL;
}
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return NULL;
}
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
+ object_unparent(OBJECT(dev));
return NULL;
}
return SCSI_DEVICE(dev);
return NULL;
}
return SCSI_DEVICE(dev);
void usb_unregister_port(USBBus *bus, USBPort *port)
{
void usb_unregister_port(USBBus *bus, USBPort *port)
{
- if (port->dev)
- qdev_free(&port->dev->qdev);
+ if (port->dev) {
+ object_unparent(OBJECT(port->dev));
+ }
QTAILQ_REMOVE(&bus->free, port, next);
bus->nfree--;
}
QTAILQ_REMOVE(&bus->free, port, next);
bus->nfree--;
}
return -1;
dev = port->dev;
return -1;
dev = port->dev;
+ object_unparent(OBJECT(dev));
return NULL;
}
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
return NULL;
}
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+ object_unparent(OBJECT(dev));
return NULL;
}
if (qdev_init(&dev->qdev) < 0)
return NULL;
}
if (qdev_init(&dev->qdev) < 0)
+ object_unparent(OBJECT(dev));
/* Destroy the VirtIODevice */
void virtio_bus_destroy_device(VirtioBusState *bus)
{
/* Destroy the VirtIODevice */
void virtio_bus_destroy_device(VirtioBusState *bus)
{
BusState *qbus = BUS(bus);
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
DPRINTF("%s: remove device.\n", qbus->name);
BusState *qbus = BUS(bus);
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
DPRINTF("%s: remove device.\n", qbus->name);
if (klass->device_unplug != NULL) {
klass->device_unplug(qbus->parent);
}
if (klass->device_unplug != NULL) {
klass->device_unplug(qbus->parent);
}
- qdev = DEVICE(bus->vdev);
- qdev_free(qdev);
+ object_unparent(OBJECT(bus->vdev));
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET
&& strcmp(d->name, "xen-pci-passthrough") != 0) {
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET
&& strcmp(d->name, "xen-pci-passthrough") != 0) {
+ object_unparent(OBJECT(d));
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version);
void qdev_unplug(DeviceState *dev, Error **errp);
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version);
void qdev_unplug(DeviceState *dev, Error **errp);
-void qdev_free(DeviceState *dev);
int qdev_simple_unplug_cb(DeviceState *dev);
void qdev_machine_creation_done(void);
bool qdev_machine_modified(void);
int qdev_simple_unplug_cb(DeviceState *dev);
void qdev_machine_creation_done(void);
bool qdev_machine_modified(void);
qdev->id = id;
}
if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
qdev->id = id;
}
if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
+ object_unparent(OBJECT(qdev));
object_unref(OBJECT(qdev));
return NULL;
}
object_unref(OBJECT(qdev));
return NULL;
}