]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
fix the ns_cgroup vs clone_children
authorDaniel Lezcano <daniel.lezcano@free.fr>
Sun, 9 Jan 2011 22:53:19 +0000 (23:53 +0100)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Sun, 9 Jan 2011 22:53:19 +0000 (23:53 +0100)
The following patch fixes the bug where the clone_children compatibility
flag is available with the ns_cgroup subsystem. The 2.6.37 kernel version
should be the only one which is concerned by this modification, please
refer to Documentation/feature-removal-schedule.txt and look for ns_cgroup.

The problem is coming from we check for clone_children and we set it
automatically and then we try to create a new cgroup. As the
ns_cgroup is present the cgroup already exists and we are not allowed
to attach our pid to a new cgroup. The next error will be when we try
to create a new container because we enabled the clone_children flag
and the ns_cgroup is present, it is not allowed by the kernel.

The patch fix this by checking the mount options.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/cgroup.c

index 1c603fccf6be99d495f28e5f98cc0ea87c2a2d3e..229e26b0f7055789e6681c3c58253e9725e021eb 100644 (file)
 
 lxc_log_define(lxc_cgroup, lxc);
 
-#define MTAB "/etc/mtab"
+#define MTAB "/proc/mounts"
 
 static char nsgroup_path[MAXPATHLEN];
 
+enum {
+       CGROUP_NS_CGROUP = 1,
+       CGROUP_CLONE_CHILDREN,
+};
+
 static int get_cgroup_mount(const char *mtab, char *mnt)
 {
         struct mntent *mntent;
@@ -58,7 +63,7 @@ static int get_cgroup_mount(const char *mtab, char *mnt)
         file = setmntent(mtab, "r");
         if (!file) {
                 SYSERROR("failed to open %s", mtab);
-                goto out;
+               return -1;
         }
 
         while ((mntent = getmntent(file))) {
@@ -81,7 +86,57 @@ static int get_cgroup_mount(const char *mtab, char *mnt)
        DEBUG("using cgroup mounted at '%s'", mnt);
 
         fclose(file);
-out:
+
+        return err;
+}
+
+static int get_cgroup_flags(const char *mtab, int *flags)
+{
+        struct mntent *mntent;
+        FILE *file = NULL;
+        int err = -1;
+
+        file = setmntent(mtab, "r");
+        if (!file) {
+                SYSERROR("failed to open %s", mtab);
+               return -1;
+        }
+
+       *flags = 0;
+
+        while ((mntent = getmntent(file))) {
+
+               /* there is a cgroup mounted named "lxc" */
+               if (!strcmp(mntent->mnt_fsname, "lxc") &&
+                   !strcmp(mntent->mnt_type, "cgroup")) {
+
+                       if (hasmntopt(mntent, "ns"))
+                               *flags |= CGROUP_NS_CGROUP;
+
+                       if (hasmntopt(mntent, "clone_children"))
+                               *flags |= CGROUP_CLONE_CHILDREN;
+
+                       err = 0;
+                       break;
+               }
+
+               /* fallback to the first non-lxc cgroup found */
+                if (!strcmp(mntent->mnt_type, "cgroup") && err) {
+
+                       if (hasmntopt(mntent, "ns"))
+                               *flags |= CGROUP_NS_CGROUP;
+
+                       if (hasmntopt(mntent, "clone_children"))
+                               *flags |= CGROUP_CLONE_CHILDREN;
+
+                       err = 0;
+               }
+        };
+
+       DEBUG("cgroup flags is 0x%x", *flags);
+
+        fclose(file);
+
         return err;
 }
 
@@ -151,6 +206,7 @@ int lxc_cgroup_create(const char *name, pid_t pid)
        char cgmnt[MAXPATHLEN];
        char cgname[MAXPATHLEN];
        char clonechild[MAXPATHLEN];
+       int flags;
 
        if (get_cgroup_mount(MTAB, cgmnt)) {
                ERROR("cgroup is not mounted");
@@ -168,14 +224,28 @@ int lxc_cgroup_create(const char *name, pid_t pid)
                return -1;
        }
 
-       snprintf(clonechild, MAXPATHLEN, "%s/cgroup.clone_children", cgmnt);
+       if (get_cgroup_flags(MTAB, &flags)) {
+               SYSERROR("failed to get cgroup flags");
+               return -1;
+       }
 
-       /* we check if the kernel has ns_cgroup or clone_children */
-       if (access(clonechild, F_OK)) {
+       /* We have the deprecated ns_cgroup subsystem */
+       if (flags & CGROUP_NS_CGROUP) {
                WARN("using deprecated ns_cgroup");
                return lxc_rename_nsgroup(cgmnt, cgname, pid);
        }
 
+       /* we check if the kernel has clone_children, at this point if there
+        * no clone_children neither ns_cgroup, that means the cgroup is mounted
+        * without the ns_cgroup and it has not the compatibility flag
+        */
+       if (access(clonechild, F_OK)) {
+               ERROR("no ns_cgroup option specified");
+               return -1;
+       }
+
+       snprintf(clonechild, MAXPATHLEN, "%s/cgroup.clone_children", cgmnt);
+
        /* we enable the clone_children flag of the cgroup */
        if (cgroup_enable_clone_children(clonechild)) {
                SYSERROR("failed to enable 'clone_children flag");