This patch removes the old vcpu unplug code completely and replaces it
with the new code using device_del. The old hotplug code basically never
worked with any recent qemu and thus is useless.
As the new code is using device_del all the implications of using it
are present. Contrary to the device deletion code, the vcpu deletion
code fails if the unplug request is not executed in time.
---
src/qemu/qemu_driver.c | 74 ++++++---------------------------
src/qemu/qemu_hotplug.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hotplug.h | 7 ++++
3 files changed, 128 insertions(+), 61 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b531cf5..2248d54 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4061,11 +4061,15 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
goto endjob;
}
- if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
- goto endjob;
+ if (STRPREFIX(devAlias, "vcpu")) {
+ qemuDomainRemoveVcpuAlias(driver, vm, devAlias);
+ } else {
+ if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
+ goto endjob;
- if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
- goto endjob;
+ if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
+ goto endjob;
+ }
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps)
< 0)
VIR_WARN("unable to save domain status after removing device %s",
@@ -4660,60 +4664,6 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
static int
-qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- unsigned int vcpu)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
- virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
- int ret = -1;
- int rc;
- int oldvcpus = virDomainDefGetVcpus(vm->def);
-
- if (!vcpuinfo->online) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("vCPU '%u' is already offline"), vcpu);
- return -1;
- }
-
- vcpuinfo->online = false;
-
- qemuDomainObjEnterMonitor(driver, vm);
-
- rc = qemuMonitorSetCPU(priv->mon, vcpu, false);
-
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- goto cleanup;
-
- if (rc < 0) {
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
- vcpuinfo->online = true;
- goto cleanup;
- }
-
- if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
- goto cleanup;
-
- if (qemuDomainValidateVcpuInfo(vm) < 0) {
- /* rollback vcpu count if the setting has failed */
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
- vcpuinfo->online = true;
- goto cleanup;
- }
-
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", true);
-
- if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- return ret;
-}
-
-
-static int
qemuDomainSetVcpusAgent(virDomainObjPtr vm,
unsigned int nvcpus)
{
@@ -4888,7 +4838,6 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
unsigned int nvcpus)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- size_t i;
virCgroupPtr cgroup_temp = NULL;
char *mem_mask = NULL;
char *all_nodes_str = NULL;
@@ -4925,8 +4874,11 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
break;
}
} else {
- for (i = virDomainDefGetVcpus(vm->def) - 1; i >= nvcpus; i--) {
- if ((rc = qemuDomainHotplugDelVcpu(driver, vm, i)) < 0)
+ for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0;
nextvcpu--) {
+ if (!virBitmapIsBitSet(vcpumap, nextvcpu))
+ continue;
+
+ if ((rc = qemuDomainHotplugDelVcpu(driver, vm, nextvcpu)) < 0)
break;
}
}
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 31ef22f..1bdde5b 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4419,3 +4419,111 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
qemuDomainResetDeviceRemoval(vm);
return ret;
}
+
+
+static int
+qemuDomainRemoveVcpu(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ unsigned int vcpu)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
+ qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
+ int oldvcpus = virDomainDefGetVcpus(vm->def);
+ unsigned int nvcpus = vcpupriv->vcpus;
+ size_t i;
+
+ if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
+ return -1;
+
+ /* validation requires us to set the expected state prior to calling it */
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+ vcpuinfo->online = false;
+ }
+
+ if (qemuDomainValidateVcpuInfo(vm) < 0) {
+ /* rollback vcpu count if the setting has failed */
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
+
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+ vcpuinfo->online = true;
+ }
+ return -1;
+ }
+
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", true);
+
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+ if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+void
+qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ const char *alias)
+{
+ virDomainVcpuDefPtr vcpu;
+ qemuDomainVcpuPrivatePtr vcpupriv;
+ size_t i;
+
+ for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+ vcpu = virDomainDefGetVcpu(vm->def, i);
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
+
+ if (STREQ_NULLABLE(alias, vcpupriv->alias)) {
+ qemuDomainRemoveVcpu(driver, vm, i);
+ return;
+ }
+ }
+}
+
+
+int
+qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ unsigned int vcpu)
+{
+ virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
+ qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
+ int oldvcpus = virDomainDefGetVcpus(vm->def);
+ unsigned int nvcpus = vcpupriv->vcpus;
+ int rc;
+
+ if (!vcpupriv->alias) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("vcpu '%u' can't be unplugged"), vcpu);
+ return -1;
+ }
+
+ qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
+
+ qemuDomainObjEnterMonitor(driver, vm);
+
+ rc = qemuMonitorDelDevice(qemuDomainGetMonitor(vm), vcpupriv->alias);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ return -1;
+
+ if (rc < 0) {
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
+ return -1;
+ }
+
+ if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) {
+ if (rc == 0)
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("vcpu unplug request timed out"));
+
+ return -1;
+ }
+
+ return qemuDomainRemoveVcpu(driver, vm, vcpu);
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 165d345..b048cf4 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -105,6 +105,13 @@ int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainRNGDefPtr rng);
+int qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ unsigned int vcpu);
+void qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ const char *alias);
+
int
qemuDomainChrInsert(virDomainDefPtr vmdef,
virDomainChrDefPtr chr);
--
2.8.2