Move all the worker code into the appropriate file. This will also allow
testing of cpu hotplug.
---
src/qemu/qemu_driver.c | 330 ------------------------------------------------
src/qemu/qemu_hotplug.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hotplug.h | 7 +
3 files changed, 335 insertions(+), 330 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index af8f458..79dadff 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4608,76 +4608,6 @@ static void qemuProcessEventHandler(void *data, void *opaque)
static int
-qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- unsigned int vcpu)
-{
- virJSONValuePtr vcpuprops = NULL;
- virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
- qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
- unsigned int nvcpus = vcpupriv->vcpus;
- bool newhotplug = qemuDomainSupportsNewVcpuHotplug(vm);
- int ret = -1;
- int rc;
- int oldvcpus = virDomainDefGetVcpus(vm->def);
- size_t i;
-
- if (newhotplug) {
- if (virAsprintf(&vcpupriv->alias, "vcpu%u", vcpu) < 0)
- goto cleanup;
-
- if (!(vcpuprops = qemuBuildHotpluggableCPUProps(vcpuinfo)))
- goto cleanup;
- }
-
- qemuDomainObjEnterMonitor(driver, vm);
-
- if (newhotplug) {
- rc = qemuMonitorAddDeviceArgs(qemuDomainGetMonitor(vm), vcpuprops);
- vcpuprops = NULL;
- } else {
- rc = qemuMonitorSetCPU(qemuDomainGetMonitor(vm), vcpu, true);
- }
-
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- goto cleanup;
-
- virDomainAuditVcpu(vm, oldvcpus, oldvcpus + nvcpus, "update", rc == 0);
-
- if (rc < 0)
- goto cleanup;
-
- /* start outputting of the new XML element to allow keeping unpluggability */
- if (newhotplug)
- vm->def->individualvcpus = true;
-
- if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
- goto cleanup;
-
- /* validation requires us to set the expected state prior to calling it */
- for (i = vcpu; i < vcpu + nvcpus; i++) {
- vcpuinfo = virDomainDefGetVcpu(vm->def, i);
- vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
-
- vcpuinfo->online = true;
-
- if (vcpupriv->tid > 0 &&
- qemuProcessSetupVcpu(vm, i) < 0)
- goto cleanup;
- }
-
- if (qemuDomainValidateVcpuInfo(vm) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- virJSONValueFree(vcpuprops);
- return ret;
-}
-
-
-static int
qemuDomainSetVcpusAgent(virDomainObjPtr vm,
unsigned int nvcpus)
{
@@ -4769,266 +4699,6 @@ qemuDomainSetVcpusMax(virQEMUDriverPtr driver,
virObjectUnref(cfg);
return ret;
}
-
-
-/**
- * qemuDomainSelectHotplugVcpuEntities:
- *
- * @def: domain definition
- * @nvcpus: target vcpu count
- * @enable: set to true if vcpus should be enabled
- *
- * Tries to find which vcpu entities need to be enabled or disabled to reach
- * @nvcpus. This function works in order of the legacy hotplug but is able to
- * skip over entries that are added out of order.
- *
- * Returns the bitmap of vcpus to modify on success, NULL on error.
- */
-static virBitmapPtr
-qemuDomainSelectHotplugVcpuEntities(virDomainDefPtr def,
- unsigned int nvcpus,
- bool *enable)
-{
- virBitmapPtr ret = NULL;
- virDomainVcpuDefPtr vcpu;
- qemuDomainVcpuPrivatePtr vcpupriv;
- unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
- unsigned int curvcpus = virDomainDefGetVcpus(def);
- ssize_t i;
-
- if (!(ret = virBitmapNew(maxvcpus)))
- return NULL;
-
- if (nvcpus > curvcpus) {
- *enable = true;
-
- for (i = 0; i < maxvcpus && curvcpus < nvcpus; i++) {
- vcpu = virDomainDefGetVcpu(def, i);
- vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
-
- if (vcpu->online)
- continue;
-
- if (vcpupriv->vcpus == 0)
- continue;
-
- curvcpus += vcpupriv->vcpus;
-
- if (curvcpus > nvcpus) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("target vm vcpu granularity does not allow the
"
- "desired vcpu count"));
- goto error;
- }
-
- ignore_value(virBitmapSetBit(ret, i));
- }
- } else {
- *enable = false;
-
- for (i = maxvcpus - 1; i >= 0 && curvcpus > nvcpus; i--) {
- vcpu = virDomainDefGetVcpu(def, i);
- vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
-
- if (!vcpu->online)
- continue;
-
- if (vcpupriv->vcpus == 0)
- continue;
-
- if (!vcpupriv->alias)
- continue;
-
- curvcpus -= vcpupriv->vcpus;
-
- if (curvcpus < nvcpus) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("target vm vcpu granularity does not allow the
"
- "desired vcpu count"));
- goto error;
- }
-
- ignore_value(virBitmapSetBit(ret, i));
- }
- }
-
- if (curvcpus != nvcpus) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("failed to find appropriate hotpluggable vcpus to "
- "reach the desired target vcpu count"));
- goto error;
- }
-
- return ret;
-
- error:
- virBitmapFree(ret);
- return NULL;
-}
-
-
-static int
-qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
- virQEMUDriverConfigPtr cfg,
- virDomainObjPtr vm,
- virBitmapPtr vcpumap,
- bool enable)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
- qemuCgroupEmulatorAllNodesDataPtr emulatorCgroup = NULL;
- ssize_t nextvcpu = -1;
- int rc = 0;
- int ret = -1;
-
- if (qemuCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
- goto cleanup;
-
- if (enable) {
- while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
- if ((rc = qemuDomainHotplugAddVcpu(driver, vm, nextvcpu)) < 0)
- break;
- }
- } else {
- for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0;
nextvcpu--) {
- if (!virBitmapIsBitSet(vcpumap, nextvcpu))
- continue;
-
- if ((rc = qemuDomainHotplugDelVcpu(driver, vm, nextvcpu)) < 0)
- break;
- }
- }
-
- qemuDomainVcpuPersistOrder(vm->def);
-
- if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps)
< 0)
- goto cleanup;
-
- if (rc < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- qemuCgroupEmulatorAllNodesRestore(emulatorCgroup);
-
- return ret;
-}
-
-
-/**
- * qemuDomainSetVcpusConfig:
- * @def: config/offline definition of a domain
- * @nvcpus: target vcpu count
- *
- * Properly handle cold(un)plug of vcpus:
- * - plug in inactive vcpus/uplug active rather than rewriting state
- * - fix hotpluggable state
- */
-static void
-qemuDomainSetVcpusConfig(virDomainDefPtr def,
- unsigned int nvcpus,
- bool hotpluggable)
-{
- virDomainVcpuDefPtr vcpu;
- size_t curvcpus = virDomainDefGetVcpus(def);
- size_t maxvcpus = virDomainDefGetVcpusMax(def);
- size_t i;
-
- /* ordering information may become invalid, thus clear it */
- virDomainDefVcpuOrderClear(def);
-
- if (curvcpus == nvcpus)
- return;
-
- if (curvcpus < nvcpus) {
- for (i = 0; i < maxvcpus; i++) {
- vcpu = virDomainDefGetVcpu(def, i);
-
- if (!vcpu || vcpu->online)
- continue;
-
- vcpu->online = true;
- if (hotpluggable) {
- vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
- def->individualvcpus = true;
- } else {
- vcpu->hotpluggable = VIR_TRISTATE_BOOL_NO;
- }
-
- if (++curvcpus == nvcpus)
- break;
- }
- } else {
- for (i = maxvcpus; i != 0; i--) {
- vcpu = virDomainDefGetVcpu(def, i - 1);
-
- if (!vcpu || !vcpu->online)
- continue;
-
- vcpu->online = false;
- vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
-
- if (--curvcpus == nvcpus)
- break;
- }
- }
-}
-
-
-static int
-qemuDomainSetVcpusInternal(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virDomainDefPtr def,
- virDomainDefPtr persistentDef,
- unsigned int nvcpus,
- bool hotpluggable)
-{
- virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
- virBitmapPtr vcpumap = NULL;
- bool enable;
- int ret = -1;
-
- if (def && nvcpus > virDomainDefGetVcpusMax(def)) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("requested vcpus is greater than max allowable"
- " vcpus for the live domain: %u > %u"),
- nvcpus, virDomainDefGetVcpusMax(def));
- goto cleanup;
- }
-
- if (persistentDef && nvcpus > virDomainDefGetVcpusMax(persistentDef)) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("requested vcpus is greater than max allowable"
- " vcpus for the persistent domain: %u > %u"),
- nvcpus, virDomainDefGetVcpusMax(persistentDef));
- goto cleanup;
- }
-
- if (def) {
- if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus,
- &enable)))
- goto cleanup;
-
- if (qemuDomainSetVcpusLive(driver, cfg, vm, vcpumap, enable) < 0)
- goto cleanup;
- }
-
- if (persistentDef) {
- qemuDomainSetVcpusConfig(persistentDef, nvcpus, hotpluggable);
-
- if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) <
0)
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- virBitmapFree(vcpumap);
- virObjectUnref(cfg);
- return ret;
-}
-
-
static int
qemuDomainSetVcpusFlags(virDomainPtr dom,
unsigned int nvcpus,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 55af888..c83bb6e 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5299,3 +5299,331 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
return qemuDomainRemoveVcpu(driver, vm, vcpu);
}
+
+
+static int
+qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ unsigned int vcpu)
+{
+ virJSONValuePtr vcpuprops = NULL;
+ virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
+ qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
+ unsigned int nvcpus = vcpupriv->vcpus;
+ bool newhotplug = qemuDomainSupportsNewVcpuHotplug(vm);
+ int ret = -1;
+ int rc;
+ int oldvcpus = virDomainDefGetVcpus(vm->def);
+ size_t i;
+
+ if (newhotplug) {
+ if (virAsprintf(&vcpupriv->alias, "vcpu%u", vcpu) < 0)
+ goto cleanup;
+
+ if (!(vcpuprops = qemuBuildHotpluggableCPUProps(vcpuinfo)))
+ goto cleanup;
+ }
+
+ qemuDomainObjEnterMonitor(driver, vm);
+
+ if (newhotplug) {
+ rc = qemuMonitorAddDeviceArgs(qemuDomainGetMonitor(vm), vcpuprops);
+ vcpuprops = NULL;
+ } else {
+ rc = qemuMonitorSetCPU(qemuDomainGetMonitor(vm), vcpu, true);
+ }
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ goto cleanup;
+
+ virDomainAuditVcpu(vm, oldvcpus, oldvcpus + nvcpus, "update", rc == 0);
+
+ if (rc < 0)
+ goto cleanup;
+
+ /* start outputting of the new XML element to allow keeping unpluggability */
+ if (newhotplug)
+ vm->def->individualvcpus = true;
+
+ if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
+ goto cleanup;
+
+ /* validation requires us to set the expected state prior to calling it */
+ for (i = vcpu; i < vcpu + nvcpus; i++) {
+ vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
+
+ vcpuinfo->online = true;
+
+ if (vcpupriv->tid > 0 &&
+ qemuProcessSetupVcpu(vm, i) < 0)
+ goto cleanup;
+ }
+
+ if (qemuDomainValidateVcpuInfo(vm) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virJSONValueFree(vcpuprops);
+ return ret;
+}
+
+
+/**
+ * qemuDomainSelectHotplugVcpuEntities:
+ *
+ * @def: domain definition
+ * @nvcpus: target vcpu count
+ * @enable: set to true if vcpus should be enabled
+ *
+ * Tries to find which vcpu entities need to be enabled or disabled to reach
+ * @nvcpus. This function works in order of the legacy hotplug but is able to
+ * skip over entries that are added out of order.
+ *
+ * Returns the bitmap of vcpus to modify on success, NULL on error.
+ */
+static virBitmapPtr
+qemuDomainSelectHotplugVcpuEntities(virDomainDefPtr def,
+ unsigned int nvcpus,
+ bool *enable)
+{
+ virBitmapPtr ret = NULL;
+ virDomainVcpuDefPtr vcpu;
+ qemuDomainVcpuPrivatePtr vcpupriv;
+ unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
+ unsigned int curvcpus = virDomainDefGetVcpus(def);
+ ssize_t i;
+
+ if (!(ret = virBitmapNew(maxvcpus)))
+ return NULL;
+
+ if (nvcpus > curvcpus) {
+ *enable = true;
+
+ for (i = 0; i < maxvcpus && curvcpus < nvcpus; i++) {
+ vcpu = virDomainDefGetVcpu(def, i);
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
+
+ if (vcpu->online)
+ continue;
+
+ if (vcpupriv->vcpus == 0)
+ continue;
+
+ curvcpus += vcpupriv->vcpus;
+
+ if (curvcpus > nvcpus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("target vm vcpu granularity does not allow the
"
+ "desired vcpu count"));
+ goto error;
+ }
+
+ ignore_value(virBitmapSetBit(ret, i));
+ }
+ } else {
+ *enable = false;
+
+ for (i = maxvcpus - 1; i >= 0 && curvcpus > nvcpus; i--) {
+ vcpu = virDomainDefGetVcpu(def, i);
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
+
+ if (!vcpu->online)
+ continue;
+
+ if (vcpupriv->vcpus == 0)
+ continue;
+
+ if (!vcpupriv->alias)
+ continue;
+
+ curvcpus -= vcpupriv->vcpus;
+
+ if (curvcpus < nvcpus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("target vm vcpu granularity does not allow the
"
+ "desired vcpu count"));
+ goto error;
+ }
+
+ ignore_value(virBitmapSetBit(ret, i));
+ }
+ }
+
+ if (curvcpus != nvcpus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("failed to find appropriate hotpluggable vcpus to "
+ "reach the desired target vcpu count"));
+ goto error;
+ }
+
+ return ret;
+
+ error:
+ virBitmapFree(ret);
+ return NULL;
+}
+
+
+static int
+qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
+ virQEMUDriverConfigPtr cfg,
+ virDomainObjPtr vm,
+ virBitmapPtr vcpumap,
+ bool enable)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuCgroupEmulatorAllNodesDataPtr emulatorCgroup = NULL;
+ ssize_t nextvcpu = -1;
+ int rc = 0;
+ int ret = -1;
+
+ if (qemuCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
+ goto cleanup;
+
+ if (enable) {
+ while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
+ if ((rc = qemuDomainHotplugAddVcpu(driver, vm, nextvcpu)) < 0)
+ break;
+ }
+ } else {
+ for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0;
nextvcpu--) {
+ if (!virBitmapIsBitSet(vcpumap, nextvcpu))
+ continue;
+
+ if ((rc = qemuDomainHotplugDelVcpu(driver, vm, nextvcpu)) < 0)
+ break;
+ }
+ }
+
+ qemuDomainVcpuPersistOrder(vm->def);
+
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps)
< 0)
+ goto cleanup;
+
+ if (rc < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ qemuCgroupEmulatorAllNodesRestore(emulatorCgroup);
+
+ return ret;
+}
+
+
+/**
+ * qemuDomainSetVcpusConfig:
+ * @def: config/offline definition of a domain
+ * @nvcpus: target vcpu count
+ *
+ * Properly handle cold(un)plug of vcpus:
+ * - plug in inactive vcpus/uplug active rather than rewriting state
+ * - fix hotpluggable state
+ */
+static void
+qemuDomainSetVcpusConfig(virDomainDefPtr def,
+ unsigned int nvcpus,
+ bool hotpluggable)
+{
+ virDomainVcpuDefPtr vcpu;
+ size_t curvcpus = virDomainDefGetVcpus(def);
+ size_t maxvcpus = virDomainDefGetVcpusMax(def);
+ size_t i;
+
+ /* ordering information may become invalid, thus clear it */
+ virDomainDefVcpuOrderClear(def);
+
+ if (curvcpus == nvcpus)
+ return;
+
+ if (curvcpus < nvcpus) {
+ for (i = 0; i < maxvcpus; i++) {
+ vcpu = virDomainDefGetVcpu(def, i);
+
+ if (!vcpu || vcpu->online)
+ continue;
+
+ vcpu->online = true;
+ if (hotpluggable) {
+ vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
+ def->individualvcpus = true;
+ } else {
+ vcpu->hotpluggable = VIR_TRISTATE_BOOL_NO;
+ }
+
+ if (++curvcpus == nvcpus)
+ break;
+ }
+ } else {
+ for (i = maxvcpus; i != 0; i--) {
+ vcpu = virDomainDefGetVcpu(def, i - 1);
+
+ if (!vcpu || !vcpu->online)
+ continue;
+
+ vcpu->online = false;
+ vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
+
+ if (--curvcpus == nvcpus)
+ break;
+ }
+ }
+}
+
+
+int
+qemuDomainSetVcpusInternal(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainDefPtr def,
+ virDomainDefPtr persistentDef,
+ unsigned int nvcpus,
+ bool hotpluggable)
+{
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virBitmapPtr vcpumap = NULL;
+ bool enable;
+ int ret = -1;
+
+ if (def && nvcpus > virDomainDefGetVcpusMax(def)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("requested vcpus is greater than max allowable"
+ " vcpus for the live domain: %u > %u"),
+ nvcpus, virDomainDefGetVcpusMax(def));
+ goto cleanup;
+ }
+
+ if (persistentDef && nvcpus > virDomainDefGetVcpusMax(persistentDef)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("requested vcpus is greater than max allowable"
+ " vcpus for the persistent domain: %u > %u"),
+ nvcpus, virDomainDefGetVcpusMax(persistentDef));
+ goto cleanup;
+ }
+
+ if (def) {
+ if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus,
+ &enable)))
+ goto cleanup;
+
+ if (qemuDomainSetVcpusLive(driver, cfg, vm, vcpumap, enable) < 0)
+ goto cleanup;
+ }
+
+ if (persistentDef) {
+ qemuDomainSetVcpusConfig(persistentDef, nvcpus, hotpluggable);
+
+ if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) <
0)
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ virBitmapFree(vcpumap);
+ virObjectUnref(cfg);
+ return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 85ec724..13242ee 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -136,4 +136,11 @@ bool qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
const char *devAlias,
qemuDomainUnpluggingDeviceStatus status);
+int qemuDomainSetVcpusInternal(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainDefPtr def,
+ virDomainDefPtr persistentDef,
+ unsigned int nvcpus,
+ bool hotpluggable);
+
#endif /* __QEMU_HOTPLUG_H__ */
--
2.10.2