|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 3/8] qdev: Support forced device_del in QMP and HMP
Add an optional force argument to the QMP device_del command and expose it
in HMP as "device_del -f".
When force is requested, qdev_unplug() bypasses the pending deletion guard
and asks the selected hotplug controller to complete removal through its
force_unplug callback. Controllers that do not implement the callback
reject the operation.
Forced removal bypasses guest cooperation.
Signed-off-by: Dongli Zhang <dongli.zhang@xxxxxxxxxx>
---
hmp-commands.hx | 11 ++++++-----
qapi/qdev.json | 11 +++++++++--
system/qdev-monitor.c | 11 +++++++----
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 43ff220b5f..022502b20f 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -708,17 +708,18 @@ ERST
{
.name = "device_del",
- .args_type = "id:s",
- .params = "device",
- .help = "remove device",
+ .args_type = "force:-f,id:s",
+ .params = "[-f] device",
+ .help = "remove device, use -f to force removal",
.cmd = hmp_device_del,
.command_completion = device_del_completion,
},
SRST
-``device_del`` *id*
+``device_del`` [*-f*] *id*
Remove device *id*. *id* may be a short ID
- or a QOM object path.
+ or a QOM object path. Use -f to force removal without waiting for
+ guest cooperation.
ERST
{
diff --git a/qapi/qdev.json b/qapi/qdev.json
index 974cf9c583..cb5b5ad1db 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -90,6 +90,11 @@
#
# @id: the device's ID or QOM path
#
+# @force: if true, remove the device without waiting for guest
+# cooperation. The guest may still be using the device. This can
+# cause guest-visible errors, I/O failures, or guest crashes.
+# (since 11.2)
+#
# Errors:
# - If @id is not a valid device, DeviceNotFound
#
@@ -101,7 +106,9 @@
# will automatically complete removal for all devices. If a
# guest-side error in the hot removal process is detected, the
# device will not be removed and a `DEVICE_UNPLUG_GUEST_ERROR`
-# event is sent. Some errors cannot be detected.
+# event is sent. Some errors cannot be detected. If @force is
+# true, guest cooperation is bypassed, but backend cleanup is still
+# performed through the device's normal unrealize path.
#
# Since: 0.14
#
@@ -117,7 +124,7 @@
# "arguments": { "id": "/machine/peripheral-anon/device[0]" } }
# <- { "return": {} }
##
-{ 'command': 'device_del', 'data': {'id': 'str'} }
+{ 'command': 'device_del', 'data': {'id': 'str', '*force': 'bool'} }
##
# @DEVICE_DELETED:
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index fa3cae246b..ca10a25c46 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -956,11 +956,13 @@ void qdev_unplug(DeviceState *dev, bool force, Error
**errp)
error_propagate(errp, local_err);
}
-void qmp_device_del(const char *id, Error **errp)
+void qmp_device_del(const char *id, bool has_force, bool force, Error **errp)
{
DeviceState *dev = find_device_state(id, false, errp);
+ bool do_force = has_force && force;
+
if (dev != NULL) {
- if (dev->pending_deleted_event &&
+ if (!do_force && dev->pending_deleted_event &&
(dev->pending_deleted_expires_ms == 0 ||
dev->pending_deleted_expires_ms >
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL))) {
error_setg(errp, "Device %s is already in the "
@@ -968,7 +970,7 @@ void qmp_device_del(const char *id, Error **errp)
return;
}
- qdev_unplug(dev, false, errp);
+ qdev_unplug(dev, do_force, errp);
}
}
@@ -1046,9 +1048,10 @@ out:
void hmp_device_del(Monitor *mon, const QDict *qdict)
{
const char *id = qdict_get_str(qdict, "id");
+ bool force = qdict_get_try_bool(qdict, "force", false);
Error *err = NULL;
- qmp_device_del(id, &err);
+ qmp_device_del(id, true, force, &err);
hmp_handle_error(mon, err);
}
--
2.43.5
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |