diff options
Diffstat (limited to '0029-refactor-cgroup-module.patch')
-rw-r--r-- | 0029-refactor-cgroup-module.patch | 2538 |
1 files changed, 2538 insertions, 0 deletions
diff --git a/0029-refactor-cgroup-module.patch b/0029-refactor-cgroup-module.patch new file mode 100644 index 0000000..f5e853d --- /dev/null +++ b/0029-refactor-cgroup-module.patch @@ -0,0 +1,2538 @@ +From c26604ff3150babae729890c549f2784212073a1 Mon Sep 17 00:00:00 2001 +From: zhongtao <zhongtao17@huawei.com> +Date: Wed, 20 Mar 2024 15:53:56 +0800 +Subject: [PATCH 29/43] refactor cgroup module + +Signed-off-by: zhongtao <zhongtao17@huawei.com> +--- + 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 <stdio.h> +-#include <stdlib.h> +-#include <string.h> +-#include <errno.h> +-#include <sys/vfs.h> +-#include <linux/magic.h> +-#include <sys/stat.h> +- +-#include <isula_libutils/auto_cleanup.h> +- +-#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 <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <errno.h> ++#include <sys/vfs.h> ++#include <linux/magic.h> ++#include <sys/stat.h> ++ ++#include <isula_libutils/auto_cleanup.h> ++ ++#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 <stdbool.h> ++#include <stdint.h> ++#include <stdio.h> ++ ++#include <isula_libutils/log.h> ++ ++#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 <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <errno.h> ++#include <sys/vfs.h> ++#include <linux/magic.h> ++#include <sys/stat.h> ++ ++#include <isula_libutils/auto_cleanup.h> ++ ++#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 <stdbool.h> + #include <stdint.h> +@@ -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 <stdlib.h> + + #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 + |