hw/qdev: Check machine_hotplug_handler in hotplug_unplug_allowed_common
Commit 03fcbd9dc508 ("qdev: Check for the availability of a hotplug controller before adding a device") says: > The qdev_unplug() function contains a g_assert(hotplug_ctrl) > statement, so QEMU crashes when the user tries to device_add + > device_del a device that does not have a corresponding hotplug > controller. > The code in qdev_device_add() already checks whether the bus has a > proper hotplug controller, but for devices that do not have a > corresponding bus, here is no appropriate check available yet. In that > case we should check whether the machine itself provides a suitable > hotplug controller and refuse to plug the device if none is available. However, it forgot to add the corresponding check to qdev_unplug(). Check the machine hotplug handler once in the common qdev_hotplug_unplug_allowed_common() helper so both hotplug and hot-unplug path are covered. Fixes: 7716b8ca74 ("qdev: HotplugHandler: Add support for unplugging BUS-less devices") Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> [PMD: Split from bigger patch, part 6/6] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Message-Id: <20250110091908.64454-7-philmd@linaro.org>
This commit is contained in:
parent
ccaca8929d
commit
937874a83d
@ -48,6 +48,16 @@ static bool qdev_hotplug_unplug_allowed_common(DeviceState *dev, BusState *bus,
|
|||||||
bus->name);
|
bus->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!qdev_get_machine_hotplug_handler(dev)) {
|
||||||
|
/*
|
||||||
|
* No bus, no machine hotplug handler --> device is not hotpluggable
|
||||||
|
*/
|
||||||
|
error_setg(errp,
|
||||||
|
"Device '%s' can not be hotplugged on this machine",
|
||||||
|
object_get_typename(OBJECT(dev)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -684,19 +684,11 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts,
|
|||||||
dev = qdev_new(driver);
|
dev = qdev_new(driver);
|
||||||
|
|
||||||
/* Check whether the hotplug is allowed by the machine */
|
/* Check whether the hotplug is allowed by the machine */
|
||||||
if (phase_check(PHASE_MACHINE_READY)) {
|
if (phase_check(PHASE_MACHINE_READY) &&
|
||||||
if (!qdev_hotplug_allowed(dev, bus, errp)) {
|
!qdev_hotplug_allowed(dev, bus, errp)) {
|
||||||
goto err_del_dev;
|
goto err_del_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bus && !qdev_get_machine_hotplug_handler(dev)) {
|
|
||||||
/* No bus, no machine hotplug handler --> device is not hotpluggable */
|
|
||||||
error_setg(errp, "Device '%s' can not be hotplugged on this machine",
|
|
||||||
driver);
|
|
||||||
goto err_del_dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set dev's parent and register its id.
|
* set dev's parent and register its id.
|
||||||
* If it fails it means the id is already taken.
|
* If it fails it means the id is already taken.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user