]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Add cgroup support, the configuration file should be specified with the format:
authordlezcano <dlezcano>
Mon, 6 Oct 2008 18:47:19 +0000 (18:47 +0000)
committerdlezcano <dlezcano>
Mon, 6 Oct 2008 18:47:19 +0000 (18:47 +0000)
lxc.cgroup.xxx = yyy
where xxx is a cgroup subsystem (eg. cpu.shares) and the yyy is the value to
be set.

src/lxc/Makefile.am
src/lxc/cgroup.c [new file with mode: 0644]
src/lxc/cgroup.h [new file with mode: 0644]
src/lxc/execute.c
src/lxc/lxc.h
src/lxc/lxc_cgroup.c
src/lxc/lxc_cgroup.h
src/lxc/lxc_conf.c
src/lxc/lxc_conf.h
src/lxc/lxc_config.c
src/lxc/monitor.c

index ea85fb204fbbedfa16de6750624227638cec2334..2acd29ab81c0350fa1abf6c5c5a762e0cec49cf5 100644 (file)
@@ -25,7 +25,7 @@ liblxc_la_SOURCES = \
        checkpoint.c \
        restart.c \
        version.c \
-       lxc_cgroup.c lxc_cgroup.h \
+       cgroup.c cgroup.h \
        lxc.h \
        lxc_utils.h \
        lxc_lock.c lxc_lock.h \
@@ -57,8 +57,8 @@ bin_PROGRAMS = \
        lxc-kill \
        lxc-freeze \
        lxc-info \
+       lxc-cgroup \
        lxc-unfreeze \
-       lxc-priority \
        lxc-checkpoint \
        lxc-restart \
        lxc-version
@@ -99,8 +99,8 @@ lxc_freeze_LDADD = liblxc.la
 lxc_unfreeze_SOURCES = lxc_unfreeze.c
 lxc_unfreeze_LDADD = liblxc.la
 
-lxc_priority_SOURCES = lxc_priority.c
-lxc_priority_LDADD = liblxc.la
+lxc_cgroup_SOURCES = lxc_cgroup.c
+lxc_cgroup_LDADD = liblxc.la
 
 lxc_checkpoint_SOURCES = lxc_checkpoint.c
 lxc_checkpoint_LDADD = liblxc.la
diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
new file mode 100644 (file)
index 0000000..ddd74b9
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+#include <stdlib.h>
+#include <errno.h>
+#include <mntent.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/inotify.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include <lxc/lxc.h>
+
+#define MTAB "/etc/mtab"
+
+static int get_cgroup_mount(const char *mtab, char *mnt)
+{
+        struct mntent *mntent;
+        FILE *file = NULL;
+        int err = -1;
+
+        file = setmntent(mtab, "r");
+        if (!file) {
+                lxc_log_syserror("failed to open %s", mtab);
+                goto out;
+        }
+
+        while ((mntent = getmntent(file))) {
+                if (strcmp(mntent->mnt_type, "cgroup"))
+                        continue;
+                strcpy(mnt, mntent->mnt_dir);
+                err = 0;
+                break;
+        };
+
+        fclose(file);
+out:
+        return err;
+}
+
+int lxc_link_nsgroup(const char *name, pid_t pid)
+{
+       char lxc[MAXPATHLEN];
+       char nsgroup[MAXPATHLEN];
+       char cgroup[MAXPATHLEN];
+       int ret;
+
+       if (get_cgroup_mount(MTAB, cgroup)) {
+               lxc_log_info("cgroup is not mounted");
+               return -1;
+       }
+
+       snprintf(lxc, MAXPATHLEN, LXCPATH "/%s/nsgroup", name);
+       snprintf(nsgroup, MAXPATHLEN, "%s/%d", cgroup, pid);
+
+       unlink(lxc);
+       ret = symlink(nsgroup, lxc);
+       if (ret)
+               lxc_log_syserror("failed to create symlink %s->%s",
+                                nsgroup, lxc);
+      return ret;
+}
+
+int lxc_unlink_nsgroup(const char *name)
+{
+       char nsgroup[MAXPATHLEN];
+
+       snprintf(nsgroup, MAXPATHLEN, LXCPATH "/%s/nsgroup", name);
+       return unlink(nsgroup);
+}
+
+int lxc_cgroup_copy(const char *name, const char *subsystem)
+{
+       char destination[MAXPATHLEN];
+       char source[MAXPATHLEN];
+       char buffer[1024];
+       int nbbytes, fd_source, fd_destination, ret = -1;
+
+       snprintf(source, MAXPATHLEN, LXCPATH "/%s/cgroup/%s", name, subsystem);
+
+       if (access(source, F_OK))
+               return 0;
+
+       fd_source = open(source, O_RDONLY);
+       if (fd_source < 0) {
+               lxc_log_syserror("failed to open '%s'", source);
+               return -1;
+       }
+
+       snprintf(destination, MAXPATHLEN, LXCPATH "/%s/nsgroup/%s", name, subsystem);
+
+       fd_destination = open(destination, O_WRONLY);
+       if (fd_destination < 0) {
+               lxc_log_syserror("failed to open '%s'", destination);
+               goto out;
+       }
+
+       nbbytes = read(fd_source, buffer, sizeof(buffer));
+       if (nbbytes < 0) {
+               lxc_log_syserror("failed to read '%s'", source);
+               goto out;
+       }
+       
+       if (write(fd_destination, buffer, nbbytes) < 0) {
+               lxc_log_syserror("failed to write to '%s'", destination);
+               goto out;
+       }
+
+       ret = 0;
+out:
+       close(fd_source);
+       close(fd_destination);
+       return ret;
+}
+
+int lxc_cgroup_set(const char *name, const char *subsystem, const char *value)
+{
+       int fd, ret = -1;;
+       char path[MAXPATHLEN];
+
+        snprintf(path, MAXPATHLEN, LXCPATH "/%s/nsgroup/%s", name, subsystem);
+
+       fd = open(path, O_WRONLY);
+       if (fd < 0)
+               return -1;
+
+       if (write(fd, value, strlen(value)) < 0)
+               goto out;
+       
+       ret = 0;
+out:
+       close(fd);
+       return ret;
+}
+
+int lxc_cgroup_get(const char *name, const char *subsystem,  
+                  char *value, size_t len)
+{
+       int fd, ret = -1;;
+       char path[MAXPATHLEN];
+
+        snprintf(path, MAXPATHLEN, LXCPATH "/%s/nsgroup/%s", name, subsystem);
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return -1;
+
+       if (read(fd, value, len) < 0)
+               goto out;
+       
+       ret = 0;
+out:
+       close(fd);
+       return ret;
+}
diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
new file mode 100644 (file)
index 0000000..2aeb37b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _cgroup_h
+#define _cgroup_h
+
+#define MAXPRIOLEN 24
+
+int lxc_get_cgroup_mount(const char *mtab, char *mnt);
+int lxc_link_nsgroup(const char *name, pid_t pid);
+int lxc_unlink_nsgroup(const char *name);
+int lxc_cgroup_copy(const char *name, const char *subsystem);
+
+#endif
index 0c0fd54d4f126d46a60ce89184f3dc91befc6788..db4c872474f72aa24377b95525327d054abbfe88 100644 (file)
@@ -172,6 +172,9 @@ int lxc_execute(const char *name, int argc, char *argv[],
                goto err_pipe_read;
        }
 
+       if (lxc_link_nsgroup(name, pid))
+               lxc_log_warning("cgroupfs not found: cgroup disabled");
+
        if (clone_flags & CLONE_NEWNET && conf_create_network(name, pid)) {
                lxc_log_error("failed to create the configured network");
                goto err_create_network;
@@ -213,9 +216,6 @@ int lxc_execute(const char *name, int argc, char *argv[],
                goto err_write;
        }
 
-       if (lxc_link_nsgroup(name, pid))
-               lxc_log_warning("cgroupfs not found: cgroup disabled");
-
        if (lxc_setstate(name, RUNNING)) {
                lxc_log_error("failed to set state to %s", lxc_state2str(RUNNING));
                goto err_state_failed;
@@ -254,7 +254,8 @@ err_state_failed:
 err_child_failed:
 err_pipe_read2:
 err_pipe_write:
-       conf_destroy_network(name);
+       if (clone_flags & CLONE_NEWNET)
+               conf_destroy_network(name);
 err_create_network:
 err_pipe_read:
 err_open:
index 722d8afde7ca6bd89233a2994c1df67467bc3ac9..efe922176d42e667db5cd6b252bf9aa3c5ec30f1 100644 (file)
@@ -38,9 +38,9 @@ extern "C" {
 #include <lxc/lxc_conf.h>
 #include <lxc/lxc_log.h>
 #include <lxc/lxc_lock.h>
-#include <lxc/lxc_cgroup.h>
 #include <lxc/lxc_namespace.h>
 #include <lxc/lxc_utils.h>
+#include <lxc/cgroup.h>
 #include <lxc/monitor.h>
 
 #define LXCPATH "/var/lxc"
@@ -179,76 +179,26 @@ extern lxc_state_t lxc_state(const char *name);
 extern int lxc_kill(const char *name, int signum);
 
 /*
- * Change the priority of the container
- * @name     : the name of the container
- * @priority : an integer representing the desired priority
+ * Set a specified value for a specified subsystem. The specified
+ * subsystem must be fully specified, eg. "cpu.shares"
+ * @name      : the name of the container
+ * @subsystem : the subsystem
+ * @value     : the value to be set
  * Returns 0 on success, < 0 otherwise
  */
-extern int lxc_cgroup_set_priority(const char *name, int priority);
+extern int lxc_cgroup_set(const char *name, const char *subsystem, const char *value);
 
 /*
- * Retrieve the priority of the container
- * @name     : the name of the container
- * @priority : a pointer to an int where the priority will be stored
+ * Get a specified value for a specified subsystem. The specified
+ * subsystem must be fully specified, eg. "cpu.shares"
+ * @name      : the name of the container
+ * @subsystem : the subsystem
+ * @value     : the value to be set
+ * @len       : the len of the value variable
  * Returns 0 on success, < 0 otherwise
  */
-extern int lxc_cgroup_get_priority(const char *name, int *priority);
-
-/*
- * Set the maximum memory usable by the container
- * @name   : the name of the container
- * @memmax : the maximum usable memory in bytes
- * Returns 0 on sucess, < 0 otherwise
- */
-extern int lxc_cgroup_set_memory(const char *name, size_t memmax);
-
-/*
- * Get the maximum memory usable by the container
- * @name : the name of the container
- * @memmax : a pointer to a size_t where the value will be stored
- * Returns 0 on sucess, < 0 otherwise
- */
-extern int lxc_cgroup_get_memory(const char *name, size_t *memmax);
-
-/*
- * Get the memory statistics of the container
- * @name    : the name of the container
- * @memstat : a pointer to a structure defining the memory statistic
- * Returns 0 on sucess, < 0 otherwise
- */
-extern int lxc_cgroup_get_memstat(const char *name, 
-                                 struct lxc_mem_stat *memstat);
-
-/*
- * Set the cpuset for the container
- * @name    : the name of the container
- * @cpumask : a bitmask representing the cpu maps
- * @len     : the len of the bitmask
- * @shared  : a boolean specifying if the cpu could be shared with
- *            processes not belonging to the container
- * Returns 0 on sucess, < 0 otherwise
- */
-extern int lxc_cgroup_set_cpuset(const char *name, long *cpumask, 
-                                int len, int shared);
-
-/*
- * Get the actual cpuset for the container
- * @cpumask : a bitmask representing the cpu maps
- * @len     : the len of the bitmask
- * @shared  : a boolean specifying if the cpu is shared with
- *            processes not belonging to the container
- * Returns 0 on sucess, < 0 otherwise
- */
-extern int lxc_cgroup_get_cpuset(const char *name, long *cpumask, 
-                                int len, int *shared);
-
-/*
- * Get the cpu usage of the container
- * @name  : the name of the container
- * @usage : a value to be filled with the current container cpu usage
- * Returns 0 on sucess, < 0 otherwise
- */
-extern int lxc_cgroup_get_cpu_usage(const char *name, long long *usage);
+extern int lxc_cgroup_get(const char *name, const char *subsystem, 
+                         char *value, size_t len);
 
 /*
  * Checkpoint a container previously frozen
index e89acce26206e5b92f815da21d9b50a38c86c446..8a91566039aaa1dc3f76fa6b6743354b97582767 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define _GNU_SOURCE
-#include <stdio.h>
-#undef _GNU_SOURCE
-#include <stdlib.h>
-#include <errno.h>
-#include <mntent.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/inotify.h>
-#include <netinet/in.h>
-#include <net/if.h>
 
+#include <stdio.h>
 #include <lxc/lxc.h>
 
-#define MAXPRIOLEN 24
-#define MTAB "/etc/mtab"
-
-static int get_cgroup_mount(const char *mtab, char *mnt)
-{
-        struct mntent *mntent;
-        FILE *file = NULL;
-        int err = -1;
-
-        file = setmntent(mtab, "r");
-        if (!file) {
-                lxc_log_syserror("failed to open %s", mtab);
-                goto out;
-        }
-
-        while ((mntent = getmntent(file))) {
-                if (strcmp(mntent->mnt_type, "cgroup"))
-                        continue;
-                strcpy(mnt, mntent->mnt_dir);
-                err = 0;
-                break;
-        };
-
-        fclose(file);
-out:
-        return err;
-}
-
-int lxc_link_nsgroup(const char *name, pid_t pid)
-{
-       char lxc[MAXPATHLEN];
-       char nsgroup[MAXPATHLEN];
-       char cgroup[MAXPATHLEN];
-       int ret;
-
-       if (get_cgroup_mount(MTAB, cgroup)) {
-               lxc_log_info("cgroup is not mounted");
-               return -1;
-       }
-
-       snprintf(lxc, MAXPATHLEN, LXCPATH "/%s/nsgroup", name);
-       snprintf(nsgroup, MAXPATHLEN, "%s/%d", cgroup, pid);
-
-       unlink(lxc);
-       ret = symlink(nsgroup, lxc);
-       if (ret)
-               lxc_log_syserror("failed to create symlink %s->%s",
-                                nsgroup, lxc);
-      return ret;
-}
-
-int lxc_unlink_nsgroup(const char *name)
-{
-       char nsgroup[MAXPATHLEN];
-
-       snprintf(nsgroup, MAXPATHLEN, LXCPATH "/%s/nsgroup", name);
-       return unlink(nsgroup);
-}
-
-int lxc_cgroup_set_priority(const char *name, int priority)
-{
-       int fd;
-       char path[MAXPATHLEN], *prio = NULL;
-
-        snprintf(path, MAXPATHLEN, 
-                LXCPATH "/%s/nsgroup/cpu.shares", name);
-
-       fd = open(path, O_WRONLY);
-       if (fd < 0) {
-               lxc_log_syserror("failed to open '%s'", path);
-               return -1;
-       }
-
-       if (!asprintf(&prio, "%d", priority)) {
-               lxc_log_syserror("not enough memory");
-               goto out;
-       }
-
-       if (write(fd, prio, strlen(prio) + 1) < 0) {
-               lxc_log_syserror("failed to write to '%s'", path);
-               close(fd);
-               goto out;
-       }
-
-       lxc_monitor_send_priority(name, priority);
-
-       close(fd);
-out:
-       free(prio);
-       return 0;
-}
-
-int lxc_cgroup_get_priority(const char *name, int *priority)
-{
-       int fd, ret = -1;
-       char path[MAXPATHLEN], prio[MAXPRIOLEN];
-
-        snprintf(path, MAXPATHLEN, LXCPATH "/%s/nsgroup/cpu.shares", name);
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0) {
-               lxc_log_syserror("failed to open '%s'", path);
-               return -1;
-       }
-
-       if (read(fd, prio, MAXPRIOLEN) < 0) {
-               lxc_log_syserror("failed to read from '%s'", path);
-               goto out;
-       }
-
-       *priority = atoi(prio);
-
-       ret = 0;
-out:
-       close(fd);
-       return ret;
-}
-
-int lxc_set_memory(const char *name, size_t memmax)
-{
-       return 0;
-}
-
-int lxc_get_memory(const char *name, size_t *memmax)
-{
-       return 0;
-}
-
-int lxc_get_memstat(const char *name, struct lxc_mem_stat *memstat)
-{
-       return 0;
-}
-
-int lxc_set_cpuset(const char *name, long *cpumask, int len, int shared)
-{
-       return 0;
-}
-
-int lxc_get_cpuset(const char *name, long *cpumask, int len, int *shared)
-{
-       return 0;
-}
-
-int lxc_get_cpu_usage(const char *name, long long *usage)
+int main(int argc, char *argv[])
 {
        return 0;
 }
index 8060cdf437a45b3298db9c0262c54b9135def71a..0785d741d0c383d47c10e02eab578638905891c1 100644 (file)
 #ifndef _cgroup_h
 #define _cgroup_h
 
+#define MAXPRIOLEN 24
+
+#define CGROUP_CPU_SHARES "cpu.shares"
+#define CGROUP_CPUACCT_USAGE "cpuacct.usage"
+#define CGROUP_CPUSET_CPUS "cpuset.cpus"
+#define CGROUP_CPUSET_CPU_EXCLUSIVE "cpuset.cpu_exclusive"
+#define CGROUP_CPUSET_SCHED_LOAD_BALANCE "cpuset.sched_load_balance"
+#define CGROUP_CPUSET_SCHED_RELAX_DOMAIN_LEVEL "cpuset.sched_relax_domain_level"
+#define CGROUP_MEMORY_LIMIT_IN_BYTES "memory.limit_in_bytes"
+
+struct lxc_cgroup_memory_info {
+       unsigned long cache;
+       unsigned long rss;
+       unsigned long page_in;
+       unsigned long page_out;
+       unsigned long active;
+       unsigned long inactive;
+       unsigned long failcnt;
+       unsigned long force_empty;
+       unsigned long limit_in_bytes;
+       unsigned long max_usage_in_bytes;
+       unsigned long usage_in_bytes;
+};
+
+struct lxc_cgroup_cpuacct_info {
+       unsigned long usage;
+};
+
+struct lxc_cgroup_cpu_info {
+       unsigned long rt_period_us;
+       unsigned long rt_runtimer_us;
+       unsigned long shares;
+};
+
+struct lxc_cgroup_cpuset_info {
+       int mem_exclusive;
+       int mem_hardball;
+       int memory_migrate;
+       int memory_pressure;
+       int memory_pressure_enabled;
+       int memory_spread_page;
+       int memory_spread_slab;
+};
+
+struct lxc_cgroup_info {
+       struct lxc_cgroup_memory_info memory;
+       struct lxc_cgroup_cpuacct_info cpuacct;
+       struct lxc_cgroup_cpu_info cpu;
+       struct lxc_cgroup_cpuset_info cpuset;
+};
+
 int lxc_get_cgroup_mount(const char *mtab, char *mnt);
 int lxc_link_nsgroup(const char *name, pid_t pid);
 int lxc_unlink_nsgroup(const char *name);
+int lxc_cgroup_copy(const char *name, const char *subsystem);
 
 #endif
index 69e655178dc8c283530a757d0f38aa9a7b4df8e9..9651b509f416dd04289923065cb8ec1a9512a767 100644 (file)
@@ -394,8 +394,28 @@ out:
        return err;
 }
 
-static int configure_cgroup(const char *name, struct lxc_cgroup *cgroup)
+static int configure_cgroup(const char *name, struct lxc_list *cgroup)
 {
+       char path[MAXPATHLEN];
+       struct lxc_list *iterator;
+       struct lxc_cgroup *cg;
+       int ret = -1;
+
+       if (lxc_list_empty(cgroup))
+               return 0;
+
+       snprintf(path, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
+
+       if (mkdir(path, 0755)) {
+               lxc_log_syserror("failed to create '%s' directory", path);
+               return -1;
+       }
+
+       lxc_list_for_each(iterator, cgroup) {
+               cg = iterator->elem;
+               write_info(path, cg->subsystem, cg->value);
+       }
+       
        return 0;
 }
 
@@ -536,12 +556,20 @@ static int unconfigure_network(const char *name)
        return 0;
 }
 
+static int unconfigure_cgroup_cb(const char *name, const char *dirname, 
+                                 const char *file, void *data)
+{
+       return delete_info(dirname, file);
+}
+
 static int unconfigure_cgroup(const char *name)
 {
-       char path[MAXPATHLEN];
+       char dirname[MAXPATHLEN];
 
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-       delete_info(path, "nsgroup");
+       lxc_unlink_nsgroup(name);
+       snprintf(dirname, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
+       dir_for_each(name, dirname, unconfigure_cgroup_cb, NULL);
+       rmdir(dirname);
 
        return 0;
 }
@@ -622,6 +650,21 @@ static int setup_rootfs(const char *name)
        return 0;
 }
 
+static int setup_cgroup_cb(const char *name, const char *dirname, 
+                          const char *file, void *data)
+{
+       if (lxc_cgroup_copy(name, file))
+               lxc_log_warning("failed to setup '%s'");
+       return 0;
+}
+
+static int setup_cgroup(const char *name)
+{
+       char dirname[MAXPATHLEN];
+       snprintf(dirname, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
+       return dir_for_each(name, dirname, setup_cgroup_cb, NULL);
+}
+
 static int setup_mount(const char *name)
 {
        char path[MAXPATHLEN];
@@ -900,13 +943,13 @@ int lxc_configure(const char *name, struct lxc_conf *conf)
                return -1;
        }
 
-       if (configure_network(name, &conf->networks)) {
-               lxc_log_error("failed to configure the network");
+       if (configure_cgroup(name, &conf->cgroup)) {
+               lxc_log_error("failed to configure the control group");
                return -1;
        }
 
-       if (conf->cgroup && configure_cgroup(name, conf->cgroup)) {
-               lxc_log_error("failed to configure the control group");
+       if (configure_network(name, &conf->networks)) {
+               lxc_log_error("failed to configure the network");
                return -1;
        }
 
@@ -931,7 +974,7 @@ int lxc_unconfigure(const char *name)
        if (conf_has_network(name) && unconfigure_network(name))
                lxc_log_error("failed to cleanup the network");
 
-       if (unconfigure_cgroup(name))
+       if (conf_has_cgroup(name) && unconfigure_cgroup(name))
                lxc_log_error("failed to cleanup cgroup");
 
        if (conf_has_rootfs(name) && unconfigure_rootfs(name))
@@ -1252,6 +1295,11 @@ int lxc_setup(const char *name)
                return -1;
        }
 
+       if (conf_has_cgroup(name) && setup_cgroup(name)) {
+               lxc_log_error("failed to setup the cgroups for '%s'", name);
+               return -1;
+       }
+
        if (conf_has_rootfs(name) && setup_rootfs(name)) {
                lxc_log_error("failed to set rootfs for '%s'", name);
                return -1;
index 84feaf50b660f35bd07e92430a04b23881a68fb5..b6e64322811af440c2ab382520815852d7a57239 100644 (file)
@@ -97,10 +97,14 @@ struct lxc_network {
 };
 
 /*
- * Defines a structure to configure the control data and path
+ * Defines a generic struct to configure the control group.
+ * It is up to the programmer to specify the right subsystem.
+ * @subsystem : the targetted subsystem
+ * @value     : the value to set
  */
 struct lxc_cgroup {
-       ;
+       char *subsystem;
+       char *value;
 };
 
 /*
@@ -114,7 +118,7 @@ struct lxc_conf {
        char *rootfs;
        char *fstab;
        struct utsname *utsname;
-       struct lxc_cgroup *cgroup;
+       struct lxc_list cgroup;
        struct lxc_list networks;
 };
 
@@ -143,5 +147,6 @@ extern int conf_has(const char *name, const char *info);
 #define conf_has_rootfs(__name)  conf_has(__name, "rootfs")
 #define conf_has_utsname(__name) conf_has(__name, "utsname")
 #define conf_has_network(__name) conf_has(__name, "network")
+#define conf_has_cgroup(__name) conf_has(__name, "cgroup")
 
 #endif
index 00851912b133e9be78faa4a5ac5571749b5fc14d..d3744a7f77958d511397951fc37f00e1790db309 100644 (file)
 #include <lxc/lxc.h>
 
 typedef int (*file_cb)(char* buffer, void *data);
-typedef int (*config_cb)(char *value, struct lxc_conf *lxc_conf);
-
-static int config_mount(char *, struct lxc_conf *);
-static int config_rootfs(char *, struct lxc_conf *);
-static int config_utsname(char *, struct lxc_conf *);
-static int config_network_type(char *, struct lxc_conf *);
-static int config_network_flags(char *, struct lxc_conf *);
-static int config_network_link(char *, struct lxc_conf *);
-static int config_network_name(char *, struct lxc_conf *);
-static int config_network_hwaddr(char *, struct lxc_conf *);
-static int config_network_ipv4(char *, struct lxc_conf *);
-static int config_network_ipv6(char *, struct lxc_conf *);
+typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
+
+static int config_cgroup(const char *, char *, struct lxc_conf *);
+static int config_mount(const char *, char *, struct lxc_conf *);
+static int config_rootfs(const char *, char *, struct lxc_conf *);
+static int config_utsname(const char *, char *, struct lxc_conf *);
+static int config_network_type(const char *, char *, struct lxc_conf *);
+static int config_network_flags(const char *, char *, struct lxc_conf *);
+static int config_network_link(const char *, char *, struct lxc_conf *);
+static int config_network_name(const char *, char *, struct lxc_conf *);
+static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
+static int config_network_ipv4(const char *, char *, struct lxc_conf *);
+static int config_network_ipv6(const char *, char *, struct lxc_conf *);
 
 struct config {
        char *name;
-       int type;
        config_cb cb;
 };
 
-enum { MOUNT, ROOTFS, UTSNAME, NETTYPE, NETFLAGS, NETLINK, 
-       NETNAME, NETHWADDR, NETIPV4, NETIPV6 };
-
-struct config config[] = {
-       { "lxc.mount",             MOUNT,     config_mount           },
-       { "lxc.rootfs",            ROOTFS,    config_rootfs          },
-       { "lxc.utsname",           UTSNAME,   config_utsname         },
-       { "lxc.network.type",      NETTYPE,   config_network_type    },
-       { "lxc.network.flags",     NETFLAGS,  config_network_flags   },
-       { "lxc.network.link",      NETLINK,   config_network_link    },
-       { "lxc.network.name",      NETNAME,   config_network_name    },
-       { "lxc.network.hwaddr",    NETHWADDR, config_network_hwaddr  },
-       { "lxc.network.ipv4",      NETIPV4,   config_network_ipv4    },
-       { "lxc.network.ipv6",      NETIPV6,   config_network_ipv6    },
+static struct config config[] = {
+
+       { "lxc.cgroup",         config_cgroup         },
+       { "lxc.mount",          config_mount          },
+       { "lxc.rootfs",         config_rootfs         },
+       { "lxc.utsname",        config_utsname        },
+       { "lxc.network.type",   config_network_type   },
+       { "lxc.network.flags",  config_network_flags  },
+       { "lxc.network.link",   config_network_link   },
+       { "lxc.network.name",   config_network_name   },
+       { "lxc.network.hwaddr", config_network_hwaddr },
+       { "lxc.network.ipv4",   config_network_ipv4   },
+       { "lxc.network.ipv6",   config_network_ipv6   },
 };
 
 static const size_t config_size = sizeof(config)/sizeof(struct config);
@@ -122,7 +121,7 @@ static int char_right_gc(char *buffer, size_t len)
        return 0;
 }
 
-static int config_network_type(char *value, struct lxc_conf *lxc_conf)
+static int config_network_type(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -185,7 +184,7 @@ static int config_network_type(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_network_flags(char *value, struct lxc_conf *lxc_conf)
+static int config_network_flags(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -207,7 +206,7 @@ static int config_network_flags(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_network_link(char *value, struct lxc_conf *lxc_conf)
+static int config_network_link(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -234,7 +233,7 @@ static int config_network_link(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_network_name(char *value, struct lxc_conf *lxc_conf)
+static int config_network_name(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -261,7 +260,7 @@ static int config_network_name(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_network_hwaddr(char *value, struct lxc_conf *lxc_conf)
+static int config_network_hwaddr(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -283,7 +282,7 @@ static int config_network_hwaddr(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_network_ipv4(char *value, struct lxc_conf *lxc_conf)
+static int config_network_ipv4(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -362,7 +361,7 @@ static int config_network_ipv4(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_network_ipv6(char *value, struct lxc_conf *lxc_conf)
+static int config_network_ipv6(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct lxc_list *networks = &lxc_conf->networks;
        struct lxc_network *network;
@@ -418,7 +417,46 @@ static int config_network_ipv6(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_mount(char *value, struct lxc_conf *lxc_conf)
+static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
+{
+       char *token = "lxc.cgroup.";
+       char *subkey;
+       struct lxc_list *cglist;
+       struct lxc_cgroup *cgelem;
+
+       subkey = strstr(key, token);
+
+       if (!subkey)
+               return -1;
+
+       if (!strlen(subkey))
+               return -1;
+
+       if (strlen(subkey) == strlen(token))
+               return -1;
+       
+       subkey += strlen(token);
+
+       cglist = malloc(sizeof(*cglist));
+       if (!cglist)
+               return -1;
+
+       cgelem = malloc(sizeof(*cgelem));
+       if (!cgelem) {
+               free(cglist);
+               return -1;
+       }
+
+       cgelem->subsystem = strdup(subkey);
+       cgelem->value = strdup(value);
+       cglist->elem = cgelem;
+
+       lxc_list_add(&lxc_conf->cgroup, cglist);
+
+       return 0;
+}
+
+static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        if (strlen(value) >= MAXPATHLEN) {
                lxc_log_error("%s path is too long", value);
@@ -434,7 +472,7 @@ static int config_mount(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_rootfs(char *value, struct lxc_conf *lxc_conf)
+static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        if (strlen(value) >= MAXPATHLEN) {
                lxc_log_error("%s path is too long", value);
@@ -450,7 +488,7 @@ static int config_rootfs(char *value, struct lxc_conf *lxc_conf)
        return 0;
 }
 
-static int config_utsname(char *value, struct lxc_conf *lxc_conf)
+static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
 {
        struct utsname *utsname;
 
@@ -507,7 +545,7 @@ static int parse_line(char *buffer, void *data)
                return -1;
        }
 
-       return config->cb(value, data);
+       return config->cb(key, value, data);
 }
 
 static int file_for_each_line(const char *file, file_cb callback, void *data)
@@ -542,7 +580,7 @@ int lxc_config_init(struct lxc_conf *conf)
        conf->rootfs = NULL;
        conf->fstab = NULL;
        conf->utsname = NULL;
-       conf->cgroup = NULL;
+       lxc_list_init(&conf->cgroup);
        lxc_list_init(&conf->networks);
        return 0;
 }
index 2cd4d3514779020ff25df0caa8c2e48000e28688..8175baba483b58e31eadbd0948b0d4ebee0179b2 100644 (file)
@@ -123,13 +123,6 @@ static void lxc_monitor_send(const char *name, struct lxc_msg *msg)
        close(fd);
 }
 
-void lxc_monitor_send_priority(const char *name, int priority)
-{
-       struct lxc_msg msg = { .type = lxc_msg_priority,
-                              .value = priority };
-       lxc_monitor_send(name, &msg);
-}
-
 void lxc_monitor_send_state(const char *name, lxc_state_t state)
 {
        struct lxc_msg msg = { .type = lxc_msg_state,