[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