qdev: move deletion of children from finalize to unparent
A device will never be finalized as long as it has a reference from other devices that sit on its buses. To ensure that the references go away, deassociate a bus from its children in the unparent callback for the bus. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
							parent
							
								
									9d127820eb
								
							
						
					
					
						commit
						6853d27a12
					
				
							
								
								
									
										37
									
								
								hw/qdev.c
								
								
								
								
							
							
						
						
									
										37
									
								
								hw/qdev.c
								
								
								
								
							| 
						 | 
				
			
			@ -433,6 +433,25 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bus_unparent(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    BusState *bus = BUS(obj);
 | 
			
		||||
    BusChild *kid;
 | 
			
		||||
 | 
			
		||||
    while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
 | 
			
		||||
        DeviceState *dev = kid->child;
 | 
			
		||||
        qdev_free(dev);
 | 
			
		||||
    }
 | 
			
		||||
    if (bus->parent) {
 | 
			
		||||
        QLIST_REMOVE(bus, sibling);
 | 
			
		||||
        bus->parent->num_child_bus--;
 | 
			
		||||
        bus->parent = NULL;
 | 
			
		||||
    } else {
 | 
			
		||||
        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
 | 
			
		||||
        qemu_unregister_reset(qbus_reset_all_fn, bus);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qbus_create_inplace(void *bus, const char *typename,
 | 
			
		||||
                         DeviceState *parent, const char *name)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -805,22 +824,15 @@ static void qbus_initfn(Object *obj)
 | 
			
		|||
    QTAILQ_INIT(&bus->children);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bus_class_init(ObjectClass *class, void *data)
 | 
			
		||||
{
 | 
			
		||||
    class->unparent = bus_unparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qbus_finalize(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    BusState *bus = BUS(obj);
 | 
			
		||||
    BusChild *kid;
 | 
			
		||||
 | 
			
		||||
    while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
 | 
			
		||||
        DeviceState *dev = kid->child;
 | 
			
		||||
        qdev_free(dev);
 | 
			
		||||
    }
 | 
			
		||||
    if (bus->parent) {
 | 
			
		||||
        QLIST_REMOVE(bus, sibling);
 | 
			
		||||
        bus->parent->num_child_bus--;
 | 
			
		||||
    } else {
 | 
			
		||||
        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
 | 
			
		||||
        qemu_unregister_reset(qbus_reset_all_fn, bus);
 | 
			
		||||
    }
 | 
			
		||||
    g_free((char *)bus->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -832,6 +844,7 @@ static const TypeInfo bus_info = {
 | 
			
		|||
    .class_size = sizeof(BusClass),
 | 
			
		||||
    .instance_init = qbus_initfn,
 | 
			
		||||
    .instance_finalize = qbus_finalize,
 | 
			
		||||
    .class_init = bus_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void qdev_register_types(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue