* [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
@ 2012-08-08 12:18 Michael Tokarev
2012-08-08 12:22 ` Michael Tokarev
0 siblings, 1 reply; 11+ messages in thread
From: Michael Tokarev @ 2012-08-08 12:18 UTC (permalink / raw)
To: qemu-devel, Paolo Bonzini, Peter Maydell, Anthony Liguori
While dealing with USB issues today I noticed that
usb_del monitor command is broken, attempting to
delete any usb device immediately results in assertion
failure:
(qemu) usb_del 0.1
ERROR:qom/object.c:408:object_delete: assertion failed: (obj->ref == 0)
Aborted
I bisected this issue to commit:
commit da57febfed7bad11be79f047b59719c38abd0712
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue Mar 27 18:38:47 2012 +0200
qdev: give all devices a canonical path
A strong limitation of QOM right now is that unconverted ports
(e.g. all...) do not give a canonical path to devices that are
part of the board. This in turn makes it impossible to replace
PROP_PTR with a QOM link for example.
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
The problem is still present in current qemu/master git.
I'm not sure what to do with this.
See also http://lists.gnu.org/archive/html/qemu-devel/2012-07/msg00199.html --
Peter Maydell reoprted this very issue a while back but no one replied.
Thanks,
/mjt
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 12:18 [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del Michael Tokarev
@ 2012-08-08 12:22 ` Michael Tokarev
2012-08-08 12:39 ` Paolo Bonzini
0 siblings, 1 reply; 11+ messages in thread
From: Michael Tokarev @ 2012-08-08 12:22 UTC (permalink / raw)
To: qemu-devel, Paolo Bonzini, Peter Maydell, Anthony Liguori
On 08.08.2012 16:18, Michael Tokarev wrote:
> While dealing with USB issues today I noticed that
> usb_del monitor command is broken, attempting to
> delete any usb device immediately results in assertion
> failure:
>
> (qemu) usb_del 0.1
> ERROR:qom/object.c:408:object_delete: assertion failed: (obj->ref == 0)
> Aborted
>
>
> I bisected this issue to commit:
>
> commit da57febfed7bad11be79f047b59719c38abd0712
> Author: Paolo Bonzini <pbonzini@redhat.com>
> Date: Tue Mar 27 18:38:47 2012 +0200
>
> qdev: give all devices a canonical path
>
> A strong limitation of QOM right now is that unconverted ports
> (e.g. all...) do not give a canonical path to devices that are
> part of the board. This in turn makes it impossible to replace
> PROP_PTR with a QOM link for example.
>
> Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
>
>
> The problem is still present in current qemu/master git.
>
> I'm not sure what to do with this.
Well. This commit adds this code:
@@ -152,6 +152,16 @@ int qdev_init(DeviceState *dev)
+
+ if (!OBJECT(dev)->parent) {
+ static int unattached_count = 0;
+ gchar *name = g_strdup_printf("device[%d]", unattached_count++);
+
+ object_property_add_child(container_get("/unattached"), name,
+ OBJECT(dev), NULL);
+ g_free(name);
+ }
ie, there's now extra call to object_property_add_child(),
which does object_ref(). So no doubt there's no a new
assertion failure: (obj->ref == 0).
Once again, patch description does not reflect what is
actually done by the patch. Can we please stop this
practice of accepting patches with desrciption not
reflecting reality?
Back to the point: should there be a call to object_unref()
somewhere?
Thanks,
/mjt
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 12:22 ` Michael Tokarev
@ 2012-08-08 12:39 ` Paolo Bonzini
2012-08-08 12:48 ` Andreas Färber
2012-08-08 13:09 ` Michael Tokarev
0 siblings, 2 replies; 11+ messages in thread
From: Paolo Bonzini @ 2012-08-08 12:39 UTC (permalink / raw)
To: Michael Tokarev; +Cc: Peter Maydell, Anthony Liguori, qemu-devel
Il 08/08/2012 14:22, Michael Tokarev ha scritto:
> @@ -152,6 +152,16 @@ int qdev_init(DeviceState *dev)
> +
> + if (!OBJECT(dev)->parent) {
> + static int unattached_count = 0;
> + gchar *name = g_strdup_printf("device[%d]", unattached_count++);
> +
> + object_property_add_child(container_get("/unattached"), name,
> + OBJECT(dev), NULL);
> + g_free(name);
> + }
>
> ie, there's now extra call to object_property_add_child(),
> which does object_ref(). So no doubt there's no a new
> assertion failure: (obj->ref == 0).
>
> Once again, patch description does not reflect what is
> actually done by the patch.
Huh? The add_child ensures that there is a canonical path.
> Can we please stop this
> practice of accepting patches with desrciption not
> reflecting reality?
>
> Back to the point: should there be a call to object_unref()
> somewhere?
There should be a call to object_unparent() somewhere actually.
We've been peppering the code with them for a few months now while
waiting for "the" solution, but I fail to see what the solution
could be other than the patch below (something similar has probably
been proposed already). BTW there are probably a lot of other similar
bugs somewhere.
Paolo
-------------------- 8< -----------------
>From 6d1ea139acf85184fa721654bcc68a4544a536ca Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 8 Aug 2012 14:33:02 +0200
Subject: [PATCH] qom: object_delete should unparent the object first
object_deinit is only called when the reference count goes to zero,
and yet tries to do an object_unparent. Now, object_unparent
either does nothing or it will decrease the reference count.
Because we know the reference count is zero, the object_unparent
call in object_deinit is useless.
Instead, we need to disconnect the object from its parent just
before we remove the last reference apart from the parent's. This
happens in object_delete. Once we do this, all calls to
object_unparent peppered through QEMU can go away.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/acpi_piix4.c | 1 -
hw/qdev.c | 2 --
hw/shpc.c | 1 -
hw/xen_platform.c | 3 ---
qom/object.c | 3 +--
5 file modificati, 1 inserzione(+), 9 rimozioni(-)
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0aace60..72d6e5c 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -305,7 +305,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
if (pc->no_hotplug) {
slot_free = false;
} else {
- object_unparent(OBJECT(dev));
qdev_free(qdev);
}
}
diff --git a/hw/qdev.c b/hw/qdev.c
index b5b74b9..b5a52ac 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -159,7 +159,6 @@ int qdev_init(DeviceState *dev)
rc = dc->init(dev);
if (rc < 0) {
- object_unparent(OBJECT(dev));
qdev_free(dev);
return rc;
}
@@ -243,7 +242,6 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
- object_unparent(OBJECT(dev));
qdev_free(dev);
return 0;
}
diff --git a/hw/shpc.c b/hw/shpc.c
index 6b9884d..a5baf24 100644
--- a/hw/shpc.c
+++ b/hw/shpc.c
@@ -253,7 +253,6 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
++devfn) {
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
if (affected_dev) {
- object_unparent(OBJECT(affected_dev));
qdev_free(&affected_dev->qdev);
}
}
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index c1fe984..0d6c2ff 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
{
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET) {
- /* Until qdev_free includes a call to object_unparent, we call it here
- */
- object_unparent(&d->qdev.parent_obj);
qdev_free(&d->qdev);
}
}
diff --git a/qom/object.c b/qom/object.c
index 00bb3b0..3ccd744 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -366,8 +366,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
if (type_has_parent(type)) {
object_deinit(obj, type_get_parent(type));
}
-
- object_unparent(obj);
}
void object_finalize(void *data)
@@ -402,8 +402,9 @@ Object *object_new(const char *typename)
void object_delete(Object *obj)
{
+ object_unparent(obj);
+ g_assert(obj->ref == 1);
object_unref(obj);
- g_assert(obj->ref == 0);
g_free(obj);
}
--
1.7.11.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 12:39 ` Paolo Bonzini
@ 2012-08-08 12:48 ` Andreas Färber
2012-08-08 13:02 ` Paolo Bonzini
2012-08-08 13:09 ` Michael Tokarev
1 sibling, 1 reply; 11+ messages in thread
From: Andreas Färber @ 2012-08-08 12:48 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Peter Maydell, Anthony Liguori, Michael Tokarev, qemu-devel
Am 08.08.2012 14:39, schrieb Paolo Bonzini:
> Il 08/08/2012 14:22, Michael Tokarev ha scritto:
>> [...] should there be a call to object_unref()
>> somewhere?
>
> There should be a call to object_unparent() somewhere actually.
> We've been peppering the code with them for a few months now while
> waiting for "the" solution, but I fail to see what the solution
> could be other than the patch below (something similar has probably
> been proposed already). BTW there are probably a lot of other similar
> bugs somewhere.
>
> Paolo
>
> -------------------- 8< -----------------
> From 6d1ea139acf85184fa721654bcc68a4544a536ca Mon Sep 17 00:00:00 2001
> From: Paolo Bonzini <pbonzini@redhat.com>
> Date: Wed, 8 Aug 2012 14:33:02 +0200
> Subject: [PATCH] qom: object_delete should unparent the object first
>
> object_deinit is only called when the reference count goes to zero,
> and yet tries to do an object_unparent. Now, object_unparent
> either does nothing or it will decrease the reference count.
> Because we know the reference count is zero, the object_unparent
> call in object_deinit is useless.
>
> Instead, we need to disconnect the object from its parent just
> before we remove the last reference apart from the parent's. This
> happens in object_delete. Once we do this, all calls to
> object_unparent peppered through QEMU can go away.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/acpi_piix4.c | 1 -
> hw/qdev.c | 2 --
> hw/shpc.c | 1 -
> hw/xen_platform.c | 3 ---
> qom/object.c | 3 +--
> 5 file modificati, 1 inserzione(+), 9 rimozioni(-)
>
> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
> index 0aace60..72d6e5c 100644
> --- a/hw/acpi_piix4.c
> +++ b/hw/acpi_piix4.c
> @@ -305,7 +305,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
> if (pc->no_hotplug) {
> slot_free = false;
> } else {
> - object_unparent(OBJECT(dev));
> qdev_free(qdev);
> }
> }
> diff --git a/hw/qdev.c b/hw/qdev.c
> index b5b74b9..b5a52ac 100644
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
> @@ -159,7 +159,6 @@ int qdev_init(DeviceState *dev)
>
> rc = dc->init(dev);
> if (rc < 0) {
> - object_unparent(OBJECT(dev));
> qdev_free(dev);
> return rc;
> }
> @@ -243,7 +242,6 @@ void qbus_reset_all_fn(void *opaque)
> int qdev_simple_unplug_cb(DeviceState *dev)
> {
> /* just zap it */
> - object_unparent(OBJECT(dev));
> qdev_free(dev);
> return 0;
> }
> diff --git a/hw/shpc.c b/hw/shpc.c
> index 6b9884d..a5baf24 100644
> --- a/hw/shpc.c
> +++ b/hw/shpc.c
> @@ -253,7 +253,6 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
> ++devfn) {
> PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
> if (affected_dev) {
> - object_unparent(OBJECT(affected_dev));
> qdev_free(&affected_dev->qdev);
> }
> }
> diff --git a/hw/xen_platform.c b/hw/xen_platform.c
> index c1fe984..0d6c2ff 100644
> --- a/hw/xen_platform.c
> +++ b/hw/xen_platform.c
> @@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
> {
> if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
> PCI_CLASS_NETWORK_ETHERNET) {
> - /* Until qdev_free includes a call to object_unparent, we call it here
> - */
> - object_unparent(&d->qdev.parent_obj);
> qdev_free(&d->qdev);
> }
> }
> diff --git a/qom/object.c b/qom/object.c
> index 00bb3b0..3ccd744 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -366,8 +366,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
> if (type_has_parent(type)) {
> object_deinit(obj, type_get_parent(type));
> }
> -
> - object_unparent(obj);
> }
>
> void object_finalize(void *data)
> @@ -402,8 +402,9 @@ Object *object_new(const char *typename)
>
> void object_delete(Object *obj)
> {
> + object_unparent(obj);
> + g_assert(obj->ref == 1);
> object_unref(obj);
> - g_assert(obj->ref == 0);
> g_free(obj);
> }
>
Adding object_unparent() to object_delete() looks okay to me, but we
should not forget about the upcoming i440fx and prep_pci use cases where
we want to embed children in the parent's struct, so that
object_delete() will never be called on it. Thus object_unparent() would
need to remain present in the deinit path, no?
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 12:48 ` Andreas Färber
@ 2012-08-08 13:02 ` Paolo Bonzini
0 siblings, 0 replies; 11+ messages in thread
From: Paolo Bonzini @ 2012-08-08 13:02 UTC (permalink / raw)
To: Andreas Färber
Cc: Peter Maydell, Anthony Liguori, Michael Tokarev, qemu-devel
Il 08/08/2012 14:48, Andreas Färber ha scritto:
> Adding object_unparent() to object_delete() looks okay to me, but we
> should not forget about the upcoming i440fx and prep_pci use cases where
> we want to embed children in the parent's struct, so that
> object_delete() will never be called on it. Thus object_unparent() would
> need to remain present in the deinit path, no?
object_property_del_all should take care of it for embedded objects:
- the outermost struct is deleted via object_delete
- it is unparented and unrefed, so refcount goes to 0 and finalize is called
- finalize calls object_property_del_all
- object_finalize_child_property calls unref on the nested object, so
refcount goes to 0 and finalize is called. Things can then proceed
recursively.
It would be more complicated (and would cause memory leaks) if you got
nested objects that were allocated. To account for this, I understood
you would need something like the following:
- you add a "void (*release)(void *obj)" member to Object.
- object_new sets the release member to g_free
- object_delete does not call g_free anymore
- object_finalize calls the release member if it is not NULL
Do you have time to implement it?
Paolo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 12:39 ` Paolo Bonzini
2012-08-08 12:48 ` Andreas Färber
@ 2012-08-08 13:09 ` Michael Tokarev
2012-08-08 14:42 ` Michael Tokarev
1 sibling, 1 reply; 11+ messages in thread
From: Michael Tokarev @ 2012-08-08 13:09 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Peter Maydell, Anthony Liguori, qemu-devel
On 08.08.2012 16:39, Paolo Bonzini wrote:
> Il 08/08/2012 14:22, Michael Tokarev ha scritto:
>> @@ -152,6 +152,16 @@ int qdev_init(DeviceState *dev)
>> +
>> + if (!OBJECT(dev)->parent) {
>> + static int unattached_count = 0;
>> + gchar *name = g_strdup_printf("device[%d]", unattached_count++);
>> +
>> + object_property_add_child(container_get("/unattached"), name,
>> + OBJECT(dev), NULL);
>> + g_free(name);
>> + }
>>
>> ie, there's now extra call to object_property_add_child(),
>> which does object_ref(). So no doubt there's no a new
>> assertion failure: (obj->ref == 0).
>>
>> Once again, patch description does not reflect what is
>> actually done by the patch.
>
> Huh? The add_child ensures that there is a canonical path.
>
>> Can we please stop this
>> practice of accepting patches with desrciption not
>> reflecting reality?
I must clarify this.
I'm not trying to blame Paolo for the wrong patch which
"broke" things (it exposed an old bug in other codepath).
I'm just saying that the patch description appears to be
"too innocent" -- yes, now each device has a path, or,
in other words, a NAME, but this patch ALSO changes
refcounting, and THIS is what I'm referring to above --
it isn't only gives a name, but also links "unowned"
objects to a bus. To me it is a wrong (too innocent)
description. I browsed comits trying to find which
change might have caused it, and provided ther was
a mention of "references" or "connecting" in this patch
description somewhere, I'd found this change much faster,
without a painful (*) bisection.
Maybe it is just me who does not know this code area
well enough, so things aren't as obvious for me as for
others, I dunno, but to me the description -- the only
thing I'm trying to "blame" Paolo for here -- might be
quite a bit better.
(*) painful because this bisection come in the process
of another bisection dealing with another usb issue,
which come to yet another bug in usb handling somewhere
(giving another assertion).
>> Back to the point: should there be a call to object_unref()
>> somewhere?
>
> There should be a call to object_unparent() somewhere actually.
> We've been peppering the code with them for a few months now while
> waiting for "the" solution, but I fail to see what the solution
> could be other than the patch below (something similar has probably
> been proposed already). BTW there are probably a lot of other similar
> bugs somewhere.
This sounds ecouraging -- "alot of other similar bugs".. :(
Something similar should be applied to 1.1-stable. FWIW, some
changes are not needed there, like this:
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
> @@ -159,7 +159,6 @@ int qdev_init(DeviceState *dev)
>
> rc = dc->init(dev);
> if (rc < 0) {
> - object_unparent(OBJECT(dev));
> qdev_free(dev);
> return rc;
> }
and this:
> --- a/hw/shpc.c
> +++ b/hw/shpc.c
> @@ -253,7 +253,6 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
> ++devfn) {
> PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
> if (affected_dev) {
> - object_unparent(OBJECT(affected_dev));
> qdev_free(&affected_dev->qdev);
> }
> }
the lines being removed does not exist in 1.1-stable.
I can guess this is due to previous attempts to fix
similar issues in other places.
Thank you!
/mjt
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 13:09 ` Michael Tokarev
@ 2012-08-08 14:42 ` Michael Tokarev
2012-08-08 16:08 ` Michael Tokarev
2012-08-20 17:58 ` Anthony Liguori
0 siblings, 2 replies; 11+ messages in thread
From: Michael Tokarev @ 2012-08-08 14:42 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Peter Maydell, Anthony Liguori, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 432 bytes --]
On 08.08.2012 17:09, Michael Tokarev wrote:
[]
> Something similar should be applied to 1.1-stable. FWIW, some
> changes are not needed there.
Cherry-pick to stable-1.1 removes the two unneeded hunks.
This is what I plan to include into debian package. It
fixes the original usb_del issue, and I didn't find new
regressions so far - tried a few device_del and similar.
Should it go to qemu/stable-1.1 as well?
Thank you!
/mjt
[-- Attachment #2: qom:-object_delete-should-unparent-the-object-first.diff --]
[-- Type: text/x-patch, Size: 2688 bytes --]
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed Aug 8 14:39:11 2012 +0200
Bug-Debian: http://bugs.debian.org/684282
Comment: cherry-picked from qemu/master to stable-1.1 (mjt)
qom: object_delete should unparent the object first
object_deinit is only called when the reference count goes to zero,
and yet tries to do an object_unparent. Now, object_unparent
either does nothing or it will decrease the reference count.
Because we know the reference count is zero, the object_unparent
call in object_deinit is useless.
Instead, we need to disconnect the object from its parent just
before we remove the last reference apart from the parent's. This
happens in object_delete. Once we do this, all calls to
object_unparent peppered through QEMU can go away.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0345490..585da4e 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -299,7 +299,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
if (pc->no_hotplug) {
slot_free = false;
} else {
- object_unparent(OBJECT(dev));
qdev_free(qdev);
}
}
diff --git a/hw/qdev.c b/hw/qdev.c
index 6a8f6bd..9bb1c6b 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -240,7 +240,6 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
- object_unparent(OBJECT(dev));
qdev_free(dev);
return 0;
}
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index 0214f37..84221df 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
{
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET) {
- /* Until qdev_free includes a call to object_unparent, we call it here
- */
- object_unparent(&d->qdev.parent_obj);
qdev_free(&d->qdev);
}
}
diff --git a/qom/object.c b/qom/object.c
index 6f839ad..58dd886 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -347,8 +347,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
if (type_has_parent(type)) {
object_deinit(obj, type_get_parent(type));
}
-
- object_unparent(obj);
}
void object_finalize(void *data)
@@ -385,8 +383,9 @@ Object *object_new(const char *typename)
void object_delete(Object *obj)
{
+ object_unparent(obj);
+ g_assert(obj->ref == 1);
object_unref(obj);
- g_assert(obj->ref == 0);
g_free(obj);
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 14:42 ` Michael Tokarev
@ 2012-08-08 16:08 ` Michael Tokarev
2012-08-20 17:58 ` Anthony Liguori
1 sibling, 0 replies; 11+ messages in thread
From: Michael Tokarev @ 2012-08-08 16:08 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Peter Maydell, Anthony Liguori, qemu-devel
On 08.08.2012 18:42, Michael Tokarev wrote:
> Should it go to qemu/stable-1.1 as well?
qemu/stable-1.1 also includes f63e60327b8e239ae97fa71060940ca20a8bf38e.
FWIW.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-08 14:42 ` Michael Tokarev
2012-08-08 16:08 ` Michael Tokarev
@ 2012-08-20 17:58 ` Anthony Liguori
2012-08-21 7:06 ` Paolo Bonzini
1 sibling, 1 reply; 11+ messages in thread
From: Anthony Liguori @ 2012-08-20 17:58 UTC (permalink / raw)
To: Michael Tokarev, Paolo Bonzini; +Cc: Peter Maydell, qemu-devel
Michael Tokarev <mjt@tls.msk.ru> writes:
> On 08.08.2012 17:09, Michael Tokarev wrote:
> []
>> Something similar should be applied to 1.1-stable. FWIW, some
>> changes are not needed there.
>
> Cherry-pick to stable-1.1 removes the two unneeded hunks.
> This is what I plan to include into debian package. It
> fixes the original usb_del issue, and I didn't find new
> regressions so far - tried a few device_del and similar.
>
> Should it go to qemu/stable-1.1 as well?
>
> Thank you!
>
> /mjtAuthor: Paolo Bonzini <pbonzini@redhat.com>
> Date: Wed Aug 8 14:39:11 2012 +0200
> Bug-Debian: http://bugs.debian.org/684282
> Comment: cherry-picked from qemu/master to stable-1.1 (mjt)
>
> qom: object_delete should unparent the object first
>
> object_deinit is only called when the reference count goes to zero,
> and yet tries to do an object_unparent. Now, object_unparent
> either does nothing or it will decrease the reference count.
> Because we know the reference count is zero, the object_unparent
> call in object_deinit is useless.
>
> Instead, we need to disconnect the object from its parent just
> before we remove the last reference apart from the parent's. This
> happens in object_delete. Once we do this, all calls to
> object_unparent peppered through QEMU can go away.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
>
> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
> index 0345490..585da4e 100644
> --- a/hw/acpi_piix4.c
> +++ b/hw/acpi_piix4.c
> @@ -299,7 +299,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
> if (pc->no_hotplug) {
> slot_free = false;
> } else {
> - object_unparent(OBJECT(dev));
> qdev_free(qdev);
> }
> }
> diff --git a/hw/qdev.c b/hw/qdev.c
> index 6a8f6bd..9bb1c6b 100644
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
> @@ -240,7 +240,6 @@ void qbus_reset_all_fn(void *opaque)
> int qdev_simple_unplug_cb(DeviceState *dev)
> {
> /* just zap it */
> - object_unparent(OBJECT(dev));
> qdev_free(dev);
> return 0;
> }
> diff --git a/hw/xen_platform.c b/hw/xen_platform.c
> index 0214f37..84221df 100644
> --- a/hw/xen_platform.c
> +++ b/hw/xen_platform.c
> @@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
> {
> if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
> PCI_CLASS_NETWORK_ETHERNET) {
> - /* Until qdev_free includes a call to object_unparent, we call it here
> - */
> - object_unparent(&d->qdev.parent_obj);
> qdev_free(&d->qdev);
> }
> }
> diff --git a/qom/object.c b/qom/object.c
> index 6f839ad..58dd886 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -347,8 +347,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
> if (type_has_parent(type)) {
> object_deinit(obj, type_get_parent(type));
> }
> -
> - object_unparent(obj);
> }
>
> void object_finalize(void *data)
> @@ -385,8 +383,9 @@ Object *object_new(const char *typename)
>
> void object_delete(Object *obj)
> {
> + object_unparent(obj);
> + g_assert(obj->ref == 1);
> object_unref(obj);
> - g_assert(obj->ref == 0);
> g_free(obj);
> }
This won't work with composition. object_delete() is never called for
child<> objects.
Regards,
Anthony Liguori
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-20 17:58 ` Anthony Liguori
@ 2012-08-21 7:06 ` Paolo Bonzini
2012-08-21 19:53 ` Anthony Liguori
0 siblings, 1 reply; 11+ messages in thread
From: Paolo Bonzini @ 2012-08-21 7:06 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Peter Maydell, Michael Tokarev, qemu-devel
Il 20/08/2012 19:58, Anthony Liguori ha scritto:
> Michael Tokarev <mjt@tls.msk.ru> writes:
>
>> On 08.08.2012 17:09, Michael Tokarev wrote:
>> []
>>> Something similar should be applied to 1.1-stable. FWIW, some
>>> changes are not needed there.
>>
>> Cherry-pick to stable-1.1 removes the two unneeded hunks.
>> This is what I plan to include into debian package. It
>> fixes the original usb_del issue, and I didn't find new
>> regressions so far - tried a few device_del and similar.
>>
>> Should it go to qemu/stable-1.1 as well?
>>
>> Thank you!
>>
>> /mjtAuthor: Paolo Bonzini <pbonzini@redhat.com>
>> Date: Wed Aug 8 14:39:11 2012 +0200
>> Bug-Debian: http://bugs.debian.org/684282
>> Comment: cherry-picked from qemu/master to stable-1.1 (mjt)
>>
>> qom: object_delete should unparent the object first
>>
>> object_deinit is only called when the reference count goes to zero,
>> and yet tries to do an object_unparent. Now, object_unparent
>> either does nothing or it will decrease the reference count.
>> Because we know the reference count is zero, the object_unparent
>> call in object_deinit is useless.
>>
>> Instead, we need to disconnect the object from its parent just
>> before we remove the last reference apart from the parent's. This
>> happens in object_delete. Once we do this, all calls to
>> object_unparent peppered through QEMU can go away.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
>>
>> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
>> index 0345490..585da4e 100644
>> --- a/hw/acpi_piix4.c
>> +++ b/hw/acpi_piix4.c
>> @@ -299,7 +299,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
>> if (pc->no_hotplug) {
>> slot_free = false;
>> } else {
>> - object_unparent(OBJECT(dev));
>> qdev_free(qdev);
>> }
>> }
>> diff --git a/hw/qdev.c b/hw/qdev.c
>> index 6a8f6bd..9bb1c6b 100644
>> --- a/hw/qdev.c
>> +++ b/hw/qdev.c
>> @@ -240,7 +240,6 @@ void qbus_reset_all_fn(void *opaque)
>> int qdev_simple_unplug_cb(DeviceState *dev)
>> {
>> /* just zap it */
>> - object_unparent(OBJECT(dev));
>> qdev_free(dev);
>> return 0;
>> }
>> diff --git a/hw/xen_platform.c b/hw/xen_platform.c
>> index 0214f37..84221df 100644
>> --- a/hw/xen_platform.c
>> +++ b/hw/xen_platform.c
>> @@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
>> {
>> if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
>> PCI_CLASS_NETWORK_ETHERNET) {
>> - /* Until qdev_free includes a call to object_unparent, we call it here
>> - */
>> - object_unparent(&d->qdev.parent_obj);
>> qdev_free(&d->qdev);
>> }
>> }
>> diff --git a/qom/object.c b/qom/object.c
>> index 6f839ad..58dd886 100644
>> --- a/qom/object.c
>> +++ b/qom/object.c
>> @@ -347,8 +347,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
>> if (type_has_parent(type)) {
>> object_deinit(obj, type_get_parent(type));
>> }
>> -
>> - object_unparent(obj);
>> }
>>
>> void object_finalize(void *data)
>> @@ -385,8 +383,9 @@ Object *object_new(const char *typename)
>>
>> void object_delete(Object *obj)
>> {
>> + object_unparent(obj);
>> + g_assert(obj->ref == 1);
>> object_unref(obj);
>> - g_assert(obj->ref == 0);
>> g_free(obj);
>> }
>
> This won't work with composition. object_delete() is never called for
> child<> objects.
For non-heap-allocated children, their last ref will go away when the
parent's child<> property is eliminated. This will remove the last
reference and call object_finalize (which will take care of multiple
levels of compositions).
The same holds for heap-allocated children, but indeed you will leak the
memory for the object because object_delete is not called. However this
is already the case, the patch is not introducing a regression.
Paolo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del
2012-08-21 7:06 ` Paolo Bonzini
@ 2012-08-21 19:53 ` Anthony Liguori
0 siblings, 0 replies; 11+ messages in thread
From: Anthony Liguori @ 2012-08-21 19:53 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Peter Maydell, Michael Tokarev, qemu-devel
Paolo Bonzini <pbonzini@redhat.com> writes:
> Il 20/08/2012 19:58, Anthony Liguori ha scritto:
>> Michael Tokarev <mjt@tls.msk.ru> writes:
>>
>>> On 08.08.2012 17:09, Michael Tokarev wrote:
>>> []
>>>> Something similar should be applied to 1.1-stable. FWIW, some
>>>> changes are not needed there.
>>>
>>> Cherry-pick to stable-1.1 removes the two unneeded hunks.
>>> This is what I plan to include into debian package. It
>>> fixes the original usb_del issue, and I didn't find new
>>> regressions so far - tried a few device_del and similar.
>>>
>>> Should it go to qemu/stable-1.1 as well?
>>>
>>> Thank you!
>>>
>>> /mjtAuthor: Paolo Bonzini <pbonzini@redhat.com>
>>> Date: Wed Aug 8 14:39:11 2012 +0200
>>> Bug-Debian: http://bugs.debian.org/684282
>>> Comment: cherry-picked from qemu/master to stable-1.1 (mjt)
>>>
>>> qom: object_delete should unparent the object first
>>>
>>> object_deinit is only called when the reference count goes to zero,
>>> and yet tries to do an object_unparent. Now, object_unparent
>>> either does nothing or it will decrease the reference count.
>>> Because we know the reference count is zero, the object_unparent
>>> call in object_deinit is useless.
>>>
>>> Instead, we need to disconnect the object from its parent just
>>> before we remove the last reference apart from the parent's. This
>>> happens in object_delete. Once we do this, all calls to
>>> object_unparent peppered through QEMU can go away.
>>>
>>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>>> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
>>>
>>> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
>>> index 0345490..585da4e 100644
>>> --- a/hw/acpi_piix4.c
>>> +++ b/hw/acpi_piix4.c
>>> @@ -299,7 +299,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
>>> if (pc->no_hotplug) {
>>> slot_free = false;
>>> } else {
>>> - object_unparent(OBJECT(dev));
>>> qdev_free(qdev);
>>> }
>>> }
>>> diff --git a/hw/qdev.c b/hw/qdev.c
>>> index 6a8f6bd..9bb1c6b 100644
>>> --- a/hw/qdev.c
>>> +++ b/hw/qdev.c
>>> @@ -240,7 +240,6 @@ void qbus_reset_all_fn(void *opaque)
>>> int qdev_simple_unplug_cb(DeviceState *dev)
>>> {
>>> /* just zap it */
>>> - object_unparent(OBJECT(dev));
>>> qdev_free(dev);
>>> return 0;
>>> }
>>> diff --git a/hw/xen_platform.c b/hw/xen_platform.c
>>> index 0214f37..84221df 100644
>>> --- a/hw/xen_platform.c
>>> +++ b/hw/xen_platform.c
>>> @@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
>>> {
>>> if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
>>> PCI_CLASS_NETWORK_ETHERNET) {
>>> - /* Until qdev_free includes a call to object_unparent, we call it here
>>> - */
>>> - object_unparent(&d->qdev.parent_obj);
>>> qdev_free(&d->qdev);
>>> }
>>> }
>>> diff --git a/qom/object.c b/qom/object.c
>>> index 6f839ad..58dd886 100644
>>> --- a/qom/object.c
>>> +++ b/qom/object.c
>>> @@ -347,8 +347,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
>>> if (type_has_parent(type)) {
>>> object_deinit(obj, type_get_parent(type));
>>> }
>>> -
>>> - object_unparent(obj);
>>> }
>>>
>>> void object_finalize(void *data)
>>> @@ -385,8 +383,9 @@ Object *object_new(const char *typename)
>>>
>>> void object_delete(Object *obj)
>>> {
>>> + object_unparent(obj);
>>> + g_assert(obj->ref == 1);
>>> object_unref(obj);
>>> - g_assert(obj->ref == 0);
>>> g_free(obj);
>>> }
>>
>> This won't work with composition. object_delete() is never called for
>> child<> objects.
>
> For non-heap-allocated children, their last ref will go away when the
> parent's child<> property is eliminated. This will remove the last
> reference and call object_finalize (which will take care of multiple
> levels of compositions).
>
> The same holds for heap-allocated children, but indeed you will leak the
> memory for the object because object_delete is not called. However this
> is already the case, the patch is not introducing a regression.
Ok, can you submit as a top level patch and I'll apply it for 1.2?
Regards,
Anthony Liguori
>
> Paolo
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-08-21 19:54 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-08 12:18 [Qemu-devel] commit da57febfed "qdev: give all devices a canonical path" broke usb_del Michael Tokarev
2012-08-08 12:22 ` Michael Tokarev
2012-08-08 12:39 ` Paolo Bonzini
2012-08-08 12:48 ` Andreas Färber
2012-08-08 13:02 ` Paolo Bonzini
2012-08-08 13:09 ` Michael Tokarev
2012-08-08 14:42 ` Michael Tokarev
2012-08-08 16:08 ` Michael Tokarev
2012-08-20 17:58 ` Anthony Liguori
2012-08-21 7:06 ` Paolo Bonzini
2012-08-21 19:53 ` Anthony Liguori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).