[CRIU] [PATCH] cgroups: get controllers from /proc/self/cgroups (v2)

Tycho Andersen tycho.andersen at canonical.com
Fri Sep 11 08:43:56 PDT 2015


On Fri, Sep 11, 2015 at 06:35:46PM +0300, Andrey Vagin wrote:
> Some controllers can be disabled in kernel options. In this case they
> are shown in /proc/cgroups, but they could not be mounted.
> 
> All enabled controllers can be collected from /proc/self/cgroup.
> 
> https://github.com/xemul/criu/issues/28
> 
> v2: ',' is used to separate controllers
> 
> Cc: Tycho Andersen <tycho.andersen at canonical.com>

Acked-by: Tycho Andersen <tycho.andersen at canonical.com>

> Reported-by: Ross Boucher <boucher at gmail.com>
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
>  cgroup.c             |  7 ++---
>  include/cgroup.h     |  3 +-
>  include/proc_parse.h |  2 +-
>  proc_parse.c         | 85 +++++++++++++++++++++++++++++-----------------------
>  4 files changed, 52 insertions(+), 45 deletions(-)
> 
> diff --git a/cgroup.c b/cgroup.c
> index 10009be..7bdccf8 100644
> --- a/cgroup.c
> +++ b/cgroup.c
> @@ -188,7 +188,7 @@ static struct cg_set *get_cg_set(struct list_head *ctls, unsigned int n_ctls)
>  	return cs;
>  }
>  
> -struct cg_controller *new_controller(const char *name, int heirarchy)
> +struct cg_controller *new_controller(const char *name)
>  {
>  	struct cg_controller *nc = xmalloc(sizeof(*nc));
>  	if (!nc)
> @@ -208,7 +208,6 @@ struct cg_controller *new_controller(const char *name, int heirarchy)
>  	}
>  
>  	nc->n_controllers = 1;
> -	nc->heirarchy = heirarchy;
>  
>  	nc->n_heads = 0;
>  	INIT_LIST_HEAD(&nc->heads);
> @@ -218,7 +217,7 @@ struct cg_controller *new_controller(const char *name, int heirarchy)
>  
>  int parse_cg_info(void)
>  {
> -	if (parse_cgroups(&cgroups, &n_cgroups) < 0)
> +	if (collect_controllers(&cgroups, &n_cgroups) < 0)
>  		return -1;
>  
>  	return 0;
> @@ -522,7 +521,7 @@ static int collect_cgroups(struct list_head *ctls)
>  				pr_err("controller %s not found\n", cc->name);
>  				return -1;
>  			} else {
> -				struct cg_controller *nc = new_controller(cc->name, -1);
> +				struct cg_controller *nc = new_controller(cc->name);
>  				list_add_tail(&nc->l, &cg->l);
>  				n_cgroups++;
>  				current_controller = nc;
> diff --git a/include/cgroup.h b/include/cgroup.h
> index 14fef67..37ba3cb 100644
> --- a/include/cgroup.h
> +++ b/include/cgroup.h
> @@ -40,7 +40,6 @@ struct cgroup_dir {
>   * The heads are subdirectories organized in their tree format.
>   */
>  struct cg_controller {
> -	int			heirarchy;
>  	unsigned int		n_controllers;
>  	char			**controllers;
>  
> @@ -51,7 +50,7 @@ struct cg_controller {
>  	/* for cgroup list in cgroup.c */
>  	struct list_head	l;
>  };
> -struct cg_controller *new_controller(const char *name, int heirarchy);
> +struct cg_controller *new_controller(const char *name);
>  
>  /* parse all global cgroup information into structures */
>  int parse_cg_info(void);
> diff --git a/include/proc_parse.h b/include/proc_parse.h
> index b4fb57d..92fc477 100644
> --- a/include/proc_parse.h
> +++ b/include/proc_parse.h
> @@ -180,7 +180,7 @@ struct cg_ctl {
>  extern int parse_task_cgroup(int pid, struct list_head *l, unsigned int *n);
>  extern void put_ctls(struct list_head *);
>  
> -int parse_cgroups(struct list_head *cgroups, unsigned int *n_cgroups);
> +int collect_controllers(struct list_head *cgroups, unsigned int *n_cgroups);
>  
>  /* callback for AUFS support */
>  extern int aufs_parse(struct mount_info *mi);
> diff --git a/proc_parse.c b/proc_parse.c
> index fad6bae..1547063 100644
> --- a/proc_parse.c
> +++ b/proc_parse.c
> @@ -2024,67 +2024,76 @@ void put_ctls(struct list_head *l)
>  	}
>  }
>  
> -
>  /* Parse and create all the real controllers. This does not include things with
>   * the "name=" prefix, e.g. systemd.
>   */
> -int parse_cgroups(struct list_head *cgroups, unsigned int *n_cgroups)
> +int collect_controllers(struct list_head *cgroups, unsigned int *n_cgroups)
>  {
> +	int exit_code = -1;
>  	FILE *f;
> -	char buf[1024], name[1024];
> -	int heirarchy, exit_code = -1;
> -	struct cg_controller *cur = NULL;
>  
> -	f = fopen_proc(PROC_GEN, "cgroups");
> -	if (!f) {
> -		pr_perror("failed opening /proc/cgroups");
> +	f = fopen_proc(PROC_SELF, "cgroup");
> +	if (f == NULL)
>  		return -1;
> -	}
>  
> -	/* throw away the header */
> -	if (!fgets(buf, 1024, f))
> -		goto out;
> +	while (fgets(buf, BUF_SIZE, f)) {
> +		struct cg_controller *nc = NULL;
> +		char *controllers, *off;
>  
> -	while (fgets(buf, 1024, f)) {
> -		char *n;
> -		char found = 0;
> +		controllers = strchr(buf, ':');
> +		if (!controllers) {
> +			pr_err("Unable to parse \"%s\"\n", buf);
> +			goto err;
> +		}
> +		controllers++;
>  
> -		if (sscanf(buf, "%s %d", name, &heirarchy) != 2) {
> -			pr_err("Unable to parse: %s\n", buf);
> -			goto out;
> +		off = strchr(controllers, ':');
> +		if (!off) {
> +			pr_err("Unable to parse \"%s\"\n", buf);
> +			goto err;
>  		}
> -		list_for_each_entry(cur, cgroups, l) {
> -			if (cur->heirarchy == heirarchy) {
> +		*off = '\0';
> +		while (1) {
> +			off = strchr(controllers, ',');
> +			if (off)
> +				*off = '\0';
> +
> +			if (!strncmp("name=", controllers, 5))
> +				goto skip;
> +
> +			if (!nc) {
> +				nc = new_controller(controllers);
> +				if (!nc)
> +					goto err;
> +				list_add_tail(&nc->l, cgroups);
> +				(*n_cgroups)++;
> +			} else {
>  				void *m;
> +				char *n;
>  
> -				found = 1;
> -				cur->n_controllers++;
> -				m = xrealloc(cur->controllers, sizeof(char *) * cur->n_controllers);
> +				nc->n_controllers++;
> +				m = xrealloc(nc->controllers, sizeof(char *) * nc->n_controllers);
>  				if (!m)
> -					goto out;
> +					goto err;
>  
> -				cur->controllers = m;
> +				nc->controllers = m;
>  
> -				n = xstrdup(name);
> +				n = xstrdup(controllers);
>  				if (!n)
> -					goto out;
> +					goto err;
>  
> -				cur->controllers[cur->n_controllers-1] = n;
> -				break;
> +				nc->controllers[nc->n_controllers-1] = n;
>  			}
> -		}
> -
> -		if (!found) {
> -			struct cg_controller *nc = new_controller(name, heirarchy);
> -			if (!nc)
> -				goto out;
> -			list_add_tail(&nc->l, &cur->l);
> -			(*n_cgroups)++;
> +			
> +skip:
> +			if (!off)
> +				break;
> +			controllers = off + 1;
>  		}
>  	}
>  
>  	exit_code = 0;
> -out:
> +err:
>  	fclose(f);
>  	return exit_code;
>  }
> -- 
> 2.4.3
> 


More information about the CRIU mailing list