It is possible for libvirtd to go down before DEVICE_DELETED event is
delivered upon usb hostdev unplug and to receive the event after the
libvirtd is up. In order to handle this case we need to save
usb hostdev deleteAction in status file.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
---
src/conf/domain_conf.c | 26 ++++++++++++++++++++++++++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_driver.c | 20 ++++++++++++++++++--
3 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index db065f6a5b..c2d141fc74 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1236,6 +1236,13 @@ VIR_ENUM_IMPL(virDomainShmemModel,
"ivshmem-doorbell",
);
+VIR_ENUM_IMPL(virDomainHostdevDeleteAction,
+ VIR_DOMAIN_HOSTDEV_DELETE_ACTION_LAST,
+ "none",
+ "delete",
+ "unplug"
+);
+
VIR_ENUM_IMPL(virDomainLaunchSecurity,
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
"",
@@ -7546,6 +7553,7 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
VIR_AUTOFREE(char *) startupPolicy = NULL;
VIR_AUTOFREE(char *) autoAddress = NULL;
+ VIR_AUTOFREE(char *) deleteAction = NULL;
if ((startupPolicy = virXMLPropString(node, "startupPolicy"))) {
def->startupPolicy =
@@ -7563,6 +7571,18 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
usbsrc->autoAddress = true;
}
+ if ((deleteAction = virXMLPropString(node, "deleteAction"))) {
+ def->deleteAction =
+ virDomainHostdevDeleteActionTypeFromString(deleteAction);
+
+ if (def->deleteAction <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown deleteAction '%s'"),
+ deleteAction);
+ goto out;
+ }
+ }
+
/* Product can validly be 0, so we need some extra help to determine
* if it is uninitialized*/
got_product = false;
@@ -24979,6 +24999,12 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
if (def->missing && !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
virBufferAddLit(buf, " missing='yes'");
+
+ if (def->deleteAction && (flags & VIR_DOMAIN_DEF_FORMAT_STATUS))
{
+ const char *deleteAction;
+ deleteAction =
virDomainHostdevDeleteActionTypeToString(def->deleteAction);
+ virBufferAsprintf(buf, " deleteAction='%s'",
deleteAction);
+ }
}
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index da005e5423..d596551d3a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -340,6 +340,7 @@ typedef enum {
VIR_DOMAIN_HOSTDEV_DELETE_ACTION_LAST
} virDomainHostdevDeleteActionType;
+VIR_ENUM_DECL(virDomainHostdevDeleteAction);
/* basic device for direct passthrough */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 51f1d5d4a2..b12b39d61d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5256,10 +5256,13 @@ processUSBAddedEvent(virQEMUDriverPtr driver,
{
virDomainHostdevDefPtr hostdev;
virDomainHostdevSubsysUSBPtr usbsrc;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
size_t i;
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
+ virObjectUnref(cfg);
return;
+ }
if (!virDomainObjIsActive(vm)) {
VIR_DEBUG("Domain is not running");
@@ -5287,8 +5290,13 @@ processUSBAddedEvent(virQEMUDriverPtr driver,
if (qemuDomainAttachHostDevice(driver, vm, hostdev) < 0)
goto cleanup;
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps)
< 0)
+ VIR_WARN("unable to save domain status after plugging device %s",
+ hostdev->info->alias);
+
cleanup:
qemuDomainObjEndJob(driver, vm);
+ virObjectUnref(cfg);
}
@@ -5300,9 +5308,12 @@ processUSBRemovedEvent(virQEMUDriverPtr driver,
size_t i;
virDomainHostdevDefPtr hostdev;
virDomainDeviceDef dev = { .type = VIR_DOMAIN_DEVICE_HOSTDEV };
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
+ virObjectUnref(cfg);
return;
+ }
if (!virDomainObjIsActive(vm)) {
VIR_DEBUG("Domain is not running");
@@ -5338,8 +5349,13 @@ processUSBRemovedEvent(virQEMUDriverPtr driver,
if (qemuDomainDetachDeviceLive(vm, &dev, driver, true, true) < 0)
goto cleanup;
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps)
< 0)
+ VIR_WARN("unable to save domain status after unplugging device %s",
+ hostdev->info->alias);
+
cleanup:
qemuDomainObjEndJob(driver, vm);
+ virObjectUnref(cfg);
}
--
2.23.0