[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