With multifunction devices, multiple delete requests are sent
to qemu and all the requests should be queued up.
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
---
src/qemu/qemu_domain.h | 3 ++-
src/qemu/qemu_hotplug.c | 38 ++++++++++++++++++++++++--------------
2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 339d0ba82c..85cbc2b5e8 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -195,7 +195,8 @@ typedef enum {
typedef struct _qemuDomainUnpluggingDevice qemuDomainUnpluggingDevice;
typedef qemuDomainUnpluggingDevice *qemuDomainUnpluggingDevicePtr;
struct _qemuDomainUnpluggingDevice {
- const char *alias;
+ const char **aliases;
+ size_t naliases;
qemuDomainUnpluggingDeviceStatus status;
};
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 007ecb0923..7dffaf9502 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4542,16 +4542,21 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
static void
qemuDomainMarkDeviceAliasForRemoval(virDomainObjPtr vm,
- const char *alias)
+ const char *alias,
+ bool fresh)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- memset(&priv->unplug, 0, sizeof(priv->unplug));
+ if (fresh)
+ memset(&priv->unplug, 0, sizeof(priv->unplug));
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
return;
- priv->unplug.alias = alias;
+ if (VIR_REALLOC_N(priv->unplug.aliases, priv->unplug.naliases + 1) < 0)
+ return;
+
+ priv->unplug.aliases[priv->unplug.naliases++] = alias;
}
@@ -4560,7 +4565,7 @@ qemuDomainMarkDeviceForRemoval(virDomainObjPtr vm,
virDomainDeviceInfoPtr info)
{
- qemuDomainMarkDeviceAliasForRemoval(vm, info->alias);
+ qemuDomainMarkDeviceAliasForRemoval(vm, info->alias, true);
}
@@ -4568,7 +4573,8 @@ static void
qemuDomainResetDeviceRemoval(virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- priv->unplug.alias = NULL;
+ VIR_FREE(priv->unplug.aliases);
+ priv->unplug.naliases = 0;
}
/* Returns:
@@ -4596,13 +4602,14 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
return 1;
until += qemuDomainRemoveDeviceWaitTime;
- while (priv->unplug.alias) {
+ /* All devices should get released around same time*/
+ while (priv->unplug.naliases) {
if ((rc = virDomainObjWaitUntil(vm, until)) == 1)
return 0;
if (rc < 0) {
VIR_WARN("Failed to wait on unplug condition for domain '%s'
"
- "device '%s'", vm->def->name,
priv->unplug.alias);
+ "device '%s'", vm->def->name,
priv->unplug.aliases[0]);
return 1;
}
}
@@ -4627,14 +4634,17 @@ qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
const char *devAlias,
qemuDomainUnpluggingDeviceStatus status)
{
+ size_t i;
qemuDomainObjPrivatePtr priv = vm->privateData;
- if (STREQ_NULLABLE(priv->unplug.alias, devAlias)) {
- VIR_DEBUG("Removal of device '%s' continues in waiting thread",
devAlias);
- qemuDomainResetDeviceRemoval(vm);
- priv->unplug.status = status;
- virDomainObjBroadcast(vm);
- return true;
+ for (i = 0; i < priv->unplug.naliases; i++) {
+ if (STREQ_NULLABLE(priv->unplug.aliases[i], devAlias)) {
+ VIR_DEBUG("Removal of device '%s' continues in waiting
thread", devAlias);
+ VIR_DELETE_ELEMENT(priv->unplug.aliases, i, priv->unplug.naliases);
+ priv->unplug.status = status;
+ virDomainObjBroadcast(vm);
+ return true;
+ }
}
return false;
}
@@ -5675,7 +5685,7 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
return -1;
}
- qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
+ qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias, true);
qemuDomainObjEnterMonitor(driver, vm);