* [Qemu-devel] [PATCH] xen: use qdev_unplug() insteda of g_free() in xen_pv_find_xendev()
@ 2017-01-30 15:14 Juergen Gross
2017-01-30 15:46 ` Peter Maydell
0 siblings, 1 reply; 3+ messages in thread
From: Juergen Gross @ 2017-01-30 15:14 UTC (permalink / raw)
To: qemu-devel, xen-devel
Cc: anthony.perard, kraxel, sstabellini, roger.pau, Juergen Gross
The error exits of xen_pv_find_xendev() free the new xen-device via
g_free() which is wrong.
As the xen-device has been initialized as qdev it must be removed
via qdev_unplug().
This bug has been introduced with commit 3a6c9172ac5951e6dac2b3f6
("xen: create qdev for each backend device").
Reported-by: Roger Pau Monné <roger.pau@citrix.com>
Tested-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
---
hw/xen/xen_backend.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index d119004..030772b 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -145,7 +145,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
xendev->evtchndev = xenevtchn_open(NULL, 0);
if (xendev->evtchndev == NULL) {
xen_pv_printf(NULL, 0, "can't open evtchn device\n");
- g_free(xendev);
+ qdev_unplug(&xendev->qdev, NULL);
return NULL;
}
fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
@@ -155,7 +155,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
if (xendev->gnttabdev == NULL) {
xen_pv_printf(NULL, 0, "can't open gnttab device\n");
xenevtchn_close(xendev->evtchndev);
- g_free(xendev);
+ qdev_unplug(&xendev->qdev, NULL);
return NULL;
}
} else {
--
2.10.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] xen: use qdev_unplug() insteda of g_free() in xen_pv_find_xendev()
2017-01-30 15:14 [Qemu-devel] [PATCH] xen: use qdev_unplug() insteda of g_free() in xen_pv_find_xendev() Juergen Gross
@ 2017-01-30 15:46 ` Peter Maydell
2017-01-30 15:58 ` Juergen Gross
0 siblings, 1 reply; 3+ messages in thread
From: Peter Maydell @ 2017-01-30 15:46 UTC (permalink / raw)
To: Juergen Gross
Cc: QEMU Developers, xen-devel, Anthony PERARD, Stefano Stabellini,
Gerd Hoffmann, Roger Pau Monné
On 30 January 2017 at 15:14, Juergen Gross <jgross@suse.com> wrote:
> The error exits of xen_pv_find_xendev() free the new xen-device via
> g_free() which is wrong.
>
> As the xen-device has been initialized as qdev it must be removed
> via qdev_unplug().
>
> This bug has been introduced with commit 3a6c9172ac5951e6dac2b3f6
> ("xen: create qdev for each backend device").
>
> Reported-by: Roger Pau Monné <roger.pau@citrix.com>
> Tested-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> hw/xen/xen_backend.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
> index d119004..030772b 100644
> --- a/hw/xen/xen_backend.c
> +++ b/hw/xen/xen_backend.c
> @@ -145,7 +145,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> xendev->evtchndev = xenevtchn_open(NULL, 0);
> if (xendev->evtchndev == NULL) {
> xen_pv_printf(NULL, 0, "can't open evtchn device\n");
> - g_free(xendev);
> + qdev_unplug(&xendev->qdev, NULL);
> return NULL;
> }
> fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> @@ -155,7 +155,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> if (xendev->gnttabdev == NULL) {
> xen_pv_printf(NULL, 0, "can't open gnttab device\n");
> xenevtchn_close(xendev->evtchndev);
> - g_free(xendev);
> + qdev_unplug(&xendev->qdev, NULL);
> return NULL;
> }
> } else {
I think this will leak memory (and that we're already leaking
memory), because the code is creating the xendev with
xendev = g_malloc0(ops->size);
object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
This is saying "I own and am responsible for freeing the memory
that the device object lives in". If you want the object system
to handle freeing the memory for you when the reference count
goes to zero, then you need to create it with
xendev = object_new()
which we can't do here because we're allocating ops->size bytes
rather than just the size of the object type.
Two options I think:
(1) have your code do
OBJECT(xendev)->free = g_free;
after the object_initialize (to tell the object system how
to free this object)
(2) call both qdev_unplug and g_free
I think (1) is better because it will definitely work even
if the qdev bus system is holding on to an object reference
after it returns from qdev_unplug() for some reason, and
it will also mean we free the memory when we do a
qdev_unplug in xen_pv_del_xendev(), rather than leaking it.
Side note: Using DEVICE(xendev) is better QOM style than
&xendev->qdev.
(The weirdness with doing a g_malloc0(ops->size) appears
to be because Xen backends have their own setup for saying
"allocate this many bytes for my data", rather than having
XenBlkDev, XenConsole, etc be QOM subclasses of XenDevice.
Presumably that code all predates QEMU's QOMification.)
We also do OBJECT(thing)->free = something in hw/core/sysbus.c;
maybe we should have a function to abstract this away?
Not sure.
thanks
-- PMM
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] xen: use qdev_unplug() insteda of g_free() in xen_pv_find_xendev()
2017-01-30 15:46 ` Peter Maydell
@ 2017-01-30 15:58 ` Juergen Gross
0 siblings, 0 replies; 3+ messages in thread
From: Juergen Gross @ 2017-01-30 15:58 UTC (permalink / raw)
To: Peter Maydell
Cc: QEMU Developers, xen-devel, Anthony PERARD, Stefano Stabellini,
Gerd Hoffmann, Roger Pau Monné
On 30/01/17 16:46, Peter Maydell wrote:
> On 30 January 2017 at 15:14, Juergen Gross <jgross@suse.com> wrote:
>> The error exits of xen_pv_find_xendev() free the new xen-device via
>> g_free() which is wrong.
>>
>> As the xen-device has been initialized as qdev it must be removed
>> via qdev_unplug().
>>
>> This bug has been introduced with commit 3a6c9172ac5951e6dac2b3f6
>> ("xen: create qdev for each backend device").
>>
>> Reported-by: Roger Pau Monné <roger.pau@citrix.com>
>> Tested-by: Roger Pau Monné <roger.pau@citrix.com>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> hw/xen/xen_backend.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
>> index d119004..030772b 100644
>> --- a/hw/xen/xen_backend.c
>> +++ b/hw/xen/xen_backend.c
>> @@ -145,7 +145,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
>> xendev->evtchndev = xenevtchn_open(NULL, 0);
>> if (xendev->evtchndev == NULL) {
>> xen_pv_printf(NULL, 0, "can't open evtchn device\n");
>> - g_free(xendev);
>> + qdev_unplug(&xendev->qdev, NULL);
>> return NULL;
>> }
>> fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
>> @@ -155,7 +155,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
>> if (xendev->gnttabdev == NULL) {
>> xen_pv_printf(NULL, 0, "can't open gnttab device\n");
>> xenevtchn_close(xendev->evtchndev);
>> - g_free(xendev);
>> + qdev_unplug(&xendev->qdev, NULL);
>> return NULL;
>> }
>> } else {
>
> I think this will leak memory (and that we're already leaking
> memory), because the code is creating the xendev with
> xendev = g_malloc0(ops->size);
> object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
>
> This is saying "I own and am responsible for freeing the memory
> that the device object lives in". If you want the object system
> to handle freeing the memory for you when the reference count
> goes to zero, then you need to create it with
> xendev = object_new()
> which we can't do here because we're allocating ops->size bytes
> rather than just the size of the object type.
>
> Two options I think:
> (1) have your code do
> OBJECT(xendev)->free = g_free;
> after the object_initialize (to tell the object system how
> to free this object)
> (2) call both qdev_unplug and g_free
>
> I think (1) is better because it will definitely work even
> if the qdev bus system is holding on to an object reference
> after it returns from qdev_unplug() for some reason, and
> it will also mean we free the memory when we do a
> qdev_unplug in xen_pv_del_xendev(), rather than leaking it.
I agree. I'll send V2 with (1) included.
> Side note: Using DEVICE(xendev) is better QOM style than
> &xendev->qdev.
Okay. Will change.
Thanks for the very precise description.
Juergen
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-01-30 15:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-30 15:14 [Qemu-devel] [PATCH] xen: use qdev_unplug() insteda of g_free() in xen_pv_find_xendev() Juergen Gross
2017-01-30 15:46 ` Peter Maydell
2017-01-30 15:58 ` Juergen Gross
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).