Commit 43654d34 by Christian Brauner

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: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 104cd543
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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();
}
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment