[CRIU] [PATCH 09/11] cgroup: Optimize ifpriomap restoring

Dmitry Safonov dsafonov at virtuozzo.com
Wed Jul 26 00:08:14 MSK 2017


Skip writing 0 for interfaces, as it's the default value.

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/cgroup.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 71 insertions(+), 4 deletions(-)

diff --git a/criu/cgroup.c b/criu/cgroup.c
index f8dbeeb4b580..de7ca72385cf 100644
--- a/criu/cgroup.c
+++ b/criu/cgroup.c
@@ -20,6 +20,7 @@
 #include "util-pie.h"
 #include "namespaces.h"
 #include "seize.h"
+#include "string.h"
 #include "protobuf.h"
 #include "images/core.pb-c.h"
 #include "images/cgroup.pb-c.h"
@@ -1310,6 +1311,70 @@ static void add_freezer_state_for_restore(CgroupPropEntry *entry, char *path, si
 	freezer_path[path_len] = 0;
 }
 
+/*
+ * Filter out ifpriomap interfaces which have 0 as priority.
+ * As by default new ifpriomap has 0 as a priority for each
+ * interface, this will save up some write()'s.
+ * As this property is used rarely, this may save a whole bunch
+ * of syscalls, skipping all ifpriomap restore.
+ */
+static int filter_ifpriomap(char *out, char *line)
+{
+	char *next_line, *space;
+	bool written = false;
+	size_t len;
+
+	if (*line == '\0')
+		return 0;
+
+	do {
+		next_line = strchrnul(line, '\n');
+		len = next_line - line;
+
+		space = strchr(line, ' ');
+		if (!space) {
+			pr_err("Invalid value for ifpriomap: `%s'\n", line);
+			return -1;
+		}
+
+		if (!strtol(space, NULL, 10))
+			goto next;
+
+		/* Copying with last \n or \0 */
+		strncpy(out, line, len + 1);
+		out += len + 1;
+		written = true;
+next:
+		line = next_line + 1;
+	} while(*next_line != '\0');
+
+	if (written)
+		*(out - 1) = '\0';
+
+	return 0;
+}
+
+static int restore_cgroup_ifpriomap(CgroupPropEntry *cpe, char *path, int off)
+{
+	CgroupPropEntry priomap = *cpe;
+	int ret = -1;
+
+	priomap.value = xmalloc(strlen(cpe->value) + 1);
+	priomap.value[0] = '\0';
+
+	if (filter_ifpriomap(priomap.value, cpe->value))
+		goto out;
+
+	if (strlen(priomap.value))
+		ret = restore_cgroup_prop(&priomap, path, off, true, true);
+	else
+		ret = 0;
+
+out:
+	xfree(priomap.value);
+	return ret;
+}
+
 static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **ents,
 					 unsigned int n_ents)
 {
@@ -1325,7 +1390,6 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
 		off2 += sprintf(path + off, "/%s", e->dir_name);
 		for (j = 0; j < e->n_properties; ++j) {
 			CgroupPropEntry *p = e->properties[j];
-			bool pm = false;
 
 			if (!strcmp(p->name, "freezer.state")) {
 				add_freezer_state_for_restore(p, path, off2);
@@ -1344,10 +1408,13 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
 			 * The kernel can't handle it in one write()
 			 * Number of network interfaces on host may differ.
 			 */
-			if (strcmp(p->name, "net_prio.ifpriomap") == 0)
-				pm = true;
+			if (strcmp(p->name, "net_prio.ifpriomap") == 0) {
+				if (restore_cgroup_ifpriomap(p, path, off2))
+					return -1;
+				continue;
+			}
 
-			if (restore_cgroup_prop(p, path, off2, pm, pm) < 0)
+			if (restore_cgroup_prop(p, path, off2, false, false) < 0)
 				return -1;
 		}
 skip:
-- 
2.13.3



More information about the CRIU mailing list