[libvirt] [PATCHv2 4/8] Add vcpu functions to libxl driver
Jim Fehlig
jfehlig at novell.com
Mon Mar 28 22:17:31 UTC 2011
Markus Groß wrote:
> ---
> src/libxl/libxl_driver.c | 310 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 305 insertions(+), 5 deletions(-)
>
ACK.
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index aa135dd..3251e66 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"
> @@ -1311,6 +1312,305 @@ 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;
> + }
> +
> + if (!nvcpus) {
> + libxlError(VIR_ERR_INVALID_ARG, _("nvcpus is zero"));
> + return -1;
> + }
> +
> + 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;
> +
> + 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);
> +
> + /* Exactly one of LIVE or CONFIG must be set. */
> + if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
> + libxlError(VIR_ERR_INVALID_ARG,
> + _("invalid flag combination: (0x%x)"), flags);
> + return -1;
> + }
> +
> + 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;
> + libxl_vcpuinfo *vcpuinfo;
> + int maxcpu, hostcpus;
> + unsigned int i;
> + unsigned char *cpumap;
> +
> + 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;
> + }
> +
> + if (cpumaps && maplen > 0)
> + memset(cpumaps, 0, maplen * maxinfo);
> + 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;
> +
> + if (cpumaps && maplen > 0) {
> + 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)
> {
> @@ -1685,11 +1985,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 */
>
More information about the libvir-list
mailing list