mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-08-01 14:30:53 +00:00
cgroups: get controllers from /proc/self/cgroups (v2)
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@canonical.com> Reported-by: Ross Boucher <boucher@gmail.com> Signed-off-by: Andrey Vagin <avagin@openvz.org> Acked-by: Tycho Andersen <tycho.andersen@canonical.com> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
5db3f4c337
commit
d3be641acd
4 changed files with 53 additions and 46 deletions
7
cgroup.c
7
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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
87
proc_parse.c
87
proc_parse.c
|
|
@ -2015,67 +2015,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;
|
||||
|
||||
if (sscanf(buf, "%s %d", name, &heirarchy) != 2) {
|
||||
pr_err("Unable to parse: %s\n", buf);
|
||||
goto out;
|
||||
controllers = strchr(buf, ':');
|
||||
if (!controllers) {
|
||||
pr_err("Unable to parse \"%s\"\n", buf);
|
||||
goto err;
|
||||
}
|
||||
list_for_each_entry(cur, cgroups, l) {
|
||||
if (cur->heirarchy == heirarchy) {
|
||||
controllers++;
|
||||
|
||||
off = strchr(controllers, ':');
|
||||
if (!off) {
|
||||
pr_err("Unable to parse \"%s\"\n", buf);
|
||||
goto err;
|
||||
}
|
||||
*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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue