Commit 610e1536 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

cgroup: Handle multiline properties in restore_cgroup_prop()

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: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 831d155c
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment