As of now, libcgroup does not support multiline values setting from 
configuration files. i.e. values in a form:

net_prio.ifpriomap="lo 7
eth0 66
eth1 5
eth2 4
eth3 3";

Thus, setting of more network interfaces can not be done from configuration 
file. Or

devices.allow="a *:* w
c 8:* r";

thus setting list of allow devices can not be set as well. The only way is to 
set it from userspace, e.g.:
# echo "lo 7" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
# echo "eth 0" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
# echo "eth 1" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
# echo "eth 2" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap
# echo "eth 3" > /sys/fs/cgroup/net_prio/testGroup/net_prio.ifpriomap

This patch allows setting of multiline variables.

How this support works:
Multiline value is broken in lines and each line is set by write (man 2 write) 
syscall (without bufferring).
This implies change of fopen with open, fclose with close.
There is no control on multiline value, thus "eth0\n  \t\n" can be set. 
However, setting
of "  \t" will fail as write command returns -1. Thus administrator has to set 
correct
multiline values.

Tested on virtual machine with fedora and rhel with network interface lo, 
eth0-eth3. Configuration file:

# cat /etc/cgconfig.conf
group testGroup {
        net_prio {
                net_prio.ifpriomap="lo 7
eth0    66
eth1 5
eth2 4
eth3 3";
        }
}

net_prio has to be created before:
# modprobe netprio_cgroup
# mkdir /sys/fs/cgroup/net_prio
# mount -t cgroup -onet_prio none /sys/fs/cgroup/net_prio

Changelog:
        test of success of strdup call
        free str_val before return (str_val is changing in while cycle,
                thus str_start_val points to the start of str_val before while)

Signed-off-by: Jan Chaloupka <jchal...@redhat.com>
---
 src/api.c |   50 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/src/api.c b/src/api.c
index 5751b8f..d6c9d3a 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1495,13 +1495,18 @@ static int cg_create_control_group(const char *path)
  */
 static int cg_set_control_value(char *path, const char *val)
 {
-       FILE *control_file = NULL;
+       int ctl_file;
+       char *str_val;
+       char *str_val_start;
+       char *pos;
+       size_t len;
+
        if (!cg_test_mounted_fs())
                return ECGROUPNOTMOUNTED;
 
-       control_file = fopen(path, "r+e");
+       ctl_file = open(path, O_RDWR | O_CLOEXEC);
 
-       if (!control_file) {
+       if (ctl_file == -1) {
                if (errno == EPERM) {
                        /*
                         * We need to set the correct error value, does the
@@ -1512,6 +1517,7 @@ static int cg_set_control_value(char *path, const char 
*val)
                         */
                        char *path_dir_end;
                        char *tasks_path;
+                       FILE *control_file;
 
                        path_dir_end = strrchr(path, '/');
                        if (path_dir_end == NULL)
@@ -1543,15 +1549,47 @@ static int cg_set_control_value(char *path, const char 
*val)
                return ECGROUPVALUENOTEXIST;
        }
 
-       if (fprintf(control_file, "%s", val) < 0) {
+       /* Split the multiline value into lines. */
+       /* One line is a special case of multiline value. */
+       str_val = strdup(val);
+       if (str_val == NULL) {
                last_errno = errno;
-               fclose(control_file);
+               close(ctl_file);
                return ECGOTHER;
        }
-       if (fclose(control_file) < 0) {
+
+       str_val_start = str_val;
+       pos = str_val;
+
+       do {
+               str_val = pos;
+               pos = strchr(str_val, '\n');
+
+               if (pos) {
+                       *pos = '\0';
+                       ++pos;
+               }
+
+               len = strlen(str_val);
+               if (len > 0) {
+                       if (write(ctl_file, str_val, len) == -1) {
+                               last_errno = errno;
+                               free(str_val_start);
+                               close(ctl_file);
+                               return ECGOTHER;
+                       }
+               } else
+                       cgroup_warn("Warning: skipping empty line for %s\n",
+                               path);
+       } while(pos);
+
+       if (close(ctl_file)) {
                last_errno = errno;
+               free(str_val_start);
                return ECGOTHER;
        }
+
+       free(str_val_start);
        return 0;
 }
 


------------------------------------------------------------------------------
Slashdot TV.  Video for Nerds.  Stuff that Matters.
http://pubads.g.doubleclick.net/gampad/clk?id=160591471&iu=/4140/ostg.clktrk
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to