We need to handle case when libvirtd is restarted after qemu device is
deleted in order to reattach hostdev and before device deleted event is
delivired. First we need to save delete_cause in status xml so that if
event is delivered after libvirtd started back we can proceed with
reattaching. Second if we missed the event we need to continue with
reattaching too.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
---
src/conf/domain_conf.c | 26 ++++++++++++++++++++++++++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_driver.c | 20 ++++++++++++++++++--
src/qemu/qemu_process.c | 6 ++----
4 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9a2385e31c..ecab83147e 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(virDomainHostdevDeleteCause,
+ VIR_DOMAIN_HOSTDEV_DELETE_CAUSE_LAST,
+ "none",
+ "client",
+ "reattaching"
+);
+
VIR_ENUM_IMPL(virDomainLaunchSecurity,
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
"",
@@ -7534,6 +7541,7 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
VIR_AUTOFREE(char *) startupPolicy = NULL;
VIR_AUTOFREE(char *) autoAddress = NULL;
VIR_AUTOFREE(char *) missing = NULL;
+ VIR_AUTOFREE(char *) deleteCause = NULL;
if ((startupPolicy = virXMLPropString(node, "startupPolicy"))) {
def->startupPolicy =
@@ -7556,6 +7564,18 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
def->missing = true;
}
+ if ((deleteCause = virXMLPropString(node, "deleteCause"))) {
+ def->deleteCause =
+ virDomainHostdevDeleteCauseTypeFromString(deleteCause);
+
+ if (def->deleteCause <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown deleteCause '%s'"),
+ deleteCause);
+ goto out;
+ }
+ }
+
/* Product can validly be 0, so we need some extra help to determine
* if it is uninitialized*/
got_product = false;
@@ -24911,6 +24931,12 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
if (def->missing && !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
virBufferAddLit(buf, " missing='yes'");
+
+ if (def->deleteCause && (flags & VIR_DOMAIN_DEF_FORMAT_STATUS)) {
+ const char *deleteCause;
+ deleteCause = virDomainHostdevDeleteCauseTypeToString(def->deleteCause);
+ virBufferAsprintf(buf, " deleteCause='%s'", deleteCause);
+ }
}
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 49392d0286..a2de4c7657 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -333,6 +333,7 @@ typedef enum {
VIR_DOMAIN_HOSTDEV_DELETE_CAUSE_LAST
} virDomainHostdevDeleteCauseType;
+VIR_ENUM_DECL(virDomainHostdevDeleteCause);
/* basic device for direct passthrough */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 352f6d0376..b912766445 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5265,11 +5265,14 @@ processUSBAddedEvent(virQEMUDriverPtr driver,
struct qemuUdevUSBAddData *data)
{
virDomainDeviceDef dev = { .type = VIR_DOMAIN_DEVICE_HOSTDEV };
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainHostdevDefPtr hostdev;
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");
@@ -5295,8 +5298,13 @@ processUSBAddedEvent(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 reattaching device %s",
+ hostdev->info->alias);
+
cleanup:
qemuDomainObjEndJob(driver, vm);
+ virObjectUnref(cfg);
}
@@ -5307,10 +5315,13 @@ processUSBRemovedEvent(virQEMUDriverPtr driver,
{
size_t i;
virDomainDeviceDef dev = { .type = VIR_DOMAIN_DEVICE_HOSTDEV };
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainHostdevDefPtr hostdev;
- 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");
@@ -5335,8 +5346,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 reattaching device %s",
+ hostdev->info->alias);
+
cleanup:
qemuDomainObjEndJob(driver, vm);
+ virObjectUnref(cfg);
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c9921646e9..5cb97de4f3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3720,7 +3720,6 @@ qemuProcessUpdateDevices(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- virDomainDeviceDef dev;
const char **qemuDevices;
char **old;
char **tmp;
@@ -3735,10 +3734,9 @@ qemuProcessUpdateDevices(virQEMUDriverPtr driver,
if ((tmp = old)) {
while (*tmp) {
if (!virStringListHasString(qemuDevices, *tmp) &&
- virDomainDefFindDevice(vm->def, *tmp, &dev, false) == 0
&&
- qemuDomainRemoveDevice(driver, vm, &dev) < 0) {
+ qemuDomainRemoveDeviceAlias(driver, vm, *tmp) < 0)
goto cleanup;
- }
+
tmp++;
}
}
--
2.23.0