In a multifunction hot-unplug, QEMU will unplug all the
functions in a single detach operation, sequentially, triggered
by the detach of function zero for Pseries guests or any
function for x86 guests. This impacts the amount of timeout
we're supposed to wait - an unplug operation with 4
hostdevs will naturally take longer than a single
hostdev unplug.
The previous existing timeout wasn't enough to handle this
multifunction detach case, timing out the detach operation
needlessly. This patch handles it by adding a new
qemuDomainWaitForMultipleDeviceRemoval function that
considers the number of naliases to be unplugged when
calculating unplugTimeout.
Signed-off-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
---
src/qemu/qemu_hotplug.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 9d6671f4f6..23c7d57682 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5276,15 +5276,21 @@ qemuDomainGetUnplugTimeout(virDomainObjPtr vm)
* - we failed to reliably wait for the event and thus use fallback behavior
*/
static int
-qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
+qemuDomainWaitForMultipleDeviceRemoval(virDomainObjPtr vm,
+ bool isMultiFunctionDevice)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- unsigned long long until;
+ unsigned long long until, waitTime;
int rc;
if (virTimeMillisNow(&until) < 0)
return 1;
- until += qemuDomainGetUnplugTimeout(vm);
+
+ waitTime = qemuDomainGetUnplugTimeout(vm);
+ if (isMultiFunctionDevice)
+ waitTime *= priv->unplug.naliases;
+
+ until += waitTime;
/* All devices should get released around same time*/
while (priv->unplug.naliases) {
@@ -5307,6 +5313,17 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
return 1;
}
+/* For a single device, call qemuDomainWaitForMultipleDeviceRemoval with
+ * isMultiFunctionDevice = false.
+ *
+ * Returns: same values as qemuDomainWaitForMultipleDeviceRemoval.
+ */
+static int
+qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
+{
+ return qemuDomainWaitForMultipleDeviceRemoval(vm, false);
+}
+
/* Returns:
* true there was a thread waiting for devAlias to be removed and this
* thread will take care of finishing the removal
@@ -6188,7 +6205,7 @@ qemuDomainDetachMultifunctionDevice(virDomainObjPtr vm,
if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1;
- if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1) {
+ if ((ret = qemuDomainWaitForMultipleDeviceRemoval(vm, true)) == 1) {
FOR_EACH_DEV_IN_DEVLIST()
ret = qemuDomainRemoveHostDevice(driver, vm, detach);
}
--
2.26.2