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

Ryota Ozaki ozaki.ryota at gmail.com
Thu May 6 15:53:43 UTC 2010


On Fri, May 7, 2010 at 12:26 AM, Balbir Singh <balbir at linux.vnet.ibm.com> wrote:
> 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

OK, I will.

>
>> +            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.

Because of concern of overhead as Daniel said, though I don't figure out
well how much it is. Is it negligible than we expect?

Thanks,
  ozaki-r

>
> Balbir
>




More information about the libvir-list mailing list