From 8323e2145817b6aea5bf8a9506beae002e7c8017 Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Fri, 22 Aug 2014 14:22:32 +0000 Subject: [PATCH] cg: restore special cpuset properties cpuset.cpus and cpuset.mems can't be written to for the first time after they have tasks, so the traditional mechanism of restoring properties after restoring the tasks won't work here. Instead, we copy the parent values of the properties into them, restore the tasks, and then restore via the traditional mechanism the actual values of these properties. Signed-off-by: Tycho Andersen Signed-off-by: Pavel Emelyanov --- cgroup.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/cgroup.c b/cgroup.c index 940e6eb9f..24d27fef9 100644 --- a/cgroup.c +++ b/cgroup.c @@ -50,8 +50,12 @@ static const char *memory_props[] = { static const char *cpuset_props[] = { /* * cpuset.cpus and cpuset.mems must be set before the process moves - * into its cgroup and hence can't be done here + * into its cgroup; they are "initialized" below to whatever the root + * values are in copy_special_cg_props so as not to cause ENOSPC when + * values are restored via this code. */ + "cpuset.cpus", + "cpuset.mems", "cpuset.memory_migrate", "cpuset.cpu_exclusive", "cpuset.mem_exclusive", @@ -856,6 +860,54 @@ static int ctrl_dir_and_opt(CgControllerEntry *ctl, char *dir, int ds, return doff; } +static const char *special_cpuset_props[] = { + "cpuset.cpus", + "cpuset.mems", + NULL, +}; + +static int copy_special_cg_props(const char *controller, const char *path) +{ + int cg = get_service_fd(CGROUP_YARD); + + pr_info("copying special cg props for %s\n", controller); + + if (strstr(controller, "cpuset")) { + int i; + + for (i = 0; special_cpuset_props[i]; i++) { + char fpath[PATH_MAX], buf[1024]; + const char *prop = special_cpuset_props[i]; + int ret; + FILE *f; + + snprintf(fpath, PATH_MAX, "%s/%s", controller, prop); + f = fopenat(cg, fpath, "r"); + if (!f) + return -1; + + ret = fscanf(f, "%1024s", buf); + fclose(f); + + if (ret <= 0) { + continue; + } + + pr_info("copying %s for %s/%s\n", buf, controller, prop); + + snprintf(fpath, PATH_MAX, "%s/%s/%s", controller, path, prop); + f = fopenat(cg, fpath, "w"); + if (!f) + return -1; + + fprintf(f, "%s", buf); + fclose(f); + } + } + + return 0; +} + static int move_in_cgroup(CgSetEntry *se) { int cg, i; @@ -882,6 +934,12 @@ static int move_in_cgroup(CgSetEntry *se) } aux_off = ctrl_dir_and_opt(ctrl, aux, sizeof(aux), NULL, 0); + + if (copy_special_cg_props(aux, ce->path) < 0) { + pr_perror("Couldn't copy special cgroup properties\n"); + return -1; + } + snprintf(aux + aux_off, sizeof(aux) - aux_off, "/%s/tasks", ce->path); pr_debug(" `-> %s\n", aux); err = fd = openat(cg, aux, O_WRONLY);