confile: add lxc.cgroup2.[controller].[property]

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2018-01-31 16:44:30 +01:00
parent 8777796839
commit 54860ed027
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
4 changed files with 150 additions and 46 deletions

View File

@ -1330,17 +1330,31 @@ dev/null proc/kcore none bind,relative 0 0
<variablelist>
<varlistentry>
<term>
<option>lxc.cgroup.[subsystem name]</option>
<option>lxc.cgroup.[controller name]</option>
</term>
<listitem>
<para>
specify the control group value to be set. The
subsystem name is the literal name of the control group
subsystem. The permitted names and the syntax of their
values is not dictated by LXC, instead it depends on the
features of the Linux kernel running at the time the
container is started,
eg. <option>lxc.cgroup.cpuset.cpus</option>
Specify the control group value to be set on a legacy cgroup
hierarchy. The controller name is the literal name of the control
group. The permitted names and the syntax of their values is not
dictated by LXC, instead it depends on the features of the Linux
kernel running at the time the container is started, eg.
<option>lxc.cgroup.cpuset.cpus</option>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.cgroup2.[controller name]</option>
</term>
<listitem>
<para>
Specify the control group value to be set on the unified cgroup
shierarchy. The controller name is the literal name of the control
group. The permitted names and the syntax of their values is not
dictated by LXC, instead it depends on the features of the Linux
kernel running at the time the container is started, eg.
<option>lxc.cgroup2.memory.high</option>
</para>
</listitem>
</varlistentry>

View File

@ -2555,6 +2555,7 @@ struct lxc_conf *lxc_conf_init(void)
}
new->logfd = -1;
lxc_list_init(&new->cgroup);
lxc_list_init(&new->cgroup2);
lxc_list_init(&new->network);
lxc_list_init(&new->mount_list);
lxc_list_init(&new->caps);
@ -3446,23 +3447,38 @@ int lxc_clear_config_keepcaps(struct lxc_conf *c)
return 0;
}
int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
{
struct lxc_list *it,*next;
bool all = false;
char *global_token, *namespaced_token;
struct lxc_list *it, *next, *list;
const char *k = NULL;
bool all = false;
if (strcmp(key, "lxc.cgroup") == 0)
if (version == CGROUP2_SUPER_MAGIC) {
global_token = "lxc.cgroup2";
namespaced_token = "lxc.cgroup2.";
list = &c->cgroup2;
} else if (version == CGROUP_SUPER_MAGIC) {
global_token = "lxc.cgroup";
namespaced_token = "lxc.cgroup.";
list = &c->cgroup;
} else {
return -1;
}
if (strcmp(key, global_token) == 0)
all = true;
else if (strncmp(key, "lxc.cgroup.", sizeof("lxc.cgroup.") - 1) == 0)
k = key + sizeof("lxc.cgroup.") - 1;
else if (strncmp(key, namespaced_token, sizeof(namespaced_token) - 1) == 0)
k = key + sizeof(namespaced_token) - 1;
else
return -1;
lxc_list_for_each_safe(it, &c->cgroup, next) {
lxc_list_for_each_safe(it, list, next) {
struct lxc_cgroup *cg = it->elem;
if (!all && strcmp(cg->subsystem, k) != 0)
continue;
lxc_list_del(it);
free(cg->subsystem);
free(cg->value);
@ -3680,7 +3696,8 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_seccomp_free(conf);
lxc_clear_config_caps(conf);
lxc_clear_config_keepcaps(conf);
lxc_clear_cgroups(conf, "lxc.cgroup");
lxc_clear_cgroups(conf, "lxc.cgroup", CGROUP_SUPER_MAGIC);
lxc_clear_cgroups(conf, "lxc.cgroup2", CGROUP2_SUPER_MAGIC);
lxc_clear_hooks(conf, "lxc.hook");
lxc_clear_mount_entries(conf);
lxc_clear_idmaps(conf);

View File

@ -52,6 +52,8 @@ typedef void * scmp_filter_ctx;
* programmer to specify the right subsystem.
* @subsystem : the targeted subsystem
* @value : the value to set
* @version : The version of the cgroup filesystem on which the controller
* resides.
*
* @controllers : The controllers to use for this container.
* @dir : The name of the directory containing the container's cgroup.
@ -61,6 +63,7 @@ struct lxc_cgroup {
union {
/* information about a specific controller */
struct /* controller */ {
int version;
char *subsystem;
char *value;
};
@ -282,7 +285,10 @@ struct lxc_conf {
int reboot;
signed long personality;
struct utsname *utsname;
struct lxc_list cgroup;
struct {
struct lxc_list cgroup;
struct lxc_list cgroup2;
};
struct {
struct lxc_list id_map;
@ -433,7 +439,7 @@ extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
extern void lxc_delete_tty(struct lxc_tty_info *tty_info);
extern int lxc_clear_config_caps(struct lxc_conf *c);
extern int lxc_clear_config_keepcaps(struct lxc_conf *c);
extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key);
extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version);
extern int lxc_clear_mount_entries(struct lxc_conf *c);
extern int lxc_clear_automounts(struct lxc_conf *c);
extern int lxc_clear_hooks(struct lxc_conf *c, const char *key);

View File

@ -81,6 +81,7 @@ lxc_config_define(apparmor_profile);
lxc_config_define(cap_drop);
lxc_config_define(cap_keep);
lxc_config_define(cgroup_controller);
lxc_config_define(cgroup2_controller);
lxc_config_define(cgroup_dir);
lxc_config_define(console_logfile);
lxc_config_define(console_rotate);
@ -153,6 +154,7 @@ 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.cgroup2", false, set_config_cgroup2_controller, get_config_cgroup2_controller, clr_config_cgroup2_controller, },
{ "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.buffer.logfile", false, set_config_console_buffer_logfile, get_config_console_buffer_logfile, clr_config_console_buffer_logfile, },
@ -1374,28 +1376,33 @@ static int set_config_signal_stop(const char *key, const char *value,
return 0;
}
static int set_config_cgroup_controller(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, int version)
{
char *subkey;
char *token = "lxc.cgroup.";
const char *subkey, *token;
size_t token_len;
struct lxc_list *cglist = NULL;
struct lxc_cgroup *cgelem = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_cgroups(lxc_conf, key);
return lxc_clear_cgroups(lxc_conf, key, version);
subkey = strstr(key, token);
if (!subkey)
return -1;
if (version == CGROUP2_SUPER_MAGIC) {
token = "lxc.cgroup2.";
token_len = 12;
} else if (version == CGROUP_SUPER_MAGIC) {
token = "lxc.cgroup.";
token_len = 11;
} else {
return -EINVAL;
}
if (!strlen(subkey))
return -1;
if (strncmp(key, token, token_len) != 0)
return -EINVAL;
if (strlen(subkey) == strlen(token))
return -1;
subkey += strlen(token);
subkey = key + token_len;
if (*subkey == '\0')
return -EINVAL;
cglist = malloc(sizeof(*cglist));
if (!cglist)
@ -1407,14 +1414,21 @@ static int set_config_cgroup_controller(const char *key, const char *value,
memset(cgelem, 0, sizeof(*cgelem));
cgelem->subsystem = strdup(subkey);
cgelem->value = strdup(value);
if (!cgelem->subsystem || !cgelem->value)
if (!cgelem->subsystem)
goto out;
cglist->elem = cgelem;
cgelem->value = strdup(value);
if (!cgelem->value)
goto out;
lxc_list_add_tail(&lxc_conf->cgroup, cglist);
cgelem->version = version;
lxc_list_add_elem(cglist, cgelem);
if (version == CGROUP2_SUPER_MAGIC)
lxc_list_add_tail(&lxc_conf->cgroup2, cglist);
else
lxc_list_add_tail(&lxc_conf->cgroup, cglist);
return 0;
@ -1429,6 +1443,21 @@ out:
return -1;
}
static int set_config_cgroup_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
return __set_config_cgroup_controller(key, value, lxc_conf,
CGROUP_SUPER_MAGIC);
}
static int set_config_cgroup2_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
return __set_config_cgroup_controller(key, value, lxc_conf,
CGROUP2_SUPER_MAGIC);
}
static int set_config_cgroup_dir(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@ -2910,11 +2939,14 @@ 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_controller(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,
int version)
{
struct lxc_list *it;
int len;
size_t namespaced_token_len;
char *global_token, *namespaced_token;
struct lxc_list *it;
int fulllen = 0;
bool get_all = false;
@ -2923,10 +2955,22 @@ static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
else
memset(retv, 0, inlen);
if (!strcmp(key, "lxc.cgroup"))
if (version == CGROUP2_SUPER_MAGIC) {
global_token = "lxc.cgroup2";
namespaced_token = "lxc.cgroup2.";
namespaced_token_len = sizeof("lxc.cgroup2.") - 1;;
} else if (version == CGROUP_SUPER_MAGIC) {
global_token = "lxc.cgroup";
namespaced_token = "lxc.cgroup.";
namespaced_token_len = sizeof("lxc.cgroup.") - 1;;
} else {
return -1;
}
if (strcmp(key, global_token) == 0)
get_all = true;
else if (!strncmp(key, "lxc.cgroup.", 11))
key += 11;
else if (strncmp(key, namespaced_token, namespaced_token_len) == 0)
key += namespaced_token_len;
else
return -1;
@ -2934,8 +2978,11 @@ static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
struct lxc_cgroup *cg = it->elem;
if (get_all) {
strprint(retv, inlen, "lxc.cgroup.%s = %s\n",
cg->subsystem, cg->value);
if (version != cg->version)
continue;
strprint(retv, inlen, "%s.%s = %s\n",
global_token, cg->subsystem, cg->value);
} else if (!strcmp(cg->subsystem, key)) {
strprint(retv, inlen, "%s\n", cg->value);
}
@ -2944,6 +2991,20 @@ static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
return fulllen;
}
static int get_config_cgroup_controller(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
return __get_config_cgroup_controller(key, retv, inlen, c,
CGROUP_SUPER_MAGIC);
}
static int get_config_cgroup2_controller(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
return __get_config_cgroup_controller(key, retv, inlen, c,
CGROUP2_SUPER_MAGIC);
}
static int get_config_cgroup_dir(const char *key, char *retv, int inlen,
struct lxc_conf *lxc_conf, void *data)
{
@ -3632,7 +3693,13 @@ static inline int clr_config_selinux_context(const char *key,
static inline int clr_config_cgroup_controller(const char *key,
struct lxc_conf *c, void *data)
{
return lxc_clear_cgroups(c, key);
return lxc_clear_cgroups(c, key, CGROUP_SUPER_MAGIC);
}
static inline int clr_config_cgroup2_controller(const char *key,
struct lxc_conf *c, void *data)
{
return lxc_clear_cgroups(c, key, CGROUP2_SUPER_MAGIC);
}
static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf,