From: Long YunJian <long.yunjian(a)zte.com.cn>
We detach windows disk with libvirt-python api dom.detachDeviceFlags(xmlstr,3),
but files in windows disk is opened and busy, and libvirt return success.
We found disk not detached actually. so, we close files those opened in windows,
and want to detach again. However, we failed with device not found but disk is
exist actually.
first time detach disk:
a. get vmdef from domain->newDef here:
qemuDomainDetachDeviceLiveAndConfig
virDomainObjCopyPersistentDef
virDomainObjGetPersistentDef
domain->newDef
b. delete disk config here:
qemuDomainDetachDeviceLiveAndConfig
qemuDomainDetachDeviceConfig
virDomainDiskRemoveByName
virDomainDiskRemove
c. update from vmdef to newDef
qemuDomainDetachDeviceLiveAndConfig
virDomainObjAssignDef
domain->newDef = vmdef
second time detach disk:
get vmdef from domain->newDef here:
qemuDomainDetachDeviceLiveAndConfig
virDomainObjCopyPersistentDef
virDomainObjGetPersistentDef
domain->newDef
and then, report device not found here for disk config deleted at the first time:
qemuDomainDetachDeviceLiveAndConfig
qemuDomainDetachDeviceConfig
virDomainDiskRemoveByName
to fix this problem, let detach disk again, we add disk to config if timeout,
and let it deleted in processDeviceDeletedEvent if guestos detach disk successfinnaly.
Signed-off-by: Long YunJian <long.yunjian(a)zte.com.cn>
---
src/qemu/qemu_driver.c | 35 +++++++++++++++++++++++++++++++++++
src/qemu/qemu_hotplug.c | 12 +++++++++++-
tests/qemuhotplugtest.c | 2 +-
3 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d01f788aea..0ab661251c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3598,6 +3598,9 @@ processDeviceDeletedEvent(virQEMUDriver *driver,
const char *devAlias)
{
virDomainDeviceDef dev;
+ virDomainDiskDef *det_disk = NULL;
+ g_autofree char *disk_dst_name = NULL;
+ bool devicedisk = false;
VIR_DEBUG("Removing device %s from domain %p %s",
devAlias, vm, vm->def->name);
@@ -3616,8 +3619,19 @@ processDeviceDeletedEvent(virQEMUDriver *driver,
if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
goto endjob;
+ if (dev.type & VIR_DOMAIN_DEVICE_DISK) {
+ devicedisk = true;
+ disk_dst_name = g_strdup(dev.data.disk->dst);
+ }
+
if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
goto endjob;
+
+ if (devicedisk && disk_dst_name) {
+ if ((det_disk = virDomainDiskRemoveByName(vm->newDef, disk_dst_name))) {
+ virDomainDiskDefFree(det_disk);
+ }
+ }
}
qemuDomainSaveStatus(vm);
@@ -7491,6 +7505,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
g_autoptr(virDomainDeviceDef) dev_live = NULL;
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
g_autoptr(virDomainDef) vmdef = NULL;
+ bool timeout = false;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -7530,6 +7545,10 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
if ((rc = qemuDomainDetachDeviceLive(vm, dev_live, driver, false)) < 0)
return -1;
+ if (rc == 2) {
+ timeout = true;
+ rc = 0;
+ }
if (rc == 0 && qemuDomainUpdateDeviceList(vm, VIR_ASYNC_JOB_NONE) <
0)
return -1;
@@ -7542,6 +7561,22 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
if (virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir) < 0)
return -1;
+ /* if timeout, add device to vmdef, and delete at processDeviceDeletedEvent */
+ if (timeout && (dev_config->type & VIR_DOMAIN_DEVICE_DISK)) {
+ g_autoptr(virDomainDeviceDef) devConf = NULL;
+ unsigned int attach_parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
+ VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
+
+ if (!(devConf = virDomainDeviceDefParse(xml, vmdef,
+ driver->xmlopt,
priv->qemuCaps,
+ attach_parse_flags)))
+ return -1;
+ if (qemuDomainAttachDeviceConfig(vmdef, devConf, priv->qemuCaps,
+ attach_parse_flags,
+ driver->xmlopt) < 0)
+ return -1;
+ }
+
virDomainObjAssignDef(vm, &vmdef, false, NULL);
/* Event sending if persistent config has changed */
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 774962b0df..98b47bfa9c 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -6090,6 +6090,13 @@ qemuDomainDetachDeviceLease(virQEMUDriver *driver,
}
+/* Returns:
+ * -1 Unplug of the device failed
+ *
+ * 0 Unplug of the device success
+ *
+ * 2 removal of the device did not finish in qemuDomainRemoveDeviceWaitTime
+ */
int
qemuDomainDetachDeviceLive(virDomainObj *vm,
virDomainDeviceDef *match,
@@ -6297,7 +6304,10 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
if (async) {
ret = 0;
} else {
- if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+ ret = qemuDomainWaitForDeviceRemoval(vm);
+ if (ret == 0)
+ ret = 2;
+ if (ret == 1)
ret = qemuDomainRemoveDevice(driver, vm, &detach);
}
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index 961a7a3c64..6c1c6112d9 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -238,7 +238,7 @@ testQemuHotplug(const void *data)
case DETACH:
ret = qemuDomainDetachDeviceLive(vm, dev, &driver, false);
- if (ret == 0 || fail)
+ if (ret == 2 || ret == 0 || fail)
ret = testQemuHotplugCheckResult(vm, domain_xml,
domain_filename, fail);
break;
--
2.31.1