Markus Groß wrote:
Here is a new version of this patch:
https://www.redhat.com/archives/libvir-list/2011-April/msg00337.html
v2:
- store the cputune info for the whole runtime of the domain
- remove cputune info when domain is destroyed
The nodeGetInfo code had to be moved into a helper
function to reuse it without a virConnectPtr.
---
src/libxl/libxl_driver.c | 159 +++++++++++++++++++++++++++++++++++-----------
1 files changed, 122 insertions(+), 37 deletions(-)
I tested all sorts of combinations of starting domains (hvm and pv),
pinning vcpus, shutting down domains, and restarting libvirt - looks
good! Thanks Markus.
ACK and pushed.
Regards,
Jim
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 3040914..247d78e 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -199,6 +199,46 @@ libxlAutostartDomain(void *payload, const void *name
ATTRIBUTE_UNUSED,
virDomainObjUnlock(vm);
}
+static int
+libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
+{
+ libxl_physinfo phy_info;
+ const libxl_version_info* ver_info;
+ struct utsname utsname;
+
+ if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxl_get_physinfo_info failed"));
+ return -1;
+ }
+
+ if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxl_get_version_info failed"));
+ return -1;
+ }
+
+ uname(&utsname);
+ if (virStrncpy(info->model,
+ utsname.machine,
+ strlen(utsname.machine),
+ sizeof(info->model)) == NULL) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("machine type %s too big for destination"),
+ utsname.machine);
+ return -1;
+ }
+
+ info->memory = phy_info.total_pages * (ver_info->pagesize / 1024);
+ info->cpus = phy_info.nr_cpus;
+ info->nodes = phy_info.nr_nodes;
+ info->cores = phy_info.cores_per_socket;
+ info->threads = phy_info.threads_per_core;
+ info->sockets = 1;
+ info->mhz = phy_info.cpu_khz / 1000;
+ return 0;
+}
+
/*
* Cleanup function for domain that has reached shutoff state.
*
@@ -210,6 +250,7 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
libxlDomainObjPrivatePtr priv = vm->privateData;
int vnc_port;
char *file;
+ int i;
if (priv->eventHdl >= 0) {
virEventRemoveHandle(priv->eventHdl);
@@ -238,6 +279,16 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
}
}
+ /* Remove any cputune settings */
+ if (vm->def->cputune.nvcpupin) {
+ for (i = 0; i < vm->def->cputune.nvcpupin; ++i) {
+ VIR_FREE(vm->def->cputune.vcpupin[i]->cpumask);
+ VIR_FREE(vm->def->cputune.vcpupin[i]);
+ }
+ VIR_FREE(vm->def->cputune.vcpupin);
+ vm->def->cputune.nvcpupin = 0;
+ }
+
if (virAsprintf(&file, "%s/%s.xml", driver->stateDir,
vm->def->name) > 0) {
if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR)
VIR_DEBUG("Failed to remove domain XML for %s",
vm->def->name);
@@ -391,6 +442,62 @@ error:
return -1;
}
+static int
+libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
+{
+ libxlDomainObjPrivatePtr priv = vm->privateData;
+ virDomainDefPtr def = vm->def;
+ libxl_cpumap map;
+ uint8_t *cpumask = NULL;
+ uint8_t *cpumap = NULL;
+ virNodeInfo nodeinfo;
+ size_t cpumaplen;
+ unsigned int pos;
+ int vcpu, i;
+ int ret = -1;
+
+ if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0)
+ goto cleanup;
+
+ cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+
+ for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) {
+ if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid)
+ continue;
+
+ if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ cpumask = (uint8_t*) def->cputune.vcpupin[vcpu]->cpumask;
+
+ for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; ++i) {
+ if (cpumask[i]) {
+ pos = i / 8;
+ cpumap[pos] |= 1 << (i % 8);
+ }
+ }
+
+ map.size = cpumaplen;
+ map.map = cpumap;
+
+ if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0)
{
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to pin vcpu '%d' with libxenlight"),
vcpu);
+ goto cleanup;
+ }
+
+ VIR_FREE(cpumap);
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cpumap);
+ return ret;
+}
+
/*
* Start a domain through libxenlight.
*
@@ -440,6 +547,9 @@ libxlVmStart(libxlDriverPrivatePtr driver,
if (libxlCreateDomEvents(vm) < 0)
goto error;
+ if (libxlDomainSetVcpuAffinites(driver, vm) < 0)
+ goto error;
+
if (!start_paused) {
libxl_domain_unpause(&priv->ctx, domid);
vm->state = VIR_DOMAIN_RUNNING;
@@ -756,7 +866,7 @@ libxlReload(void)
&libxl_driver->domains,
libxl_driver->configDir,
libxl_driver->autostartDir,
- 0, NULL, libxl_driver);
+ 1, NULL, libxl_driver);
virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain,
libxl_driver);
@@ -869,42 +979,7 @@ libxlGetMaxVcpus(virConnectPtr conn, const char *type
ATTRIBUTE_UNUSED)
static int
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
- libxl_physinfo phy_info;
- const libxl_version_info* ver_info;
- libxlDriverPrivatePtr driver = conn->privateData;
- struct utsname utsname;
-
- if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
- libxlError(VIR_ERR_INTERNAL_ERROR,
- _("libxl_get_physinfo_info failed"));
- return -1;
- }
-
- if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
- libxlError(VIR_ERR_INTERNAL_ERROR,
- _("libxl_get_version_info failed"));
- return -1;
- }
-
- uname(&utsname);
- if (virStrncpy(info->model,
- utsname.machine,
- strlen(utsname.machine),
- sizeof(info->model)) == NULL) {
- libxlError(VIR_ERR_INTERNAL_ERROR,
- _("machine type %s too big for destination"),
- utsname.machine);
- return -1;
- }
-
- info->memory = phy_info.total_pages * (ver_info->pagesize / 1024);
- info->cpus = phy_info.nr_cpus;
- info->nodes = phy_info.nr_nodes;
- info->cores = phy_info.cores_per_socket;
- info->threads = phy_info.threads_per_core;
- info->sockets = 1;
- info->mhz = phy_info.cpu_khz / 1000;
- return 0;
+ return libxlDoNodeGetInfo(conn->privateData, info);
}
static char *
@@ -1712,6 +1787,16 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned
char *cpumap,
_("Failed to pin vcpu '%d' with libxenlight"),
vcpu);
goto cleanup;
}
+
+ if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("failed to update or add vcpupin xml"));
+ goto cleanup;
+ }
+
+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+ goto cleanup;
+
ret = 0;
cleanup: