|
|
6ae9ed |
From 7693fcc1d88c699d9863287f144d6d37b0456100 Mon Sep 17 00:00:00 2001
|
|
|
6ae9ed |
Message-Id: <7693fcc1d88c699d9863287f144d6d37b0456100@dist-git>
|
|
|
6ae9ed |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
6ae9ed |
Date: Wed, 24 Aug 2016 16:11:40 -0400
|
|
|
6ae9ed |
Subject: [PATCH] qemu: hotplug: Add support for VCPU unplug
|
|
|
6ae9ed |
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1224341
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1097930
|
|
|
6ae9ed |
|
|
|
6ae9ed |
This patch removes the old vcpu unplug code completely and replaces it
|
|
|
6ae9ed |
with the new code using device_del. The old hotplug code basically never
|
|
|
6ae9ed |
worked with any recent qemu and thus is useless.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
As the new code is using device_del all the implications of using it
|
|
|
6ae9ed |
are present. Contrary to the device deletion code, the vcpu deletion
|
|
|
6ae9ed |
code fails if the unplug request is not executed in time.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
(cherry picked from commit e3229f6e4461cd1721dc68a32e16ab1718ae716e)
|
|
|
6ae9ed |
---
|
|
|
6ae9ed |
src/qemu/qemu_driver.c | 74 ++++++---------------------------
|
|
|
6ae9ed |
src/qemu/qemu_hotplug.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
6ae9ed |
src/qemu/qemu_hotplug.h | 7 ++++
|
|
|
6ae9ed |
3 files changed, 128 insertions(+), 61 deletions(-)
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
6ae9ed |
index 900aacd..1ef8bc4 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_driver.c
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_driver.c
|
|
|
6ae9ed |
@@ -4067,11 +4067,15 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
goto endjob;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
|
|
|
6ae9ed |
- goto endjob;
|
|
|
6ae9ed |
+ if (STRPREFIX(devAlias, "vcpu")) {
|
|
|
6ae9ed |
+ qemuDomainRemoveVcpuAlias(driver, vm, devAlias);
|
|
|
6ae9ed |
+ } else {
|
|
|
6ae9ed |
+ if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
|
|
|
6ae9ed |
+ goto endjob;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
|
|
|
6ae9ed |
- goto endjob;
|
|
|
6ae9ed |
+ if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
|
|
|
6ae9ed |
+ goto endjob;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
|
|
|
6ae9ed |
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
|
|
|
6ae9ed |
VIR_WARN("unable to save domain status after removing device %s",
|
|
|
6ae9ed |
@@ -4666,60 +4670,6 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
static int
|
|
|
6ae9ed |
-qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
- virDomainObjPtr vm,
|
|
|
6ae9ed |
- unsigned int vcpu)
|
|
|
6ae9ed |
-{
|
|
|
6ae9ed |
- qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
6ae9ed |
- virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
|
|
|
6ae9ed |
- int ret = -1;
|
|
|
6ae9ed |
- int rc;
|
|
|
6ae9ed |
- int oldvcpus = virDomainDefGetVcpus(vm->def);
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- if (!vcpuinfo->online) {
|
|
|
6ae9ed |
- virReportError(VIR_ERR_INVALID_ARG,
|
|
|
6ae9ed |
- _("vCPU '%u' is already offline"), vcpu);
|
|
|
6ae9ed |
- return -1;
|
|
|
6ae9ed |
- }
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- vcpuinfo->online = false;
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- qemuDomainObjEnterMonitor(driver, vm);
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- rc = qemuMonitorSetCPU(priv->mon, vcpu, false);
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
6ae9ed |
- goto cleanup;
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- if (rc < 0) {
|
|
|
6ae9ed |
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
|
|
|
6ae9ed |
- vcpuinfo->online = true;
|
|
|
6ae9ed |
- goto cleanup;
|
|
|
6ae9ed |
- }
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
|
|
|
6ae9ed |
- goto cleanup;
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- if (qemuDomainValidateVcpuInfo(vm) < 0) {
|
|
|
6ae9ed |
- /* rollback vcpu count if the setting has failed */
|
|
|
6ae9ed |
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
|
|
|
6ae9ed |
- vcpuinfo->online = true;
|
|
|
6ae9ed |
- goto cleanup;
|
|
|
6ae9ed |
- }
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", true);
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu) < 0)
|
|
|
6ae9ed |
- goto cleanup;
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- ret = 0;
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
- cleanup:
|
|
|
6ae9ed |
- return ret;
|
|
|
6ae9ed |
-}
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
-
|
|
|
6ae9ed |
-static int
|
|
|
6ae9ed |
qemuDomainSetVcpusAgent(virDomainObjPtr vm,
|
|
|
6ae9ed |
unsigned int nvcpus)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
@@ -4895,7 +4845,6 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
unsigned int nvcpus)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
6ae9ed |
- size_t i;
|
|
|
6ae9ed |
virCgroupPtr cgroup_temp = NULL;
|
|
|
6ae9ed |
char *mem_mask = NULL;
|
|
|
6ae9ed |
char *all_nodes_str = NULL;
|
|
|
6ae9ed |
@@ -4932,8 +4881,11 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
break;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
} else {
|
|
|
6ae9ed |
- for (i = virDomainDefGetVcpus(vm->def) - 1; i >= nvcpus; i--) {
|
|
|
6ae9ed |
- if ((rc = qemuDomainHotplugDelVcpu(driver, vm, i)) < 0)
|
|
|
6ae9ed |
+ for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0; nextvcpu--) {
|
|
|
6ae9ed |
+ if (!virBitmapIsBitSet(vcpumap, nextvcpu))
|
|
|
6ae9ed |
+ continue;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((rc = qemuDomainHotplugDelVcpu(driver, vm, nextvcpu)) < 0)
|
|
|
6ae9ed |
break;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
|
|
6ae9ed |
index a1a9bd1..f038be5 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_hotplug.c
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_hotplug.c
|
|
|
6ae9ed |
@@ -4346,3 +4346,111 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
qemuDomainResetDeviceRemoval(vm);
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuDomainRemoveVcpu(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
+ virDomainObjPtr vm,
|
|
|
6ae9ed |
+ unsigned int vcpu)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
|
|
|
6ae9ed |
+ qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
|
|
|
6ae9ed |
+ int oldvcpus = virDomainDefGetVcpus(vm->def);
|
|
|
6ae9ed |
+ unsigned int nvcpus = vcpupriv->vcpus;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* validation requires us to set the expected state prior to calling it */
|
|
|
6ae9ed |
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
|
|
|
6ae9ed |
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
|
|
|
6ae9ed |
+ vcpuinfo->online = false;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuDomainValidateVcpuInfo(vm) < 0) {
|
|
|
6ae9ed |
+ /* rollback vcpu count if the setting has failed */
|
|
|
6ae9ed |
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
|
|
|
6ae9ed |
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
|
|
|
6ae9ed |
+ vcpuinfo->online = true;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", true);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
|
|
|
6ae9ed |
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
|
|
|
6ae9ed |
+ if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return 0;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+void
|
|
|
6ae9ed |
+qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
+ virDomainObjPtr vm,
|
|
|
6ae9ed |
+ const char *alias)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpu;
|
|
|
6ae9ed |
+ qemuDomainVcpuPrivatePtr vcpupriv;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(vm->def, i);
|
|
|
6ae9ed |
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (STREQ_NULLABLE(alias, vcpupriv->alias)) {
|
|
|
6ae9ed |
+ qemuDomainRemoveVcpu(driver, vm, i);
|
|
|
6ae9ed |
+ return;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+int
|
|
|
6ae9ed |
+qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
+ virDomainObjPtr vm,
|
|
|
6ae9ed |
+ unsigned int vcpu)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
|
|
|
6ae9ed |
+ qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
|
|
|
6ae9ed |
+ int oldvcpus = virDomainDefGetVcpus(vm->def);
|
|
|
6ae9ed |
+ unsigned int nvcpus = vcpupriv->vcpus;
|
|
|
6ae9ed |
+ int rc;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!vcpupriv->alias) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
6ae9ed |
+ _("vcpu '%u' can't be unplugged"), vcpu);
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ qemuDomainObjEnterMonitor(driver, vm);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ rc = qemuMonitorDelDevice(qemuDomainGetMonitor(vm), vcpupriv->alias);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (rc < 0) {
|
|
|
6ae9ed |
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) {
|
|
|
6ae9ed |
+ if (rc == 0)
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
6ae9ed |
+ _("vcpu unplug request timed out"));
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return qemuDomainRemoveVcpu(driver, vm, vcpu);
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
|
|
|
6ae9ed |
index 165d345..b048cf4 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_hotplug.h
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_hotplug.h
|
|
|
6ae9ed |
@@ -105,6 +105,13 @@ int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
virDomainObjPtr vm,
|
|
|
6ae9ed |
virDomainRNGDefPtr rng);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+int qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
+ virDomainObjPtr vm,
|
|
|
6ae9ed |
+ unsigned int vcpu);
|
|
|
6ae9ed |
+void qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
+ virDomainObjPtr vm,
|
|
|
6ae9ed |
+ const char *alias);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
int
|
|
|
6ae9ed |
qemuDomainChrInsert(virDomainDefPtr vmdef,
|
|
|
6ae9ed |
virDomainChrDefPtr chr);
|
|
|
6ae9ed |
--
|
|
|
6ae9ed |
2.10.0
|
|
|
6ae9ed |
|