
On Fri, Feb 10, 2017 at 06:10:20PM +0100, Peter Krempa wrote:
Add code that validates user's selection of cores and then uses the existing code to plug in the vCPU. --- src/qemu/qemu_driver.c | 74 +++++++++++++++++++++++ src/qemu/qemu_hotplug.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_hotplug.h | 7 +++ 3 files changed, 234 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 89bc833de..2b875b3e9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20190,6 +20190,79 @@ qemuDomainSetGuestVcpus(virDomainPtr dom, }
+static int +qemuDomainSetVcpu(virDomainPtr dom, + const char *cpumap, + int state, + unsigned int flags) +{ + virQEMUDriverPtr driver = dom->conn->privateData; + virDomainObjPtr vm = NULL; + virDomainDefPtr def = NULL; + virDomainDefPtr persistentDef = NULL; + virBitmapPtr map = NULL; + ssize_t lastvcpu; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (state != 0 && state != 1) { + virReportInvalidArg(state, "%s", _("unsupported state value")); + return -1; + } + + if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0) + goto cleanup; + + if ((lastvcpu = virBitmapLastSetBit(map)) < 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("no vcpus selected for modification")); + goto cleanup; + } + + if (!(vm = qemuDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainSetVcpuEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + + if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0) + goto endjob; + + if (persistentDef) { + if (lastvcpu >= virDomainDefGetVcpusMax(persistentDef)) { + virReportError(VIR_ERR_INVALID_ARG, + _("vcpu %zd is not present in persistent config"), + lastvcpu); + goto endjob; + } + } + + if (def) { + if (lastvcpu >= virDomainDefGetVcpusMax(def)) { + virReportError(VIR_ERR_INVALID_ARG, + _("vcpu %zd is not present in live config"), + lastvcpu); + goto endjob; + } + } + + ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map, !!state); + + endjob: + qemuDomainObjEndJob(driver, vm); + + cleanup: + virBitmapFree(map); + virDomainObjEndAPI(&vm); + return ret; +} + + static virHypervisorDriver qemuHypervisorDriver = { .name = QEMU_DRIVER_NAME, .connectOpen = qemuConnectOpen, /* 0.2.0 */ @@ -20403,6 +20476,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainMigrateStartPostCopy = qemuDomainMigrateStartPostCopy, /* 1.3.3 */ .domainGetGuestVcpus = qemuDomainGetGuestVcpus, /* 2.0.0 */ .domainSetGuestVcpus = qemuDomainSetGuestVcpus, /* 2.0.0 */ + .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */ };
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 2f209f12b..363d1070b 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -5700,3 +5700,156 @@ qemuDomainSetVcpusInternal(virQEMUDriverPtr driver, virObjectUnref(cfg); return ret; } + + +static void +qemuDomainSetVcpuInactive(virDomainDefPtr def, + virBitmapPtr map, + bool state)
qemuDomainSetVcpuConfig is probably a better name because we use *Live vs *Config naming.
+{ + virDomainVcpuDefPtr vcpu; + ssize_t next = -1; + + def->individualvcpus = true; + + while ((next = virBitmapNextSetBit(map, next)) > 0) { + if (!(vcpu = virDomainDefGetVcpu(def, next))) + continue; + + vcpu->online = state; + vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES; + vcpu->order = 0; + } +} + + +/** + * qemuDomainFilterHotplugVcpuEntities: + * + * Returns a bitmap of hotpluggable vcpu entities that correspond to the logical + * vcpus requested in @vcpus. + */ +static virBitmapPtr +qemuDomainFilterHotplugVcpuEntities(virDomainDefPtr def, + virBitmapPtr vcpus, + bool state) +{ + qemuDomainVcpuPrivatePtr vcpupriv; + virDomainVcpuDefPtr vcpu; + virBitmapPtr map = NULL; + virBitmapPtr ret = NULL; + ssize_t next = -1; + size_t i; + + if (!(map = virBitmapNewCopy(vcpus))) + return NULL; + + /* make sure that all selected vcpus are in the correct state */ + while ((next = virBitmapNextSetBit(map, next)) > 0) { + if (!(vcpu = virDomainDefGetVcpu(def, next))) + continue; + + if (vcpu->online == state) { + virReportError(VIR_ERR_INVALID_ARG, + _("vcpu '%zu' is already in requested state"), next); + goto cleanup; + } + + if (vcpu->online && !vcpu->hotpluggable) { + virReportError(VIR_ERR_INVALID_ARG, + _("vcpu '%zu' can't be hotunplugged"), next); + goto cleanup; + } + } + + /* Make sure that all vCPUs belonging to a single hotpluggable entity were + * selected and then de-select any sub-threads of it. */ + next = -1; + while ((next = virBitmapNextSetBit(map, next)) > 0) { + if (!(vcpu = virDomainDefGetVcpu(def, next))) + continue; + + vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
Remove the extra space :) ACK with the issues fixed. Pavel