On Wed, Sep 11, 2013 at 11:50:54AM -0500, Serge Hallyn wrote:
> 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.
> 

Tested on Android with a 2.6.32 kernel, I can confirm that I'm now able
to start containers!

Acked-by: Stéphane Graber <stgra...@ubuntu.com>

> 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

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com

Attachment: signature.asc
Description: Digital signature

------------------------------------------------------------------------------
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