[libvirt] [PATCH 1/2] cgroup: Change virCgroupRemove to remove all child groups at first

Ryota Ozaki ozaki.ryota at gmail.com
Wed Jun 23 11:51:32 UTC 2010


Hi Eric.

Thanks for your kind review.

On Wed, Jun 23, 2010 at 6:42 AM, Eric Blake <eblake at redhat.com> wrote:
> On 05/23/2010 07:15 AM, Ryota Ozaki wrote:
>> As same as normal directories, a cgroup cannot be removed if it
>> contains sub groups. This patch changes virCgroupRemove to remove
>> all child groups (subdirectories) of a target group before removing
>> the target group.
>>
>> The handling is required when we run lxc with ns subsystem of cgroup.
>> Ns subsystem automatically creates child cgroups on every process
>> forks, but unfortunately the groups are not removed on process exits,
>> so we have to remove them by ourselves.
>>
>> With this patch, such child groups are surely removed at lxc
>> shutdown, i.e., lxcVmCleanup which calls virCgroupRemove.
>> ---
>>  src/util/cgroup.c |   48 ++++++++++++++++++++++++++++++++++++++++++++----
>>  1 files changed, 44 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/util/cgroup.c b/src/util/cgroup.c
>> index b8b2eb5..531c131 100644
>> --- a/src/util/cgroup.c
>> +++ b/src/util/cgroup.c
>> @@ -23,6 +23,7 @@
>>  #include <sys/stat.h>
>>  #include <sys/types.h>
>>  #include <libgen.h>
>> +#include <dirent.h>
>>
>>  #include "internal.h"
>>  #include "util.h"
>> @@ -561,11 +562,52 @@ cleanup:
>>  }
>>  #endif
>>
>> +static int virCgroupRemoveRecursively(char *grppath)
>> +{
>> +    DIR *grpdir;
>> +    struct dirent *ent;
>> +    int rc = 0;
>> +
>> +    grpdir = opendir(grppath);
>> +    if (grpdir == NULL) {
>> +        VIR_ERROR("Unable to open %s (%d)", grppath, errno);
>> +        rc = -errno;
>> +        return rc;
>> +    }
>> +
>> +    while ((ent = readdir(grpdir)) != NULL) {
>
> Technically, any loop over readdir must first set errno to 0, then call
> readdir, and if it is NULL, check if errno is still 0.  Otherwise, you
> can miss subtle readdir failures.

Oh, right. So revised version will be like this:

for (;;) {
  errno = 0;
  ent = readdir(grpdir);
  if (ent == NULL) {
    if (errno)
      VIR_ERROR(_("Failed to readdir for %s (%d)")_, grppath, errno);
    break;
  }
    ...
}

If I miss something, please let me know.

>
>> +        char path[PATH_MAX];
>
> I'd rather get out of the habit of stack-allocating PATH_MAX bytes,
> since it is not portably guaranteed to fit in a page of memory, and
> especially since you are using recursion and will chew through lots of
> stack in a deep hierarchy.

I just followed other codes that use PATH_MAX, but indeed, the codes
are not recursive unlike mine.

OK. I'll fix.

>
>> +        int ret;
>> +
>> +        if (ent->d_name[0] == '.') continue;
>> +        if (ent->d_type != DT_DIR) continue;
>> +
>> +        ret = snprintf(path, sizeof(path), "%s/%s", grppath, ent->d_name);
>
> Rather, we can construct path via virAsprintf(), and VIR_FREE() it later.
>
>> +        if (ret < 0)
>> +            break;
>> +        rc = virCgroupRemoveRecursively(path);
>> +        if (rc != 0)
>> +            break;
>> +    }
>> +    DEBUG("Removing cgroup %s", grppath);
>> +    if (rmdir(grppath) != 0 && errno != ENOENT) {
>> +        rc = -errno;
>> +        VIR_ERROR("Unable to remove %s (%d)", grppath, errno);
>> +    }
>> +
>> +    return rc;
>> +}
>> +
>>  /**
>>   * virCgroupRemove:
>>   *
>>   * @group: The group to be removed
>>   *
>> + * It first removes all child groups recursively
>> + * in depth first order and then removes @group
>> + * because the presence of the child groups
>> + * prevents removing @group.
>> + *
>>   * Returns: 0 on success
>>   */
>>  int virCgroupRemove(virCgroupPtr group)
>> @@ -585,10 +627,8 @@ int virCgroupRemove(virCgroupPtr group)
>>                                        &grppath) != 0)
>>              continue;
>>
>> -        DEBUG("Removing cgroup %s", grppath);
>> -        if (rmdir(grppath) != 0 && errno != ENOENT) {
>> -            rc = -errno;
>> -        }
>> +        DEBUG("Removing cgroup %s and all child cgroups", grppath);
>> +        rc = virCgroupRemoveRecursively(grppath);
>
> But other than the missed error handling, this patch looks like the
> right technical approach for the problem.

Thanks again.
  ozaki-r

>
> --
> Eric Blake   eblake at redhat.com    +1-801-349-2682
> Libvirt virtualization library http://libvirt.org
>
>




More information about the libvir-list mailing list