[CRIU] [PATCH] zdtm/cgroup_ifpriomap: Find cgroup's controller's name to mount

Dmitry Safonov 0x7f454c46 at gmail.com
Sun Feb 11 15:16:00 MSK 2018


I've also dropped `noauto' in this patch, reverting the
commit be98273cf137 ("zdtm: mark static/cgroup_ifpriomap as noauto")
Don't see any sense to separate it as another patch.

Fixes: #383

Signed-off-by: Dmitry Safonov <0x7f454c46 at gmail.com>
---
 test/zdtm/static/cgroup_ifpriomap.c    | 96 ++++++++++++++++++++++++++++++++--
 test/zdtm/static/cgroup_ifpriomap.desc |  2 +-
 test/zdtm/static/cgroup_ifpriomap.hook |  9 +++-
 3 files changed, 101 insertions(+), 6 deletions(-)

diff --git a/test/zdtm/static/cgroup_ifpriomap.c b/test/zdtm/static/cgroup_ifpriomap.c
index d14508060194..264f03b34b6f 100644
--- a/test/zdtm/static/cgroup_ifpriomap.c
+++ b/test/zdtm/static/cgroup_ifpriomap.c
@@ -42,12 +42,12 @@ static int mount_cg(const char *controller)
 		pr_perror("Can't make dir");
 		return -1;
 	}
-	if (mkdir(mnt_point, 0700) < 0) {
+	if (mkdir(mnt_point, 0700) < 0 && errno != EEXIST) {
 		pr_perror("Can't make dir `%s'", mnt_point);
 		return -1;
 	}
 	if (mount("none", mnt_point, "cgroup", 0, controller)) {
-		pr_perror("Can't mount cgroups");
+		pr_perror("Can't mount `%s' cgroup", controller);
 		goto err_rm;
 	}
 	if (mkdir(subdir, 0700) < 0 && errno != EEXIST) {
@@ -224,20 +224,107 @@ static int compare_maps(void)
 	return 0;
 }
 
+static ssize_t parse_cgroup_line(FILE *fcgroup, size_t *buf_sz, char **buf)
+{
+	ssize_t line_sz;
+
+	/* Reading cgroup mount nr */
+	errno = 0;
+	line_sz = getdelim(buf, buf_sz, ':', fcgroup);
+	if (errno) {
+		pr_perror("failed to read from file");
+		return -1;
+	}
+
+	if (line_sz == -1) /* EOF */
+		return 0;
+
+	/* Reading mounted controller name */
+	errno = 0;
+	line_sz = getdelim(buf, buf_sz, ':', fcgroup);
+	if (line_sz == -1) { /* no EOF here */
+		pr_perror("failed to read from file");
+		return -1;
+	}
+
+	/*
+	 * Reading the rest of the line.
+	 * It's zdtm's test, no need to optimize = use fgetc()
+	 */
+	do {
+		char c = fgetc(fcgroup);
+
+		if (c == '\n' || c == EOF)
+			break;
+	} while (true);
+
+	return line_sz;
+}
+
+/*
+ * Controller's name may differ depending on the kernel's config:
+ * `net_prio' if only CONFIG_CGROUP_NET_PRIO is set
+ * `net_cls,net_prio' if also CONFIG_CGROUP_NET_CLASSID is set
+ */
+static int get_controller_name(char **name)
+{
+	FILE *self_cgroup = fopen("/proc/self/cgroup", "r");
+	size_t buf_sz = 0;
+	int ret = -1;
+
+	*name = NULL;
+	if (!self_cgroup) {
+		pr_perror("failed to open self/cgroup");
+		return -1;
+	}
+
+	do {
+		ssize_t len = parse_cgroup_line(self_cgroup, &buf_sz, name);
+
+		if (len < 0) {
+			free(*name);
+			goto out_close;
+		}
+
+		if (len == 0) /* EOF */
+			break;
+
+		if (strstr(*name, "net_prio")) {
+			/* erasing ':' delimiter */
+			(*name)[len-1] = '\0';
+			ret = 0;
+			goto out_close;
+		}
+	} while(1);
+
+	/* self/cgroup has no mount for net_prio - try to map it */
+	*name = "net_prio";
+	ret = 0;
+
+out_close:
+	fclose(self_cgroup);
+	return ret;
+}
+
 int main(int argc, char **argv)
 {
 	char subdir[PATH_MAX];
 	char path[PATH_MAX];
 	int ret = -1;
+	char *controller_name;
 
 	srand(time(NULL));
 
 	test_init(argc, argv);
 
-	if (mount_cg("net_prio") < 0)
+	if (get_controller_name(&controller_name))
+		return -1;
+
+	if (mount_cg(controller_name) < 0)
 		return -1;
 
-	sprintf(path, "%s/net_prio/%s/net_prio.ifpriomap", dirname, cgname);
+	sprintf(path, "%s/%s/%s/net_prio.ifpriomap",
+		dirname, controller_name, cgname);
 
 	if (read_map(path, maps, PRIOMAPS_SZ))
 		goto out_umount;
@@ -266,6 +353,7 @@ out_umount:
 	sprintf(subdir, "%s/%s/%s", dirname, "net_prio", cgname);
 	rmdir(subdir);
 	umount_cg("net_prio");
+	free(controller_name);
 
 	return ret;
 }
diff --git a/test/zdtm/static/cgroup_ifpriomap.desc b/test/zdtm/static/cgroup_ifpriomap.desc
index 3bb68f00a190..5fa9d5079040 100644
--- a/test/zdtm/static/cgroup_ifpriomap.desc
+++ b/test/zdtm/static/cgroup_ifpriomap.desc
@@ -1 +1 @@
-{'flavor': 'h', 'flags': 'suid excl noauto', 'opts': '--manage-cgroups=full'}
+{'flavor': 'h', 'flags': 'suid excl', 'opts': '--manage-cgroups=full'}
diff --git a/test/zdtm/static/cgroup_ifpriomap.hook b/test/zdtm/static/cgroup_ifpriomap.hook
index 692c5ebe26a6..926ffee0c9fb 100755
--- a/test/zdtm/static/cgroup_ifpriomap.hook
+++ b/test/zdtm/static/cgroup_ifpriomap.hook
@@ -2,8 +2,15 @@
 
 [ "$1" == "--clean" -o "$1" == "--pre-restore" ] || exit 0
 
+# Controller's name may differ depending on the kernel's config:
+# `net_prio' if only CONFIG_CGROUP_NET_PRIO is set
+# `net_cls,net_prio' if also CONFIG_CGROUP_NET_CLASSID is set
+controller=$(sed -n '/net_prio/s/.*:\([^:]*net_prio[^:]*\):.*/\1/p' /proc/self/cgroup)
+
+echo "Controller's name '$controller'"
+
 tname=$(mktemp -d cgclean.XXXXXX)
-mount -t cgroup none $tname -o "net_prio"
+mount -t cgroup foobar $tname -o "$controller"
 
 echo "Cleaning $tname"
 
-- 
2.15.1



More information about the CRIU mailing list