|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/8] qdev: hotplug: Add force_unplug handler callback
Add a HotplugHandlerClass force_unplug callback and a wrapper used by the
generic qdev unplug path.
When qdev_unplug() is called with force=true, delegate to the hotplug
controller if it implements force_unplug. Controllers without the callback
return a normal error. This makes forced removal available only for
controllers that explicitly implement the operation.
Signed-off-by: Dongli Zhang <dongli.zhang@xxxxxxxxxx>
---
hw/core/hotplug.c | 11 +++++++++++
include/hw/core/hotplug.h | 12 ++++++++++++
system/qdev-monitor.c | 10 +++++++++-
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c
index 68aabad8ae..0e44d98cf7 100644
--- a/hw/core/hotplug.c
+++ b/hw/core/hotplug.c
@@ -57,6 +57,17 @@ void hotplug_handler_unplug(HotplugHandler *plug_handler,
}
}
+void hotplug_handler_force_unplug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp)
+{
+ HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+
+ if (hdc->force_unplug) {
+ hdc->force_unplug(plug_handler, plugged_dev, errp);
+ }
+}
+
static const TypeInfo hotplug_handler_info = {
.name = TYPE_HOTPLUG_HANDLER,
.parent = TYPE_INTERFACE,
diff --git a/include/hw/core/hotplug.h b/include/hw/core/hotplug.h
index a9840ed485..300ac4fa8f 100644
--- a/include/hw/core/hotplug.h
+++ b/include/hw/core/hotplug.h
@@ -48,6 +48,8 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
* @unplug: unplug callback.
* Used for device removal with devices that implement
* asynchronous and synchronous (surprise) removal.
+ * @force_unplug: force unplug callback.
+ * Used to complete enforced removal without guest cooperation.
* @is_hotpluggable_bus: called to check if bus/its parent allow hotplug on bus
*/
struct HotplugHandlerClass {
@@ -59,6 +61,7 @@ struct HotplugHandlerClass {
hotplug_fn plug;
hotplug_fn unplug_request;
hotplug_fn unplug;
+ hotplug_fn force_unplug;
bool (*is_hotpluggable_bus)(HotplugHandler *plug_handler, BusState *bus);
};
@@ -96,4 +99,13 @@ void hotplug_handler_unplug_request(HotplugHandler
*plug_handler,
void hotplug_handler_unplug(HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp);
+
+/**
+ * hotplug_handler_force_unplug:
+ *
+ * Calls #HotplugHandlerClass.force_unplug callback of @plug_handler.
+ */
+void hotplug_handler_force_unplug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
#endif
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index 3606a347a0..fa3cae246b 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -937,7 +937,15 @@ void qdev_unplug(DeviceState *dev, bool force, Error
**errp)
/* If device supports async unplug just request it to be done,
* otherwise just remove it synchronously */
hdc = HOTPLUG_HANDLER_GET_CLASS(hotplug_ctrl);
- if (hdc->unplug_request) {
+
+ if (force) {
+ if (!hdc->force_unplug) {
+ error_setg(&local_err, "Device '%s' does not support forced
unplug",
+ dev->id ? dev->id : object_get_typename(OBJECT(dev)));
+ } else {
+ hotplug_handler_force_unplug(hotplug_ctrl, dev, &local_err);
+ }
+ } else if (hdc->unplug_request) {
hotplug_handler_unplug_request(hotplug_ctrl, dev, &local_err);
} else {
hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
--
2.43.5
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |