From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:43551) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TxGWV-0005He-MP for qemu-devel@nongnu.org; Mon, 21 Jan 2013 07:30:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TxGWU-0006fU-2i for qemu-devel@nongnu.org; Mon, 21 Jan 2013 07:30:47 -0500 Received: from mail-ee0-f51.google.com ([74.125.83.51]:42984) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TxGWT-0006fN-SY for qemu-devel@nongnu.org; Mon, 21 Jan 2013 07:30:46 -0500 Received: by mail-ee0-f51.google.com with SMTP id d17so2773989eek.10 for ; Mon, 21 Jan 2013 04:30:43 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 21 Jan 2013 13:30:17 +0100 Message-Id: <1358771422-14282-8-git-send-email-pbonzini@redhat.com> In-Reply-To: <1358771422-14282-1-git-send-email-pbonzini@redhat.com> References: <1358771422-14282-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH v2 07/12] qdev: move unrealization of devices from finalize to unparent List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aliguori@us.ibm.com, afaerber@suse.de 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 --- hw/qdev.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 83420ac..aad360f 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); } } -- 1.8.1