Markus Groß wrote:
---
src/libxl/libxl_driver.c | 295 +++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 290 insertions(+), 5 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 7ee3930..49fc90f 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -27,6 +27,7 @@
#include <config.h>
#include <sys/utsname.h>
+#include <math.h>
#include <libxl.h>
#include "internal.h"
@@ -1207,6 +1208,290 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
return ret;
}
+static int
+libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
+ unsigned int flags)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ libxlDomainObjPrivatePtr priv;
+ virDomainDefPtr def;
+ virDomainObjPtr vm;
+ libxl_cpumap map;
+ uint8_t *bitmask = NULL;
+ unsigned int maplen;
+ unsigned int i, pos;
+ int max;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
+ * mixed with LIVE. */
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
+ (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
+ libxlError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
+ return -1;
+ }
I think we should ensure nvcpus != 0
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching
uuid"));
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
+ libxlError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot set vcpus on an inactive domain"));
+ goto cleanup;
+ }
+
+ if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ libxlError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot change persistent config of a transient
domain"));
+ goto cleanup;
+ }
+
+ if ((max = libxlGetMaxVcpus(dom->conn, NULL)) < 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("could not determine max vcpus for the domain"));
+ goto cleanup;
+ }
+
+ if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus <
max) {
+ max = vm->def->maxvcpus;
+ }
+
+ if (nvcpus > max) {
+ libxlError(VIR_ERR_INVALID_ARG,
+ _("requested vcpus is greater than max allowable"
+ " vcpus for the domain: %d > %d"), nvcpus, max);
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ if (!(def = virDomainObjGetPersistentDef(driver->caps, vm)))
+ goto cleanup;
+
[...]
+ maplen = (unsigned int) ceil((double) nvcpus / 8);
+ if (VIR_ALLOC_N(bitmask, maplen) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ memset(bitmask, 0, maplen);
+ for (i = 0; i < nvcpus; ++i) {
+ pos = (unsigned int) floor((double) i / 8);
+ bitmask[pos] |= 1 << (i % 8);
+ }
+
+ map.size = maplen;
+ map.map = bitmask;
Hmm, could this be simplified to
if (libxl_cpumap_alloc(&priv->ctx, &map)) {
virReportOOMError()
goto cleanup;
}
for (i = 0; i < nvcpus; i++)
libxl_cpumap_set(&map, i);
+
+ switch (flags) {
+ case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
+ def->maxvcpus = nvcpus;
+ if (nvcpus < def->vcpus)
+ def->vcpus = nvcpus;
+ ret = 0;
+ break;
+
+ case VIR_DOMAIN_VCPU_CONFIG:
+ def->vcpus = nvcpus;
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE:
+ if (libxl_set_vcpuonline(&priv->ctx, dom->id, &map) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set vcpus for domain '%d'"
+ " with libxenlight"), dom->id);
+ goto cleanup;
+ }
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
+ if (libxl_set_vcpuonline(&priv->ctx, dom->id, &map) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set vcpus for domain '%d'"
+ " with libxenlight"), dom->id);
+ goto cleanup;
+ }
+ def->vcpus = nvcpus;
+ break;
+ }
+
+ ret = 0;
+
+ if (flags & VIR_DOMAIN_VCPU_CONFIG)
+ ret = virDomainSaveConfig(driver->configDir, def);
+
+cleanup:
+ VIR_FREE(bitmask);
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+static int
+libxlDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
+{
+ return libxlDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
+}
+
+static int
+libxlDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ virDomainDefPtr def;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
Documentation for this function says that it is an error to set both
VIR_DOMAIN_VCPU_LIVE and VIR_DOMAIN_VCPU_CONFIG, so we should check for it.
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching
uuid"));
+ goto cleanup;
+ }
+
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("Domain is not running"));
+ goto cleanup;
+ }
+ def = vm->def;
+ } else {
+ def = vm->newDef ? vm->newDef : vm->def;
+ }
+
+ ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+static int
+libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
+ int maplen)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ libxlDomainObjPrivatePtr priv;
+ virDomainObjPtr vm;
+ int ret = -1;
+ libxl_cpumap map;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching
uuid"));
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot pin vcpus on an inactive domain"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ map.size = maplen;
+ map.map = cpumap;
+ if (libxl_set_vcpuaffinity(&priv->ctx, dom->id, vcpu, &map) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to pin vcpu '%d' with libxenlight"),
vcpu);
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+
+static int
+libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ libxlDomainObjPrivatePtr priv;
+ virDomainObjPtr vm;
+ int ret = -1;
+
Extra newline.
+ libxl_vcpuinfo *vcpuinfo;
+ int maxcpu, hostcpus;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching
uuid"));
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not
running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+ if ((vcpuinfo = libxl_list_vcpu(&priv->ctx, dom->id, &maxcpu,
+ &hostcpus)) == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to list vcpus for domain '%d' with
libxenlight"),
+ dom->id);
+ goto cleanup;
+ }
+
+ memset(cpumaps, 0, maplen * maxinfo);
Documentation for this function says cpumaps can be NULL.
+ unsigned int i = 0;
I thought I recalled variable declaration only at start of a block but
don't see anything about it in HACKING. Perhaps someone else can clarify.
Regards,
Jim
+ for (i = 0; i < maxcpu && i < maxinfo; ++i) {
+ info[i].number = vcpuinfo[i].vcpuid;
+ info[i].cpu = vcpuinfo[i].cpu;
+ info[i].cpuTime = vcpuinfo[i].vcpu_time;
+ if (vcpuinfo[i].running)
+ info[i].state = VIR_VCPU_RUNNING;
+ else if (vcpuinfo[i].blocked)
+ info[i].state = VIR_VCPU_BLOCKED;
+ else
+ info[i].state = VIR_VCPU_OFFLINE;
+
+ unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, i);
+ memcpy(cpumap, vcpuinfo[i].cpumap.map,
+ MIN(maplen, vcpuinfo[i].cpumap.size));
+
+ libxl_vcpuinfo_destroy(&vcpuinfo[i]);
+ }
+ VIR_FREE(vcpuinfo);
+
+ ret = maxinfo;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
static char *
libxlDomainDumpXML(virDomainPtr dom, int flags)
{
@@ -1561,11 +1846,11 @@ static virDriver libxlDriver = {
NULL, /* domainSave */
NULL, /* domainRestore */
NULL, /* domainCoreDump */
- NULL, /* domainSetVcpus */
- NULL, /* domainSetVcpusFlags */
- NULL, /* domainGetVcpusFlags */
- NULL, /* domainPinVcpu */
- NULL, /* domainGetVcpus */
+ libxlDomainSetVcpus, /* domainSetVcpus */
+ libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */
+ libxlDomainGetVcpusFlags, /* domainGetVcpusFlags */
+ libxlDomainPinVcpu, /* domainPinVcpu */
+ libxlDomainGetVcpus, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
NULL, /* domainGetSecurityLabel */
NULL, /* nodeGetSecurityModel */