Commit 9561fda8 authored by Stefan Hajnoczi's avatar Stefan Hajnoczi Committed by Andreas Färber
Browse files

qom: Make QOM link property unref optional



Some object_property_add_link() callers expect property deletion to
unref the link property object.  Other callers expect to manage the
refcount themselves.  The former are currently broken and therefore leak
the link property object.

This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require.  The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.

This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.

Rationale for refcount behavior:

 * hw/core/qdev.c
   - bus children are explicitly unreferenced, don't interfere
   - parent_bus is essentially a read-only property that doesn't hold a
     refcount, don't unref
   - hotplug_handler is leaked, do unref

 * hw/dma/xilinx_axidma.c
   - rx stream "dma" links are set using set_link, therefore they
     need unref
   - tx streams are set using set_link, therefore they need unref

 * hw/net/xilinx_axienet.c
   - same reasoning as hw/dma/xilinx_axidma.c

 * hw/pcmcia/pxa2xx.c
   - pxa2xx bypasses set_link and therefore does not use refcounts

 * hw/s390x/s390-virtio-bus.c
 * hw/virtio/virtio-pci.c
 * hw/virtio/virtio-rng.c
 * ui/console.c
   - set_link is used and there is no explicit unref, do unref

Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarAndreas Färber <afaerber@suse.de>
parent c6aed983
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -97,8 +97,7 @@ static void bus_add_child(BusState *bus, DeviceState *child)
    snprintf(name, sizeof(name), "child[%d]", kid->index);
    object_property_add_link(OBJECT(bus), name,
                             object_get_typename(OBJECT(child)),
                             (Object **)&kid->child,
                             NULL);
                             (Object **)&kid->child, 0, NULL);
}

void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
@@ -824,7 +823,8 @@ static void device_initfn(Object *obj)
    } while (class != object_class_by_name(TYPE_DEVICE));

    object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
                             (Object **)&dev->parent_bus, &error_abort);
                             (Object **)&dev->parent_bus, 0,
                             &error_abort);
}

static void device_post_init(Object *obj)
@@ -944,7 +944,9 @@ static void qbus_initfn(Object *obj)
    QTAILQ_INIT(&bus->children);
    object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
                             TYPE_HOTPLUG_HANDLER,
                             (Object **)&bus->hotplug_handler, NULL);
                             (Object **)&bus->hotplug_handler,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             NULL);
    object_property_add_bool(obj, "realized",
                             bus_get_realized, bus_set_realized, NULL);
}
+12 −4
Original line number Diff line number Diff line
@@ -537,9 +537,13 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
    Error *local_errp = NULL;

    object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
                             (Object **)&ds->dma, &local_errp);
                             (Object **)&ds->dma,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &local_errp);
    object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
                             (Object **)&cs->dma, &local_errp);
                             (Object **)&cs->dma,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &local_errp);
    if (local_errp) {
        goto xilinx_axidma_realize_fail;
    }
@@ -571,10 +575,14 @@ static void xilinx_axidma_init(Object *obj)
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);

    object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
                             (Object **)&s->tx_data_dev, &error_abort);
                             (Object **)&s->tx_data_dev,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &error_abort);
    object_property_add_link(obj, "axistream-control-connected",
                             TYPE_STREAM_SLAVE,
                             (Object **)&s->tx_control_dev, &error_abort);
                             (Object **)&s->tx_control_dev,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &error_abort);

    object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
                      TYPE_XILINX_AXI_DMA_DATA_STREAM);
+12 −4
Original line number Diff line number Diff line
@@ -945,9 +945,13 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
    Error *local_errp = NULL;

    object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
                             (Object **) &ds->enet, &local_errp);
                             (Object **) &ds->enet,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &local_errp);
    object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
                             (Object **) &cs->enet, &local_errp);
                             (Object **) &cs->enet,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &local_errp);
    if (local_errp) {
        goto xilinx_enet_realize_fail;
    }
@@ -982,10 +986,14 @@ static void xilinx_enet_init(Object *obj)
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);

    object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
                             (Object **) &s->tx_data_dev, &error_abort);
                             (Object **) &s->tx_data_dev,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &error_abort);
    object_property_add_link(obj, "axistream-control-connected",
                             TYPE_STREAM_SLAVE,
                             (Object **) &s->tx_control_dev, &error_abort);
                             (Object **) &s->tx_control_dev,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &error_abort);

    object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
                      TYPE_XILINX_AXI_ENET_DATA_STREAM);
+1 −1
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];

    object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
                             (Object **)&s->card, NULL);
                             (Object **)&s->card, 0, NULL);
}

/* Insert a new card into a slot */
+2 −1
Original line number Diff line number Diff line
@@ -313,7 +313,8 @@ static void s390_virtio_rng_instance_init(Object *obj)
    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
                             (Object **)&dev->vdev.conf.rng, NULL);
                             (Object **)&dev->vdev.conf.rng,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}

static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
Loading