[CRIU] [PATCH] cgroup: don't look up existing mount point

Andrew Vagin avagin at openvz.org
Tue Jul 15 05:06:41 PDT 2014


A mount point, which is mounted by someone else, may be umounted in any moment.

For example the test system executes tests concurrently and sometimes one
test looks up a mount point, which has been mounted by another test.

==================================== ERROR ====================================
Test: zdtm/live/static/inotify00, Namespace: 1
Dump log   : /var/lib/jenkins/jobs/CRIU-dump/workspace/test/dump/inotify00/15535/1/dump.log
--------------------------------- grep Error ---------------------------------
(00.021951) Error (cgroup.c:409): cg: failed walking /var/lib/jenkins/jobs/CRIU-dump/workspace/test/dump/signalfd00/15538/1/.criu.cgmounts.UGj28v/ for empty cgroups
(00.021967) Error (cr-dump.c:1601): Dump core (pid: 15535) failed with -1
(00.025509) Error (cr-dump.c:1914): Dumping FAILED.
------------------------------------- END -------------------------------------
================================= ERROR OVER =================================

Reported-by: Jenkins Criuovich
Cc: Tycho Andersen <tycho.andersen at canonical.com>
Signed-off-by: Andrew Vagin <avagin at openvz.org>
---
 cgroup.c | 123 ++++++++++++++-------------------------------------------------
 1 file changed, 26 insertions(+), 97 deletions(-)

diff --git a/cgroup.c b/cgroup.c
index 5114935..9ee54d3 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -14,6 +14,7 @@
 #include "proc_parse.h"
 #include "util.h"
 #include "fdset.h"
+#include "util-pie.h"
 #include "protobuf.h"
 #include "protobuf/core.pb-c.h"
 #include "protobuf/cgroup.pb-c.h"
@@ -44,7 +45,6 @@ static u32 cg_set_ids = 1;
 
 static LIST_HEAD(cgroups);
 static unsigned int n_cgroups;
-static struct mount_info *cg_mntinfo;
 
 static CgSetEntry *find_rst_set_by_id(u32 id)
 {
@@ -161,53 +161,9 @@ int parse_cg_info(void)
 	if (parse_cgroups(&cgroups, &n_cgroups) < 0)
 		return -1;
 
-	cg_mntinfo = parse_mountinfo(getpid(), NULL);
-
-	if (!cg_mntinfo)
-		return -1;
 	return 0;
 }
 
-static int get_cgroup_mount_point(const char *controller, char *path)
-{
-	struct mount_info *m;
-	char name[1024];
-
-	for (m = cg_mntinfo; m != NULL; m = m->next) {
-		if (strcmp(m->fstype->name, "cgroup") == 0) {
-			char *start, *end;
-
-			start = strstr(m->options, "name=");
-			if (start) {
-				/* strlen("name=") == 5 */
-				start = start + 5;
-
-				end = strstr(start, ",");
-				if (end) {
-					strncpy(name, start, end - start);
-					name[end - start] = '\0';
-				} else
-					strcpy(name, start);
-			} else {
-				start = strrchr(m->mountpoint, '/');
-				if (!start) {
-					pr_err("bad path %s\n", m->mountpoint);
-					return -1;
-				}
-				strcpy(name, start+1);
-			}
-
-			if (strcmp(name, controller) == 0) {
-				/* skip the leading '.' in mountpoint */
-				strcpy(path, m->mountpoint + 1);
-				return 0;
-			}
-		}
-	}
-
-	return -1;
-}
-
 /* Check that co-mounted controllers from /proc/cgroups (e.g. cpu and cpuacct)
  * are contained in a name from /proc/self/cgroup (e.g. cpu,cpuacct). */
 bool cgroup_contains(char **controllers, unsigned int n_controllers, char *name)
@@ -274,7 +230,6 @@ static int add_cgroup(const char *fpath, const struct stat *sb, int typeflag)
 
 	if (typeflag == FTW_D) {
 		int mtype;
-		struct mount_info *mi;
 
 		strncpy(pbuf, fpath, PATH_MAX);
 
@@ -287,27 +242,11 @@ static int add_cgroup(const char *fpath, const struct stat *sb, int typeflag)
 		}
 		ncd->path = NULL;
 
-		for (mi = cg_mntinfo; mi != NULL; mi = mi->next) {
-			if (is_path_prefix(fpath, mi->mountpoint + 1)) {
-				ncd->path = xstrdup(fpath + strlen(mi->mountpoint));
-				if (!ncd->path) {
-					ret = -1;
-					goto out;
-				}
-				break;
-			}
-		}
-
+		/* chop off the first strlen(".criu.cgmounts.XXXXXX") */
+		ncd->path = xstrdup(fpath + 21);
 		if (!ncd->path) {
-			/* We couldn't find fpath in mountinfo, which means we
-			 * mounted it ourselves, so we just chop off the first
-			 * strlen(".criu.cgmounts.XXXXXX").
-			 */
-			ncd->path = xstrdup(fpath + 21);
-			if (!ncd->path) {
-				ret = -1;
-				goto out;
-			}
+			ret = -1;
+			goto out;
 		}
 
 		mtype = find_dir(ncd->path, &current_controller->heads, &match);
@@ -346,11 +285,11 @@ static int collect_cgroups(struct list_head *ctls)
 {
 	struct cg_ctl *cc;
 	int ret = 0;
+	int fd = -1;
 
 	list_for_each_entry(cc, ctls, l) {
-		char path[PATH_MAX];
-		char *name, mount_point[PATH_MAX], prefix[] = ".criu.cgmounts.XXXXXX";
-		bool temp_mount = false;
+		char path[PATH_MAX], opts[1024];
+		char *name, prefix[] = ".criu.cgmounts.XXXXXX";
 		struct cg_controller *cg;
 
 		if (strstartswith(cc->name, "name="))
@@ -358,34 +297,27 @@ static int collect_cgroups(struct list_head *ctls)
 		else
 			name = cc->name;
 
-		if (get_cgroup_mount_point(name, mount_point) < 0) {
-			/* Someone is trying to dump a process that is in
-			 * a controller that isn't mounted, so we mount it for
-			 * them.
-			 */
-			char opts[1024];
-			temp_mount = true;
-
-			if (mkdtemp(prefix) == NULL) {
-				pr_perror("can't make dir for cg mounts\n");
-				return -1;
-			}
-
-			if (name == cc->name)
-				sprintf(opts, "%s", name);
-			else
-				sprintf(opts, "none,%s", cc->name);
+		if (mkdtemp(prefix) == NULL) {
+			pr_perror("can't make dir for cg mounts\n");
+			return -1;
+		}
 
-			if (mount("none", prefix, "cgroup", 0, opts) < 0) {
-				pr_perror("couldn't mount %s\n", opts);
-				rmdir(prefix);
-				return -1;
-			}
+		if (name == cc->name)
+			sprintf(opts, "%s", name);
+		else
+			sprintf(opts, "none,%s", cc->name);
 
-			strcpy(mount_point, prefix);
+		if (mount("none", prefix, "cgroup", 0, opts) < 0) {
+			pr_perror("couldn't mount %s\n", opts);
+			rmdir(prefix);
+			return -1;
 		}
 
-		snprintf(path, PATH_MAX, "%s/%s", mount_point, cc->path);
+		fd = open_detach_mount(prefix);
+		if (fd < 0)
+			return -1;
+
+		snprintf(path, PATH_MAX, "/proc/self/fd/%d/%s", fd, cc->path);
 
 		current_controller = NULL;
 
@@ -420,10 +352,7 @@ static int collect_cgroups(struct list_head *ctls)
 		}
 
 out:
-		if (temp_mount) {
-			umount(prefix);
-			rmdir(prefix);
-		}
+		close_safe(&fd);
 
 		if (ret < 0)
 			return ret;
-- 
1.9.3



More information about the CRIU mailing list