[lxc-devel] [PATCH] cgroup: re-introduce ns cgroup support

Stéphane Graber stgraber at ubuntu.com
Wed Sep 11 18:11:17 UTC 2013


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 <stgraber at ubuntu.com>

> Signed-off-by: Serge Hallyn <serge.hallyn at 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 at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20130911/788388cf/attachment.pgp>


More information about the lxc-devel mailing list