qdev: unplug blocker for devices
Add blocker to prevent hot-unplug of devices TYPE_VFIO_USER_SERVER, which is introduced shortly, attaches itself to a PCIDevice on which it depends. If the attached PCIDevice gets removed while the server in use, it could cause it crash. To prevent this, TYPE_VFIO_USER_SERVER adds an unplug blocker for the PCIDevice. Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com> Signed-off-by: John G Johnson <john.g.johnson@oracle.com> Signed-off-by: Jagannathan Raman <jag.raman@oracle.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: c41ef80b7cc063314d629737bed2159e5713f2e0.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
e2848bc574
commit
217c7f01ad
@ -468,6 +468,28 @@ char *qdev_get_dev_path(DeviceState *dev)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qdev_add_unplug_blocker(DeviceState *dev, Error *reason)
|
||||||
|
{
|
||||||
|
dev->unplug_blockers = g_slist_prepend(dev->unplug_blockers, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qdev_del_unplug_blocker(DeviceState *dev, Error *reason)
|
||||||
|
{
|
||||||
|
dev->unplug_blockers = g_slist_remove(dev->unplug_blockers, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qdev_unplug_blocked(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
|
|
||||||
|
if (dev->unplug_blockers) {
|
||||||
|
error_propagate(errp, error_copy(dev->unplug_blockers->data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool device_get_realized(Object *obj, Error **errp)
|
static bool device_get_realized(Object *obj, Error **errp)
|
||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
@ -704,6 +726,8 @@ static void device_finalize(Object *obj)
|
|||||||
|
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
|
||||||
|
g_assert(!dev->unplug_blockers);
|
||||||
|
|
||||||
QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
|
QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
|
||||||
QLIST_REMOVE(ngl, node);
|
QLIST_REMOVE(ngl, node);
|
||||||
qemu_free_irqs(ngl->in, ngl->num_in);
|
qemu_free_irqs(ngl->in, ngl->num_in);
|
||||||
|
@ -193,6 +193,7 @@ struct DeviceState {
|
|||||||
int instance_id_alias;
|
int instance_id_alias;
|
||||||
int alias_required_for_version;
|
int alias_required_for_version;
|
||||||
ResettableState reset;
|
ResettableState reset;
|
||||||
|
GSList *unplug_blockers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeviceListener {
|
struct DeviceListener {
|
||||||
@ -419,6 +420,34 @@ void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
|
|||||||
void qdev_machine_creation_done(void);
|
void qdev_machine_creation_done(void);
|
||||||
bool qdev_machine_modified(void);
|
bool qdev_machine_modified(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdev_add_unplug_blocker: Add an unplug blocker to a device
|
||||||
|
*
|
||||||
|
* @dev: Device to be blocked from unplug
|
||||||
|
* @reason: Reason for blocking
|
||||||
|
*/
|
||||||
|
void qdev_add_unplug_blocker(DeviceState *dev, Error *reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdev_del_unplug_blocker: Remove an unplug blocker from a device
|
||||||
|
*
|
||||||
|
* @dev: Device to be unblocked
|
||||||
|
* @reason: Pointer to the Error used with qdev_add_unplug_blocker.
|
||||||
|
* Used as a handle to lookup the blocker for deletion.
|
||||||
|
*/
|
||||||
|
void qdev_del_unplug_blocker(DeviceState *dev, Error *reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdev_unplug_blocked: Confirm if a device is blocked from unplug
|
||||||
|
*
|
||||||
|
* @dev: Device to be tested
|
||||||
|
* @reason: Returns one of the reasons why the device is blocked,
|
||||||
|
* if any
|
||||||
|
*
|
||||||
|
* Returns: true if device is blocked from unplug, false otherwise
|
||||||
|
*/
|
||||||
|
bool qdev_unplug_blocked(DeviceState *dev, Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GpioPolarity: Polarity of a GPIO line
|
* GpioPolarity: Polarity of a GPIO line
|
||||||
*
|
*
|
||||||
|
@ -899,6 +899,10 @@ void qdev_unplug(DeviceState *dev, Error **errp)
|
|||||||
HotplugHandlerClass *hdc;
|
HotplugHandlerClass *hdc;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (qdev_unplug_blocked(dev, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) {
|
if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) {
|
||||||
error_setg(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
|
error_setg(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user