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) ...@@ -2343,7 +2343,7 @@ struct cgroup_ops *cgfs_ops_init(void)
return &cgfs_ops; return &cgfs_ops;
} }
static void *cgfs_init(const char *name) static void *cgfs_init(struct lxc_handler *handler)
{ {
struct cgfs_data *d; struct cgfs_data *d;
...@@ -2352,7 +2352,7 @@ static void *cgfs_init(const char *name) ...@@ -2352,7 +2352,7 @@ static void *cgfs_init(const char *name)
return NULL; return NULL;
memset(d, 0, sizeof(*d)); memset(d, 0, sizeof(*d));
d->name = strdup(name); d->name = strdup(handler->name);
if (!d->name) if (!d->name)
goto err1; goto err1;
......
...@@ -53,8 +53,9 @@ ...@@ -53,8 +53,9 @@
#include "cgroup.h" #include "cgroup.h"
#include "cgroup_utils.h" #include "cgroup_utils.h"
#include "commands.h" #include "commands.h"
#include "conf.h"
#include "log.h" #include "log.h"
#include "storage.h" #include "storage/storage.h"
#include "utils.h" #include "utils.h"
lxc_log_define(lxc_cgfsng, lxc); lxc_log_define(lxc_cgfsng, lxc);
...@@ -81,17 +82,21 @@ struct hierarchy { ...@@ -81,17 +82,21 @@ struct hierarchy {
/* /*
* The cgroup data which is attached to the lxc_handler. * The cgroup data which is attached to the lxc_handler.
* @cgroup_pattern - a copy of the lxc.cgroup.pattern * @cgroup_pattern : A copy of the lxc.cgroup.pattern
* @container_cgroup - if not null, the cgroup which was created for * @container_cgroup : If not null, the cgroup which was created for the
* the container. For each hierarchy, it is created under the * container. For each hierarchy, it is created under the
* @hierarchy->base_cgroup directory. Relative to the base_cgroup * @hierarchy->base_cgroup directory. Relative to the
* it is the same for all hierarchies. * base_cgroup it is the same for all hierarchies.
* @name - the container name * @name : The name of the container.
* @cgroup_meta : A copy of the container's cgroup information. This
* overrides @cgroup_pattern.
*/ */
struct cgfsng_handler_data { struct cgfsng_handler_data {
char *cgroup_pattern; char *cgroup_pattern;
char *container_cgroup; /* cgroup we created for the container */ char *container_cgroup; /* cgroup we created for the container */
char *name; /* container name */ 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) ...@@ -220,6 +225,10 @@ static void free_handler_data(struct cgfsng_handler_data *d)
free(d->cgroup_pattern); free(d->cgroup_pattern);
free(d->container_cgroup); free(d->container_cgroup);
free(d->name); 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); free(d);
} }
...@@ -986,8 +995,12 @@ static void lxc_cgfsng_print_handler_data(const struct cgfsng_handler_data *d) ...@@ -986,8 +995,12 @@ static void lxc_cgfsng_print_handler_data(const struct cgfsng_handler_data *d)
printf("Cgroup information:\n"); printf("Cgroup information:\n");
printf(" container name: %s\n", d->name ? d->name : "(null)"); printf(" container name: %s\n", d->name ? d->name : "(null)");
printf(" lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(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(" lxc.cgroup.pattern: %s\n",
printf(" cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(null)"); 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() static void lxc_cgfsng_print_hierarchies()
...@@ -1150,18 +1163,25 @@ static bool collect_hierarchy_info(void) ...@@ -1150,18 +1163,25 @@ static bool collect_hierarchy_info(void)
return parse_hierarchies(); 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; const char *cgroup_pattern;
struct cgfsng_handler_data *d;
d = must_alloc(sizeof(*d)); d = must_alloc(sizeof(*d));
memset(d, 0, 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"); 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"); ERROR("Error getting cgroup pattern");
goto out_free; goto out_free;
} }
...@@ -1324,12 +1344,16 @@ static inline bool cgfsng_create(void *hdata) ...@@ -1324,12 +1344,16 @@ static inline bool cgfsng_create(void *hdata)
if (!d) if (!d)
return false; return false;
if (d->container_cgroup) { if (d->container_cgroup) {
WARN("cgfsng_create called a second time"); WARN("cgfsng_create called a second time");
return false; 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) { if (!tmp) {
ERROR("Failed expanding cgroup name pattern"); ERROR("Failed expanding cgroup name pattern");
return false; return false;
......
...@@ -540,7 +540,7 @@ static void cgm_remove_cgroup(const char *controller, const char *path) ...@@ -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); 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; struct cgm_data *d;
...@@ -554,7 +554,7 @@ static void *cgm_init(const char *name) ...@@ -554,7 +554,7 @@ static void *cgm_init(const char *name)
} }
memset(d, 0, sizeof(*d)); memset(d, 0, sizeof(*d));
d->name = strdup(name); d->name = strdup(handler->name);
if (!d->name) { if (!d->name) {
cgm_dbus_disconnect(); cgm_dbus_disconnect();
goto err1; goto err1;
......
...@@ -65,7 +65,7 @@ bool cgroup_init(struct lxc_handler *handler) ...@@ -65,7 +65,7 @@ bool cgroup_init(struct lxc_handler *handler)
if (ops) { if (ops) {
INFO("cgroup driver %s initing for %s", ops->name, handler->name); 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; return handler->cgroup_data != NULL;
...@@ -209,7 +209,8 @@ int lxc_cgroup_get(const char *filename, char *value, size_t len, ...@@ -209,7 +209,8 @@ int lxc_cgroup_get(const char *filename, char *value, size_t len,
return -1; return -1;
} }
void cgroup_disconnect(void) { void cgroup_disconnect(void)
{
if (ops && ops->disconnect) if (ops && ops->disconnect)
ops->disconnect(); ops->disconnect();
} }
......
...@@ -41,7 +41,7 @@ typedef enum { ...@@ -41,7 +41,7 @@ typedef enum {
struct cgroup_ops { struct cgroup_ops {
const char *name; const char *name;
void *(*init)(const char *name); void *(*init)(struct lxc_handler *handler);
void (*destroy)(void *hdata, struct lxc_conf *conf); void (*destroy)(void *hdata, struct lxc_conf *conf);
bool (*create)(void *hdata); bool (*create)(void *hdata);
bool (*enter)(void *hdata, pid_t pid); bool (*enter)(void *hdata, pid_t pid);
......
...@@ -2769,6 +2769,7 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2769,6 +2769,7 @@ struct lxc_conf *lxc_conf_init(void)
* default to running as UID/GID 0 when using lxc-execute */ * default to running as UID/GID 0 when using lxc-execute */
new->init_uid = 0; new->init_uid = 0;
new->init_gid = 0; new->init_gid = 0;
memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
return new; return new;
} }
...@@ -4606,6 +4607,8 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -4606,6 +4607,8 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_aliens(conf); lxc_clear_aliens(conf);
lxc_clear_environment(conf); lxc_clear_environment(conf);
lxc_clear_limits(conf, "lxc.prlimit"); lxc_clear_limits(conf, "lxc.prlimit");
free(conf->cgroup_meta.dir);
free(conf->cgroup_meta.controllers);
free(conf); free(conf);
} }
......
...@@ -144,14 +144,29 @@ struct lxc_netdev { ...@@ -144,14 +144,29 @@ struct lxc_netdev {
}; };
/* /*
* Defines a generic struct to configure the control group. * Defines a generic struct to configure the control group. It is up to the
* It is up to the programmer to specify the right subsystem. * programmer to specify the right subsystem.
* @subsystem : the targeted subsystem * @subsystem : the targeted subsystem
* @value : the value to set * @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 { struct lxc_cgroup {
char *subsystem; union {
char *value; /* 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 #if !HAVE_SYS_RESOURCE_H
...@@ -422,6 +437,13 @@ struct lxc_conf { ...@@ -422,6 +437,13 @@ struct lxc_conf {
* legacy configuration keys. * legacy configuration keys.
*/ */
bool contains_legacy_key; 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 #ifdef HAVE_TLS
...@@ -459,7 +481,6 @@ extern int lxc_delete_autodev(struct lxc_handler *handler); ...@@ -459,7 +481,6 @@ extern int lxc_delete_autodev(struct lxc_handler *handler);
extern void lxc_clear_includes(struct lxc_conf *conf); extern void lxc_clear_includes(struct lxc_conf *conf);
extern int do_rootfs_setup(struct lxc_conf *conf, const char *name, extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
const char *lxcpath); const char *lxcpath);
struct cgroup_process_info;
extern int lxc_setup(struct lxc_handler *handler); extern int lxc_setup(struct lxc_handler *handler);
extern int setup_resource_limits(struct lxc_list *limits, pid_t pid); 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); extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf);
......
...@@ -82,7 +82,8 @@ lxc_config_define(tty_dir); ...@@ -82,7 +82,8 @@ lxc_config_define(tty_dir);
lxc_config_define(apparmor_profile); lxc_config_define(apparmor_profile);
lxc_config_define(apparmor_allow_incomplete); lxc_config_define(apparmor_allow_incomplete);
lxc_config_define(selinux_context); 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(idmaps);
lxc_config_define(log_level); lxc_config_define(log_level);
lxc_config_define(log_file); lxc_config_define(log_file);
...@@ -142,7 +143,8 @@ static struct lxc_config_t config[] = { ...@@ -142,7 +143,8 @@ static struct lxc_config_t config[] = {
{ "lxc.autodev", false, set_config_autodev, get_config_autodev, clr_config_autodev, }, { "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.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.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.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.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, }, { "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, ...@@ -1368,8 +1370,8 @@ static int set_config_signal_stop(const char *key, const char *value,
return 0; return 0;
} }
static int set_config_cgroup(const char *key, const char *value, static int set_config_cgroup_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
char *subkey; char *subkey;
char *token = "lxc.cgroup."; char *token = "lxc.cgroup.";
...@@ -1423,6 +1425,18 @@ out: ...@@ -1423,6 +1425,18 @@ out:
return -1; 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, static int set_config_prlimit(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
...@@ -2624,8 +2638,8 @@ static int get_config_selinux_context(const char *key, char *retv, int inlen, ...@@ -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 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed, in
* 'lxc.cgroup.subsystem.key = value' format. * 'lxc.cgroup.subsystem.key = value' format.
*/ */
static int get_config_cgroup(const char *key, char *retv, int inlen, static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
struct lxc_list *it; struct lxc_list *it;
int len; int len;
...@@ -2658,6 +2672,22 @@ static int get_config_cgroup(const char *key, char *retv, int inlen, ...@@ -2658,6 +2672,22 @@ static int get_config_cgroup(const char *key, char *retv, int inlen,
return fulllen; 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, static int get_config_idmaps(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
...@@ -3197,12 +3227,23 @@ static inline int clr_config_selinux_context(const char *key, ...@@ -3197,12 +3227,23 @@ static inline int clr_config_selinux_context(const char *key,
return 0; return 0;
} }
static inline int clr_config_cgroup(const char *key, struct lxc_conf *c, static inline int clr_config_cgroup_controller(const char *key,
void *data) struct lxc_conf *c, void *data)
{ {
return lxc_clear_cgroups(c, key); 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, static inline int clr_config_idmaps(const char *key, struct lxc_conf *c,
void *data) 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