[CRIU] [PATCH 05/11] cgroup: Handle multiline properties in restore_cgroup_prop()
Dmitry Safonov
dsafonov at virtuozzo.com
Wed Jul 26 00:08:10 MSK 2017
We need to write some multiline properties line-by-line,
instead of writing all buffer at once - because kernel doesn't
support parsing them in one write().
Previously, it was done for devices.allow list, but I need it
also for netprio.ifpriomap. To make easier reusing this code,
add split_lines parameter to restore_cgroup_prop().
Dropping next_device_entry() and multiply calls to
restore_cgroup_prop() also improves performance: previously
for each property's line, cgroup file was re-open() and close()
again, while new code only calls write() for each line, reducing
number of syscalls done for each line.
This also makes it suitable for future:
if patch(s) for parsing all lines of property with one write()
would be accepted, then we can easily change call to something:
restore_cgroup_prop(&dev_allow, paux, off, !kdat.cgroup_multiline_write);
We can even use split_lines = true by default for all cases,
as strchrnul() will only find zero-terminator as does strlen().
But I don't want to do it - if there are cgroup files which
supportes multi-line write(), it'll add syscalls.
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/cgroup.c | 73 ++++++++++++++++++++++++-----------------------------------
1 file changed, 30 insertions(+), 43 deletions(-)
diff --git a/criu/cgroup.c b/criu/cgroup.c
index 4069bb6424ea..caadb8d186df 100644
--- a/criu/cgroup.c
+++ b/criu/cgroup.c
@@ -1197,10 +1197,10 @@ static int restore_perms(int fd, const char *path, CgroupPerms *perms)
return 0;
}
-static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
- char *path, int off)
+static int restore_cgroup_prop(const CgroupPropEntry *cg_prop_entry_p,
+ char *path, int off, bool split_lines)
{
- int cg, fd, len, ret = -1;
+ int cg, fd, ret = -1;
CgroupPerms *perms = cg_prop_entry_p->perms;
if (!cg_prop_entry_p->value) {
@@ -1231,10 +1231,28 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
goto out;
}
- len = strlen(cg_prop_entry_p->value);
- if (write(fd, cg_prop_entry_p->value, len) != len) {
- pr_perror("Failed writing %s to %s", cg_prop_entry_p->value, path);
- goto out;
+ if (split_lines) {
+ char *line = cg_prop_entry_p->value;
+ char *next_line;
+ size_t len;
+
+ do {
+ next_line = strchrnul(line, '\n');
+ len = next_line - line;
+
+ if (write(fd, line, len) != len) {
+ pr_perror("Failed writing %s to %s", line, path);
+ goto out;
+ }
+ line = next_line + 1;
+ } while(*next_line != '\0');
+ } else {
+ size_t len = strlen(cg_prop_entry_p->value);
+
+ if (write(fd, cg_prop_entry_p->value, len) != len) {
+ pr_perror("Failed writing %s to %s", cg_prop_entry_p->value, path);
+ goto out;
+ }
}
ret = 0;
@@ -1257,7 +1275,7 @@ int restore_freezer_state(void)
return 0;
freezer_path_len = strlen(freezer_path);
- return restore_cgroup_prop(freezer_state_entry, freezer_path, freezer_path_len);
+ return restore_cgroup_prop(freezer_state_entry, freezer_path, freezer_path_len, false);
}
static void add_freezer_state_for_restore(CgroupPropEntry *entry, char *path, size_t path_len)
@@ -1289,25 +1307,6 @@ static void add_freezer_state_for_restore(CgroupPropEntry *entry, char *path, si
freezer_path[path_len] = 0;
}
-static int next_device_entry(char *buf)
-{
- char *pos = buf;
-
- while (1) {
- if (*pos == '\n') {
- *pos = '\0';
- pos++;
- break;
- } else if (*pos == '\0') {
- break;
- }
-
- pos++;
- }
-
- return pos - buf;
-}
-
static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **ents,
unsigned int n_ents)
{
@@ -1336,7 +1335,7 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
if (is_special_property(e->properties[j]->name))
continue;
- if (restore_cgroup_prop(e->properties[j], path, off2) < 0) {
+ if (restore_cgroup_prop(e->properties[j], path, off2, false) < 0) {
return -1;
}
@@ -1385,14 +1384,13 @@ static int restore_devices_list(char *paux, size_t off, CgroupPropEntry *pr)
{
CgroupPropEntry dev_allow = *pr;
CgroupPropEntry dev_deny = *pr;
- char *pos;
int ret;
dev_allow.name = "devices.allow";
dev_deny.name = "devices.deny";
dev_deny.value = "a";
- ret = restore_cgroup_prop(&dev_deny, paux, off);
+ ret = restore_cgroup_prop(&dev_deny, paux, off, false);
/*
* An emptry string here means nothing is allowed,
@@ -1405,18 +1403,7 @@ static int restore_devices_list(char *paux, size_t off, CgroupPropEntry *pr)
if (ret < 0)
return -1;
- pos = dev_allow.value;
- while (*pos) {
- int offset = next_device_entry(pos);
-
- dev_allow.value = pos;
- ret = restore_cgroup_prop(&dev_allow, paux, off);
- if (ret < 0)
- return -1;
- pos += offset;
- }
-
- return 0;
+ return restore_cgroup_prop(&dev_allow, paux, off, true);
}
static int restore_special_property(char *paux, size_t off, CgroupPropEntry *pr)
@@ -1442,7 +1429,7 @@ static int restore_special_property(char *paux, size_t off, CgroupPropEntry *pr)
return restore_devices_list(paux, off, pr);
}
- return restore_cgroup_prop(pr, paux, off);
+ return restore_cgroup_prop(pr, paux, off, false);
}
static int restore_special_props(char *paux, size_t off, CgroupDirEntry *e)
--
2.13.3
More information about the CRIU
mailing list