mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-14 13:31:27 +00:00
conf: port cgroup settings to new list type
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
parent
91d04bf9db
commit
c9dbb8edf9
@ -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");
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user