[libvirt] [PATCH] lxc: implement missing APIs to control the amount of memory
Daniel P. Berrange
berrange at redhat.com
Tue Oct 6 13:09:06 UTC 2009
On Mon, Oct 05, 2009 at 09:17:37AM +0900, Ryota Ozaki wrote:
> Hi,
>
> The patch implements the missing memory control APIs for lxc, i.e.,
> domainGetMaxMemory, domainSetMaxMemory, domainSetMemory, and improves
> domainGetInfo to return proper amount of used memory via cgroup.
>
> And also it includes trivial two fixes; add missing virCgroupSetMemory in
> libvirt_private.syms and fix invalid lxcError argument in lxcDomainGetInfo.
>
> Thanks,
> ozaki-r
>
> >From 530e56db9367fcb325aeaa7fb0d52a008db2f19f Mon Sep 17 00:00:00 2001
> From: Ryota Ozaki <ozaki.ryota at gmail.com>
> 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);
>
> --
ACK, this looks reasonable to me
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
More information about the libvir-list
mailing list