1 From 691430206f1104b752b0e52386f317e639137788 Mon Sep 17 00:00:00 2001
2 From: Jan Chaloupka <jchaloup@redhat.com>
3 Date: Mon, 15 Sep 2014 13:29:39 +0200
4 Subject: [PATCH] api.c: support for setting multiline values in control files
6 As of now, libcgroup does not support multiline values setting from configuration files. i.e. values in a form:
8 net_prio.ifpriomap="lo 7
14 Thus, setting of more network interfaces can not be done from configuration file. Or
16 devices.allow="a *:* w
19 thus setting list of allow devices can not be set as well. The only way is to set it from userspace, e.g.:
20 # echo "lo 7" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
21 # echo "eth 0" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
22 # echo "eth 1" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
23 # echo "eth 2" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
24 # echo "eth 3" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
26 This patch allows setting of multiline variables.
28 How this support works:
29 Multiline value is broken in lines and each line is set by write (man 2 write) syscall (without bufferring).
30 This implies change of fopen with open, fclose with close.
31 There is no control on multiline value, thus "eth0\n \t\n" can be set. However, setting
32 of " \t" will fail as write command returns -1. Thus administrator has to set correct
35 Tested on virtual machine with fedora and rhel with network interface lo, eth0-eth3. Configuration file:
37 # cat /etc/cgconfig.conf
40 net_prio.ifpriomap="lo 7
48 net_prio has to be created before:
49 # modprobe netprio_cgroup
50 # mkdir /sys/fs/cgroup/net_prio
51 # mount -t cgroup -onet_prio none /sys/fs/cgroup/net_prio
54 test of success of strdup call
55 free str_val before return (str_val is changing in while cycle,
56 thus str_start_val points to the start of str_val before while)
58 Signed-off-by: Jan Chaloupka <jchaloup@redhat.com>
60 src/api.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------
61 1 file changed, 44 insertions(+), 6 deletions(-)
63 diff --git a/src/api.c b/src/api.c
64 index 5751b8f..d6c9d3a 100644
67 @@ -1495,13 +1495,18 @@ static int cg_create_control_group(const char *path)
69 static int cg_set_control_value(char *path, const char *val)
71 - FILE *control_file = NULL;
74 + char *str_val_start;
78 if (!cg_test_mounted_fs())
79 return ECGROUPNOTMOUNTED;
81 - control_file = fopen(path, "r+e");
82 + ctl_file = open(path, O_RDWR | O_CLOEXEC);
84 - if (!control_file) {
85 + if (ctl_file == -1) {
88 * We need to set the correct error value, does the
89 @@ -1512,6 +1517,7 @@ static int cg_set_control_value(char *path, const char *val)
95 path_dir_end = strrchr(path, '/');
96 if (path_dir_end == NULL)
97 @@ -1543,15 +1549,47 @@ static int cg_set_control_value(char *path, const char *val)
98 return ECGROUPVALUENOTEXIST;
101 - if (fprintf(control_file, "%s", val) < 0) {
102 + /* Split the multiline value into lines. */
103 + /* One line is a special case of multiline value. */
104 + str_val = strdup(val);
105 + if (str_val == NULL) {
107 - fclose(control_file);
111 - if (fclose(control_file) < 0) {
113 + str_val_start = str_val;
118 + pos = strchr(str_val, '\n');
125 + len = strlen(str_val);
127 + if (write(ctl_file, str_val, len) == -1) {
128 + last_errno = errno;
129 + free(str_val_start);
134 + cgroup_warn("Warning: skipping empty line for %s\n",
138 + if (close(ctl_file)) {
140 + free(str_val_start);
144 + free(str_val_start);