]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
confile: add "lxc.cgroup.dir"
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 23 Aug 2017 13:03:01 +0000 (15:03 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 25 Aug 2017 04:35:49 +0000 (06:35 +0200)
"lxc.cgroup.dir" can be used to set the name of the directory the container's
cgroup will be created in. For example, setting

    lxc.uts.name = c1
    lxc.cgroup.dir = lxd

would make liblxc create the cgroup

    lxd/c1

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfs.c
src/lxc/cgroups/cgfsng.c
src/lxc/cgroups/cgmanager.c
src/lxc/cgroups/cgroup.c
src/lxc/cgroups/cgroup.h
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c

index 0e50dd3f5374ae30dae91d3941cc993c21d15002..bcbd66134eb4884ed8b3acea1316674ace3f1c9e 100644 (file)
@@ -2343,7 +2343,7 @@ struct cgroup_ops *cgfs_ops_init(void)
        return &cgfs_ops;
 }
 
-static void *cgfs_init(const char *name)
+static void *cgfs_init(struct lxc_handler *handler)
 {
        struct cgfs_data *d;
 
@@ -2352,7 +2352,7 @@ static void *cgfs_init(const char *name)
                return NULL;
 
        memset(d, 0, sizeof(*d));
-       d->name = strdup(name);
+       d->name = strdup(handler->name);
        if (!d->name)
                goto err1;
 
index 86679741d7215e9a7a2cc13a00cef8b6751fb564..fc658faf24eabe81ea2481af43eced14f0baddd1 100644 (file)
@@ -53,8 +53,9 @@
 #include "cgroup.h"
 #include "cgroup_utils.h"
 #include "commands.h"
+#include "conf.h"
 #include "log.h"
-#include "storage.h"
+#include "storage/storage.h"
 #include "utils.h"
 
 lxc_log_define(lxc_cgfsng, lxc);
@@ -81,17 +82,21 @@ struct hierarchy {
 
 /*
  * The cgroup data which is attached to the lxc_handler.
- * @cgroup_pattern - a copy of the lxc.cgroup.pattern
- * @container_cgroup - if not null, the cgroup which was created for
- *   the container.  For each hierarchy, it is created under the
- *   @hierarchy->base_cgroup directory.  Relative to the base_cgroup
- *   it is the same for all hierarchies.
- * @name - the container name
+ * @cgroup_pattern   : A copy of the lxc.cgroup.pattern
+ * @container_cgroup : If not null, the cgroup which was created for the
+ *                     container. For each hierarchy, it is created under the
+ *                     @hierarchy->base_cgroup directory. Relative to the
+ *                     base_cgroup it is the same for all hierarchies.
+ * @name             : The name of the container.
+ * @cgroup_meta      : A copy of the container's cgroup information. This
+ *                     overrides @cgroup_pattern.
  */
 struct cgfsng_handler_data {
        char *cgroup_pattern;
        char *container_cgroup; /* cgroup we created for the container */
        char *name; /* container name */
+       /* per-container cgroup information */
+       struct lxc_cgroup cgroup_meta;
 };
 
 /*
@@ -220,6 +225,10 @@ static void free_handler_data(struct cgfsng_handler_data *d)
        free(d->cgroup_pattern);
        free(d->container_cgroup);
        free(d->name);
+       if (d->cgroup_meta.dir)
+               free(d->cgroup_meta.dir);
+       if (d->cgroup_meta.controllers)
+               free(d->cgroup_meta.controllers);
        free(d);
 }
 
@@ -986,8 +995,12 @@ static void lxc_cgfsng_print_handler_data(const struct cgfsng_handler_data *d)
        printf("Cgroup information:\n");
        printf("  container name: %s\n", d->name ? d->name : "(null)");
        printf("  lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(null)");
-       printf("  lxc.cgroup.pattern: %s\n", d->cgroup_pattern ? d->cgroup_pattern : "(null)");
-       printf("  cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(null)");
+       printf("  lxc.cgroup.pattern: %s\n",
+              d->cgroup_pattern ? d->cgroup_pattern : "(null)");
+       printf("  lxc.cgroup.dir: %s\n",
+              d->cgroup_meta.dir ? d->cgroup_meta.dir : "(null)");
+       printf("  cgroup: %s\n",
+              d->container_cgroup ? d->container_cgroup : "(null)");
 }
 
 static void lxc_cgfsng_print_hierarchies()
@@ -1150,18 +1163,25 @@ static bool collect_hierarchy_info(void)
        return parse_hierarchies();
 }
 
-static void *cgfsng_init(const char *name)
+static void *cgfsng_init(struct lxc_handler *handler)
 {
-       struct cgfsng_handler_data *d;
        const char *cgroup_pattern;
+       struct cgfsng_handler_data *d;
 
        d = must_alloc(sizeof(*d));
        memset(d, 0, sizeof(*d));
 
-       d->name = must_copy_string(name);
+       /* copy container name */
+       d->name = must_copy_string(handler->name);
+
+       /* copy per-container cgroup information */
+       d->cgroup_meta.dir = must_copy_string(handler->conf->cgroup_meta.dir);
+       d->cgroup_meta.controllers = must_copy_string(handler->conf->cgroup_meta.controllers);
 
+       /* copy system-wide cgroup information */
        cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
-       if (!cgroup_pattern) { /* lxc.cgroup.pattern is only NULL on error */
+       if (!cgroup_pattern) {
+               /* lxc.cgroup.pattern is only NULL on error. */
                ERROR("Error getting cgroup pattern");
                goto out_free;
        }
@@ -1324,12 +1344,16 @@ static inline bool cgfsng_create(void *hdata)
 
        if (!d)
                return false;
+
        if (d->container_cgroup) {
                WARN("cgfsng_create called a second time");
                return false;
        }
 
-       tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern);
+       if (d->cgroup_meta.dir)
+               tmp = strdup(d->cgroup_meta.dir);
+       else
+               tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern);
        if (!tmp) {
                ERROR("Failed expanding cgroup name pattern");
                return false;
index cb98ce7b7ec8ad2a35f5f8ae69f955c8c5df3fb9..6c6278e5968bc83a2fcb677a30d1a7de1671015e 100644 (file)
@@ -540,7 +540,7 @@ static void cgm_remove_cgroup(const char *controller, const char *path)
                INFO("cgroup removal attempt: %s:%s did not exist", controller, path);
 }
 
-static void *cgm_init(const char *name)
+static void *cgm_init(struct lxc_handler *handler)
 {
        struct cgm_data *d;
 
@@ -554,7 +554,7 @@ static void *cgm_init(const char *name)
        }
 
        memset(d, 0, sizeof(*d));
-       d->name = strdup(name);
+       d->name = strdup(handler->name);
        if (!d->name) {
                cgm_dbus_disconnect();
                goto err1;
index 085953342c7507b3974d8ff13164fd66515e753a..674e3090527db148781b40c0e7d355bc51f204cb 100644 (file)
@@ -65,7 +65,7 @@ bool cgroup_init(struct lxc_handler *handler)
 
        if (ops) {
                INFO("cgroup driver %s initing for %s", ops->name, handler->name);
-               handler->cgroup_data = ops->init(handler->name);
+               handler->cgroup_data = ops->init(handler);
        }
 
        return handler->cgroup_data != NULL;
@@ -209,7 +209,8 @@ int lxc_cgroup_get(const char *filename, char *value, size_t len,
        return -1;
 }
 
-void cgroup_disconnect(void) {
+void cgroup_disconnect(void)
+{
        if (ops && ops->disconnect)
                ops->disconnect();
 }
index 11b251e698edb0f2ea0f8c8890d26cb56e4fbf8b..f17a6abe0adc2b69191966f2cc599738fbc7510c 100644 (file)
@@ -41,7 +41,7 @@ typedef enum {
 struct cgroup_ops {
        const char *name;
 
-       void *(*init)(const char *name);
+       void *(*init)(struct lxc_handler *handler);
        void (*destroy)(void *hdata, struct lxc_conf *conf);
        bool (*create)(void *hdata);
        bool (*enter)(void *hdata, pid_t pid);
index 8f58ef541afff315ab0352ef023b2017297bc22f..93d4c15880ebb0c3563687702c1e0817b35a3523 100644 (file)
@@ -2769,6 +2769,7 @@ struct lxc_conf *lxc_conf_init(void)
         * default to running as UID/GID 0 when using lxc-execute */
        new->init_uid = 0;
        new->init_gid = 0;
+       memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
 
        return new;
 }
@@ -4606,6 +4607,8 @@ void lxc_conf_free(struct lxc_conf *conf)
        lxc_clear_aliens(conf);
        lxc_clear_environment(conf);
        lxc_clear_limits(conf, "lxc.prlimit");
+       free(conf->cgroup_meta.dir);
+       free(conf->cgroup_meta.controllers);
        free(conf);
 }
 
index b12b1afb90e404435ac20a353436f75feabc15ec..f085bc94c67c89b295151cf321ea67300aa91206 100644 (file)
@@ -144,14 +144,29 @@ struct lxc_netdev {
 };
 
 /*
- * Defines a generic struct to configure the control group.
- * It is up to the programmer to specify the right subsystem.
+ * Defines a generic struct to configure the control group. It is up to the
+ * programmer to specify the right subsystem.
  * @subsystem : the targeted subsystem
  * @value     : the value to set
+ *
+ * @controllers : The controllers to use for this container.
+ * @dir         : The name of the directory containing the container's cgroup.
+ *                Not that this is a per-container setting.
  */
 struct lxc_cgroup {
-       char *subsystem;
-       char *value;
+       union {
+               /* information about a specific controller */
+               struct /* controller */ {
+                       char *subsystem;
+                       char *value;
+               };
+
+               /* meta information about cgroup configuration */
+               struct /* meta */ {
+                       char *controllers;
+                       char *dir;
+               };
+       };
 };
 
 #if !HAVE_SYS_RESOURCE_H
@@ -422,6 +437,13 @@ struct lxc_conf {
         * legacy configuration keys.
         */
        bool contains_legacy_key;
+
+       /* Contains generic info about the cgroup configuration for this
+        * container. Note that struct lxc_cgroup contains a union. It is only
+        * valid to access the members of the anonymous "meta" struct within
+        * that union.
+        */
+       struct lxc_cgroup cgroup_meta;
 };
 
 #ifdef HAVE_TLS
@@ -459,7 +481,6 @@ extern int lxc_delete_autodev(struct lxc_handler *handler);
 extern void lxc_clear_includes(struct lxc_conf *conf);
 extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
                           const char *lxcpath);
-struct cgroup_process_info;
 extern int lxc_setup(struct lxc_handler *handler);
 extern int setup_resource_limits(struct lxc_list *limits, pid_t pid);
 extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf);
index ad74b8d1f3bb08e6e67a1850cf67ee72c2c784f5..730ea1d240bc6906b8301c39459d9be5c9398824 100644 (file)
@@ -82,7 +82,8 @@ lxc_config_define(tty_dir);
 lxc_config_define(apparmor_profile);
 lxc_config_define(apparmor_allow_incomplete);
 lxc_config_define(selinux_context);
-lxc_config_define(cgroup);
+lxc_config_define(cgroup_controller);
+lxc_config_define(cgroup_dir);
 lxc_config_define(idmaps);
 lxc_config_define(log_level);
 lxc_config_define(log_file);
@@ -142,7 +143,8 @@ static struct lxc_config_t config[] = {
        { "lxc.autodev",                   false,                  set_config_autodev,                     get_config_autodev,                     clr_config_autodev,                   },
        { "lxc.cap.drop",                  false,                  set_config_cap_drop,                    get_config_cap_drop,                    clr_config_cap_drop,                  },
        { "lxc.cap.keep",                  false,                  set_config_cap_keep,                    get_config_cap_keep,                    clr_config_cap_keep,                  },
-       { "lxc.cgroup",                    false,                  set_config_cgroup,                      get_config_cgroup,                      clr_config_cgroup,                    },
+       { "lxc.cgroup.dir",                false,                  set_config_cgroup_dir,                  get_config_cgroup_dir,                  clr_config_cgroup_dir,                },
+       { "lxc.cgroup",                    false,                  set_config_cgroup_controller,           get_config_cgroup_controller,           clr_config_cgroup_controller,         },
        { "lxc.console.logfile",           false,                  set_config_console_logfile,             get_config_console_logfile,             clr_config_console_logfile,           },
        { "lxc.console.path",              false,                  set_config_console_path,                get_config_console_path,                clr_config_console_path,              },
        { "lxc.environment",               false,                  set_config_environment,                 get_config_environment,                 clr_config_environment,               },
@@ -1368,8 +1370,8 @@ static int set_config_signal_stop(const char *key, const char *value,
        return 0;
 }
 
-static int set_config_cgroup(const char *key, const char *value,
-                            struct lxc_conf *lxc_conf, void *data)
+static int set_config_cgroup_controller(const char *key, const char *value,
+                                       struct lxc_conf *lxc_conf, void *data)
 {
        char *subkey;
        char *token = "lxc.cgroup.";
@@ -1423,6 +1425,18 @@ out:
        return -1;
 }
 
+static int set_config_cgroup_dir(const char *key, const char *value,
+                                struct lxc_conf *lxc_conf, void *data)
+{
+       if (lxc_config_value_empty(value))
+               return clr_config_cgroup_dir(key, lxc_conf, NULL);
+
+       if (lxc_conf->cgroup_meta.dir)
+               clr_config_cgroup_dir(key, lxc_conf, NULL);
+
+       return set_config_string_item(&lxc_conf->cgroup_meta.dir, value);
+}
+
 static int set_config_prlimit(const char *key, const char *value,
                            struct lxc_conf *lxc_conf, void *data)
 {
@@ -2624,8 +2638,8 @@ static int get_config_selinux_context(const char *key, char *retv, int inlen,
  * If you ask for 'lxc.cgroup", then all cgroup entries will be printed, in
  * 'lxc.cgroup.subsystem.key = value' format.
  */
-static int get_config_cgroup(const char *key, char *retv, int inlen,
-                            struct lxc_conf *c, void *data)
+static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
+                                       struct lxc_conf *c, void *data)
 {
        struct lxc_list *it;
        int len;
@@ -2658,6 +2672,22 @@ static int get_config_cgroup(const char *key, char *retv, int inlen,
        return fulllen;
 }
 
+static int get_config_cgroup_dir(const char *key, char *retv, int inlen,
+                                struct lxc_conf *lxc_conf, void *data)
+{
+       int len;
+       int fulllen = 0;
+
+       if (!retv)
+               inlen = 0;
+       else
+               memset(retv, 0, inlen);
+
+       strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.dir);
+
+       return fulllen;
+}
+
 static int get_config_idmaps(const char *key, char *retv, int inlen,
                             struct lxc_conf *c, void *data)
 {
@@ -3197,12 +3227,23 @@ static inline int clr_config_selinux_context(const char *key,
        return 0;
 }
 
-static inline int clr_config_cgroup(const char *key, struct lxc_conf *c,
-                                   void *data)
+static inline int clr_config_cgroup_controller(const char *key,
+                                              struct lxc_conf *c, void *data)
 {
        return lxc_clear_cgroups(c, key);
 }
 
+static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf,
+                                void *data)
+{
+       if (lxc_conf->cgroup_meta.dir) {
+               free(lxc_conf->cgroup_meta.dir);
+               lxc_conf->cgroup_meta.dir = NULL;
+       }
+
+       return 0;
+}
+
 static inline int clr_config_idmaps(const char *key, struct lxc_conf *c,
                                    void *data)
 {