[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