Skip to content

Commit

Permalink
qdev: DEVICE_DELETED event
Browse files Browse the repository at this point in the history
libvirt has a long-standing bug: when removing the device,
it can request removal but does not know when the
removal completes. Add an event so we can fix this in a robust way.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
mstsirkin committed Mar 17, 2013
1 parent b1999e8 commit 0402a5d
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 1 deletion.
16 changes: 16 additions & 0 deletions QMP/qmp-events.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,22 @@ Example:
Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
event.

DEVICE_DELETED
-----------------

Emitted whenever the device removal completion is acknowledged
by the guest.
At this point, it's safe to reuse the specified device ID.
Device removal can be initiated by the guest or by HMP/QMP commands.

Data:

- "device": device name (json-string, optional)

{ "event": "DEVICE_DELETED",
"data": { "device": "virtio-net-pci-0" },
"timestamp": { "seconds": 1265044230, "microseconds": 450486 } }

DEVICE_TRAY_MOVED
-----------------

Expand Down
11 changes: 11 additions & 0 deletions hw/qdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
#include "qapi/qmp/qjson.h"
#include "monitor/monitor.h"

int qdev_hotplug = 0;
static bool qdev_hot_added = false;
Expand Down Expand Up @@ -761,6 +763,7 @@ static void device_unparent(Object *obj)
DeviceState *dev = DEVICE(obj);
DeviceClass *dc = DEVICE_GET_CLASS(dev);
BusState *bus;
QObject *event_data;

while (dev->num_child_bus) {
bus = QLIST_FIRST(&dev->child_bus);
Expand All @@ -779,6 +782,14 @@ static void device_unparent(Object *obj)
object_unref(OBJECT(dev->parent_bus));
dev->parent_bus = NULL;
}

if (dev->id) {
event_data = qobject_from_jsonf("{ 'device': %s }", dev->id);
} else {
event_data = qobject_from_jsonf("{ }");
}
monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
qobject_decref(event_data);
}

static void device_class_init(ObjectClass *class, void *data)
Expand Down
1 change: 1 addition & 0 deletions include/monitor/monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef enum MonitorEvent {
QEVENT_BLOCK_JOB_CANCELLED,
QEVENT_BLOCK_JOB_ERROR,
QEVENT_BLOCK_JOB_READY,
QEVENT_DEVICE_DELETED,
QEVENT_DEVICE_TRAY_MOVED,
QEVENT_SUSPEND,
QEVENT_SUSPEND_DISK,
Expand Down
1 change: 1 addition & 0 deletions monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ static const char *monitor_event_names[] = {
[QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
[QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
[QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
[QEVENT_DEVICE_DELETED] = "DEVICE_DELETED",
[QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
[QEVENT_SUSPEND] = "SUSPEND",
[QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
Expand Down
4 changes: 3 additions & 1 deletion qapi-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2354,7 +2354,9 @@
# Notes: When this command completes, the device may not be removed from the
# guest. Hot removal is an operation that requires guest cooperation.
# This command merely requests that the guest begin the hot removal
# process.
# process. Completion of the device removal process is signaled with a
# DEVICE_DELETED event. Guest reset will automatically complete removal
# for all devices.
#
# Since: 0.14.0
##
Expand Down

0 comments on commit 0402a5d

Please sign in to comment.