提交 4670f1dd 编写于 作者: J Jiri Denemark

qemu: Finish device removal in the original thread

If QEMU supports DEVICE_DELETED event, we always call
qemuDomainRemoveDevice from the event handler. However, we will need to
push this call away from the main event loop and begin a job for it (see
the following commit), we need to make sure the device is fully removed
by the original thread (and within its existing job) in case the
DEVICE_DELETED event arrives before qemuDomainWaitForDeviceRemoval times
out.

Without this patch, device removals would be guaranteed to never finish
before the timeout because the could would be blocked by the original
job being still active.
Signed-off-by: NJiri Denemark <jdenemar@redhat.com>
上级 f8a0c9ed
...@@ -2780,8 +2780,9 @@ qemuDomainResetDeviceRemoval(virDomainObjPtr vm) ...@@ -2780,8 +2780,9 @@ qemuDomainResetDeviceRemoval(virDomainObjPtr vm)
/* Returns: /* Returns:
* -1 on error * -1 on error
* 0 when DEVICE_DELETED event is unsupported * 0 when DEVICE_DELETED event is unsupported
* 1 when device removal finished * 1 when DEVICE_DELETED arrived before the timeout and the caller is
* 2 device removal did not finish in QEMU_REMOVAL_WAIT_TIME * responsible for finishing the removal
* 2 device removal did not finish in qemuDomainRemoveDeviceWaitTime
*/ */
static int static int
qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm) qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
...@@ -2812,7 +2813,13 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm) ...@@ -2812,7 +2813,13 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
return 1; return 1;
} }
void /* Returns:
* true there was a thread waiting for devAlias to be removed and this
* thread will take care of finishing the removal
* false the thread that started the removal is already gone and delegate
* finishing the removal to a new thread
*/
bool
qemuDomainSignalDeviceRemoval(virDomainObjPtr vm, qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
const char *devAlias) const char *devAlias)
{ {
...@@ -2821,7 +2828,9 @@ qemuDomainSignalDeviceRemoval(virDomainObjPtr vm, ...@@ -2821,7 +2828,9 @@ qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
if (STREQ_NULLABLE(priv->unpluggingDevice, devAlias)) { if (STREQ_NULLABLE(priv->unpluggingDevice, devAlias)) {
qemuDomainResetDeviceRemoval(vm); qemuDomainResetDeviceRemoval(vm);
virCondSignal(&priv->unplugFinished); virCondSignal(&priv->unplugFinished);
return true;
} }
return false;
} }
...@@ -2833,6 +2842,7 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver, ...@@ -2833,6 +2842,7 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
int ret = -1; int ret = -1;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
char *drivestr = NULL; char *drivestr = NULL;
int rc;
if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) { if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) {
virReportError(VIR_ERR_OPERATION_FAILED, virReportError(VIR_ERR_OPERATION_FAILED,
...@@ -2889,7 +2899,8 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver, ...@@ -2889,7 +2899,8 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
if (!qemuDomainWaitForDeviceRemoval(vm)) rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1)
qemuDomainRemoveDiskDevice(driver, vm, detach); qemuDomainRemoveDiskDevice(driver, vm, detach);
ret = 0; ret = 0;
...@@ -2907,6 +2918,7 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver, ...@@ -2907,6 +2918,7 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
int ret = -1; int ret = -1;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
char *drivestr = NULL; char *drivestr = NULL;
int rc;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
virReportError(VIR_ERR_OPERATION_FAILED, virReportError(VIR_ERR_OPERATION_FAILED,
...@@ -2943,7 +2955,8 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver, ...@@ -2943,7 +2955,8 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
if (!qemuDomainWaitForDeviceRemoval(vm)) rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1)
qemuDomainRemoveDiskDevice(driver, vm, detach); qemuDomainRemoveDiskDevice(driver, vm, detach);
ret = 0; ret = 0;
...@@ -3063,6 +3076,7 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver, ...@@ -3063,6 +3076,7 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
int idx, ret = -1; int idx, ret = -1;
virDomainControllerDefPtr detach = NULL; virDomainControllerDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
int rc;
if ((idx = virDomainControllerFind(vm->def, if ((idx = virDomainControllerFind(vm->def,
dev->data.controller->type, dev->data.controller->type,
...@@ -3128,7 +3142,8 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver, ...@@ -3128,7 +3142,8 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
} }
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
if (!qemuDomainWaitForDeviceRemoval(vm)) rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1)
qemuDomainRemoveControllerDevice(driver, vm, detach); qemuDomainRemoveControllerDevice(driver, vm, detach);
ret = 0; ret = 0;
...@@ -3280,10 +3295,13 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver, ...@@ -3280,10 +3295,13 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
return -1; return -1;
} }
if (ret < 0) if (ret < 0) {
virDomainAuditHostdev(vm, detach, "detach", false); virDomainAuditHostdev(vm, detach, "detach", false);
else if (!qemuDomainWaitForDeviceRemoval(vm)) } else {
qemuDomainRemoveHostDevice(driver, vm, detach); int rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1)
qemuDomainRemoveHostDevice(driver, vm, detach);
}
qemuDomainResetDeviceRemoval(vm); qemuDomainResetDeviceRemoval(vm);
...@@ -3361,6 +3379,7 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, ...@@ -3361,6 +3379,7 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
int vlan; int vlan;
char *hostnet_name = NULL; char *hostnet_name = NULL;
int rc;
if ((detachidx = virDomainNetFindIdx(vm->def, dev->data.net)) < 0) if ((detachidx = virDomainNetFindIdx(vm->def, dev->data.net)) < 0)
goto cleanup; goto cleanup;
...@@ -3440,7 +3459,8 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, ...@@ -3440,7 +3459,8 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
} }
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
if (!qemuDomainWaitForDeviceRemoval(vm)) rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1)
qemuDomainRemoveNetDevice(driver, vm, detach); qemuDomainRemoveNetDevice(driver, vm, detach);
ret = 0; ret = 0;
...@@ -3578,6 +3598,7 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver, ...@@ -3578,6 +3598,7 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
virDomainChrDefPtr tmpChr; virDomainChrDefPtr tmpChr;
char *charAlias = NULL; char *charAlias = NULL;
char *devstr = NULL; char *devstr = NULL;
int rc;
if (!(tmpChr = virDomainChrFind(vmdef, chr))) { if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s", virReportError(VIR_ERR_OPERATION_INVALID, "%s",
...@@ -3605,7 +3626,8 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver, ...@@ -3605,7 +3626,8 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
} }
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
if (!qemuDomainWaitForDeviceRemoval(vm)) rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1)
qemuDomainRemoveChrDevice(driver, vm, tmpChr); qemuDomainRemoveChrDevice(driver, vm, tmpChr);
ret = 0; ret = 0;
......
...@@ -106,7 +106,7 @@ void qemuDomainRemoveDevice(virQEMUDriverPtr driver, ...@@ -106,7 +106,7 @@ void qemuDomainRemoveDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virDomainDeviceDefPtr dev); virDomainDeviceDefPtr dev);
void qemuDomainSignalDeviceRemoval(virDomainObjPtr vm, bool qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
const char *devAlias); const char *devAlias);
#endif /* __QEMU_HOTPLUG_H__ */ #endif /* __QEMU_HOTPLUG_H__ */
...@@ -1381,7 +1381,8 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED, ...@@ -1381,7 +1381,8 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
VIR_DEBUG("Device %s removed from domain %p %s", VIR_DEBUG("Device %s removed from domain %p %s",
devAlias, vm, vm->def->name); devAlias, vm, vm->def->name);
qemuDomainSignalDeviceRemoval(vm, devAlias); if (qemuDomainSignalDeviceRemoval(vm, devAlias))
goto cleanup;
if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
goto cleanup; goto cleanup;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册