]> git.pld-linux.org Git - packages/libcgroup.git/blob - libcgroup-0.41-api.c-support-for-setting-multiline-values-in-contro.patch
fba6b9b660606c033120bfedee881303636a4a02
[packages/libcgroup.git] / libcgroup-0.41-api.c-support-for-setting-multiline-values-in-contro.patch
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
5
6 As of now, libcgroup does not support multiline values setting from configuration files. i.e. values in a form:
7
8 net_prio.ifpriomap="lo 7
9 eth0 66
10 eth1 5
11 eth2 4
12 eth3 3";
13
14 Thus, setting of more network interfaces can not be done from configuration file. Or
15
16 devices.allow="a *:* w
17 c 8:* r";
18
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
25
26 This patch allows setting of multiline variables.
27
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
33 multiline values.
34
35 Tested on virtual machine with fedora and rhel with network interface lo, eth0-eth3. Configuration file:
36
37 # cat /etc/cgconfig.conf
38 group testGroup {
39         net_prio {
40                 net_prio.ifpriomap="lo 7
41 eth0    66
42 eth1 5
43 eth2 4
44 eth3 3";
45         }
46 }
47
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
52
53 Changelog:
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)
57
58 Signed-off-by: Jan Chaloupka <jchaloup@redhat.com>
59 ---
60  src/api.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------
61  1 file changed, 44 insertions(+), 6 deletions(-)
62
63 diff --git a/src/api.c b/src/api.c
64 index 5751b8f..d6c9d3a 100644
65 --- a/src/api.c
66 +++ b/src/api.c
67 @@ -1495,13 +1495,18 @@ static int cg_create_control_group(const char *path)
68   */
69  static int cg_set_control_value(char *path, const char *val)
70  {
71 -       FILE *control_file = NULL;
72 +       int ctl_file;
73 +       char *str_val;
74 +       char *str_val_start;
75 +       char *pos;
76 +       size_t len;
77 +
78         if (!cg_test_mounted_fs())
79                 return ECGROUPNOTMOUNTED;
80  
81 -       control_file = fopen(path, "r+e");
82 +       ctl_file = open(path, O_RDWR | O_CLOEXEC);
83  
84 -       if (!control_file) {
85 +       if (ctl_file == -1) {
86                 if (errno == EPERM) {
87                         /*
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)
90                          */
91                         char *path_dir_end;
92                         char *tasks_path;
93 +                       FILE *control_file;
94  
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;
99         }
100  
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) {
106                 last_errno = errno;
107 -               fclose(control_file);
108 +               close(ctl_file);
109                 return ECGOTHER;
110         }
111 -       if (fclose(control_file) < 0) {
112 +
113 +       str_val_start = str_val;
114 +       pos = str_val;
115 +
116 +       do {
117 +               str_val = pos;
118 +               pos = strchr(str_val, '\n');
119 +
120 +               if (pos) {
121 +                       *pos = '\0';
122 +                       ++pos;
123 +               }
124 +
125 +               len = strlen(str_val);
126 +               if (len > 0) {
127 +                       if (write(ctl_file, str_val, len) == -1) {
128 +                               last_errno = errno;
129 +                               free(str_val_start);
130 +                               close(ctl_file);
131 +                               return ECGOTHER;
132 +                       }
133 +               } else
134 +                       cgroup_warn("Warning: skipping empty line for %s\n",
135 +                               path);
136 +       } while(pos);
137 +
138 +       if (close(ctl_file)) {
139                 last_errno = errno;
140 +               free(str_val_start);
141                 return ECGOTHER;
142         }
143 +
144 +       free(str_val_start);
145         return 0;
146  }
147  
148 -- 
149 1.9.3
150
This page took 0.071112 seconds and 2 git commands to generate.