diff options
author | Daniel Lezcano <daniel.lezcano@free.fr> | 2011-01-09 23:53:19 +0100 |
---|---|---|
committer | Daniel Lezcano <dlezcano@fr.ibm.com> | 2011-01-09 23:53:19 +0100 |
commit | 5193cc3d9366791bc0de70274ca8ca3f111430b8 (patch) | |
tree | 8f3c2ac2382ca546cd94e9d64b71b53de0952953 | |
parent | Correcting charset argument when calling locale-gen. (diff) | |
download | lxc-5193cc3d9366791bc0de70274ca8ca3f111430b8.tar.gz lxc-5193cc3d9366791bc0de70274ca8ca3f111430b8.tar.bz2 lxc-5193cc3d9366791bc0de70274ca8ca3f111430b8.zip |
fix the ns_cgroup vs clone_children
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>
-rw-r--r-- | src/lxc/cgroup.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c index 1c603fc..229e26b 100644 --- a/src/lxc/cgroup.c +++ b/src/lxc/cgroup.c @@ -45,10 +45,15 @@ 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"); |