Patchwork [v4,08/13] qdev: move unrealization of devices from finalize to unparent

login
register
mail settings
Submitter Paolo Bonzini
Date Jan. 25, 2013, 1:12 p.m.
Message ID <1359119559-19075-9-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/215736/
State New
Headers show

Comments

Paolo Bonzini - Jan. 25, 2013, 1:12 p.m.
Similarly, a bus holds a reference back to the device, and this will
prevent the device from going away as soon as this reference is counted
properly.  To avoid this, move the unrealization of devices to the
unparent callback.  This includes recursively unparenting all the buses
and (after the previous patch) the devices on those buses, which ensures
that the web of references completely disappears for all devices that
reside (in the qdev tree) below the one being unplugged.

After this patch, the qdev tree and the bus<->child relationship is
defined as "A is above B, iff unplugging A will automatically unplug B".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/qdev.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)

Patch

diff --git a/hw/qdev.c b/hw/qdev.c
index 3c1ec7d..6f1b311 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -738,23 +738,8 @@  static void device_initfn(Object *obj)
 static void device_finalize(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
-    BusState *bus;
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-
-    if (dev->realized) {
-        while (dev->num_child_bus) {
-            bus = QLIST_FIRST(&dev->child_bus);
-            qbus_free(bus);
-        }
-        if (qdev_get_vmsd(dev)) {
-            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
-        }
-        if (dc->exit) {
-            dc->exit(dev);
-        }
-        if (dev->opts) {
-            qemu_opts_del(dev->opts);
-        }
+    if (dev->opts) {
+        qemu_opts_del(dev->opts);
     }
 }
 
@@ -771,8 +756,22 @@  static void device_class_base_init(ObjectClass *class, void *data)
 static void device_unparent(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+    BusState *bus;
 
-    if (dev->parent_bus != NULL) {
+    while (dev->num_child_bus) {
+        bus = QLIST_FIRST(&dev->child_bus);
+        qbus_free(bus);
+    }
+    if (dev->realized) {
+        if (qdev_get_vmsd(dev)) {
+            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+        }
+        if (dc->exit) {
+            dc->exit(dev);
+        }
+    }
+    if (dev->parent_bus) {
         bus_remove_child(dev->parent_bus, dev);
     }
 }