conf: port cgroup settings to new list type

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2021-08-25 19:20:57 +02:00
parent 91d04bf9db
commit c9dbb8edf9
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
4 changed files with 72 additions and 122 deletions

View File

@ -2707,11 +2707,8 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
struct lxc_conf *conf,
bool do_devices)
{
__do_free struct lxc_list *sorted_cgroup_settings = NULL;
struct lxc_list *cgroup_settings = &conf->cgroup;
struct lxc_list *iterator, *next;
struct lxc_cgroup *cg;
bool ret = false;
struct list_head *cgroup_settings;
struct lxc_cgroup *cgroup;
if (!ops)
return ret_set_errno(false, ENOENT);
@ -2720,7 +2717,7 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
return ret_set_errno(false, EINVAL);
cgroup_settings = &conf->cgroup;
if (lxc_list_empty(cgroup_settings))
if (list_empty(cgroup_settings))
return true;
if (!ops->hierarchies)
@ -2729,35 +2726,23 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
if (pure_unified_layout(ops))
return log_warn_errno(true, EINVAL, "Ignoring legacy cgroup limits on pure cgroup2 system");
sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings);
if (!sorted_cgroup_settings)
return false;
lxc_list_for_each(iterator, sorted_cgroup_settings) {
cg = iterator->elem;
if (do_devices == strnequal("devices", cg->subsystem, 7)) {
if (cg_legacy_set_data(ops, cg->subsystem, cg->value, strnequal("cpuset", cg->subsystem, 6))) {
sort_cgroup_settings(conf);
list_for_each_entry(cgroup, cgroup_settings, head) {
if (do_devices == strnequal("devices", cgroup->subsystem, 7)) {
if (cg_legacy_set_data(ops, cgroup->subsystem, cgroup->value, strnequal("cpuset", cgroup->subsystem, 6))) {
if (do_devices && (errno == EACCES || errno == EPERM)) {
SYSWARN("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value);
SYSWARN("Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
continue;
}
SYSERROR("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value);
goto out;
SYSERROR("Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
return false;
}
DEBUG("Set controller \"%s\" set to \"%s\"", cg->subsystem, cg->value);
DEBUG("Set controller \"%s\" set to \"%s\"", cgroup->subsystem, cgroup->value);
}
}
ret = true;
INFO("Limits for the legacy cgroup hierarchies have been setup");
out:
lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) {
lxc_list_del(iterator);
free(iterator);
}
return ret;
return true;
}
/*
@ -2793,9 +2778,10 @@ static int bpf_device_cgroup_prepare(struct cgroup_ops *ops,
__cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
struct lxc_handler *handler)
{
struct lxc_list *cgroup_settings, *iterator;
struct list_head *cgroup_settings;
struct hierarchy *h;
struct lxc_conf *conf;
struct lxc_cgroup *cgroup;
if (!ops)
return ret_set_errno(false, ENOENT);
@ -2811,7 +2797,7 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
conf = handler->conf;
cgroup_settings = &conf->cgroup2;
if (lxc_list_empty(cgroup_settings))
if (list_empty(cgroup_settings))
return true;
if (!pure_unified_layout(ops))
@ -2821,18 +2807,17 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
return false;
h = ops->unified;
lxc_list_for_each (iterator, cgroup_settings) {
struct lxc_cgroup *cg = iterator->elem;
list_for_each_entry(cgroup, cgroup_settings, head) {
int ret;
if (strnequal("devices", cg->subsystem, 7))
ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem, cg->value);
if (strnequal("devices", cgroup->subsystem, 7))
ret = bpf_device_cgroup_prepare(ops, conf, cgroup->subsystem, cgroup->value);
else
ret = lxc_write_openat(h->path_lim, cg->subsystem, cg->value, strlen(cg->value));
ret = lxc_write_openat(h->path_lim, cgroup->subsystem, cgroup->value, strlen(cgroup->value));
if (ret < 0)
return log_error_errno(false, errno, "Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value);
return log_error_errno(false, errno, "Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
TRACE("Set \"%s\" to \"%s\"", cg->subsystem, cg->value);
TRACE("Set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
}
return log_info(true, "Limits for the unified cgroup hierarchy have been setup");

View File

@ -3379,8 +3379,8 @@ struct lxc_conf *lxc_conf_init(void)
new->rootfs.fd_path_pin = -EBADF;
new->rootfs.dfd_idmapped = -EBADF;
new->logfd = -1;
lxc_list_init(&new->cgroup);
lxc_list_init(&new->cgroup2);
INIT_LIST_HEAD(&new->cgroup);
INIT_LIST_HEAD(&new->cgroup2);
/* Block ("allowlist") all devices by default. */
new->bpf_devices.list_type = LXC_BPF_DEVICE_CGROUP_ALLOWLIST;
INIT_LIST_HEAD(&(new->bpf_devices).devices);
@ -4538,11 +4538,12 @@ int lxc_clear_namespace(struct lxc_conf *c)
int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
{
char *global_token, *namespaced_token;
size_t namespaced_token_len;
struct lxc_list *it, *next, *list;
const char *k = key;
bool all = false;
char *global_token, *namespaced_token;
size_t namespaced_token_len;
struct list_head *list;
struct lxc_cgroup *cgroup, *ncgroup;
if (version == CGROUP2_SUPER_MAGIC) {
global_token = "lxc.cgroup2";
@ -4565,21 +4566,18 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
else
return ret_errno(EINVAL);
lxc_list_for_each_safe(it, list, next) {
struct lxc_cgroup *cg = it->elem;
if (!all && !strequal(cg->subsystem, k))
list_for_each_entry_safe(cgroup, ncgroup, list, head) {
if (!all && !strequal(cgroup->subsystem, k))
continue;
lxc_list_del(it);
free(cg->subsystem);
free(cg->value);
free(cg);
free(it);
list_del(&cgroup->head);
free(cgroup->subsystem);
free(cgroup->value);
free(cgroup);
}
if (all)
lxc_list_init(list);
INIT_LIST_HEAD(list);
return 0;
}
@ -5817,54 +5815,25 @@ void suggest_default_idmap(void)
ERROR("lxc.idmap = g 0 %u %u", gid, grange);
}
static void free_cgroup_settings(struct lxc_list *result)
{
struct lxc_list *iterator, *next;
lxc_list_for_each_safe (iterator, result, next) {
lxc_list_del(iterator);
free_disarm(iterator);
}
free_disarm(result);
}
/* Return the list of cgroup_settings sorted according to the following rules
* 1. Put memory.limit_in_bytes before memory.memsw.limit_in_bytes
*/
struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings)
void sort_cgroup_settings(struct lxc_conf *conf)
{
struct lxc_list *result;
struct lxc_cgroup *cg = NULL;
struct lxc_list *it = NULL, *item = NULL, *memsw_limit = NULL;
result = lxc_list_new();
if (!result)
return NULL;
lxc_list_init(result);
struct lxc_cgroup *cgroup, *memsw_limit, *ncgroup;
/* Iterate over the cgroup settings and copy them to the output list. */
lxc_list_for_each (it, cgroup_settings) {
item = zalloc(sizeof(*item));
if (!item) {
free_cgroup_settings(result);
return NULL;
}
item->elem = it->elem;
cg = it->elem;
if (strequal(cg->subsystem, "memory.memsw.limit_in_bytes")) {
list_for_each_entry_safe(cgroup, ncgroup, &conf->cgroup, head) {
if (strequal(cgroup->subsystem, "memory.memsw.limit_in_bytes")) {
/* Store the memsw_limit location */
memsw_limit = item;
} else if (strequal(cg->subsystem, "memory.limit_in_bytes") &&
memsw_limit != NULL) {
/* lxc.cgroup.memory.memsw.limit_in_bytes is found
memsw_limit = cgroup;
} else if (memsw_limit && strequal(cgroup->subsystem, "memory.limit_in_bytes")) {
/*
* lxc.cgroup.memory.memsw.limit_in_bytes is found
* before lxc.cgroup.memory.limit_in_bytes, swap these
* two items */
item->elem = memsw_limit->elem;
memsw_limit->elem = it->elem;
* two items.
*/
list_swap(&memsw_limit->head, &cgroup->head);
}
lxc_list_add_tail(result, item);
}
return result;
}

View File

@ -78,6 +78,8 @@ struct lxc_cgroup {
bool relative;
};
};
struct list_head head;
};
static void free_lxc_cgroup(struct lxc_cgroup *ptr)
@ -344,8 +346,8 @@ struct lxc_conf {
struct utsname *utsname;
struct {
struct lxc_list cgroup;
struct lxc_list cgroup2;
struct list_head cgroup;
struct list_head cgroup2;
struct bpf_devices bpf_devices;
};
@ -557,7 +559,7 @@ __hidden extern int parse_mount_attrs(struct lxc_mount_options *opts, const char
__hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
__hidden extern void suggest_default_idmap(void);
__hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers);
__hidden extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings);
__hidden extern void sort_cgroup_settings(struct lxc_conf *conf);
__hidden extern int run_script(const char *name, const char *section, const char *script, ...);
__hidden extern int run_script_argv(const char *name, unsigned int hook_version, const char *section,
const char *script, const char *hookname, char **argsin);

View File

@ -1858,8 +1858,7 @@ static int set_config_signal_stop(const char *key, const char *value,
static int __set_config_cgroup_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, int version)
{
__do_free struct lxc_list *cglist = NULL;
call_cleaner(free_lxc_cgroup) struct lxc_cgroup *cgelem = NULL;
call_cleaner(free_lxc_cgroup) struct lxc_cgroup *new_cgroup = NULL;
const char *subkey, *token;
size_t token_len;
@ -1883,31 +1882,25 @@ static int __set_config_cgroup_controller(const char *key, const char *value,
if (*subkey == '\0')
return ret_errno(EINVAL);
cglist = lxc_list_new();
if (!cglist)
new_cgroup = zalloc(sizeof(*new_cgroup));
if (!new_cgroup)
return ret_errno(ENOMEM);
cgelem = zalloc(sizeof(*cgelem));
if (!cgelem)
new_cgroup->subsystem = strdup(subkey);
if (!new_cgroup->subsystem)
return ret_errno(ENOMEM);
cgelem->subsystem = strdup(subkey);
if (!cgelem->subsystem)
new_cgroup->value = strdup(value);
if (!new_cgroup->value)
return ret_errno(ENOMEM);
cgelem->value = strdup(value);
if (!cgelem->value)
return ret_errno(ENOMEM);
cgelem->version = version;
lxc_list_add_elem(cglist, move_ptr(cgelem));
new_cgroup->version = version;
if (version == CGROUP2_SUPER_MAGIC)
lxc_list_add_tail(&lxc_conf->cgroup2, cglist);
list_add_tail(&new_cgroup->head, &lxc_conf->cgroup2);
else
lxc_list_add_tail(&lxc_conf->cgroup, cglist);
move_ptr(cglist);
list_add_tail(&new_cgroup->head, &lxc_conf->cgroup);
move_ptr(new_cgroup);
return 0;
}
@ -3842,12 +3835,13 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
int inlen, struct lxc_conf *c,
int version)
{
int fulllen = 0;
bool get_all = false;
int len;
size_t namespaced_token_len;
char *global_token, *namespaced_token;
struct lxc_list *it;
int fulllen = 0;
bool get_all = false;
struct list_head *list;
struct lxc_cgroup *cgroup;
if (!retv)
inlen = 0;
@ -3858,10 +3852,12 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
global_token = "lxc.cgroup2";
namespaced_token = "lxc.cgroup2.";
namespaced_token_len = STRLITERALLEN("lxc.cgroup2.");
list = &c->cgroup2;
} else if (version == CGROUP_SUPER_MAGIC) {
global_token = "lxc.cgroup";
namespaced_token = "lxc.cgroup.";
namespaced_token_len = STRLITERALLEN("lxc.cgroup.");
list = &c->cgroup;
} else {
return ret_errno(EINVAL);
}
@ -3873,17 +3869,15 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
else
return ret_errno(EINVAL);
lxc_list_for_each(it, &c->cgroup) {
struct lxc_cgroup *cg = it->elem;
list_for_each_entry(cgroup, list, head) {
if (get_all) {
if (version != cg->version)
if (version != cgroup->version)
continue;
strprint(retv, inlen, "%s.%s = %s\n", global_token,
cg->subsystem, cg->value);
} else if (strequal(cg->subsystem, key)) {
strprint(retv, inlen, "%s\n", cg->value);
cgroup->subsystem, cgroup->value);
} else if (strequal(cgroup->subsystem, key)) {
strprint(retv, inlen, "%s\n", cgroup->value);
}
}