From: Tom Hromatka Date: Mon, 31 Jan 2022 16:21:54 +0000 (-0700) Subject: abstraction-map: Add cpu.cfs_{quota,period}_us <-> cpu.max mapping X-Git-Tag: v3.0~227 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6755104f320492bfbe4c3ac896c15dac8702af9b;p=thirdparty%2Flibcgroup.git abstraction-map: Add cpu.cfs_{quota,period}_us <-> cpu.max mapping Add custom functions to map cpu.cfs_quota_us <-> cpu.max and cpu.cfs_period_us <-> cpu.max. These mappings can be 1->N or N->1 and utilize custom values for limits, "-1" in cgroup v1 and "max" in cgroup v2. Signed-off-by: Tom Hromatka Reviewed-by: Kamalesh Babulal --- diff --git a/src/Makefile.am b/src/Makefile.am index 2008ebd7..80d95a1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,8 @@ lib_LTLIBRARIES = libcgroup.la libcgroup_la_SOURCES = parse.h parse.y lex.l api.c config.c \ libcgroup-internal.h libcgroup.map wrapper.c log.c \ abstraction-common.c abstraction-common.h \ - abstraction-map.c abstraction-map.h + abstraction-map.c abstraction-map.h \ + abstraction-cpu.c libcgroup_la_LIBADD = -lpthread $(CODE_COVERAGE_LIBS) libcgroup_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) -DSTATIC=static libcgroup_la_LDFLAGS = -Wl,--version-script,$(srcdir)/libcgroup.map \ diff --git a/src/abstraction-common.c b/src/abstraction-common.c index 6852afcb..e6d51443 100644 --- a/src/abstraction-common.c +++ b/src/abstraction-common.c @@ -183,7 +183,7 @@ out: } static int convert_controller(struct cgroup_controller * const out_cgc, - const struct cgroup_controller * const in_cgc) + struct cgroup_controller * const in_cgc) { int ret; int i; @@ -195,6 +195,12 @@ static int convert_controller(struct cgroup_controller * const out_cgc, goto out; } + if (strcmp(in_cgc->name, "cpu") == 0) { + ret = cgroup_convert_cpu_nto1(out_cgc, in_cgc); + if (ret) + goto out; + } + for (i = 0; i < in_cgc->index; i++) { ret = convert_setting(out_cgc, in_cgc->values[i]); if (ret) diff --git a/src/abstraction-common.h b/src/abstraction-common.h index 73eccba6..8e508e25 100644 --- a/src/abstraction-common.h +++ b/src/abstraction-common.h @@ -86,6 +86,34 @@ int cgroup_convert_passthrough(struct cgroup_controller * const dst_cgc, const char * const out_setting, void *in_dflt, void *out_dflt); +/* cpu */ +int cgroup_convert_cpu_nto1(struct cgroup_controller * const out_cgc, + struct cgroup_controller * const in_cgc); + +int cgroup_convert_cpu_quota_to_max( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt); + +int cgroup_convert_cpu_period_to_max( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt); + +int cgroup_convert_cpu_max_to_quota( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt); + +int cgroup_convert_cpu_max_to_period( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/abstraction-cpu.c b/src/abstraction-cpu.c new file mode 100644 index 00000000..4b5cfe2d --- /dev/null +++ b/src/abstraction-cpu.c @@ -0,0 +1,308 @@ +/** + * Libcgroup abstraction layer for the cpu controller + * + * Copyright (c) 2021-2022 Oracle and/or its affiliates. + * Author: Tom Hromatka + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "abstraction-common.h" +#include "abstraction-map.h" + +#define LL_MAX 8192 + +static const char * const MAX = "max"; +static const char * const CPU_MAX = "cpu.max"; +static const char * const CFS_QUOTA_US = "cpu.cfs_quota_us"; +static const char * const CFS_PERIOD_US = "cpu.cfs_period_us"; + +static int read_setting(const char * const cgroup_name, + const char * const controller_name, + const char * const setting_name, + char ** const value) +{ + char tmp_line[LL_MAX]; + void *handle; + int ret; + + ret = cgroup_read_value_begin(controller_name, cgroup_name, + setting_name, &handle, tmp_line, LL_MAX); + if (ret == ECGEOF) + goto read_end; + else if (ret != 0) + goto end; + + *value = strdup(tmp_line); + if ((*value) == NULL) { + ret = ECGOTHER; + goto end; + } + +read_end: + cgroup_read_value_end(&handle); + if (ret == ECGEOF) + ret = 0; + +end: + return ret; +} + +static int get_max(struct cgroup_controller * const cgc, + char ** const max) +{ + return read_setting(cgc->cgroup->name, "cpu", "cpu.max", max); +} + +static int get_quota_from_max(struct cgroup_controller * const cgc, + char ** const quota) +{ + char *token, *max = NULL, *saveptr = NULL; + int ret; + + ret = get_max(cgc, &max); + if (ret) + goto out; + + token = strtok_r(max, " ", &saveptr); + + *quota = strdup(token); + if ((*quota) == NULL) + ret = ECGOTHER; + +out: + if (max) + free(max); + + return ret; +} + +static int get_period_from_max(struct cgroup_controller * const cgc, + char ** const period) +{ + char *token, *max = NULL, *saveptr = NULL; + int ret; + + ret = get_max(cgc, &max); + if (ret) + goto out; + + token = strtok_r(max, " ", &saveptr); + token = strtok_r(NULL, " ", &saveptr); + + *period = strdup(token); + if ((*period) == NULL) + ret = ECGOTHER; + +out: + if (max) + free(max); + + return ret; +} + +int cgroup_convert_cpu_quota_to_max( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt) +{ + char max_line[LL_MAX] = {0}; + char *period = NULL; + int ret; + + if (strlen(in_value) == 0) { + /* There's no value to convert. Populate the setting */ + ret = cgroup_add_value_string(dst_cgc, out_setting, NULL); + if (ret) + goto out; + } else { + ret = get_period_from_max(dst_cgc, &period); + if (ret) + goto out; + + if (strcmp(in_value, "-1") == 0) + snprintf(max_line, LL_MAX, "%s %s", MAX, period); + else + snprintf(max_line, LL_MAX, "%s %s", in_value, period); + + ret = cgroup_add_value_string(dst_cgc, out_setting, max_line); + if (ret) + goto out; + } + + dst_cgc->values[dst_cgc->index - 1]->prev_name = + strdup(CFS_QUOTA_US); +out: + if (period) + free(period); + + return ret; +} + +int cgroup_convert_cpu_period_to_max( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt) +{ + char max_line[LL_MAX] = {0}; + char *quota = NULL; + int ret; + + if (strlen(in_value) == 0) { + /* There's no value to convert. Populate the setting and + * return + */ + ret = cgroup_add_value_string(dst_cgc, out_setting, NULL); + if (ret) + goto out; + } else { + ret = get_quota_from_max(dst_cgc, "a); + if (ret) + goto out; + + if (strcmp(in_value, "-1") == 0) + snprintf(max_line, LL_MAX, "%s %s", quota, MAX); + else + snprintf(max_line, LL_MAX, "%s %s", quota, in_value); + ret = cgroup_add_value_string(dst_cgc, out_setting, max_line); + if (ret) + goto out; + } + + dst_cgc->values[dst_cgc->index - 1]->prev_name = + strdup(CFS_PERIOD_US); + +out: + if (quota) + free(quota); + + return ret; +} + +int cgroup_convert_cpu_max_to_quota( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt) +{ + char *token, *copy = NULL, *saveptr = NULL; + int ret; + + if (strlen(in_value) == 0) { + /* There's no value to convert. Populate the setting and + * return + */ + return cgroup_add_value_string(dst_cgc, out_setting, NULL); + } + + copy = strdup(in_value); + if (!copy) + return ECGOTHER; + + token = strtok_r(copy, " ", &saveptr); + + if (strcmp(token, MAX) == 0) + ret = cgroup_add_value_string(dst_cgc, out_setting, "-1"); + else + ret = cgroup_add_value_string(dst_cgc, out_setting, token); + + if (copy) + free(copy); + + return ret; +} + +int cgroup_convert_cpu_max_to_period( + struct cgroup_controller * const dst_cgc, + const char * const in_value, + const char * const out_setting, + void *in_dflt, void *out_dflt) +{ + char *token, *copy = NULL, *saveptr = NULL; + int ret; + + if (strlen(in_value) == 0) { + /* There's no value to convert. Populate the setting and + * return + */ + return cgroup_add_value_string(dst_cgc, out_setting, NULL); + } + + copy = strdup(in_value); + if (!copy) + return ECGOTHER; + + token = strtok_r(copy, " ", &saveptr); + token = strtok_r(NULL, " ", &saveptr); + + ret = cgroup_add_value_string(dst_cgc, out_setting, token); + + if (copy) + free(copy); + + return ret; +} + +int cgroup_convert_cpu_nto1(struct cgroup_controller * const out_cgc, + struct cgroup_controller * const in_cgc) +{ + char *cfs_quota = NULL, *cfs_period = NULL; + char max_line[LL_MAX] = {0}; + int i, ret = 0; + + for (i = 0; i < in_cgc->index; i++) { + if (strcmp(in_cgc->values[i]->name, CFS_QUOTA_US) == 0) + cfs_quota = in_cgc->values[i]->value; + else if (strcmp(in_cgc->values[i]->name, CFS_PERIOD_US) == 0) + cfs_period = in_cgc->values[i]->value; + } + + if (cfs_quota && cfs_period) { + if (strcmp(cfs_quota, "-1") == 0) { + snprintf(max_line, LL_MAX, "%s %s", MAX, cfs_period); + max_line[LL_MAX - 1] = '\0'; + } else { + snprintf(max_line, LL_MAX, "%s %s", cfs_quota, + cfs_period); + max_line[LL_MAX - 1] = '\0'; + } + + ret = cgroup_add_value_string(out_cgc, CPU_MAX, max_line); + if (ret) + goto out; + + ret = cgroup_remove_value(in_cgc, CFS_QUOTA_US); + if (ret) + goto out; + + ret = cgroup_remove_value(in_cgc, CFS_PERIOD_US); + if (ret) + goto out; + } + +out: + return ret; +} diff --git a/src/abstraction-map.c b/src/abstraction-map.c index 0516b000..074ece9f 100644 --- a/src/abstraction-map.c +++ b/src/abstraction-map.c @@ -33,12 +33,16 @@ const struct cgroup_abstraction_map cgroup_v1_to_v2_map[] = { {cgroup_convert_int, "cpu.shares", (void *)1024, "cpu.weight", (void *)100}, + {cgroup_convert_cpu_quota_to_max, "cpu.cfs_quota_us", NULL, "cpu.max", NULL}, + {cgroup_convert_cpu_period_to_max, "cpu.cfs_period_us", NULL, "cpu.max", NULL}, }; const int cgroup_v1_to_v2_map_sz = sizeof(cgroup_v1_to_v2_map) / sizeof(cgroup_v1_to_v2_map[0]); const struct cgroup_abstraction_map cgroup_v2_to_v1_map[] = { {cgroup_convert_int, "cpu.weight", (void *)100, "cpu.shares", (void *)1024}, + {cgroup_convert_cpu_max_to_quota, "cpu.max", NULL, "cpu.cfs_quota_us", NULL}, + {cgroup_convert_cpu_max_to_period, "cpu.max", NULL, "cpu.cfs_period_us", NULL}, }; const int cgroup_v2_to_v1_map_sz = sizeof(cgroup_v2_to_v1_map) / sizeof(cgroup_v2_to_v1_map[0]);