From 530e56db9367fcb325aeaa7fb0d52a008db2f19f Mon Sep 17 00:00:00 2001 From: Ryota Ozaki Date: Mon, 5 Oct 2009 02:07:04 +0900 Subject: [PATCH] lxc: implement missing APIs to control the amount of memory * src/libvirt_private.syms: Export virCgroupGetMemoryUsage and add missing virCgroupSetMemory * src/lxc/lxc_driver.c: Implement missing memory functions * src/util/cgroup.c, src/util/cgroup.h: Add the function to get used memory --- src/libvirt_private.syms | 2 + src/lxc/lxc_driver.c | 122 ++++++++++++++++++++++++++++++++++++++++++++-- src/util/cgroup.c | 20 ++++++++ src/util/cgroup.h | 1 + 4 files changed, 140 insertions(+), 5 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 49bbf96..3be3724 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -53,6 +53,8 @@ virCgroupForDriver; virCgroupRemove; virCgroupFree; virCgroupAddTask; +virCgroupSetMemory; +virCgroupGetMemoryUsage; virCgroupSetCpuShares; virCgroupGetCpuShares; virCgroupDenyDevicePath; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 5fb4105..8ec4ae4 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -450,6 +450,7 @@ static int lxcDomainGetInfo(virDomainPtr dom, if (!virDomainIsActive(vm) || driver->cgroup == NULL) { info->cpuTime = 0; + info->memory = vm->def->memory; } else { if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) { lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, @@ -458,13 +459,18 @@ static int lxcDomainGetInfo(virDomainPtr dom, } if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) { - lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain")); + lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read cputime for domain")); + goto cleanup; + } + if (virCgroupGetMemoryUsage(cgroup, &(info->memory)) < 0) { + lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read memory usage for domain")); goto cleanup; } } info->maxMem = vm->def->maxmem; - info->memory = vm->def->memory; info->nrVirtCpu = 1; ret = 0; @@ -501,6 +507,112 @@ cleanup: return ret; } +/* Returns max memory in kb, 0 if error */ +static unsigned long lxcDomainGetMaxMemory(virDomainPtr dom) { + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + unsigned long ret = 0; + + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + ret = vm->def->maxmem; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (newmax < vm->def->memory) { + lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG, + "%s", _("cannot set max memory lower than current memory")); + goto cleanup; + } + + vm->def->maxmem = newmax; + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) { + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + virCgroupPtr cgroup = NULL; + int ret = -1; + + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (newmem > vm->def->maxmem) { + lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG, + "%s", _("cannot set memory higher than max memory")); + goto cleanup; + } + + if (virDomainIsActive(vm)) { + if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) { + lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, + _("Unable to get cgroup for %s\n"), vm->def->name); + goto cleanup; + } + + if (virCgroupSetMemory(cgroup, newmem) < 0) { + lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "%s", _("cannot set memory for domain")); + goto cleanup; + } + } else { + vm->def->memory = newmem; + } + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (cgroup) + virCgroupFree(&cgroup); + return ret; +} + static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { @@ -2103,9 +2215,9 @@ static virDriver lxcDriver = { NULL, /* domainReboot */ lxcDomainDestroy, /* domainDestroy */ lxcGetOSType, /* domainGetOSType */ - NULL, /* domainGetMaxMemory */ - NULL, /* domainSetMaxMemory */ - NULL, /* domainSetMemory */ + lxcDomainGetMaxMemory, /* domainGetMaxMemory */ + lxcDomainSetMaxMemory, /* domainSetMaxMemory */ + lxcDomainSetMemory, /* domainSetMemory */ lxcDomainGetInfo, /* domainGetInfo */ NULL, /* domainSave */ NULL, /* domainRestore */ diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 2e646fd..e56d293 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -702,6 +702,26 @@ int virCgroupSetMemory(virCgroupPtr group, unsigned long kb) } /** + * virCgroupGetMemoryUsage: + * + * @group: The cgroup to change memory for + * @kb: Pointer to returned used memory in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) +{ + uint64_t usage_in_bytes; + int ret; + ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + "memory.usage_in_bytes", &usage_in_bytes); + if (ret == 0) + *kb = (unsigned long) usage_in_bytes >> 10; + return ret; +} + +/** * virCgroupDenyAllDevices: * * @group: The cgroup to deny devices for diff --git a/src/util/cgroup.h b/src/util/cgroup.h index aba56c6..aa36632 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -41,6 +41,7 @@ int virCgroupForDomain(virCgroupPtr driver, int virCgroupAddTask(virCgroupPtr group, pid_t pid); int virCgroupSetMemory(virCgroupPtr group, unsigned long kb); +int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb); int virCgroupDenyAllDevices(virCgroupPtr group); -- 1.6.5.rc2