From c26604ff3150babae729890c549f2784212073a1 Mon Sep 17 00:00:00 2001 From: zhongtao Date: Wed, 20 Mar 2024 15:53:56 +0800 Subject: [PATCH 29/43] refactor cgroup module Signed-off-by: zhongtao --- src/cmd/isulad/main.c | 6 + src/daemon/common/CMakeLists.txt | 4 + src/daemon/common/cgroup.c | 625 ---------------- src/daemon/common/cgroup/CMakeLists.txt | 5 + src/daemon/common/cgroup/cgroup.c | 136 ++++ src/daemon/common/cgroup/cgroup.h | 48 ++ src/daemon/common/cgroup/cgroup_common.c | 131 ++++ .../{cgroup.h => cgroup/cgroup_common.h} | 62 +- src/daemon/common/{ => cgroup}/cgroup_v1.c | 699 +++++++++++++++--- src/daemon/common/cgroup/cgroup_v1.h | 30 + src/daemon/common/{ => cgroup}/cgroup_v2.c | 162 ++-- src/daemon/common/cgroup/cgroup_v2.h | 30 + src/daemon/common/sysinfo.c | 33 +- src/daemon/common/sysinfo.h | 4 +- .../v1/v1_cri_pod_sandbox_manager_service.cc | 13 +- .../cri_pod_sandbox_manager_service.cc | 13 +- src/daemon/executor/container_cb/execution.c | 13 +- 17 files changed, 1124 insertions(+), 890 deletions(-) delete mode 100644 src/daemon/common/cgroup.c create mode 100644 src/daemon/common/cgroup/CMakeLists.txt create mode 100644 src/daemon/common/cgroup/cgroup.c create mode 100644 src/daemon/common/cgroup/cgroup.h create mode 100644 src/daemon/common/cgroup/cgroup_common.c rename src/daemon/common/{cgroup.h => cgroup/cgroup_common.h} (60%) rename src/daemon/common/{ => cgroup}/cgroup_v1.c (52%) create mode 100644 src/daemon/common/cgroup/cgroup_v1.h rename src/daemon/common/{ => cgroup}/cgroup_v2.c (88%) create mode 100644 src/daemon/common/cgroup/cgroup_v2.h diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c index 7c0c072e..9fa87bdb 100644 --- a/src/cmd/isulad/main.c +++ b/src/cmd/isulad/main.c @@ -82,6 +82,7 @@ #include "network_api.h" #endif #include "id_name_manager.h" +#include "cgroup.h" sem_t g_daemon_shutdown_sem; sem_t g_daemon_wait_shutdown_sem; @@ -1706,6 +1707,11 @@ static int pre_init_daemon(int argc, char **argv) goto out; } + if (cgroup_ops_init() != 0) { + ERROR("Failed to init cgroup"); + goto out; + } + if (server_conf_parse_save(argc, (const char **)argv)) { ERROR("%s", g_isulad_errmsg ? g_isulad_errmsg : "Failed to parse and save server conf"); goto out; diff --git a/src/daemon/common/CMakeLists.txt b/src/daemon/common/CMakeLists.txt index d634507b..e88578dd 100644 --- a/src/daemon/common/CMakeLists.txt +++ b/src/daemon/common/CMakeLists.txt @@ -9,16 +9,20 @@ if (GRPC_CONNECTOR) add_subdirectory(cri) endif() +add_subdirectory(cgroup) + set(local_daemon_common_srcs ${daemon_common_top_srcs}) set(DAEMON_COMMON_SRCS ${COMMON_CRI_SRCS} + ${COMMON_CGROUP_SRCS} ${local_daemon_common_srcs} PARENT_SCOPE ) set(DAEMON_COMMON_INCS ${COMMON_CRI_INCS} + ${COMMON_CGROUP_INCS} ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE ) diff --git a/src/daemon/common/cgroup.c b/src/daemon/common/cgroup.c deleted file mode 100644 index 3c58f7fa..00000000 --- a/src/daemon/common/cgroup.c +++ /dev/null @@ -1,625 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2017-2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: zhangxiaoyu - * Create: 2023-03-29 - * Description: provide cgroup functions - ******************************************************************************/ -#include "cgroup.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "err_msg.h" -#include "utils.h" -#include "utils_array.h" -#include "sysinfo.h" - -#ifndef CGROUP_SUPER_MAGIC -#define CGROUP_SUPER_MAGIC 0x27e0eb -#endif - -static cgroup_layer_t *new_cgroup_layer(size_t len) -{ - cgroup_layer_t *layers = NULL; - - if (len == 0) { - return NULL; - } - - layers = (cgroup_layer_t *)util_common_calloc_s(sizeof(cgroup_layer_t)); - if (layers == NULL) { - ERROR("Out of memory"); - return NULL; - } - - layers->items = (cgroup_layers_item **)util_smart_calloc_s(sizeof(cgroup_layers_item *), len); - if (layers->items == NULL) { - ERROR("Out of memory"); - free(layers); - return NULL; - } - - layers->len = 0; - layers->cap = len; - - return layers; -} - -static int add_cgroup_layer(cgroup_layer_t *layers, char **clist, char *mountpoint) -{ -#define CGROUP_LAYER_MAX_CAPABILITY 1024 - size_t new_size; - cgroup_layers_item *newh = NULL; - cgroup_layers_item **tmp = NULL; - - if (layers->len >= CGROUP_LAYER_MAX_CAPABILITY) { - ERROR("Too many cgroup layers"); - return -1; - } - - newh = util_common_calloc_s(sizeof(cgroup_layers_item)); - if (newh == NULL) { - ERROR("Out of memory"); - return -1; - } - newh->controllers = clist; - newh->mountpoint = mountpoint; - - if (layers->len < layers->cap) { - goto out; - } - - if (layers->cap > CGROUP_LAYER_MAX_CAPABILITY / 2) { - new_size = CGROUP_LAYER_MAX_CAPABILITY; - } else { - new_size = layers->cap * 2; - } - - if (util_mem_realloc((void **)&tmp, new_size * sizeof(cgroup_layers_item *), - layers->items, layers->cap * sizeof(cgroup_layers_item *)) != 0) { - ERROR("Failed to realloc memory"); - free(newh); - return -1; - } - - layers->items = tmp; - tmp = NULL; - layers->cap = new_size; - -out: - layers->items[layers->len] = newh; - layers->len++; - return 0; -} - -void common_free_cgroup_layer(cgroup_layer_t *layers) -{ - size_t i; - - if (layers == NULL) { - return; - } - - for (i = 0; i < layers->len && layers->items[i]; i++) { - free(layers->items[i]->mountpoint); - layers->items[i]->mountpoint = NULL; - util_free_array(layers->items[i]->controllers); - layers->items[i]->controllers = NULL; - free(layers->items[i]); - layers->items[i] = NULL; - } - - free(layers->items); - layers->items = NULL; - layers->len = 0; - layers->cap = 0; - - free(layers); -} - -static int append_subsystem_to_list(char ***klist, char ***nlist, const char *ptoken) -{ - int ret = 0; - - if (strncmp(ptoken, "name=", strlen("name=")) == 0) { - ret = util_array_append(nlist, ptoken); - if (ret != 0) { - ERROR("Failed to append string"); - return -1; - } - } else { - ret = util_array_append(klist, ptoken); - if (ret != 0) { - ERROR("Failed to append string"); - return -1; - } - } - - return 0; -} - -static int get_cgroup_subsystems(char ***klist, char ***nlist) -{ - int ret = 0; - size_t length = 0; - FILE *fp = NULL; - char *pline = NULL; - - fp = util_fopen("/proc/self/cgroup", "r"); - if (fp == NULL) { - return -1; - } - - while (getline(&pline, &length, fp) != -1) { - char *pos = NULL; - char *pos2 = NULL; - char *ptoken = NULL; - char *psave = NULL; - pos = strchr(pline, ':'); - if (pos == NULL) { - ERROR("Invalid cgroup entry: must contain at least two colons: %s", pline); - ret = -1; - goto out; - } - pos++; - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - ERROR("Invalid cgroup entry: must contain at least two colons: %s", pline); - ret = -1; - goto out; - } - *pos2 = '\0'; - - if ((pos2 - pos) == 0) { - INFO("Not supported cgroup entry: %s", pline); - continue; - } - - for (ptoken = strtok_r(pos, ",", &psave); ptoken; ptoken = strtok_r(NULL, ",", &psave)) { - if (append_subsystem_to_list(klist, nlist, ptoken)) { - goto out; - } - } - } - -out: - free(pline); - fclose(fp); - if (ret != 0) { - util_free_array(*klist); - *klist = NULL; - util_free_array(*nlist); - *nlist = NULL; - } - return ret; -} - -static int append_controller(const char **klist, const char **nlist, char ***clist, const char *entry) -{ - int ret = 0; - char *dup_entry = NULL; - - if (util_array_contain(klist, entry) && util_array_contain(nlist, entry)) { - ERROR("Refusing to use ambiguous controller \"%s\"", entry); - ERROR("It is both a named and kernel subsystem"); - return -1; - } - - if (strncmp(entry, "name=", 5) == 0) { - dup_entry = util_strdup_s(entry); - } else if (util_array_contain(klist, entry)) { - dup_entry = util_strdup_s(entry); - } else { - dup_entry = util_string_append(entry, "name="); - } - if (dup_entry == NULL) { - ERROR("Out of memory"); - return -1; - } - - ret = util_array_append(clist, dup_entry); - if (ret != 0) { - ERROR("Failed to append array"); - } - - free(dup_entry); - return ret; -} - -static inline bool is_cgroup_mountpoint(const char *mp) -{ - return strncmp(mp, "/sys/fs/cgroup/", strlen("/sys/fs/cgroup/")) == 0; -} - -static char **cgroup_get_controllers(const char **klist, const char **nlist, const char *line) -{ - int index; - char *dup = NULL; - char *pos2 = NULL; - char *tok = NULL; - const char *pos = line; - char *psave = NULL; - char *sep = ","; - char **pret = NULL; - - // line example - // 108 99 0:55 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755 - for (index = 0; index < 4; index++) { - pos = strchr(pos, ' '); - if (pos == NULL) { - ERROR("Invalid mountinfo format \"%s\"", line); - return NULL; - } - pos++; - } - - if (!is_cgroup_mountpoint(pos)) { - return NULL; - } - - pos += strlen("/sys/fs/cgroup/"); - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - ERROR("Invalid mountinfo format \"%s\"", line); - return NULL; - } - - *pos2 = '\0'; - dup = util_strdup_s(pos); - *pos2 = ' '; - - for (tok = strtok_r(dup, sep, &psave); tok; tok = strtok_r(NULL, sep, &psave)) { - if (append_controller(klist, nlist, &pret, tok)) { - ERROR("Failed to append controller"); - util_free_array(pret); - pret = NULL; - break; - } - } - - free(dup); - - return pret; -} - -int cgroup_get_mountpoint_and_root(char *pline, char **mountpoint, char **root) -{ - int index; - char *posmp = NULL; - char *posrt = NULL; - char *pos = pline; - - // find root - // line example - // 108 99 0:55 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755 - for (index = 0; index < 3; index++) { - pos = strchr(pos, ' '); - if (pos == NULL) { - return -1; - } - pos++; - } - posrt = pos; - - // find mountpoint - pos = strchr(pos, ' '); - if (pos == NULL) { - return -1; - } - - *pos = '\0'; - if (root != NULL) { - *root = util_strdup_s(posrt); - } - - pos++; - posmp = pos; - - if (!is_cgroup_mountpoint(posmp)) { - return -1; - } - - pos = strchr(pos + strlen("/sys/fs/cgroup/"), ' '); - if (pos == NULL) { - return -1; - } - *pos = '\0'; - - if (mountpoint != NULL) { - *mountpoint = util_strdup_s(posmp); - } - - return 0; -} - -static bool lists_intersect(const char **controllers, const char **list) -{ - int index; - - if (controllers == NULL || list == NULL) { - return false; - } - - for (index = 0; controllers[index]; index++) { - if (util_array_contain(list, controllers[index])) { - return true; - } - } - - return false; -} - -static bool controller_list_is_dup(const cgroup_layer_t *llist, const char **clist) -{ - size_t index; - - if (llist == NULL) { - return false; - } - - for (index = 0; index < llist->len && llist->items[index]; index++) { - if (lists_intersect((const char **)llist->items[index]->controllers, (const char **)clist)) { - return true; - } - } - - return false; -} - -cgroup_layer_t *common_cgroup_layers_find(void) -{ - int nret; - int ret = 0; - FILE *fp = NULL; - size_t length = 0; - const size_t cgroup_layer_item_num = 10; - char *pline = NULL; - char **klist = NULL; - char **nlist = NULL; - cgroup_layer_t *layers = NULL; - - layers = new_cgroup_layer(cgroup_layer_item_num); - if (layers == NULL) { - ERROR("Failed to new cgroup layer"); - return NULL; - } - - ret = get_cgroup_subsystems(&klist, &nlist); - if (ret != 0) { - ERROR("Failed to retrieve available legacy cgroup controllers\n"); - goto out; - } - - fp = util_fopen("/proc/self/mountinfo", "r"); - if (fp == NULL) { - ERROR("Failed to open \"/proc/self/mountinfo\"\n"); - ret = -1; - goto out; - } - - while (getline(&pline, &length, fp) != -1) { - char *mountpoint = NULL; - char **clist = NULL; - int mret; - - clist = cgroup_get_controllers((const char **)klist, (const char **)nlist, pline); - if (clist == NULL) { - goto list_out; - } - - if (controller_list_is_dup(layers, (const char **)clist)) { - goto list_out; - } - - mret = cgroup_get_mountpoint_and_root(pline, &mountpoint, NULL); - if (mret != 0 || mountpoint == NULL) { - ERROR("Failed parsing mountpoint from \"%s\"\n", pline); - goto list_out; - } - - nret = add_cgroup_layer(layers, clist, mountpoint); - if (nret != 0) { - ERROR("Failed to add hierarchies"); - goto list_out; - } - - continue; -list_out: - util_free_array(clist); - free(mountpoint); - } -out: - util_free_array(klist); - util_free_array(nlist); - if (fp != NULL) { - fclose(fp); - } - free(pline); - - if (ret != 0) { - common_free_cgroup_layer(layers); - return NULL; - } - - return layers; -} - -char *common_find_cgroup_subsystem_mountpoint(const cgroup_layer_t *layers, const char *subsystem) -{ - size_t i; - - for (i = 0; i < layers->len && layers->items[i]; i++) { - char **cit = NULL; - - for (cit = layers->items[i]->controllers; cit && *cit; cit++) { - if (strcmp(*cit, subsystem) == 0) { - return layers->items[i]->mountpoint; - } - } - } - return NULL; -} - -/* find cgroup mountpoint and root */ -int common_find_cgroup_mnt_and_root(const char *subsystem, char **mountpoint, char **root) -{ - int ret = 0; - FILE *fp = NULL; - size_t length = 0; - char *pline = NULL; - - if (subsystem == NULL) { - ERROR("Empty subsystem"); - return -1; - } - - fp = util_fopen("/proc/self/mountinfo", "r"); - if (fp == NULL) { - ERROR("Failed to open \"/proc/self/mountinfo\"\n"); - ret = -1; - goto free_out; - } - - while (getline(&pline, &length, fp) != -1) { - char *dup = NULL; - char *p = NULL; - char *tok = NULL; - char *mp = NULL; - char *rt = NULL; - char *saveptr = NULL; - char *sep = ","; - int mret; - - mret = cgroup_get_mountpoint_and_root(pline, &mp, &rt); - if (mret != 0 || mp == NULL || rt == NULL) { - goto mp_out; - } - - p = mp; - p += strlen("/sys/fs/cgroup/"); - dup = util_strdup_s(p); - if (dup == NULL) { - ERROR("Out of memory"); - free(mp); - ret = -1; - goto free_out; - } - - for (tok = strtok_r(dup, sep, &saveptr); tok; tok = strtok_r(NULL, sep, &saveptr)) { - if (strcmp(tok, subsystem) != 0) { - continue; - } - if (mountpoint != NULL) { - *mountpoint = mp; - } else { - free(mp); - } - if (root != NULL) { - *root = rt; - } else { - free(rt); - } - free(dup); - goto free_out; - } - free(dup); -mp_out: - free(mp); - free(rt); - continue; - } -free_out: - if (fp != NULL) { - fclose(fp); - } - free(pline); - return ret; -} - -int common_get_cgroup_version(void) -{ - struct statfs fs = { 0 }; - - if (statfs(CGROUP_MOUNTPOINT, &fs) != 0) { - SYSERROR("failed to statfs %s", CGROUP_MOUNTPOINT); - return -1; - } - - if (fs.f_type == CGROUP2_SUPER_MAGIC) { - return CGROUP_VERSION_2; - } - - return CGROUP_VERSION_1; -} - -static int get_value_ull(const char *content, void *result) -{ - uint64_t ull_result = 0; - - if (util_safe_uint64(content, &ull_result) != 0) { - ERROR("Failed to convert %s to uint64", content); - return -1; - } - - *(uint64_t *)result = ull_result; - return 0; -} - -int get_match_value_ull(const char *content, const char *match, void *result) -{ - __isula_auto_free char *llu_string = NULL; - __isula_auto_free char *match_with_space = NULL; - __isula_auto_array_t char **lines = NULL; - char **worker = NULL; - - if (match == NULL) { - return get_value_ull(content, result); - } - - // match full string - match_with_space = util_string_append(" ", match); - if (match_with_space == NULL) { - ERROR("Failed to append string"); - return -1; - } - - lines = util_string_split(content, '\n'); - if (lines == NULL) { - ERROR("Failed to split content %s", content); - return -1; - } - - for (worker = lines; worker && *worker; worker++) { - if (util_has_prefix(*worker, match_with_space)) { - break; - } - } - if (*worker == NULL) { - ERROR("Cannot find match string %s", match); - return -1; - } - - llu_string = util_sub_string(*worker, strlen(match_with_space), strlen(*worker) - strlen(match_with_space)); - if (llu_string == NULL) { - ERROR("Failed to sub string"); - return -1; - } - llu_string = util_trim_space(llu_string); - - return get_value_ull(llu_string, result); -} \ No newline at end of file diff --git a/src/daemon/common/cgroup/CMakeLists.txt b/src/daemon/common/cgroup/CMakeLists.txt new file mode 100644 index 00000000..e8c1726c --- /dev/null +++ b/src/daemon/common/cgroup/CMakeLists.txt @@ -0,0 +1,5 @@ +# get current directory sources files +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} local_common_cgroup_srcs) + +set(COMMON_CGROUP_SRCS ${local_common_cgroup_srcs} PARENT_SCOPE) +set(COMMON_CGROUP_INCS ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) diff --git a/src/daemon/common/cgroup/cgroup.c b/src/daemon/common/cgroup/cgroup.c new file mode 100644 index 00000000..837b514a --- /dev/null +++ b/src/daemon/common/cgroup/cgroup.c @@ -0,0 +1,136 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2017-2023. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: zhangxiaoyu + * Create: 2023-03-29 + * Description: provide cgroup functions + ******************************************************************************/ +#include "cgroup.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "err_msg.h" +#include "utils.h" +#include "utils_array.h" +#include "sysinfo.h" +#include "cgroup_v1.h" +#include "cgroup_v2.h" +#include "path.h" + +#ifndef CGROUP_SUPER_MAGIC +#define CGROUP_SUPER_MAGIC 0x27e0eb +#endif + +static cgroup_ops g_cgroup_ops; + +static int get_cgroup_version_for_init(void) +{ + struct statfs fs = { 0 }; + + if (statfs(CGROUP_MOUNTPOINT, &fs) != 0) { + SYSERROR("failed to statfs %s", CGROUP_MOUNTPOINT); + return -1; + } + + if (fs.f_type == CGROUP2_SUPER_MAGIC) { + return CGROUP_VERSION_2; + } + + return CGROUP_VERSION_1; +} + +/* connect client ops init */ +int cgroup_ops_init(void) +{ + (void)memset(&g_cgroup_ops, 0, sizeof(g_cgroup_ops)); + int cgroupVersion = get_cgroup_version_for_init(); + if (cgroupVersion < 0) { + ERROR("Invalid cgroup version"); + return -1; + } + + if (cgroupVersion == CGROUP_VERSION_1) { + return cgroup_v1_ops_init(&g_cgroup_ops); + } else { + return cgroup_v2_ops_init(&g_cgroup_ops); + } +} + +int common_get_cgroup_version(void) +{ + if (g_cgroup_ops.get_cgroup_version == NULL) { + ERROR("Unimplemented get_cgroup_version ops"); + return -1; + } + + return g_cgroup_ops.get_cgroup_version(); +} + +int common_get_cgroup_info(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, + cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, + cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, + cgroup_files_info_t *filesinfo, bool quiet) +{ + if (g_cgroup_ops.get_cgroup_info == NULL) { + ERROR("Unimplemented get_cgroup_info ops"); + return -1; + } + + return g_cgroup_ops.get_cgroup_info(meminfo, cpuinfo, hugetlbinfo, blkioinfo, cpusetinfo, pidsinfo, filesinfo, quiet); +} + +int common_get_cgroup_metrics(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics) +{ + if (g_cgroup_ops.get_cgroup_metrics == NULL) { + ERROR("Unimplemented get_cgroup_metrics ops"); + return -1; + } + + return g_cgroup_ops.get_cgroup_metrics(cgroup_path, cgroup_metrics); +} + +int common_get_cgroup_mnt_and_root_path(const char *subsystem, char **mountpoint, char **root) +{ + if (g_cgroup_ops.get_cgroup_mnt_and_root_path == NULL) { + ERROR("Unimplemented get_cgroup_mnt_and_root_path ops"); + return -1; + } + + return g_cgroup_ops.get_cgroup_mnt_and_root_path(subsystem, mountpoint, root); +} + +// only for cgroup v1 +char *common_get_init_cgroup_path(const char *subsystem) +{ + if (g_cgroup_ops.get_init_cgroup_path == NULL) { + ERROR("Unimplemented get_init_cgroup_path ops"); + return NULL; + } + + return g_cgroup_ops.get_init_cgroup_path(subsystem); +} + +char *common_get_own_cgroup_path(const char *subsystem) +{ + if (g_cgroup_ops.get_own_cgroup_path == NULL) { + ERROR("Unimplemented get_own_cgroup_path ops"); + return NULL; + } + + return g_cgroup_ops.get_own_cgroup_path(subsystem); +} \ No newline at end of file diff --git a/src/daemon/common/cgroup/cgroup.h b/src/daemon/common/cgroup/cgroup.h new file mode 100644 index 00000000..1efc3ca6 --- /dev/null +++ b/src/daemon/common/cgroup/cgroup.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2017-2023. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: zhangxiaoyu + * Create: 2023-03-29 + * Description: provide cgroup definition + ******************************************************************************/ +#ifndef DAEMON_COMMON_CGROUP_H +#define DAEMON_COMMON_CGROUP_H + +#include +#include +#include + +#include + +#include "cgroup_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int cgroup_ops_init(void); + +int common_get_cgroup_version(void); +int common_get_cgroup_info(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, + cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, + cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, + cgroup_files_info_t *filesinfo, bool quiet); +int common_get_cgroup_metrics(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics); +int common_get_cgroup_mnt_and_root_path(const char *subsystem, char **mountpoint, char **root); + +// only for cgroup v1 +char *common_get_init_cgroup_path(const char *subsystem); +char *common_get_own_cgroup_path(const char *subsystem); + +#ifdef __cplusplus +} +#endif + +#endif // DAEMON_COMMON_CGROUP_H diff --git a/src/daemon/common/cgroup/cgroup_common.c b/src/daemon/common/cgroup/cgroup_common.c new file mode 100644 index 00000000..0fb9405c --- /dev/null +++ b/src/daemon/common/cgroup/cgroup_common.c @@ -0,0 +1,131 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: zhongtao + * Create: 2024-03-22 + * Description: provide cgroup common func definition + ******************************************************************************/ +#include "cgroup_common.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "err_msg.h" +#include "utils.h" +#include "utils_array.h" +#include "sysinfo.h" +#include "cgroup_v1.h" +#include "cgroup_v2.h" +#include "path.h" + +static int get_value_ull(const char *content, void *result) +{ + uint64_t ull_result = 0; + + if (util_safe_uint64(content, &ull_result) != 0) { + ERROR("Failed to convert %s to uint64", content); + return -1; + } + + *(uint64_t *)result = ull_result; + return 0; +} + +int get_match_value_ull(const char *content, const char *match, void *result) +{ + __isula_auto_free char *llu_string = NULL; + __isula_auto_free char *match_with_space = NULL; + __isula_auto_array_t char **lines = NULL; + char **worker = NULL; + + if (match == NULL) { + return get_value_ull(content, result); + } + + // match full string + match_with_space = util_string_append(" ", match); + if (match_with_space == NULL) { + ERROR("Failed to append string"); + return -1; + } + + lines = util_string_split(content, '\n'); + if (lines == NULL) { + ERROR("Failed to split content %s", content); + return -1; + } + + for (worker = lines; worker && *worker; worker++) { + if (util_has_prefix(*worker, match_with_space)) { + break; + } + } + if (*worker == NULL) { + ERROR("Cannot find match string %s", match); + return -1; + } + + llu_string = util_sub_string(*worker, strlen(match_with_space), strlen(*worker) - strlen(match_with_space)); + if (llu_string == NULL) { + ERROR("Failed to sub string"); + return -1; + } + llu_string = util_trim_space(llu_string); + + return get_value_ull(llu_string, result); +} + +int get_cgroup_value_helper(const char *path, struct cgfile_t *cgfile, void *result) +{ + int nret = 0; + char file_path[PATH_MAX] = { 0 }; + char real_path[PATH_MAX] = { 0 }; + char *content = NULL; + + if (path == NULL || strlen(path) == 0 || result == NULL) { + ERROR("%s: Invalid arguments", cgfile->name); + return -1; + } + + nret = snprintf(file_path, sizeof(file_path), "%s/%s", path, cgfile->file); + if (nret < 0 || (size_t)nret >= sizeof(file_path)) { + ERROR("%s: failed to snprintf", cgfile->name); + return -1; + } + + if (util_clean_path(file_path, real_path, sizeof(real_path)) == NULL) { + ERROR("%s: failed to clean path %s", cgfile->name, file_path); + return -1; + } + + content = util_read_content_from_file(real_path); + if (content == NULL) { + ERROR("%s: failed to read file %s", cgfile->name, real_path); + return -1; + } + + util_trim_newline(content); + content = util_trim_space(content); + + nret = cgfile->get_value(content, cgfile->match, result); + if (nret != 0) { + ERROR("%s: failed to get value", cgfile->name); + } + + free(content); + return nret; +} \ No newline at end of file diff --git a/src/daemon/common/cgroup.h b/src/daemon/common/cgroup/cgroup_common.h similarity index 60% rename from src/daemon/common/cgroup.h rename to src/daemon/common/cgroup/cgroup_common.h index 251e3a3d..2a0935cb 100644 --- a/src/daemon/common/cgroup.h +++ b/src/daemon/common/cgroup/cgroup_common.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2017-2023. All rights reserved. + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. * iSulad licensed under the Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: @@ -8,12 +8,12 @@ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR * PURPOSE. * See the Mulan PSL v2 for more details. - * Author: zhangxiaoyu - * Create: 2023-03-29 - * Description: provide cgroup definition + * Author: zhongtao + * Create: 2024-03-22 + * Description: provide cgroup common func definition ******************************************************************************/ -#ifndef DAEMON_COMMON_CGROUP_H -#define DAEMON_COMMON_CGROUP_H +#ifndef DAEMON_COMMON_CGROUP_COMMON_H +#define DAEMON_COMMON_CGROUP_COMMON_H #include #include @@ -40,10 +40,6 @@ struct cgfile_t { int get_match_value_ull(const char *content, const char *match, void *result); -int common_get_cgroup_version(void); - -int common_find_cgroup_mnt_and_root(const char *subsystem, char **mountpoint, char **root); - static inline void common_cgroup_do_log(bool quiet, bool do_log, const char *msg) { if (!quiet && do_log) { @@ -51,23 +47,7 @@ static inline void common_cgroup_do_log(bool quiet, bool do_log, const char *msg } } -typedef struct { - char **controllers; - char *mountpoint; -} cgroup_layers_item; - -typedef struct { - cgroup_layers_item **items; - size_t len; - size_t cap; -} cgroup_layer_t; - -char *common_find_cgroup_subsystem_mountpoint(const cgroup_layer_t *layers, const char *subsystem); - -cgroup_layer_t *common_cgroup_layers_find(void); - -void common_free_cgroup_layer(cgroup_layer_t *layers); - +int get_cgroup_value_helper(const char *path, struct cgfile_t *cgfile, void *result); typedef struct { bool limit; @@ -113,17 +93,6 @@ typedef struct { bool fileslimit; } cgroup_files_info_t; -int common_get_cgroup_info_v1(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, - cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, - cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, - cgroup_files_info_t *filesinfo, bool quiet); - -int common_get_cgroup_info_v2(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, - cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, - cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, - cgroup_files_info_t *filesinfo, bool quiet); - - typedef struct { uint64_t cpu_use_nanos; } cgroup_cpu_metrics_t; @@ -147,15 +116,22 @@ typedef struct { cgroup_pids_metrics_t cgpids_metrics; } cgroup_metrics_t; -int common_get_cgroup_v1_metrics(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics); -int common_get_cgroup_v2_metrics(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics); +typedef struct { + int (*get_cgroup_version)(void); + int (*get_cgroup_info)(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, + cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, + cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, + cgroup_files_info_t *filesinfo, bool quiet); + int (*get_cgroup_metrics)(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics); -char *common_get_init_cgroup(const char *subsystem); + int (*get_cgroup_mnt_and_root_path)(const char *subsystem, char **mountpoint, char **root); -char *common_get_own_cgroup(const char *subsystem); + char *(*get_init_cgroup_path)(const char *subsystem); + char *(*get_own_cgroup_path)(const char *subsystem); +} cgroup_ops; #ifdef __cplusplus } #endif -#endif // DAEMON_COMMON_CGROUP_H +#endif // DAEMON_COMMON_CGROUP_COMMON_H diff --git a/src/daemon/common/cgroup_v1.c b/src/daemon/common/cgroup/cgroup_v1.c similarity index 52% rename from src/daemon/common/cgroup_v1.c rename to src/daemon/common/cgroup/cgroup_v1.c index e34100bc..51cf7512 100644 --- a/src/daemon/common/cgroup_v1.c +++ b/src/daemon/common/cgroup/cgroup_v1.c @@ -18,13 +18,31 @@ #include #include "utils.h" -#include "path.h" #include "sysinfo.h" +#include "err_msg.h" #define CGROUP_HUGETLB_LIMIT "hugetlb.%s.limit_in_bytes" +#define CGROUP_MOUNT_PATH_PREFIX "/sys/fs/cgroup/" -static int get_value_ll(const char *content, const char *match, void *result); -static int get_value_string(const char *content, const char *match, void *result); + +static int get_value_ll(const char *content, const char *match, void *result) +{ + long long ll_result = 0; + + if (util_safe_llong(content, &ll_result) != 0) { + ERROR("Failed to convert %s to long long", content); + return -1; + } + + *(int64_t *)result = (int64_t)ll_result; + return 0; +} + +static int get_value_string(const char *content, const char *match, void *result) +{ + *(char **)result = util_strdup_s(content); + return 0; +} typedef enum { // CPU subsystem @@ -90,105 +108,579 @@ static struct cgfile_t g_cgroup_v1_files[] = { [PIDS_CURRENT] = {"pids_current", "pids.current", NULL, get_match_value_ull}, }; -static int get_value_ll(const char *content, const char *match, void *result) +typedef struct { + char **controllers; + char *mountpoint; +} cgroup_layers_item; + +typedef struct { + cgroup_layers_item **items; + size_t len; + size_t cap; +} cgroup_layer_t; + +static char *common_find_cgroup_subsystem_mountpoint(const cgroup_layer_t *layers, const char *subsystem) { - long long ll_result = 0; + size_t i; - if (util_safe_llong(content, &ll_result) != 0) { - ERROR("Failed to convert %s to long long", content); + for (i = 0; i < layers->len && layers->items[i]; i++) { + char **cit = NULL; + + for (cit = layers->items[i]->controllers; cit && *cit; cit++) { + if (strcmp(*cit, subsystem) == 0) { + return layers->items[i]->mountpoint; + } + } + } + return NULL; +} + + +static cgroup_layer_t *new_cgroup_layer(size_t len) +{ + cgroup_layer_t *layers = NULL; + + if (len == 0) { + return NULL; + } + + layers = (cgroup_layer_t *)util_common_calloc_s(sizeof(cgroup_layer_t)); + if (layers == NULL) { + ERROR("Out of memory"); + return NULL; + } + + layers->items = (cgroup_layers_item **)util_smart_calloc_s(sizeof(cgroup_layers_item *), len); + if (layers->items == NULL) { + ERROR("Out of memory"); + free(layers); + return NULL; + } + + layers->len = 0; + layers->cap = len; + + return layers; +} + +static int add_cgroup_layer(cgroup_layer_t *layers, char **clist, char *mountpoint) +{ +#define CGROUP_LAYER_MAX_CAPABILITY 1024 + size_t new_size; + cgroup_layers_item *newh = NULL; + cgroup_layers_item **tmp = NULL; + + if (layers->len >= CGROUP_LAYER_MAX_CAPABILITY) { + ERROR("Too many cgroup layers"); return -1; } - *(int64_t *)result = (int64_t)ll_result; + newh = util_common_calloc_s(sizeof(cgroup_layers_item)); + if (newh == NULL) { + ERROR("Out of memory"); + return -1; + } + newh->controllers = clist; + newh->mountpoint = mountpoint; + + if (layers->len < layers->cap) { + goto out; + } + + if (layers->cap > CGROUP_LAYER_MAX_CAPABILITY / 2) { + new_size = CGROUP_LAYER_MAX_CAPABILITY; + } else { + new_size = layers->cap * 2; + } + + if (util_mem_realloc((void **)&tmp, new_size * sizeof(cgroup_layers_item *), + layers->items, layers->cap * sizeof(cgroup_layers_item *)) != 0) { + ERROR("Failed to realloc memory"); + free(newh); + return -1; + } + + layers->items = tmp; + tmp = NULL; + layers->cap = new_size; + +out: + layers->items[layers->len] = newh; + layers->len++; return 0; } -static int get_value_string(const char *content, const char *match, void *result) +static void common_free_cgroup_layer(cgroup_layer_t *layers) { - *(char **)result = util_strdup_s(content); + size_t i; + + if (layers == NULL) { + return; + } + + for (i = 0; i < layers->len && layers->items[i]; i++) { + free(layers->items[i]->mountpoint); + layers->items[i]->mountpoint = NULL; + util_free_array(layers->items[i]->controllers); + layers->items[i]->controllers = NULL; + free(layers->items[i]); + layers->items[i] = NULL; + } + + free(layers->items); + layers->items = NULL; + layers->len = 0; + layers->cap = 0; + + free(layers); +} + +static int append_subsystem_to_list(char ***klist, char ***nlist, const char *ptoken) +{ + int ret = 0; + + if (strncmp(ptoken, "name=", strlen("name=")) == 0) { + ret = util_array_append(nlist, ptoken); + if (ret != 0) { + ERROR("Failed to append string"); + return -1; + } + } else { + ret = util_array_append(klist, ptoken); + if (ret != 0) { + ERROR("Failed to append string"); + return -1; + } + } + return 0; } -static bool check_cgroup_v1_helper(const char *mountpoint, const cgroup_v1_files_index index, const bool quiet) +static int get_cgroup_subsystems(char ***klist, char ***nlist) { - int nret = 0; - char path[PATH_MAX] = { 0 }; + int ret = 0; + size_t length = 0; + FILE *fp = NULL; + char *pline = NULL; - if (index >= CGROUP_V1_FILES_INDEX_MAXS) { - ERROR("Index out of range"); - return false; + fp = util_fopen("/proc/self/cgroup", "r"); + if (fp == NULL) { + return -1; } - if (mountpoint == NULL) { - ERROR("%s: invalid arguments", g_cgroup_v1_files[index].name); - return false; + while (getline(&pline, &length, fp) != -1) { + char *pos = NULL; + char *pos2 = NULL; + char *ptoken = NULL; + char *psave = NULL; + pos = strchr(pline, ':'); + if (pos == NULL) { + ERROR("Invalid cgroup entry: must contain at least two colons: %s", pline); + ret = -1; + goto out; + } + pos++; + pos2 = strchr(pos, ':'); + if (pos2 == NULL) { + ERROR("Invalid cgroup entry: must contain at least two colons: %s", pline); + ret = -1; + goto out; + } + *pos2 = '\0'; + + if ((pos2 - pos) == 0) { + INFO("Not supported cgroup entry: %s", pline); + continue; + } + + for (ptoken = strtok_r(pos, ",", &psave); ptoken; ptoken = strtok_r(NULL, ",", &psave)) { + if (append_subsystem_to_list(klist, nlist, ptoken)) { + goto out; + } + } } - nret = snprintf(path, sizeof(path), "%s/%s", mountpoint, g_cgroup_v1_files[index].file); - if (nret < 0 || (size_t)nret >= sizeof(path)) { - ERROR("%s: failed to snprintf", g_cgroup_v1_files[index].name); - return false; +out: + free(pline); + fclose(fp); + if (ret != 0) { + util_free_array(*klist); + *klist = NULL; + util_free_array(*nlist); + *nlist = NULL; } + return ret; +} - if (util_file_exists(path)) { - return true; +static int append_controller(const char **klist, const char **nlist, char ***clist, const char *entry) +{ + int ret = 0; + char *dup_entry = NULL; + + if (util_array_contain(klist, entry) && util_array_contain(nlist, entry)) { + ERROR("Refusing to use ambiguous controller \"%s\"", entry); + ERROR("It is both a named and kernel subsystem"); + return -1; } - if (!quiet) { - WARN("Your kernel does not support cgroup %s", g_cgroup_v1_files[index].name); + if (strncmp(entry, "name=", 5) == 0) { + dup_entry = util_strdup_s(entry); + } else if (util_array_contain(klist, entry)) { + dup_entry = util_strdup_s(entry); + } else { + dup_entry = util_string_append(entry, "name="); + } + if (dup_entry == NULL) { + ERROR("Out of memory"); + return -1; + } + + ret = util_array_append(clist, dup_entry); + if (ret != 0) { + ERROR("Failed to append array"); + } + + free(dup_entry); + return ret; +} + +static inline bool is_cgroup_mountpoint(const char *mp) +{ + return strncmp(mp, CGROUP_MOUNT_PATH_PREFIX, strlen(CGROUP_MOUNT_PATH_PREFIX)) == 0; +} + +static char **cgroup_get_controllers(const char **klist, const char **nlist, const char *line) +{ + int index; + char *dup = NULL; + char *pos2 = NULL; + char *tok = NULL; + const char *pos = line; + char *psave = NULL; + char *sep = ","; + char **pret = NULL; + + // line example + // 108 99 0:55 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755 + for (index = 0; index < 4; index++) { + pos = strchr(pos, ' '); + if (pos == NULL) { + ERROR("Invalid mountinfo format \"%s\"", line); + return NULL; + } + pos++; + } + + if (!is_cgroup_mountpoint(pos)) { + return NULL; + } + + pos += strlen(CGROUP_MOUNT_PATH_PREFIX); + pos2 = strchr(pos, ' '); + if (pos2 == NULL) { + ERROR("Invalid mountinfo format \"%s\"", line); + return NULL; + } + + *pos2 = '\0'; + dup = util_strdup_s(pos); + *pos2 = ' '; + + for (tok = strtok_r(dup, sep, &psave); tok; tok = strtok_r(NULL, sep, &psave)) { + if (append_controller(klist, nlist, &pret, tok)) { + ERROR("Failed to append controller"); + util_free_array(pret); + pret = NULL; + break; + } + } + + free(dup); + + return pret; +} + +static bool lists_intersect(const char **controllers, const char **list) +{ + int index; + + if (controllers == NULL || list == NULL) { + return false; + } + + for (index = 0; controllers[index]; index++) { + if (util_array_contain(list, controllers[index])) { + return true; + } } return false; } -static int get_cgroup_v1_value_helper(const char *path, const cgroup_v1_files_index index, - void *result) +static bool controller_list_is_dup(const cgroup_layer_t *llist, const char **clist) { - int nret = 0; - char file_path[PATH_MAX] = { 0 }; - char real_path[PATH_MAX] = { 0 }; - char *content = NULL; + size_t index; - if (index >= CGROUP_V1_FILES_INDEX_MAXS) { - ERROR("Index out of range"); + if (llist == NULL) { return false; } - if (path == NULL || strlen(path) == 0 || result == NULL) { - ERROR("%s: Invalid arguments", g_cgroup_v1_files[index].name); + for (index = 0; index < llist->len && llist->items[index]; index++) { + if (lists_intersect((const char **)llist->items[index]->controllers, (const char **)clist)) { + return true; + } + } + + return false; +} + +static int cgroup_get_mountpoint_and_root(char *pline, char **mountpoint, char **root) +{ + int index; + char *posmp = NULL; + char *posrt = NULL; + char *pos = pline; + + // find root + // line example + // 108 99 0:55 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755 + for (index = 0; index < 3; index++) { + pos = strchr(pos, ' '); + if (pos == NULL) { + return -1; + } + pos++; + } + posrt = pos; + + // find mountpoint + pos = strchr(pos, ' '); + if (pos == NULL) { return -1; } - nret = snprintf(file_path, sizeof(file_path), "%s/%s", path, g_cgroup_v1_files[index].file); - if (nret < 0 || (size_t)nret >= sizeof(file_path)) { - ERROR("%s: failed to snprintf", g_cgroup_v1_files[index].name); + *pos = '\0'; + if (root != NULL) { + *root = util_strdup_s(posrt); + } + + pos++; + posmp = pos; + + if (!is_cgroup_mountpoint(posmp)) { return -1; } - if (util_clean_path(file_path, real_path, sizeof(real_path)) == NULL) { - ERROR("%s: failed to clean path %s", g_cgroup_v1_files[index].name, file_path); + pos = strchr(pos + strlen(CGROUP_MOUNT_PATH_PREFIX), ' '); + if (pos == NULL) { return -1; } + *pos = '\0'; + + if (mountpoint != NULL) { + *mountpoint = util_strdup_s(posmp); + } + + return 0; +} + +/* find cgroup mountpoint and root */ +static int get_cgroup_mnt_and_root_path_v1(const char *subsystem, char **mountpoint, char **root) +{ + int ret = 0; + FILE *fp = NULL; + size_t length = 0; + char *pline = NULL; - content = util_read_content_from_file(real_path); - if (content == NULL) { - ERROR("%s: failed to read file %s", g_cgroup_v1_files[index].name, real_path); + if (subsystem == NULL) { + ERROR("Empty subsystem"); return -1; } - util_trim_newline(content); - content = util_trim_space(content); + fp = util_fopen("/proc/self/mountinfo", "r"); + if (fp == NULL) { + ERROR("Failed to open \"/proc/self/mountinfo\"\n"); + ret = -1; + goto free_out; + } + + while (getline(&pline, &length, fp) != -1) { + char *dup = NULL; + char *p = NULL; + char *tok = NULL; + char *mp = NULL; + char *rt = NULL; + char *saveptr = NULL; + char *sep = ","; + int mret; + + mret = cgroup_get_mountpoint_and_root(pline, &mp, &rt); + if (mret != 0 || mp == NULL || rt == NULL) { + goto mp_out; + } + + p = mp; + p += strlen(CGROUP_MOUNT_PATH_PREFIX); + dup = util_strdup_s(p); + if (dup == NULL) { + ERROR("Out of memory"); + free(mp); + ret = -1; + goto free_out; + } + + for (tok = strtok_r(dup, sep, &saveptr); tok; tok = strtok_r(NULL, sep, &saveptr)) { + if (strcmp(tok, subsystem) != 0) { + continue; + } + if (mountpoint != NULL) { + *mountpoint = mp; + } else { + free(mp); + } + if (root != NULL) { + *root = rt; + } else { + free(rt); + } + free(dup); + goto free_out; + } + free(dup); +mp_out: + free(mp); + free(rt); + continue; + } +free_out: + if (fp != NULL) { + fclose(fp); + } + free(pline); + return ret; +} + +static cgroup_layer_t *common_cgroup_layers_find(void) +{ + int nret; + int ret = 0; + FILE *fp = NULL; + size_t length = 0; + const size_t cgroup_layer_item_num = 10; + char *pline = NULL; + char **klist = NULL; + char **nlist = NULL; + cgroup_layer_t *layers = NULL; + + layers = new_cgroup_layer(cgroup_layer_item_num); + if (layers == NULL) { + ERROR("Failed to new cgroup layer"); + return NULL; + } + + ret = get_cgroup_subsystems(&klist, &nlist); + if (ret != 0) { + ERROR("Failed to retrieve available legacy cgroup controllers\n"); + goto out; + } + + fp = util_fopen("/proc/self/mountinfo", "r"); + if (fp == NULL) { + ERROR("Failed to open \"/proc/self/mountinfo\"\n"); + ret = -1; + goto out; + } + + while (getline(&pline, &length, fp) != -1) { + char *mountpoint = NULL; + char **clist = NULL; + int mret; + + clist = cgroup_get_controllers((const char **)klist, (const char **)nlist, pline); + if (clist == NULL) { + goto list_out; + } + + if (controller_list_is_dup(layers, (const char **)clist)) { + goto list_out; + } + + mret = cgroup_get_mountpoint_and_root(pline, &mountpoint, NULL); + if (mret != 0 || mountpoint == NULL) { + ERROR("Failed parsing mountpoint from \"%s\"\n", pline); + goto list_out; + } + + nret = add_cgroup_layer(layers, clist, mountpoint); + if (nret != 0) { + ERROR("Failed to add hierarchies"); + goto list_out; + } + + continue; +list_out: + util_free_array(clist); + free(mountpoint); + } +out: + util_free_array(klist); + util_free_array(nlist); + if (fp != NULL) { + fclose(fp); + } + free(pline); + + if (ret != 0) { + common_free_cgroup_layer(layers); + return NULL; + } + + return layers; +} + +static int get_cgroup_v1_value_helper(const char *path, const cgroup_v1_files_index index, void *result) +{ + if (index >= CGROUP_V1_FILES_INDEX_MAXS) { + ERROR("Index out of range"); + return false; + } + + return get_cgroup_value_helper(path, &g_cgroup_v1_files[index], result); +} + +static bool check_cgroup_v1_file_exists(const char *mountpoint, const cgroup_v1_files_index index, const bool quiet) +{ + int nret = 0; + char path[PATH_MAX] = { 0 }; + + if (index >= CGROUP_V1_FILES_INDEX_MAXS) { + ERROR("Index out of range"); + return false; + } + + if (mountpoint == NULL) { + ERROR("%s: invalid arguments", g_cgroup_v1_files[index].name); + return false; + } + + nret = snprintf(path, sizeof(path), "%s/%s", mountpoint, g_cgroup_v1_files[index].file); + if (nret < 0 || (size_t)nret >= sizeof(path)) { + ERROR("%s: failed to snprintf", g_cgroup_v1_files[index].name); + return false; + } - nret = g_cgroup_v1_files[index].get_value(content, g_cgroup_v1_files[index].match, result); - if (nret != 0) { - ERROR("%s: failed to get value", g_cgroup_v1_files[index].name); + if (util_file_exists(path)) { + return true; } - free(content); - return nret; + if (!quiet) { + WARN("Your kernel does not support cgroup %s", g_cgroup_v1_files[index].name); + } + + return false; } -static void check_cgroup_v1_cpu(const cgroup_layer_t *layers, const bool quiet, cgroup_cpu_info_t *cpuinfo) +static void get_cgroup_v1_cpu_info(const cgroup_layer_t *layers, const bool quiet, cgroup_cpu_info_t *cpuinfo) { char *mountpoint = NULL; @@ -198,14 +690,14 @@ static void check_cgroup_v1_cpu(const cgroup_layer_t *layers, const bool quiet, return; } - cpuinfo->cpu_rt_period = check_cgroup_v1_helper(mountpoint, CPU_RT_PERIOD, quiet); - cpuinfo->cpu_rt_runtime = check_cgroup_v1_helper(mountpoint, CPU_RT_RUNTIME, quiet); - cpuinfo->cpu_shares = check_cgroup_v1_helper(mountpoint, CPU_SHARES, quiet); - cpuinfo->cpu_cfs_period = check_cgroup_v1_helper(mountpoint, CPU_CFS_PERIOD, quiet); - cpuinfo->cpu_cfs_quota = check_cgroup_v1_helper(mountpoint, CPU_CFS_QUOTA, quiet); + cpuinfo->cpu_rt_period = check_cgroup_v1_file_exists(mountpoint, CPU_RT_PERIOD, quiet); + cpuinfo->cpu_rt_runtime = check_cgroup_v1_file_exists(mountpoint, CPU_RT_RUNTIME, quiet); + cpuinfo->cpu_shares = check_cgroup_v1_file_exists(mountpoint, CPU_SHARES, quiet); + cpuinfo->cpu_cfs_period = check_cgroup_v1_file_exists(mountpoint, CPU_CFS_PERIOD, quiet); + cpuinfo->cpu_cfs_quota = check_cgroup_v1_file_exists(mountpoint, CPU_CFS_QUOTA, quiet); } -static void check_cgroup_v1_cpuset(const cgroup_layer_t *layers, const bool quiet, cgroup_cpuset_info_t *cpusetinfo) +static void get_cgroup_v1_cpuset_info(const cgroup_layer_t *layers, const bool quiet, cgroup_cpuset_info_t *cpusetinfo) { char *mountpoint = NULL; @@ -215,10 +707,10 @@ static void check_cgroup_v1_cpuset(const cgroup_layer_t *layers, const bool quie return; } - if (!check_cgroup_v1_helper(mountpoint, CPUSET_CPUS, quiet)) { + if (!check_cgroup_v1_file_exists(mountpoint, CPUSET_CPUS, quiet)) { return; } - if (!check_cgroup_v1_helper(mountpoint, CPUSET_MEMS, quiet)) { + if (!check_cgroup_v1_file_exists(mountpoint, CPUSET_MEMS, quiet)) { return; } @@ -238,7 +730,7 @@ static void check_cgroup_v1_cpuset(const cgroup_layer_t *layers, const bool quie cpusetinfo->cpuset = true; } -static void check_cgroup_v1_mem(const cgroup_layer_t *layers, const bool quiet, cgroup_mem_info_t *meminfo) +static void get_cgroup_v1_mem_info(const cgroup_layer_t *layers, const bool quiet, cgroup_mem_info_t *meminfo) { char *mountpoint = NULL; @@ -248,15 +740,15 @@ static void check_cgroup_v1_mem(const cgroup_layer_t *layers, const bool quiet, return; } - meminfo->limit = check_cgroup_v1_helper(mountpoint, MEMORY_LIMIT, quiet); - meminfo->swap = check_cgroup_v1_helper(mountpoint, MEMORY_SW_LIMIT, quiet); - meminfo->reservation = check_cgroup_v1_helper(mountpoint, MEMORY_SOFT_LIMIT, quiet); - meminfo->oomkilldisable = check_cgroup_v1_helper(mountpoint, MEMORY_OOM_CONTROL, quiet); - meminfo->swappiness = check_cgroup_v1_helper(mountpoint, MEMORY_SWAPPINESS, quiet); - meminfo->kernel = check_cgroup_v1_helper(mountpoint, MEMORY_KMEM_LIMIT, quiet); + meminfo->limit = check_cgroup_v1_file_exists(mountpoint, MEMORY_LIMIT, quiet); + meminfo->swap = check_cgroup_v1_file_exists(mountpoint, MEMORY_SW_LIMIT, quiet); + meminfo->reservation = check_cgroup_v1_file_exists(mountpoint, MEMORY_SOFT_LIMIT, quiet); + meminfo->oomkilldisable = check_cgroup_v1_file_exists(mountpoint, MEMORY_OOM_CONTROL, quiet); + meminfo->swappiness = check_cgroup_v1_file_exists(mountpoint, MEMORY_SWAPPINESS, quiet); + meminfo->kernel = check_cgroup_v1_file_exists(mountpoint, MEMORY_KMEM_LIMIT, quiet); } -static void check_cgroup_v1_blkio(const cgroup_layer_t *layers, const bool quiet, cgroup_blkio_info_t *blkioinfo) +static void get_cgroup_v1_blkio_info(const cgroup_layer_t *layers, const bool quiet, cgroup_blkio_info_t *blkioinfo) { char *mountpoint = NULL; @@ -266,15 +758,15 @@ static void check_cgroup_v1_blkio(const cgroup_layer_t *layers, const bool quiet return; } - blkioinfo->blkio_weight = check_cgroup_v1_helper(mountpoint, BLKIO_WEIGTH, quiet); - blkioinfo->blkio_weight_device = check_cgroup_v1_helper(mountpoint, BLKIO_WEIGTH_DEVICE, quiet); - blkioinfo->blkio_read_bps_device = check_cgroup_v1_helper(mountpoint, BLKIO_READ_BPS, quiet); - blkioinfo->blkio_write_bps_device = check_cgroup_v1_helper(mountpoint, BLKIO_WRITE_BPS, quiet); - blkioinfo->blkio_read_iops_device = check_cgroup_v1_helper(mountpoint, BLKIO_READ_IOPS, quiet); - blkioinfo->blkio_write_iops_device = check_cgroup_v1_helper(mountpoint, BLKIO_WRITE_IOPS, quiet); + blkioinfo->blkio_weight = check_cgroup_v1_file_exists(mountpoint, BLKIO_WEIGTH, quiet); + blkioinfo->blkio_weight_device = check_cgroup_v1_file_exists(mountpoint, BLKIO_WEIGTH_DEVICE, quiet); + blkioinfo->blkio_read_bps_device = check_cgroup_v1_file_exists(mountpoint, BLKIO_READ_BPS, quiet); + blkioinfo->blkio_write_bps_device = check_cgroup_v1_file_exists(mountpoint, BLKIO_WRITE_BPS, quiet); + blkioinfo->blkio_read_iops_device = check_cgroup_v1_file_exists(mountpoint, BLKIO_READ_IOPS, quiet); + blkioinfo->blkio_write_iops_device = check_cgroup_v1_file_exists(mountpoint, BLKIO_WRITE_IOPS, quiet); } -static void check_cgroup_v1_hugetlb(const cgroup_layer_t *layers, const bool quiet, cgroup_hugetlb_info_t *hugetlbinfo) +static void get_cgroup_v1_hugetlb_info(const cgroup_layer_t *layers, const bool quiet, cgroup_hugetlb_info_t *hugetlbinfo) { int nret; char *mountpoint = NULL; @@ -306,7 +798,7 @@ free_out: free(defaultpagesize); } -static void check_cgroup_v1_pids(const cgroup_layer_t *layers, const bool quiet, cgroup_pids_info_t *pidsinfo) +static void get_cgroup_v1_pids_info(const cgroup_layer_t *layers, const bool quiet, cgroup_pids_info_t *pidsinfo) { char *mountpoint = NULL; @@ -319,7 +811,7 @@ static void check_cgroup_v1_pids(const cgroup_layer_t *layers, const bool quiet, pidsinfo->pidslimit = true; } -static void check_cgroup_v1_files(const cgroup_layer_t *layers, const bool quiet, cgroup_files_info_t *filesinfo) +static void get_cgroup_v1_files_info(const cgroup_layer_t *layers, const bool quiet, cgroup_files_info_t *filesinfo) { char *mountpoint = NULL; @@ -332,7 +824,7 @@ static void check_cgroup_v1_files(const cgroup_layer_t *layers, const bool quiet filesinfo->fileslimit = true; } -int common_get_cgroup_info_v1(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, +static int get_cgroup_info_v1(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, cgroup_files_info_t *filesinfo, bool quiet) @@ -345,13 +837,13 @@ int common_get_cgroup_info_v1(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpu return -1; } - check_cgroup_v1_cpu(layers, quiet, cpuinfo); - check_cgroup_v1_cpuset(layers, quiet, cpusetinfo); - check_cgroup_v1_mem(layers, quiet, meminfo); - check_cgroup_v1_blkio(layers, quiet, blkioinfo); - check_cgroup_v1_hugetlb(layers, quiet, hugetlbinfo); - check_cgroup_v1_pids(layers, quiet, pidsinfo); - check_cgroup_v1_files(layers, quiet, filesinfo); + get_cgroup_v1_cpu_info(layers, quiet, cpuinfo); + get_cgroup_v1_cpuset_info(layers, quiet, cpusetinfo); + get_cgroup_v1_mem_info(layers, quiet, meminfo); + get_cgroup_v1_blkio_info(layers, quiet, blkioinfo); + get_cgroup_v1_hugetlb_info(layers, quiet, hugetlbinfo); + get_cgroup_v1_pids_info(layers, quiet, pidsinfo); + get_cgroup_v1_files_info(layers, quiet, filesinfo); common_free_cgroup_layer(layers); @@ -432,7 +924,7 @@ static void get_cgroup_v1_metrics_pid(const cgroup_layer_t *layers, const char * get_cgroup_v1_value_helper(path, PIDS_CURRENT, (void *)&cgroup_pids_metrics->pid_current); } -int common_get_cgroup_v1_metrics(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics) +static int get_cgroup_metrics_v1(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics) { cgroup_layer_t *layers = NULL; @@ -553,22 +1045,31 @@ static char *common_get_cgroup_path(const char *path, const char *subsystem) return res; } -char *common_get_init_cgroup(const char *subsystem) +char *get_init_cgroup_path_v1(const char *subsystem) { - if (common_get_cgroup_version() != CGROUP_VERSION_1) { - ERROR("Not implemented for cgroup v2 hierarchy"); - return NULL; - } - return common_get_cgroup_path("/proc/1/cgroup", subsystem); } -char *common_get_own_cgroup(const char *subsystem) +char *get_own_cgroup_v1(const char *subsystem) { - if (common_get_cgroup_version() != CGROUP_VERSION_1) { - ERROR("Not implemented for cgroup v2 hierarchy"); - return NULL; - } - return common_get_cgroup_path("/proc/self/cgroup", subsystem); } + +int get_cgroup_version_v1() +{ + return CGROUP_VERSION_1; +} + +int cgroup_v1_ops_init(cgroup_ops *ops) +{ + if (ops == NULL) { + return -1; + } + ops->get_cgroup_version = get_cgroup_version_v1; + ops->get_cgroup_info = get_cgroup_info_v1; + ops->get_cgroup_metrics = get_cgroup_metrics_v1; + ops->get_cgroup_mnt_and_root_path = get_cgroup_mnt_and_root_path_v1; + ops->get_init_cgroup_path = get_init_cgroup_path_v1; + ops->get_own_cgroup_path = get_own_cgroup_v1; + return 0; +} \ No newline at end of file diff --git a/src/daemon/common/cgroup/cgroup_v1.h b/src/daemon/common/cgroup/cgroup_v1.h new file mode 100644 index 00000000..c2696725 --- /dev/null +++ b/src/daemon/common/cgroup/cgroup_v1.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: zhongtao + * Create: 2024-02-19 + * Description: provide cgroup v1 definition + ******************************************************************************/ +#ifndef DAEMON_COMMON_CGROUP_CGROUP_V1_H +#define DAEMON_COMMON_CGROUP_CGROUP_V1_H + +#include "cgroup.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int cgroup_v1_ops_init(cgroup_ops *ops); + +#ifdef __cplusplus +} +#endif + +#endif // DAEMON_COMMON_CGROUP_CGROUP_V1_H diff --git a/src/daemon/common/cgroup_v2.c b/src/daemon/common/cgroup/cgroup_v2.c similarity index 88% rename from src/daemon/common/cgroup_v2.c rename to src/daemon/common/cgroup/cgroup_v2.c index 25509bda..65cf90d8 100644 --- a/src/daemon/common/cgroup_v2.c +++ b/src/daemon/common/cgroup/cgroup_v2.c @@ -105,48 +105,12 @@ static struct cgfile_t g_cgroup_v2_files[] = { static int get_cgroup_v2_value_helper(const char *path, const cgroup_v2_files_index index, void *result) { - int nret = 0; - char file_path[PATH_MAX] = { 0 }; - char real_path[PATH_MAX] = { 0 }; - char *content = NULL; - if (index >= CGROUP_V2_FILES_INDEX_MAXS) { ERROR("Index out of range"); return false; } - if (path == NULL || strlen(path) == 0 || result == NULL) { - ERROR("%s: Invalid arguments", g_cgroup_v2_files[index].name); - return -1; - } - - nret = snprintf(file_path, sizeof(file_path), "%s/%s", path, g_cgroup_v2_files[index].file); - if (nret < 0 || (size_t)nret >= sizeof(file_path)) { - ERROR("%s: failed to snprintf", g_cgroup_v2_files[index].name); - return -1; - } - - if (util_clean_path(file_path, real_path, sizeof(real_path)) == NULL) { - ERROR("%s: failed to clean path %s", g_cgroup_v2_files[index].name, file_path); - return -1; - } - - content = util_read_content_from_file(real_path); - if (content == NULL) { - ERROR("%s: failed to read file %s", g_cgroup_v2_files[index].name, real_path); - return -1; - } - - util_trim_newline(content); - content = util_trim_space(content); - - nret = g_cgroup_v2_files[index].get_value(content, g_cgroup_v2_files[index].match, result); - if (nret != 0) { - ERROR("%s: failed to get value", g_cgroup_v2_files[index].name); - } - - free(content); - return nret; + return get_cgroup_value_helper(path, &g_cgroup_v2_files[index], result); } static void get_cgroup_v2_metrics_cpu(const char *cgroup_path, cgroup_cpu_metrics_t *cgroup_cpu_metrics) @@ -306,28 +270,18 @@ static bool cgroup_v2_enabled(const char *mountpoint, const char *name) return util_file_exists(path); } -int common_get_cgroup_info_v2(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, - cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, - cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, - cgroup_files_info_t *filesinfo, bool quiet) +static void get_cgroup_v2_cpu_info(const bool quiet, cgroup_cpu_info_t *cpuinfo) { - int ret = 0; - int nret = 0; - __isula_auto_free char *size = NULL; - char path[PATH_MAX] = { 0 }; - - if (make_sure_cgroup2_isulad_path_exist() != 0) { - return -1; - } - - // cpu cgroup cpuinfo->cpu_shares = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPU_WEIGHT); common_cgroup_do_log(quiet, !(cpuinfo->cpu_shares), "Your kernel does not support cgroup2 cpu weight"); cpuinfo->cpu_cfs_period = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPU_MAX); cpuinfo->cpu_cfs_quota = cpuinfo->cpu_cfs_period; common_cgroup_do_log(quiet, !(cpuinfo->cpu_cfs_period), "Your kernel does not support cgroup2 cpu max"); +} +static int get_cgroup_v2_cpuset_info(const bool quiet, cgroup_cpuset_info_t *cpusetinfo) +{ cpusetinfo->cpuset = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_CPUS_EFFECTIVE) && cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_CPUS) && cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_MEMS_EFFECTIVE) && @@ -343,8 +297,23 @@ int common_get_cgroup_info_v2(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpu cpusetinfo->cpus = util_trim_space(cpusetinfo->cpus); cpusetinfo->mems = util_trim_space(cpusetinfo->mems); } + return 0; +} + +static void get_cgroup_v2_mem_info(const bool quiet, cgroup_mem_info_t *meminfo) +{ + meminfo->limit = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_MEMORY_MAX); + common_cgroup_do_log(quiet, !(meminfo->limit), "Your kernel does not support cgroup2 memory max"); + + meminfo->reservation = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_MEMORY_LOW); + common_cgroup_do_log(quiet, !(meminfo->reservation), "Your kernel does not support cgroup2 memory low"); - // io cgroup + meminfo->swap = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_MEMORY_SWAP_MAX); + common_cgroup_do_log(quiet, !(meminfo->swap), "Your kernel does not support cgroup2 memory swap max"); +} + +static void get_cgroup_v2_blkio_info(const bool quiet, cgroup_blkio_info_t *blkioinfo) +{ blkioinfo->blkio_weight = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_IO_BFQ_WEIGHT) || cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_IO_WEIGHT); blkioinfo->blkio_weight_device = blkioinfo->blkio_weight; @@ -355,22 +324,14 @@ int common_get_cgroup_info_v2(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpu blkioinfo->blkio_read_iops_device = blkioinfo->blkio_read_bps_device; blkioinfo->blkio_write_iops_device = blkioinfo->blkio_read_bps_device; common_cgroup_do_log(quiet, !(blkioinfo->blkio_read_bps_device), "Your kernel does not support cgroup2 io max"); +} - // memory cgroup - meminfo->limit = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_MEMORY_MAX); - common_cgroup_do_log(quiet, !(meminfo->limit), "Your kernel does not support cgroup2 memory max"); - - meminfo->reservation = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_MEMORY_LOW); - common_cgroup_do_log(quiet, !(meminfo->reservation), "Your kernel does not support cgroup2 memory low"); - - meminfo->swap = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_MEMORY_SWAP_MAX); - common_cgroup_do_log(quiet, !(meminfo->swap), "Your kernel does not support cgroup2 memory swap max"); - - // pids cgroup - pidsinfo->pidslimit = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_PIDS_MAX); - common_cgroup_do_log(quiet, !(pidsinfo->pidslimit), "Your kernel does not support cgroup2 pids max"); +static int get_cgroup_v2_hugetlb_info(const bool quiet, cgroup_hugetlb_info_t *hugetlbinfo) +{ + __isula_auto_free char *size = NULL; + int nret = 0; + char path[PATH_MAX] = { 0 }; - // hugetlb cgroup size = get_default_huge_page_size(); if (size != NULL) { nret = snprintf(path, sizeof(path), CGROUP2_HUGETLB_MAX, size); @@ -383,15 +344,55 @@ int common_get_cgroup_info_v2(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpu } else { WARN("Your kernel does not support cgroup2 hugetlb limit"); } + return 0; +} + +static void get_cgroup_v2_pids_info(const bool quiet, cgroup_pids_info_t *pidsinfo) +{ + pidsinfo->pidslimit = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_PIDS_MAX); + common_cgroup_do_log(quiet, !(pidsinfo->pidslimit), "Your kernel does not support cgroup2 pids max"); + +} - // files cgroup +static void get_cgroup_v2_files_info(const bool quiet, cgroup_files_info_t *filesinfo) +{ filesinfo->fileslimit = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_FILES_LIMIT); common_cgroup_do_log(quiet, !(filesinfo->fileslimit), "Your kernel does not support cgroup2 files limit"); - return ret; } -int common_get_cgroup_v2_metrics(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics) +static int get_cgroup_info_v2(cgroup_mem_info_t *meminfo, cgroup_cpu_info_t *cpuinfo, + cgroup_hugetlb_info_t *hugetlbinfo, cgroup_blkio_info_t *blkioinfo, + cgroup_cpuset_info_t *cpusetinfo, cgroup_pids_info_t *pidsinfo, + cgroup_files_info_t *filesinfo, bool quiet) +{ + int ret = 0; + if (make_sure_cgroup2_isulad_path_exist() != 0) { + return -1; + } + + get_cgroup_v2_cpu_info(quiet, cpuinfo); + + ret = get_cgroup_v2_cpuset_info(quiet, cpusetinfo); + if (ret != 0) { + return ret; + } + + get_cgroup_v2_mem_info(quiet, meminfo); + get_cgroup_v2_blkio_info(quiet, blkioinfo); + + ret = get_cgroup_v2_hugetlb_info(quiet, hugetlbinfo); + if (ret != 0) { + return ret; + } + + get_cgroup_v2_pids_info(quiet, pidsinfo); + get_cgroup_v2_files_info(quiet, filesinfo); + + return 0; +} + +static int get_cgroup_metrics_v2(const char *cgroup_path, cgroup_metrics_t *cgroup_metrics) { if (cgroup_path == NULL || strlen(cgroup_path) == 0 || cgroup_metrics == NULL) { ERROR("Invalid arguments"); @@ -404,3 +405,26 @@ int common_get_cgroup_v2_metrics(const char *cgroup_path, cgroup_metrics_t *cgro return 0; } + +static int get_cgroup_mnt_and_root_v2(const char *subsystem, char **mountpoint, char **root) +{ + *mountpoint = util_strdup_s(CGROUP_ISULAD_PATH); + return 0; +} + +int get_cgroup_version_v2() +{ + return CGROUP_VERSION_2; +} + +int cgroup_v2_ops_init(cgroup_ops *ops) +{ + if (ops == NULL) { + return -1; + } + ops->get_cgroup_version = get_cgroup_version_v2; + ops->get_cgroup_info = get_cgroup_info_v2; + ops->get_cgroup_metrics = get_cgroup_metrics_v2; + ops->get_cgroup_mnt_and_root_path = get_cgroup_mnt_and_root_v2; + return 0; +} \ No newline at end of file diff --git a/src/daemon/common/cgroup/cgroup_v2.h b/src/daemon/common/cgroup/cgroup_v2.h new file mode 100644 index 00000000..0e8e4818 --- /dev/null +++ b/src/daemon/common/cgroup/cgroup_v2.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: zhongtao + * Create: 2024-02-19 + * Description: provide cgroup v2 definition + ******************************************************************************/ +#ifndef DAEMON_COMMON_CGROUP_CGROUP_V2_H +#define DAEMON_COMMON_CGROUP_CGROUP_V2_H + +#include "cgroup.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int cgroup_v2_ops_init(cgroup_ops *ops); + +#ifdef __cplusplus +} +#endif + +#endif // DAEMON_COMMON_CGROUP_CGROUP_V2_H diff --git a/src/daemon/common/sysinfo.c b/src/daemon/common/sysinfo.c index a082f717..e369c3e3 100644 --- a/src/daemon/common/sysinfo.c +++ b/src/daemon/common/sysinfo.c @@ -188,15 +188,10 @@ static char **get_huge_page_sizes() struct dirent *info_archivo = NULL; int cgroup_version = 0; - cgroup_version = common_get_cgroup_version(); - if (cgroup_version == CGROUP_VERSION_2) { - hugetlbmp = util_strdup_s(CGROUP_ISULAD_PATH); - } else { - ret = common_find_cgroup_mnt_and_root("hugetlb", &hugetlbmp, NULL); - if (ret != 0 || hugetlbmp == NULL) { - ERROR("Hugetlb cgroup not supported"); - return NULL; - } + ret = common_get_cgroup_mnt_and_root_path("hugetlb", &hugetlbmp, NULL); + if (ret != 0 || hugetlbmp == NULL) { + ERROR("Hugetlb cgroup not supported"); + return NULL; } dir = opendir(hugetlbmp); @@ -211,6 +206,7 @@ static char **get_huge_page_sizes() char *pos = NULL; char *dot2 = NULL; + cgroup_version = common_get_cgroup_version(); if (cgroup_version == CGROUP_VERSION_2) { if (!is_hugetlb_max(info_archivo->d_name)) { continue; @@ -375,7 +371,6 @@ void free_sysinfo(sysinfo_t *sysinfo) /* get sys info */ sysinfo_t *get_sys_info(bool quiet) { - int cgroup_version = 0; sysinfo_t *sysinfo = NULL; int ret = 0; @@ -388,21 +383,9 @@ sysinfo_t *get_sys_info(bool quiet) sysinfo->ncpus = get_nprocs(); sysinfo->ncpus_conf = get_nprocs_conf(); - cgroup_version = common_get_cgroup_version(); - if (cgroup_version < 0) { - ret = -1; - goto out; - } - - if (cgroup_version == CGROUP_VERSION_1) { - ret = common_get_cgroup_info_v1(&sysinfo->cgmeminfo, &sysinfo->cgcpuinfo, &sysinfo->hugetlbinfo, + ret = common_get_cgroup_info(&sysinfo->cgmeminfo, &sysinfo->cgcpuinfo, &sysinfo->hugetlbinfo, &sysinfo->blkioinfo, &sysinfo->cpusetinfo, &sysinfo->pidsinfo, &sysinfo->filesinfo, quiet); - } else { - ret = common_get_cgroup_info_v2(&sysinfo->cgmeminfo, &sysinfo->cgcpuinfo, &sysinfo->hugetlbinfo, - &sysinfo->blkioinfo, &sysinfo->cpusetinfo, &sysinfo->pidsinfo, - &sysinfo->filesinfo, quiet); - } if (ret != 0) { goto out; } @@ -563,7 +546,7 @@ free_out: return minfos; } -char *sysinfo_cgroup_controller_cpurt_mnt_path(void) +char *sysinfo_get_cpurt_mnt_path(void) { int nret = 0; __isula_auto_free char *mnt = NULL; @@ -583,7 +566,7 @@ char *sysinfo_cgroup_controller_cpurt_mnt_path(void) return NULL; } - nret = common_find_cgroup_mnt_and_root("cpu", &mnt, &root); + nret = common_get_cgroup_mnt_and_root_path("cpu", &mnt, &root); if (nret != 0 || mnt == NULL || root == NULL) { ERROR("Can not find cgroup mnt and root path for subsystem 'cpu'"); isulad_set_error_message("Can not find cgroup mnt and root path for subsystem 'cpu'"); diff --git a/src/daemon/common/sysinfo.h b/src/daemon/common/sysinfo.h index cb44d1c5..6142487b 100644 --- a/src/daemon/common/sysinfo.h +++ b/src/daemon/common/sysinfo.h @@ -95,13 +95,13 @@ mountinfo_t *find_mount_info(mountinfo_t **minfos, const char *dir); void free_mounts_info(mountinfo_t **minfos); -char *sysinfo_cgroup_controller_cpurt_mnt_path(void); - // define auto free function callback for sysinfo_t define_auto_cleanup_callback(free_sysinfo, sysinfo_t) // define auto free macro for sysinfo_t #define __isula_auto_sysinfo_t auto_cleanup_tag(free_sysinfo) +char *sysinfo_get_cpurt_mnt_path(void); + #ifdef __cplusplus } #endif diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc index 3bdc3af8..f125e714 100644 --- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc @@ -872,18 +872,7 @@ void PodSandboxManagerService::GetPodSandboxCgroupMetrics(const std::string &cgr return; } - auto cgroupVersion = common_get_cgroup_version(); - if (cgroupVersion < 0) { - error.Errorf("Invalid cgroup version"); - return; - } - - if (cgroupVersion == CGROUP_VERSION_1) { - nret = common_get_cgroup_v1_metrics(cgroupParent.c_str(), &cgroupMetrics); - } else { - nret = common_get_cgroup_v2_metrics(cgroupParent.c_str(), &cgroupMetrics); - } - + nret = common_get_cgroup_metrics(cgroupParent.c_str(), &cgroupMetrics); if (nret != 0) { error.Errorf("Failed to get cgroup metrics"); } diff --git a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc index 49a7ca54..af6b5fff 100644 --- a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +++ b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc @@ -1328,18 +1328,7 @@ void PodSandboxManagerService::GetPodSandboxCgroupMetrics(const container_inspec return; } - auto cgroupVersion = common_get_cgroup_version(); - if (cgroupVersion < 0) { - error.Errorf("Invalid cgroup version"); - return; - } - - if (cgroupVersion == CGROUP_VERSION_1) { - nret = common_get_cgroup_v1_metrics(cgroupParent, &cgroupMetrics); - } else { - nret = common_get_cgroup_v2_metrics(cgroupParent, &cgroupMetrics); - } - + nret = common_get_cgroup_metrics(cgroupParent, &cgroupMetrics); if (nret != 0) { error.Errorf("Failed to get cgroup metrics"); } diff --git a/src/daemon/executor/container_cb/execution.c b/src/daemon/executor/container_cb/execution.c index 7ed8e837..88c6b354 100644 --- a/src/daemon/executor/container_cb/execution.c +++ b/src/daemon/executor/container_cb/execution.c @@ -413,6 +413,13 @@ static int cpurt_controller_init(const char *id, const host_config *host_spec) char *dirpath = NULL; int64_t cpu_rt_period = 0; int64_t cpu_rt_runtime = 0; + int cgroup_version = 0; + + // cgroup v2 is not support cpurt + cgroup_version = common_get_cgroup_version(); + if (cgroup_version == CGROUP_VERSION_2) { + return 0; + } cgroups_path = merge_container_cgroups_path(id, host_spec); if (cgroups_path == NULL || strcmp(cgroups_path, "/") == 0 || strcmp(cgroups_path, ".") == 0) { @@ -433,13 +440,13 @@ static int cpurt_controller_init(const char *id, const host_config *host_spec) // should iSulad set cpu.rt_runtime_us and cpu.rt_period_us for the parent path? // in fact, even if system.slice is used, // cpu.rt_runtime_us and cpu.rt_period_us might still needed to be set manually - __isula_auto_free char *init_cgroup = common_get_init_cgroup("cpu"); + __isula_auto_free char *init_cgroup = common_get_init_cgroup_path("cpu"); if (init_cgroup == NULL) { ERROR("Failed to get init cgroup"); return -1; } // make sure that the own cgroup path for cpu existed - __isula_auto_free char *own_cgroup = common_get_own_cgroup("cpu"); + __isula_auto_free char *own_cgroup = common_get_own_cgroup_path("cpu"); if (own_cgroup == NULL) { ERROR("Failed to get own cgroup"); return -1; @@ -453,7 +460,7 @@ static int cpurt_controller_init(const char *id, const host_config *host_spec) cgroups_path = new_cgroups_path; } - mnt_root = sysinfo_cgroup_controller_cpurt_mnt_path(); + mnt_root = sysinfo_get_cpurt_mnt_path(); if (mnt_root == NULL) { ERROR("Failed to get cpu rt controller mnt root path"); return -1; -- 2.34.1