All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH for 2.1] qdev: correctly send DEVICE_DELETED for recursively-deleted devices
@ 2014-06-26 13:10 Paolo Bonzini
  2014-06-27  7:16 ` Markus Armbruster
  0 siblings, 1 reply; 4+ messages in thread
From: Paolo Bonzini @ 2014-06-26 13:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru, afaerber

When a device is unparented (i.e. made completely hidden from management)
we want to send a DEVICE_DELETED event only if the device actually was
realized.  This avoids raising DEVICE_DELETED events when device_add
fails.

However, this does not work right for recursively-deleted
devices: the whole tree is _first_ unrealized, _then_ unparented.
Then device_unparent sees realized==false and fails to trigger
the event.  The solution is simply to move have_realized into
the DeviceState struct.  If device_add fails, we never set the
new field to true and DEVICE_DELETED is not sent.

Fixes qemu-iotests testcase 067.

Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/qdev.c         | 5 +++--
 include/hw/qdev-core.h | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index d1eba3c..c520415 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -848,6 +848,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
         if (dev->hotplugged && local_err == NULL) {
             device_reset(dev);
         }
+        dev->pending_deleted_event = false;
     } else if (!value && dev->realized) {
         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
             object_property_set_bool(OBJECT(bus), false, "realized",
@@ -862,6 +863,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
         if (dc->unrealize && local_err == NULL) {
             dc->unrealize(dev, &local_err);
         }
+        dev->pending_deleted_event = true;
     }
 
     if (local_err != NULL) {
@@ -972,7 +974,6 @@ static void device_unparent(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
     BusState *bus;
-    bool have_realized = dev->realized;
 
     if (dev->realized) {
         object_property_set_bool(obj, false, "realized", NULL);
@@ -988,7 +989,7 @@ static void device_unparent(Object *obj)
     }
 
     /* Only send event if the device had been completely realized */
-    if (have_realized) {
+    if (dev->pending_deleted_event) {
         gchar *path = object_get_canonical_path(OBJECT(dev));
 
         qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 9221cfc..0799ff2 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -156,6 +156,7 @@ struct DeviceState {
 
     const char *id;
     bool realized;
+    bool pending_deleted_event;
     QemuOpts *opts;
     int hotplugged;
     BusState *parent_bus;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH for 2.1] qdev: correctly send DEVICE_DELETED for recursively-deleted devices
  2014-06-26 13:10 [Qemu-devel] [PATCH for 2.1] qdev: correctly send DEVICE_DELETED for recursively-deleted devices Paolo Bonzini
@ 2014-06-27  7:16 ` Markus Armbruster
  2014-06-27  8:35   ` Andreas Färber
  0 siblings, 1 reply; 4+ messages in thread
From: Markus Armbruster @ 2014-06-27  7:16 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, afaerber

Paolo Bonzini <pbonzini@redhat.com> writes:

> When a device is unparented (i.e. made completely hidden from management)
> we want to send a DEVICE_DELETED event only if the device actually was
> realized.  This avoids raising DEVICE_DELETED events when device_add
> fails.
>
> However, this does not work right for recursively-deleted
> devices: the whole tree is _first_ unrealized, _then_ unparented.
> Then device_unparent sees realized==false and fails to trigger
> the event.  The solution is simply to move have_realized into
> the DeviceState struct.  If device_add fails, we never set the
> new field to true and DEVICE_DELETED is not sent.
>
> Fixes qemu-iotests testcase 067.

Suggest to add "Broken in commit 5942a19" here, to make it clear that
it's a recent regression.

> Reported-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/core/qdev.c         | 5 +++--
>  include/hw/qdev-core.h | 1 +
>  2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index d1eba3c..c520415 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -848,6 +848,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
       if (value && !dev->realized) {
[...]
>          if (dev->hotplugged && local_err == NULL) {
>              device_reset(dev);
>          }
> +        dev->pending_deleted_event = false;

Unset on completion of unrealized -> realized transition.

>      } else if (!value && dev->realized) {
>          QLIST_FOREACH(bus, &dev->child_bus, sibling) {
>              object_property_set_bool(OBJECT(bus), false, "realized",
> @@ -862,6 +863,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>          if (dc->unrealize && local_err == NULL) {
>              dc->unrealize(dev, &local_err);
>          }
> +        dev->pending_deleted_event = true;

Set on completion of realized -> unrealized transition.

>      }
>  
>      if (local_err != NULL) {
> @@ -972,7 +974,6 @@ static void device_unparent(Object *obj)
>  {
>      DeviceState *dev = DEVICE(obj);
>      BusState *bus;
> -    bool have_realized = dev->realized;
>  
>      if (dev->realized) {
>          object_property_set_bool(obj, false, "realized", NULL);
> @@ -988,7 +989,7 @@ static void device_unparent(Object *obj)
>      }
>  
>      /* Only send event if the device had been completely realized */
> -    if (have_realized) {
> +    if (dev->pending_deleted_event) {
>          gchar *path = object_get_canonical_path(OBJECT(dev));
>  
>          qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);

Let's see whether I understand how this works.  Please correct
misunderstandings.

device_unparent() runs right before device deletion, and only then.

First thing it does is setting property "realized" to false.

Does nothing if the device has never been completely realized.
dev->pending_deleted_event remains in its initial state false.
DEVICE_DELETED not sent.  Good.

Else, the device was completely realized at some time.  If it is
currently realized, we get a transition to unrealized right now, setting
dev->pending_deleted_event.  Else, the last transition must have been
realized -> unrealized, setting dev->pending_deleted_event.  Since it
gets unset only on unrealized -> realized, it's still set.

Therefore, dev->pending_deleted_event is set if and only if the device
has been completely realized.

> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 9221cfc..0799ff2 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -156,6 +156,7 @@ struct DeviceState {
>  
>      const char *id;
>      bool realized;
> +    bool pending_deleted_event;
>      QemuOpts *opts;
>      int hotplugged;
>      BusState *parent_bus;

Reviewed-by: Markus Armbruster <armbru@redhat.com>

(Tested, too, but my r-by subsumes that here)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH for 2.1] qdev: correctly send DEVICE_DELETED for recursively-deleted devices
  2014-06-27  7:16 ` Markus Armbruster
@ 2014-06-27  8:35   ` Andreas Färber
  2014-06-28 20:22     ` Bandan Das
  0 siblings, 1 reply; 4+ messages in thread
From: Andreas Färber @ 2014-06-27  8:35 UTC (permalink / raw)
  To: Markus Armbruster, Paolo Bonzini; +Cc: Bandan Das, qemu-devel

Am 27.06.2014 09:16, schrieb Markus Armbruster:
> Paolo Bonzini <pbonzini@redhat.com> writes:
> 
>> When a device is unparented (i.e. made completely hidden from management)
>> we want to send a DEVICE_DELETED event only if the device actually was
>> realized.  This avoids raising DEVICE_DELETED events when device_add
>> fails.
>>
>> However, this does not work right for recursively-deleted
>> devices: the whole tree is _first_ unrealized, _then_ unparented.
>> Then device_unparent sees realized==false and fails to trigger
>> the event.  The solution is simply to move have_realized into
>> the DeviceState struct.  If device_add fails, we never set the
>> new field to true and DEVICE_DELETED is not sent.
>>
>> Fixes qemu-iotests testcase 067.
> 
> Suggest to add "Broken in commit 5942a19" here, to make it clear that
> it's a recent regression.

I vaguely recall that something like this was in Bandan's RFC (that I
assume the above commit forward-ported, the subject would be handy to
mention too), but once again without any explanation why, so I saw no
need to apply that during hardfreeze.

Andreas

>> Reported-by: Markus Armbruster <armbru@redhat.com>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>

-- 
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] 4+ messages in thread

* Re: [Qemu-devel] [PATCH for 2.1] qdev: correctly send DEVICE_DELETED for recursively-deleted devices
  2014-06-27  8:35   ` Andreas Färber
@ 2014-06-28 20:22     ` Bandan Das
  0 siblings, 0 replies; 4+ messages in thread
From: Bandan Das @ 2014-06-28 20:22 UTC (permalink / raw)
  To: Andreas Färber; +Cc: Paolo Bonzini, Markus Armbruster, qemu-devel

Andreas Färber <afaerber@suse.de> writes:

> Am 27.06.2014 09:16, schrieb Markus Armbruster:
>> Paolo Bonzini <pbonzini@redhat.com> writes:
>> 
>>> When a device is unparented (i.e. made completely hidden from management)
>>> we want to send a DEVICE_DELETED event only if the device actually was
>>> realized.  This avoids raising DEVICE_DELETED events when device_add
>>> fails.
>>>
>>> However, this does not work right for recursively-deleted
>>> devices: the whole tree is _first_ unrealized, _then_ unparented.
>>> Then device_unparent sees realized==false and fails to trigger
>>> the event.  The solution is simply to move have_realized into
>>> the DeviceState struct.  If device_add fails, we never set the
>>> new field to true and DEVICE_DELETED is not sent.
>>>
>>> Fixes qemu-iotests testcase 067.
>> 
>> Suggest to add "Broken in commit 5942a19" here, to make it clear that
>> it's a recent regression.
>
> I vaguely recall that something like this was in Bandan's RFC (that I
> assume the above commit forward-ported, the subject would be handy to
> mention too), but once again without any explanation why, so I saw no
> need to apply that during hardfreeze.

Thanks for pointing it out, yes, I believe that my RFC had this case
covered. (For historical accuracy) Can we please include a link to the
RFC in the commit message ?

Thanks,
Bandan

> Andreas
>
>>> Reported-by: Markus Armbruster <armbru@redhat.com>
>>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> Reviewed-by: Markus Armbruster <armbru@redhat.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-06-28 20:22 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-26 13:10 [Qemu-devel] [PATCH for 2.1] qdev: correctly send DEVICE_DELETED for recursively-deleted devices Paolo Bonzini
2014-06-27  7:16 ` Markus Armbruster
2014-06-27  8:35   ` Andreas Färber
2014-06-28 20:22     ` Bandan Das

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.