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, struct lxc_conf *conf,
bool do_devices) bool do_devices)
{ {
__do_free struct lxc_list *sorted_cgroup_settings = NULL; struct list_head *cgroup_settings;
struct lxc_list *cgroup_settings = &conf->cgroup; struct lxc_cgroup *cgroup;
struct lxc_list *iterator, *next;
struct lxc_cgroup *cg;
bool ret = false;
if (!ops) if (!ops)
return ret_set_errno(false, ENOENT); 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); return ret_set_errno(false, EINVAL);
cgroup_settings = &conf->cgroup; cgroup_settings = &conf->cgroup;
if (lxc_list_empty(cgroup_settings)) if (list_empty(cgroup_settings))
return true; return true;
if (!ops->hierarchies) if (!ops->hierarchies)
@ -2729,35 +2726,23 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
if (pure_unified_layout(ops)) if (pure_unified_layout(ops))
return log_warn_errno(true, EINVAL, "Ignoring legacy cgroup limits on pure cgroup2 system"); return log_warn_errno(true, EINVAL, "Ignoring legacy cgroup limits on pure cgroup2 system");
sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings); sort_cgroup_settings(conf);
if (!sorted_cgroup_settings) list_for_each_entry(cgroup, cgroup_settings, head) {
return false; if (do_devices == strnequal("devices", cgroup->subsystem, 7)) {
if (cg_legacy_set_data(ops, cgroup->subsystem, cgroup->value, strnequal("cpuset", cgroup->subsystem, 6))) {
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))) {
if (do_devices && (errno == EACCES || errno == EPERM)) { 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; continue;
} }
SYSERROR("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value); SYSERROR("Failed to set \"%s\" to \"%s\"", cgroup->subsystem, cgroup->value);
goto out; 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"); INFO("Limits for the legacy cgroup hierarchies have been setup");
out: return true;
lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) {
lxc_list_del(iterator);
free(iterator);
}
return ret;
} }
/* /*
@ -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, __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
struct lxc_handler *handler) struct lxc_handler *handler)
{ {
struct lxc_list *cgroup_settings, *iterator; struct list_head *cgroup_settings;
struct hierarchy *h; struct hierarchy *h;
struct lxc_conf *conf; struct lxc_conf *conf;
struct lxc_cgroup *cgroup;
if (!ops) if (!ops)
return ret_set_errno(false, ENOENT); return ret_set_errno(false, ENOENT);
@ -2811,7 +2797,7 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
conf = handler->conf; conf = handler->conf;
cgroup_settings = &conf->cgroup2; cgroup_settings = &conf->cgroup2;
if (lxc_list_empty(cgroup_settings)) if (list_empty(cgroup_settings))
return true; return true;
if (!pure_unified_layout(ops)) if (!pure_unified_layout(ops))
@ -2821,18 +2807,17 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
return false; return false;
h = ops->unified; h = ops->unified;
lxc_list_for_each (iterator, cgroup_settings) { list_for_each_entry(cgroup, cgroup_settings, head) {
struct lxc_cgroup *cg = iterator->elem;
int ret; int ret;
if (strnequal("devices", cg->subsystem, 7)) if (strnequal("devices", cgroup->subsystem, 7))
ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem, cg->value); ret = bpf_device_cgroup_prepare(ops, conf, cgroup->subsystem, cgroup->value);
else 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) 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"); 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.fd_path_pin = -EBADF;
new->rootfs.dfd_idmapped = -EBADF; new->rootfs.dfd_idmapped = -EBADF;
new->logfd = -1; new->logfd = -1;
lxc_list_init(&new->cgroup); INIT_LIST_HEAD(&new->cgroup);
lxc_list_init(&new->cgroup2); INIT_LIST_HEAD(&new->cgroup2);
/* Block ("allowlist") all devices by default. */ /* Block ("allowlist") all devices by default. */
new->bpf_devices.list_type = LXC_BPF_DEVICE_CGROUP_ALLOWLIST; new->bpf_devices.list_type = LXC_BPF_DEVICE_CGROUP_ALLOWLIST;
INIT_LIST_HEAD(&(new->bpf_devices).devices); 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) 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; const char *k = key;
bool all = false; 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) { if (version == CGROUP2_SUPER_MAGIC) {
global_token = "lxc.cgroup2"; global_token = "lxc.cgroup2";
@ -4565,21 +4566,18 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
else else
return ret_errno(EINVAL); return ret_errno(EINVAL);
lxc_list_for_each_safe(it, list, next) { list_for_each_entry_safe(cgroup, ncgroup, list, head) {
struct lxc_cgroup *cg = it->elem; if (!all && !strequal(cgroup->subsystem, k))
if (!all && !strequal(cg->subsystem, k))
continue; continue;
lxc_list_del(it); list_del(&cgroup->head);
free(cg->subsystem); free(cgroup->subsystem);
free(cg->value); free(cgroup->value);
free(cg); free(cgroup);
free(it);
} }
if (all) if (all)
lxc_list_init(list); INIT_LIST_HEAD(list);
return 0; return 0;
} }
@ -5817,54 +5815,25 @@ void suggest_default_idmap(void)
ERROR("lxc.idmap = g 0 %u %u", gid, grange); 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 /* Return the list of cgroup_settings sorted according to the following rules
* 1. Put memory.limit_in_bytes before memory.memsw.limit_in_bytes * 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 *cgroup, *memsw_limit, *ncgroup;
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);
/* Iterate over the cgroup settings and copy them to the output list. */ /* Iterate over the cgroup settings and copy them to the output list. */
lxc_list_for_each (it, cgroup_settings) { list_for_each_entry_safe(cgroup, ncgroup, &conf->cgroup, head) {
item = zalloc(sizeof(*item)); if (strequal(cgroup->subsystem, "memory.memsw.limit_in_bytes")) {
if (!item) {
free_cgroup_settings(result);
return NULL;
}
item->elem = it->elem;
cg = it->elem;
if (strequal(cg->subsystem, "memory.memsw.limit_in_bytes")) {
/* Store the memsw_limit location */ /* Store the memsw_limit location */
memsw_limit = item; memsw_limit = cgroup;
} else if (strequal(cg->subsystem, "memory.limit_in_bytes") && } else if (memsw_limit && strequal(cgroup->subsystem, "memory.limit_in_bytes")) {
memsw_limit != NULL) { /*
/* lxc.cgroup.memory.memsw.limit_in_bytes is found * lxc.cgroup.memory.memsw.limit_in_bytes is found
* before lxc.cgroup.memory.limit_in_bytes, swap these * before lxc.cgroup.memory.limit_in_bytes, swap these
* two items */ * two items.
item->elem = memsw_limit->elem; */
memsw_limit->elem = it->elem; 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; bool relative;
}; };
}; };
struct list_head head;
}; };
static void free_lxc_cgroup(struct lxc_cgroup *ptr) static void free_lxc_cgroup(struct lxc_cgroup *ptr)
@ -344,8 +346,8 @@ struct lxc_conf {
struct utsname *utsname; struct utsname *utsname;
struct { struct {
struct lxc_list cgroup; struct list_head cgroup;
struct lxc_list cgroup2; struct list_head cgroup2;
struct bpf_devices bpf_devices; 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 tmp_proc_unmount(struct lxc_conf *lxc_conf);
__hidden extern void suggest_default_idmap(void); __hidden extern void suggest_default_idmap(void);
__hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers); __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(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, __hidden extern int run_script_argv(const char *name, unsigned int hook_version, const char *section,
const char *script, const char *hookname, char **argsin); 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, static int __set_config_cgroup_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, int version) struct lxc_conf *lxc_conf, int version)
{ {
__do_free struct lxc_list *cglist = NULL; call_cleaner(free_lxc_cgroup) struct lxc_cgroup *new_cgroup = NULL;
call_cleaner(free_lxc_cgroup) struct lxc_cgroup *cgelem = NULL;
const char *subkey, *token; const char *subkey, *token;
size_t token_len; size_t token_len;
@ -1883,31 +1882,25 @@ static int __set_config_cgroup_controller(const char *key, const char *value,
if (*subkey == '\0') if (*subkey == '\0')
return ret_errno(EINVAL); return ret_errno(EINVAL);
cglist = lxc_list_new(); new_cgroup = zalloc(sizeof(*new_cgroup));
if (!cglist) if (!new_cgroup)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
cgelem = zalloc(sizeof(*cgelem)); new_cgroup->subsystem = strdup(subkey);
if (!cgelem) if (!new_cgroup->subsystem)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
cgelem->subsystem = strdup(subkey); new_cgroup->value = strdup(value);
if (!cgelem->subsystem) if (!new_cgroup->value)
return ret_errno(ENOMEM); return ret_errno(ENOMEM);
cgelem->value = strdup(value); new_cgroup->version = version;
if (!cgelem->value)
return ret_errno(ENOMEM);
cgelem->version = version;
lxc_list_add_elem(cglist, move_ptr(cgelem));
if (version == CGROUP2_SUPER_MAGIC) if (version == CGROUP2_SUPER_MAGIC)
lxc_list_add_tail(&lxc_conf->cgroup2, cglist); list_add_tail(&new_cgroup->head, &lxc_conf->cgroup2);
else else
lxc_list_add_tail(&lxc_conf->cgroup, cglist); list_add_tail(&new_cgroup->head, &lxc_conf->cgroup);
move_ptr(cglist); move_ptr(new_cgroup);
return 0; return 0;
} }
@ -3842,12 +3835,13 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
int inlen, struct lxc_conf *c, int inlen, struct lxc_conf *c,
int version) int version)
{ {
int fulllen = 0;
bool get_all = false;
int len; int len;
size_t namespaced_token_len; size_t namespaced_token_len;
char *global_token, *namespaced_token; char *global_token, *namespaced_token;
struct lxc_list *it; struct list_head *list;
int fulllen = 0; struct lxc_cgroup *cgroup;
bool get_all = false;
if (!retv) if (!retv)
inlen = 0; inlen = 0;
@ -3858,10 +3852,12 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
global_token = "lxc.cgroup2"; global_token = "lxc.cgroup2";
namespaced_token = "lxc.cgroup2."; namespaced_token = "lxc.cgroup2.";
namespaced_token_len = STRLITERALLEN("lxc.cgroup2."); namespaced_token_len = STRLITERALLEN("lxc.cgroup2.");
list = &c->cgroup2;
} else if (version == CGROUP_SUPER_MAGIC) { } else if (version == CGROUP_SUPER_MAGIC) {
global_token = "lxc.cgroup"; global_token = "lxc.cgroup";
namespaced_token = "lxc.cgroup."; namespaced_token = "lxc.cgroup.";
namespaced_token_len = STRLITERALLEN("lxc.cgroup."); namespaced_token_len = STRLITERALLEN("lxc.cgroup.");
list = &c->cgroup;
} else { } else {
return ret_errno(EINVAL); return ret_errno(EINVAL);
} }
@ -3873,17 +3869,15 @@ static int __get_config_cgroup_controller(const char *key, char *retv,
else else
return ret_errno(EINVAL); return ret_errno(EINVAL);
lxc_list_for_each(it, &c->cgroup) { list_for_each_entry(cgroup, list, head) {
struct lxc_cgroup *cg = it->elem;
if (get_all) { if (get_all) {
if (version != cg->version) if (version != cgroup->version)
continue; continue;
strprint(retv, inlen, "%s.%s = %s\n", global_token, strprint(retv, inlen, "%s.%s = %s\n", global_token,
cg->subsystem, cg->value); cgroup->subsystem, cgroup->value);
} else if (strequal(cg->subsystem, key)) { } else if (strequal(cgroup->subsystem, key)) {
strprint(retv, inlen, "%s\n", cg->value); strprint(retv, inlen, "%s\n", cgroup->value);
} }
} }