]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgmanager: implement setting of cgroup limits
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Mon, 20 Jan 2014 15:09:36 +0000 (09:09 -0600)
committerStéphane Graber <stgraber@ubuntu.com>
Mon, 20 Jan 2014 20:14:41 +0000 (15:14 -0500)
Also replace a wrong free of nih-allocated variable with nih_free.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/cgmanager.c
src/lxc/cgroup.c
src/lxc/cgroup.h
src/lxc/start.c

index 97bda2c172ad9389308caff8b095bbec9885bc72..61f7f6ff87d335120ecf5ddd0831d411bcbcc052 100644 (file)
@@ -55,6 +55,7 @@ lxc_log_define(lxc_cgmanager, lxc);
 
 #include <nih-dbus/dbus_connection.h>
 #include <cgmanager-client/cgmanager-client.h>
+#include <nih/alloc.h>
 NihDBusProxy *cgroup_manager = NULL;
 
 extern struct cgroup_ops *active_cg_ops;
@@ -269,13 +270,25 @@ int cgm_get(const char *filename, char *value, size_t len, const char *name, con
        strncpy(value, result, len);
        if (strlen(result) >= len)
                value[len-1] = '\0';
-       free(result);
+       nih_free(result);
        return len;
 }
 
+static int cgm_do_set(const char *controller, const char *file,
+                        const char *cgroup, const char *value)
+{
+       int ret;
+       ret = cgmanager_set_value_sync(NULL, cgroup_manager, controller,
+                                cgroup, file, value);
+       if (ret != 0)
+               ERROR("Error setting cgroup %s limit %s", file, cgroup);
+       return ret;
+}
+
 int cgm_set(const char *filename, const char *value, const char *name, const char *lxcpath)
 {
        char *controller, *key, *cgroup;
+       int ret;
 
        controller = alloca(strlen(filename)+1);
        strcpy(controller, filename);
@@ -291,14 +304,9 @@ int cgm_set(const char *filename, const char *value, const char *name, const cha
                        controller, lxcpath, name);
                return -1;
        }
-       if (cgmanager_set_value_sync(NULL, cgroup_manager, controller, cgroup, filename, value) != 0) {
-               ERROR("Error setting value for %s from cgmanager for cgroup %s (%s:%s)",
-                       filename, cgroup, lxcpath, name);
-               free(cgroup);
-               return -1;
-       }
+       ret = cgm_do_set(controller, filename, cgroup, value);
        free(cgroup);
-       return 0;
+       return ret;
 }
 
 /*
@@ -367,6 +375,49 @@ static int cgm_unfreeze_fromhandler(struct lxc_handler *handler)
        return 0;
 }
 
+static bool setup_limits(struct lxc_handler *h, bool do_devices)
+{
+       struct lxc_list *iterator;
+       struct lxc_cgroup *cg;
+       bool ret = false;
+       struct lxc_list *cgroup_settings = &h->conf->cgroup;
+       struct cgm_data *d = h->cgroup_info->data;
+
+       if (lxc_list_empty(cgroup_settings))
+               return 0;
+
+       lxc_list_for_each(iterator, cgroup_settings) {
+               char controller[100], *p;
+               cg = iterator->elem;
+               if (do_devices != !strncmp("devices", cg->subsystem, 7))
+                       continue;
+               if (strlen(cg->subsystem) > 100) // i smell a rat
+                       goto out;
+               strcpy(controller, cg->subsystem);
+               p = strchr(controller, '.');
+               if (p)
+                       *p = '\0';
+               if (cgm_do_set(controller, cg->subsystem, d->cgroup_path
+                               , cg->value) < 0) {
+                       ERROR("Error setting %s to %s for %s\n",
+                             cg->subsystem, cg->value, h->name);
+                       goto out;
+               }
+
+               DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
+       }
+
+       ret = true;
+       INFO("cgroup limits have been setup");
+out:
+       return ret;
+}
+
+static bool cgm_setup_limits(struct lxc_handler *handler, bool with_devices)
+{
+       return setup_limits(handler, with_devices);
+}
+
 static struct cgroup_ops cgmanager_ops = {
        .destroy = cgm_destroy,
        .init = cgm_init,
@@ -377,6 +428,7 @@ static struct cgroup_ops cgmanager_ops = {
        .get = cgm_get,
        .set = cgm_set,
        .unfreeze_fromhandler = cgm_unfreeze_fromhandler,
+       .setup_limits = cgm_setup_limits,
        .name = "cgmanager"
 };
 #endif
index 85384fcc1087c56a8b59ee90e033f2b7ff74f206..4482b326be6ae02970a9580c3d3acd33482638f1 100644 (file)
@@ -70,7 +70,7 @@ static struct cgroup_process_info *find_info_for_subsystem(struct cgroup_process
 static int do_cgroup_get(const char *cgroup_path, const char *sub_filename, char *value, size_t len);
 static int do_cgroup_set(const char *cgroup_path, const char *sub_filename, const char *value);
 static bool cgroup_devices_has_allow_or_deny(struct lxc_handler *h, char *v, bool for_allow);
-static int do_setup_cgroup(struct lxc_handler *h, struct lxc_list *cgroup_settings, bool do_devices);
+static int do_setup_cgroup_limits(struct lxc_handler *h, struct lxc_list *cgroup_settings, bool do_devices);
 static int cgroup_recursive_task_count(const char *cgroup_path);
 static int count_lines(const char *fn);
 static int handle_cgroup_settings(struct cgroup_mount_point *mp, char *cgroup_path);
@@ -1838,7 +1838,7 @@ static int do_cgroup_set(const char *cgroup_path, const char *sub_filename,
        return ret;
 }
 
-static int do_setup_cgroup(struct lxc_handler *h,
+static int do_setup_cgroup_limits(struct lxc_handler *h,
                           struct lxc_list *cgroup_settings, bool do_devices)
 {
        struct lxc_list *iterator;
@@ -2182,6 +2182,11 @@ static int cgfs_unfreeze_fromhandler(struct lxc_handler *handler)
        return ret;
 }
 
+bool cgroupfs_setup_limits(struct lxc_handler *h, bool with_devices)
+{
+       return do_setup_cgroup_limits(h, &h->conf->cgroup, with_devices) == 0;
+}
+
 static struct cgroup_ops cgfs_ops = {
        .destroy = cgfs_destroy,
        .init = cgfs_init,
@@ -2192,6 +2197,7 @@ static struct cgroup_ops cgfs_ops = {
        .get = lxc_cgroupfs_get,
        .set = lxc_cgroupfs_set,
        .unfreeze_fromhandler = cgfs_unfreeze_fromhandler,
+       .setup_limits = cgroupfs_setup_limits,
        .name = "cgroupfs",
 };
 static void init_cg_ops(void)
@@ -2250,21 +2256,6 @@ bool cgroup_create(struct lxc_handler *handler)
        return active_cg_ops->create(handler);
 }
 
-/*
- * Set up per-controller configuration excluding the devices
- * cgroup
- */
-bool cgroup_setup_without_devices(struct lxc_handler *handler)
-{
-       return do_setup_cgroup(handler, &handler->conf->cgroup, false) == 0;
-}
-
-/* Set up the devices cgroup configuration for the container */
-bool cgroup_setup_devices(struct lxc_handler *handler)
-{
-       return do_setup_cgroup(handler, &handler->conf->cgroup, true) == 0;
-}
-
 /*
  * Enter the container init into its new cgroups for all
  * requested controllers */
@@ -2301,3 +2292,8 @@ int lxc_unfreeze_fromhandler(struct lxc_handler *handler)
 {
        return active_cg_ops->unfreeze_fromhandler(handler);
 }
+
+bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
+{
+       return active_cg_ops->setup_limits(handler, with_devices);
+}
index 76dcbd13d15c41a66d8c8d546738c00047687806..af5a5c8330f949dff226955dacce50c4ee7f15dc 100644 (file)
@@ -179,6 +179,7 @@ struct cgroup_ops {
        int (*set)(const char *filename, const char *value, const char *name, const char *lxcpath);
        int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
        int (*unfreeze_fromhandler)(struct lxc_handler *handler);
+       bool (*setup_limits)(struct lxc_handler *handler, bool with_devices);
        const char *name;
 };
 
@@ -207,8 +208,7 @@ struct cgfs_data {
 extern void cgroup_destroy(struct lxc_handler *handler);
 extern bool cgroup_init(struct lxc_handler *handler);
 extern bool cgroup_create(struct lxc_handler *handler);
-extern bool cgroup_setup_without_devices(struct lxc_handler *handler);
-extern bool cgroup_setup_devices(struct lxc_handler *handler);
+extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
 extern bool cgroup_enter(struct lxc_handler *handler);
 extern void cgroup_cleanup(struct lxc_handler *handler);
 extern bool cgroup_create_legacy(struct lxc_handler *handler);
index b09bd9b0828255702cdc1dbf12ddcd653eafb655..2fcd8457cc7b03cebc4aa8002eff04ce90310c4a 100644 (file)
@@ -796,8 +796,8 @@ static int lxc_spawn(struct lxc_handler *handler)
                ERROR("failed to setup the legacy cgroups for %s", name);
                goto out_delete_net;
        }
-       if (!cgroup_setup_without_devices(handler)) {
-               ERROR("failed to setup the cgroups for '%s'", name);
+       if (!cgroup_setup_limits(handler, false)) {
+               ERROR("failed to setup the cgroup limits for '%s'", name);
                goto out_delete_net;
        }
 
@@ -831,7 +831,7 @@ static int lxc_spawn(struct lxc_handler *handler)
        if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
                goto out_delete_net;
 
-       if (!cgroup_setup_devices(handler)) {
+       if (!cgroup_setup_limits(handler, true)) {
                ERROR("failed to setup the devices cgroup for '%s'", name);
                goto out_delete_net;
        }