[libvirt] [PATCH] cgroup: Enable memory.use_hierarchy of cgroup for domain

Balbir Singh balbir at linux.vnet.ibm.com
Thu May 6 15:26:27 UTC 2010


On Thu, May 6, 2010 at 7:40 PM, Ryota Ozaki <ozaki.ryota at gmail.com> wrote:
> Through conversation with Kumar L Srikanth-B22348, I found
> that the function of getting memory usage (e.g., virsh dominfo)
> doesn't work for lxc with ns subsystem of cgroup enabled.
>
> This is because of features of ns and memory subsystems.
> Ns creates child cgroup on every process fork and as a result
> processes in a container are not assigned in a cgroup for
> domain (e.g., libvirt/lxc/test1/). For example, libvirt_lxc
> and init (or somewhat specified in XML) are assigned into
> libvirt/lxc/test1/8839/ and libvirt/lxc/test1/8839/8849/,
> respectively. On the other hand, memory subsystem accounts
> memory usage within a group of processes by default, i.e.,
> it does not take any child (and descendent) groups into
> account. With the two features, virsh dominfo which just
> checks memory usage of a cgroup for domain always returns
> zero because the cgroup has no process.
>
> Setting memory.use_hierarchy of a group allows to account
> (and limit) memory usage of every descendent groups of the group.
> By setting it of a cgroup for domain, we can get proper memory
> usage of lxc with ns subsystem enabled. (To be exact, the
> setting is required only when memory and ns subsystems are
> enabled at the same time, e.g., mount -t cgroup none /cgroup.)
> ---

This does sound like a valid use case and the correct fix.

>  src/util/cgroup.c |   49 +++++++++++++++++++++++++++++++++++++++++++++----
>  1 files changed, 45 insertions(+), 4 deletions(-)
>
> diff --git a/src/util/cgroup.c b/src/util/cgroup.c
> index b8b2eb5..93cd6a9 100644
> --- a/src/util/cgroup.c
> +++ b/src/util/cgroup.c
> @@ -443,7 +443,38 @@ static int virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
>     return rc;
>  }
>
> -static int virCgroupMakeGroup(virCgroupPtr parent, virCgroupPtr group, int create)
> +static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
> +{
> +    int rc = 0;
> +    unsigned long long value;
> +    const char *filename = "memory.use_hierarchy";
> +
> +    rc = virCgroupGetValueU64(group,
> +                              VIR_CGROUP_CONTROLLER_MEMORY,
> +                              filename, &value);
> +    if (rc != 0) {
> +        VIR_ERROR("Failed to read %s/%s (%d)", group->path, filename, rc);
> +        return rc;
> +    }
> +
> +    /* Setting twice causes error, so if already enabled, skip setting */
> +    if (value == 1)
> +        return 0;
> +
> +    VIR_DEBUG("Setting up %s/%s", group->path, filename);
> +    rc = virCgroupSetValueU64(group,
> +                              VIR_CGROUP_CONTROLLER_MEMORY,
> +                              filename, 1);
> +
> +    if (rc != 0) {
> +        VIR_ERROR("Failed to set %s/%s (%d)", group->path, filename, rc);
> +    }
> +
> +    return rc;
> +}
> +
> +static int virCgroupMakeGroup(virCgroupPtr parent, virCgroupPtr group,
> +                              int create, int memory_hierarchy)
>  {
>     int i;
>     int rc = 0;
> @@ -477,6 +508,16 @@ static int virCgroupMakeGroup(virCgroupPtr parent, virCgroupPtr group, int creat
>                     break;
>                 }
>             }

Can you please add a comment here stating that memory.use_hierarchy
should always be called prior to creating subcgroups and attaching
tasks

> +            if (memory_hierarchy &&
> +                group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint != NULL &&
> +                (i == VIR_CGROUP_CONTROLLER_MEMORY ||
> +                 STREQ(group->controllers[i].mountPoint, group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint))) {
> +                rc = virCgroupSetMemoryUseHierarchy(group);
> +                if (rc != 0) {
> +                    VIR_FREE(path);
> +                    break;
> +                }
> +            }
>         }
>
>         VIR_FREE(path);
> @@ -553,7 +594,7 @@ static int virCgroupAppRoot(int privileged,
>     if (rc != 0)
>         goto cleanup;
>
> -    rc = virCgroupMakeGroup(rootgrp, *group, create);
> +    rc = virCgroupMakeGroup(rootgrp, *group, create, 0);
>
>  cleanup:
>     virCgroupFree(&rootgrp);
> @@ -653,7 +694,7 @@ int virCgroupForDriver(const char *name,
>     VIR_FREE(path);
>
>     if (rc == 0) {
> -        rc = virCgroupMakeGroup(rootgrp, *group, create);
> +        rc = virCgroupMakeGroup(rootgrp, *group, create, 0);
>         if (rc != 0)
>             virCgroupFree(group);
>     }
> @@ -703,7 +744,7 @@ int virCgroupForDomain(virCgroupPtr driver,
>     VIR_FREE(path);
>
>     if (rc == 0) {
> -        rc = virCgroupMakeGroup(driver, *group, create);
> +        rc = virCgroupMakeGroup(driver, *group, create, 1);
>         if (rc != 0)
>             virCgroupFree(group);
>     }

A comment on why Domains get hierarchy support and Drivers don't will
help unless it is very obvious to developers.

Balbir




More information about the libvir-list mailing list