If a cgroup hierarchy has ns cgroup composed, then we need to treat
that differently:

1. The container init will have already been switched to a new cgroup
called after its pid.
2. We can't move the container init to new deeper cgroup directories.

So, if we detect an ns cgroup, don't bother trying to construct a new
name according to the pattern.  Just rename the current one to the
container name, and save that path for us to later enter and remove.

Note I'm not dealing with the subpaths so nested containers probably
won't work.  However as ns cgroup is very much legacy, that should be
ok.  Eventually we should be able to drop ns cgroup support altogether,
but not just yet.

Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
---
 src/lxc/cgroup.c |   87 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/lxc/cgroup.h |    2 +-
 src/lxc/start.c  |    2 +-
 3 files changed, 85 insertions(+), 6 deletions(-)

diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
index bfdf112..0062571 100644
--- a/src/lxc/cgroup.c
+++ b/src/lxc/cgroup.c
@@ -535,8 +535,64 @@ struct cgroup_process_info 
*lxc_cgroup_process_info_get_self(struct cgroup_meta_
        return i;
 }
 
+/*
+ * If a controller has ns cgroup mounted, then in that cgroup the handler->pid
+ * is already in a new cgroup named after the pid.  'mnt' is passed in as
+ * the full current cgroup.  Say that is /sys/fs/cgroup/lxc/2975 and the 
container
+ * name is c1. .  We want to rename the cgroup directory to 
/sys/fs/cgroup/lxc/c1,
+ * and return the string /sys/fs/cgroup/lxc/c1.
+ */
+static char *cgroup_rename_nsgroup(char *mountpath, const char *oldname, int 
pid, const char *name)
+{
+       char *dir, *fulloldpath;
+       char *newname, *fullnewpath;
+       int len;
+
+       /*
+        * if cgroup is mounted at /cgroup and task is in cgroup /ab/, pid 2375 
and
+        * name is c1,
+        * dir: /ab
+        * fulloldpath = /cgroup/ab/2375
+        * fullnewpath = /cgroup/ab/c1
+        * newname = /ab/c1
+        */
+       dir = alloca(strlen(oldname) + 1);
+       strcpy(dir, oldname);
+
+       fulloldpath = alloca(strlen(oldname) + strlen(mountpath) + 22);
+       sprintf(fulloldpath, "%s/%s/%d", mountpath, oldname, pid);
+
+       len = strlen(dir) + strlen(name) + 2;
+       newname = malloc(len);
+       if (!newname) {
+               SYSERROR("Out of memory");
+               return NULL;
+       }
+       sprintf(newname, "%s/%s", dir, name);
+
+       fullnewpath = alloca(strlen(mountpath) + len + 2);
+       sprintf(fullnewpath, "%s/%s", mountpath, newname);
+
+       if (access(fullnewpath, F_OK) == 0) {
+               if (rmdir(fullnewpath) != 0) {
+                       SYSERROR("container cgroup %s already exists.", 
fullnewpath);
+                       free(newname);
+                       return NULL;
+               }
+       }
+       if (rename(fulloldpath, fullnewpath)) {
+               SYSERROR("failed to rename cgroup %s->%s", fulloldpath, 
fullnewpath);
+               free(newname);
+               return NULL;
+       }
+
+       DEBUG("'%s' renamed to '%s'", oldname, newname);
+
+       return newname;
+}
+
 /* create a new cgroup */
-extern struct cgroup_process_info *lxc_cgroup_create(const char *name, const 
char *path_pattern, struct cgroup_meta_data *meta_data, const char *sub_pattern)
+extern struct cgroup_process_info *lxc_cgroup_create(const char *name, const 
char *path_pattern, struct cgroup_meta_data *meta_data, const char 
*sub_pattern, int pid)
 {
        char **cgroup_path_components = NULL;
        char **p = NULL;
@@ -592,6 +648,8 @@ extern struct cgroup_process_info *lxc_cgroup_create(const 
char *name, const cha
                }
                info_ptr->designated_mount_point = mp;
 
+               if (lxc_string_in_array("ns", (const char **)h->subsystems))
+                       continue;
                if (handle_clone_children(mp, info_ptr->cgroup_path) < 0) {
                        ERROR("Could not set clone_children to 1 for cpuset 
hierarchy in parent cgroup.");
                        goto out_initial_error;
@@ -669,6 +727,9 @@ extern struct cgroup_process_info *lxc_cgroup_create(const 
char *name, const cha
                 */
                for (i = 0, info_ptr = base_info; info_ptr; info_ptr = 
info_ptr->next, i++) {
                        char *parts2[3];
+
+                       if (lxc_string_in_array("ns", (const char 
**)info_ptr->hierarchy->subsystems))
+                               continue;
                        current_entire_path = NULL;
 
                        parts2[0] = !strcmp(info_ptr->cgroup_path, "/") ? "" : 
info_ptr->cgroup_path;
@@ -753,9 +814,27 @@ extern struct cgroup_process_info *lxc_cgroup_create(const 
char *name, const cha
 
        /* we're done, now update the paths */
        for (i = 0, info_ptr = base_info; info_ptr; info_ptr = info_ptr->next, 
i++) {
-               free(info_ptr->cgroup_path);
-               info_ptr->cgroup_path = new_cgroup_paths[i];
-               info_ptr->cgroup_path_sub = new_cgroup_paths_sub[i];
+               /*
+                * For any path which has ns cgroup mounted, handler->pid is 
already
+                * moved into a container called '%d % (handler->pid)'.  Rename 
it to
+                * the cgroup name and record that.
+                */
+               if (lxc_string_in_array("ns", (const char 
**)info_ptr->hierarchy->subsystems)) {
+                       char *tmp = 
cgroup_rename_nsgroup(info_ptr->designated_mount_point->mount_point,
+                                       info_ptr->cgroup_path, pid, name);
+                       if (!tmp)
+                               goto out_initial_error;
+                       free(info_ptr->cgroup_path);
+                       info_ptr->cgroup_path = tmp;
+                       r = lxc_grow_array((void ***)&info_ptr->created_paths, 
&info_ptr->created_paths_capacity, info_ptr->created_paths_count + 1, 8);
+                       if (r < 0)
+                               goto out_initial_error;
+                       
info_ptr->created_paths[info_ptr->created_paths_count++] = strdup(tmp);
+               } else {
+                       free(info_ptr->cgroup_path);
+                       info_ptr->cgroup_path = new_cgroup_paths[i];
+                       info_ptr->cgroup_path_sub = new_cgroup_paths_sub[i];
+               }
        }
        /* don't use lxc_free_array since we used the array members
         * to store them in our result...
diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
index 7185ef8..bd2da25 100644
--- a/src/lxc/cgroup.h
+++ b/src/lxc/cgroup.h
@@ -113,7 +113,7 @@ extern struct cgroup_process_info 
*lxc_cgroup_process_info_get_init(struct cgrou
 extern struct cgroup_process_info *lxc_cgroup_process_info_get_self(struct 
cgroup_meta_data *meta);
 
 /* create a new cgroup */
-extern struct cgroup_process_info *lxc_cgroup_create(const char *name, const 
char *path_pattern, struct cgroup_meta_data *meta_data, const char 
*sub_pattern);
+extern struct cgroup_process_info *lxc_cgroup_create(const char *name, const 
char *path_pattern, struct cgroup_meta_data *meta_data, const char 
*sub_pattern, int pid);
 
 /* get the cgroup membership of a given container */
 extern struct cgroup_process_info *lxc_cgroup_get_container_info(const char 
*name, const char *lxcpath, struct cgroup_meta_data *meta_data);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 0356fc0..4d9a3b4 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -686,7 +686,7 @@ int lxc_spawn(struct lxc_handler *handler)
        if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
                failed_before_rename = 1;
 
-       if ((handler->cgroup = lxc_cgroup_create(name, cgroup_pattern, 
cgroup_meta, NULL)) == NULL) {
+       if ((handler->cgroup = lxc_cgroup_create(name, cgroup_pattern, 
cgroup_meta, NULL, handler->pid)) == NULL) {
                ERROR("failed to create cgroups for '%s'", name);
                goto out_delete_net;
        }
-- 
1.7.9.5


------------------------------------------------------------------------------
How ServiceNow helps IT people transform IT departments:
1. Consolidate legacy IT systems to a single system of record for IT
2. Standardize and globalize service processes across IT
3. Implement zero-touch automation to replace manual, redundant tasks
http://pubads.g.doubleclick.net/gampad/clk?id=51271111&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to