From: Christian Brauner Date: Wed, 23 Aug 2017 13:03:01 +0000 (+0200) Subject: confile: add "lxc.cgroup.dir" X-Git-Tag: lxc-2.1.0~17^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43654d3475f61c239b6b800e0ece6b28f3bfaa2c;p=thirdparty%2Flxc.git confile: add "lxc.cgroup.dir" "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 --- diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c index 0e50dd3f5..bcbd66134 100644 --- a/src/lxc/cgroups/cgfs.c +++ b/src/lxc/cgroups/cgfs.c @@ -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; diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 86679741d..fc658faf2 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -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; diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c index cb98ce7b7..6c6278e59 100644 --- a/src/lxc/cgroups/cgmanager.c +++ b/src/lxc/cgroups/cgmanager.c @@ -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; diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c index 085953342..674e30905 100644 --- a/src/lxc/cgroups/cgroup.c +++ b/src/lxc/cgroups/cgroup.c @@ -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(); } diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h index 11b251e69..f17a6abe0 100644 --- a/src/lxc/cgroups/cgroup.h +++ b/src/lxc/cgroups/cgroup.h @@ -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); diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 8f58ef541..93d4c1588 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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); } diff --git a/src/lxc/conf.h b/src/lxc/conf.h index b12b1afb9..f085bc94c 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -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); diff --git a/src/lxc/confile.c b/src/lxc/confile.c index ad74b8d1f..730ea1d24 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -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) {