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@xxxxxxxxx> --- 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 deeb94fe79..fe823bb910 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -5216,15 +5216,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) { @@ -5247,6 +5253,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 @@ -6098,7 +6115,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.24.1