From de055b79924a86da99493e5efd83ef39eea1a9dd Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Mon, 6 Oct 2014 09:03:29 -0500 Subject: [PATCH] cg: use one path style throughout cg restore code This commit is in preparation for the (hopefully last :) restore special cpuset patch. Previously, we installed the cgroup service fd after calling prepare_cgroup_dirs, which meant that we had to carry around the temporary directory name in order to put things in the right place. The restore_cgroup_prop function uses the cg service fd instead of carrying around the full path. This means that we can't sue restore_cgroup_prop, without first sanitizing the path. Instead, we install the service fd before calling prepare_cgroup_dirs, and all the code just references that instead of carrying around the temporary path. Signed-off-by: Tycho Andersen Signed-off-by: Pavel Emelyanov --- cgroup.c | 44 ++++++++++++++++++++++++++------------------ include/util.h | 2 +- util.c | 4 ++-- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/cgroup.c b/cgroup.c index 29e373d4f..9fd739c63 100644 --- a/cgroup.c +++ b/cgroup.c @@ -1153,10 +1153,12 @@ static int prepare_cgroup_dirs(char *paux, size_t off, CgroupDirEntry **ents, si { size_t i; CgroupDirEntry *e; + int cg = get_service_fd(CGROUP_YARD); for (i = 0; i < n_ents; i++) { size_t off2 = off; e = ents[i]; + struct stat st; off2 += sprintf(paux + off, "/%s", e->dir_name); @@ -1165,12 +1167,13 @@ static int prepare_cgroup_dirs(char *paux, size_t off, CgroupDirEntry **ents, si * it does exist, prevent us from overwriting the properties * later by removing the CgroupDirEntry's properties. */ - if (access(paux, F_OK) < 0) { + if (fstatat(cg, paux, &st, 0) < 0) { if (errno != ENOENT) { pr_perror("Failed accessing file %s", paux); return -1; } - if (mkdirp(paux)) { + + if (mkdirpat(cg, paux)) { pr_perror("Can't make cgroup dir %s", paux); return -1; } @@ -1211,7 +1214,7 @@ static int prepare_cgroup_dirs(char *paux, size_t off, CgroupDirEntry **ents, si static int prepare_cgroup_sfd(CgroupEntry *ce) { - int off, i; + int off, i, ret; char paux[PATH_MAX]; pr_info("Preparing cgroups yard\n"); @@ -1238,11 +1241,24 @@ static int prepare_cgroup_sfd(CgroupEntry *ce) goto err; } + pr_debug("Opening %s as cg yard\n", cg_yard); + i = open(cg_yard, O_DIRECTORY); + if (i < 0) { + pr_perror("Can't open cgyard"); + goto err; + } + + ret = install_service_fd(CGROUP_YARD, i); + close(i); + if (ret < 0) + goto err; + + paux[off++] = '/'; for (i = 0; i < ce->n_controllers; i++) { - int ctl_off = off; - char opt[128]; + int ctl_off = off, yard_off; + char opt[128], *yard; CgControllerEntry *ctrl = ce->controllers[i]; if (ctrl->n_cnames < 1) { @@ -1265,24 +1281,16 @@ static int prepare_cgroup_sfd(CgroupEntry *ce) goto err; } + /* We skip over the .criu.cgyard.XXXXXX/, since those will be + * referred to by the cg yard service fd. */ + yard = paux + strlen(cg_yard) + 1; + yard_off = ctl_off - (strlen(cg_yard) + 1); if (opts.manage_cgroups && - prepare_cgroup_dirs(paux, ctl_off, ctrl->dirs, ctrl->n_dirs)) + prepare_cgroup_dirs(yard, yard_off, ctrl->dirs, ctrl->n_dirs)) goto err; } - pr_debug("Opening %s as cg yard\n", cg_yard); - i = open(cg_yard, O_DIRECTORY); - if (i < 0) { - pr_perror("Can't open cgyard"); - goto err; - } - - off = install_service_fd(CGROUP_YARD, i); - close(i); - if (off < 0) - goto err; - return 0; err: diff --git a/include/util.h b/include/util.h index 717aeeea3..081602934 100644 --- a/include/util.h +++ b/include/util.h @@ -212,7 +212,7 @@ static inline bool strstartswith(const char *str, const char *sub) /* * mkdir -p */ -int mkdirp(const char *path); +int mkdirpat(int fd, const char *path); /* * Tests whether a path is a prefix of another path. This is different than diff --git a/util.c b/util.c index 82837300e..dd76863aa 100644 --- a/util.c +++ b/util.c @@ -687,7 +687,7 @@ struct vma_area *alloc_vma_area(void) return p; } -int mkdirp(const char *path) +int mkdirpat(int fd, const char *path) { size_t i; char made_path[PATH_MAX], *pos; @@ -707,7 +707,7 @@ int mkdirp(const char *path) pos = strchr(made_path + i, '/'); if (pos) *pos = '\0'; - if (mkdir(made_path, 0755) < 0 && errno != EEXIST) { + if (mkdirat(fd, made_path, 0755) < 0 && errno != EEXIST) { pr_perror("couldn't mkdirpat directory %s", made_path); return -1; }