From 7c7cd82619ed1f7e36d34da1afc2b417a90b3040 Mon Sep 17 00:00:00 2001
From: zhongtao <zhongtao17@huawei.com>
Date: Tue, 23 Jan 2024 17:18:51 +0800
Subject: [PATCH 27/43] =?UTF-8?q?=E3=80=90feature=E3=80=91add=20support=20?=
 =?UTF-8?q?for=20cgroup=20v2=20metrics?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: zhongtao <zhongtao17@huawei.com>
---
 src/daemon/common/cgroup.c                    | 237 ++--------
 src/daemon/common/cgroup.h                    |  11 +-
 src/daemon/common/cgroup_v1.c                 | 194 +++------
 src/daemon/common/cgroup_v2.c                 | 406 ++++++++++++++++++
 .../v1/v1_cri_pod_sandbox_manager_service.cc  |   2 +-
 .../cri_pod_sandbox_manager_service.cc        |   2 +-
 src/utils/cutils/utils_array.h                |   6 +
 7 files changed, 506 insertions(+), 352 deletions(-)
 create mode 100644 src/daemon/common/cgroup_v2.c

diff --git a/src/daemon/common/cgroup.c b/src/daemon/common/cgroup.c
index 2d1cabb2..3c58f7fa 100644
--- a/src/daemon/common/cgroup.c
+++ b/src/daemon/common/cgroup.c
@@ -29,32 +29,6 @@
 #include "utils_array.h"
 #include "sysinfo.h"
 
-// Cgroup V2 Item Definition
-#define CGROUP2_CPU_WEIGHT "cpu.weight"
-#define CGROUP2_CPU_MAX "cpu.max"
-#define CGROUP2_CPUSET_CPUS_EFFECTIVE "cpuset.cpus.effective"
-#define CGROUP2_CPUSET_MEMS_EFFECTIVE "cpuset.mems.effective"
-#define CGROUP2_CPUSET_CPUS "cpuset.cpus"
-#define CGROUP2_CPUSET_MEMS "cpuset.mems"
-#define CGROUP2_IO_WEIGHT "io.weight"
-#define CGROUP2_IO_BFQ_WEIGHT "io.bfq.weight"
-#define CGROUP2_IO_MAX "io.max"
-#define CGROUP2_MEMORY_MAX "memory.max"
-#define CGROUP2_MEMORY_LOW "memory.low"
-#define CGROUP2_MEMORY_SWAP_MAX "memory.swap.max"
-#define CGROUP2_HUGETLB_MAX "hugetlb.%s.max"
-#define CGROUP2_PIDS_MAX "pids.max"
-#define CGROUP2_FILES_LIMIT "files.limit"
-
-#define CGROUP2_CONTROLLERS_PATH CGROUP_MOUNTPOINT"/cgroup.controllers"
-#define CGROUP2_SUBTREE_CONTROLLER_PATH CGROUP_MOUNTPOINT"/cgroup.subtree_control"
-#define CGROUP2_CPUSET_CPUS_EFFECTIVE_PATH CGROUP_MOUNTPOINT"/cpuset.cpus.effective"
-#define CGROUP2_CPUSET_MEMS_EFFECTIVE_PATH CGROUP_MOUNTPOINT"/cpuset.mems.effective"
-
-#ifndef CGROUP2_SUPER_MAGIC
-#define CGROUP2_SUPER_MAGIC 0x63677270
-#endif
-
 #ifndef CGROUP_SUPER_MAGIC
 #define CGROUP_SUPER_MAGIC 0x27e0eb
 #endif
@@ -485,20 +459,6 @@ out:
     return layers;
 }
 
-/* cgroup enabled */
-static bool cgroup_enabled(const char *mountpoint, const char *name)
-{
-    char path[PATH_MAX] = { 0 };
-    int nret;
-
-    nret = snprintf(path, sizeof(path), "%s/%s", mountpoint, name);
-    if (nret < 0 || (size_t)nret >= sizeof(path)) {
-        ERROR("Path is too long");
-        return false;
-    }
-    return util_file_exists(path);
-}
-
 char *common_find_cgroup_subsystem_mountpoint(const cgroup_layer_t *layers, const char *subsystem)
 {
     size_t i;
@@ -607,188 +567,59 @@ int common_get_cgroup_version(void)
     return CGROUP_VERSION_1;
 }
 
-static int cgroup2_enable_all()
+static int get_value_ull(const char *content, void *result)
 {
-    int ret = 0;
-    int nret = 0;
-    int n = 0;
-    size_t i = 0;
-    const char *space = "";
-    char *controllers_str = NULL;
-    char *subtree_controller_str = NULL;
-    char **controllers = NULL;
-    char enable_controllers[PATH_MAX] = { 0 };
-
-    controllers_str = util_read_content_from_file(CGROUP2_CONTROLLERS_PATH);
-    if (controllers_str == NULL || strlen(controllers_str) == 0 || strcmp(controllers_str, "\n") == 0) {
-        WARN("no cgroup controller found");
-        goto out;
-    }
-
-    subtree_controller_str = util_read_content_from_file(CGROUP2_SUBTREE_CONTROLLER_PATH);
-    if (subtree_controller_str != NULL && strcmp(controllers_str, subtree_controller_str) == 0) {
-        goto out;
-    }
+    uint64_t ull_result = 0;
 
-    controllers = util_string_split(controllers_str, ' ');
-    if (controllers == NULL) {
-        ERROR("split %s failed", controllers_str);
-        ret = -1;
-        goto out;
-    }
-
-    for (i = 0; i < util_array_len((const char **)controllers); i++) {
-        nret = snprintf(enable_controllers + n, PATH_MAX - n, "%s+%s", space, controllers[i]);
-        if (nret < 0 || (size_t)nret >= PATH_MAX - n) {
-            ERROR("Path is too long");
-            goto out;
-        }
-        n += nret;
-        space = " ";
-    }
-    ret = util_write_file(CGROUP2_SUBTREE_CONTROLLER_PATH, enable_controllers, strlen(enable_controllers),
-                          DEFAULT_CGROUP_FILE_MODE);
-    if (ret != 0) {
-        SYSERROR("write %s to %s failed", enable_controllers, CGROUP2_SUBTREE_CONTROLLER_PATH);
-        goto out;
+    if (util_safe_uint64(content, &ull_result) != 0) {
+        ERROR("Failed to convert %s to uint64", content);
+        return -1;
     }
 
-out:
-    util_free_array(controllers);
-    free(controllers_str);
-    free(subtree_controller_str);
-
-    return ret;
+    *(uint64_t *)result = ull_result;
+    return 0;
 }
 
-#if defined (__ANDROID__) || defined(__MUSL__)
-static bool cgroup2_no_controller()
+int get_match_value_ull(const char *content, const char *match, void *result)
 {
-    char *controllers_str = NULL;
+    __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;
 
-    controllers_str = util_read_content_from_file(CGROUP2_CONTROLLERS_PATH);
-    if (controllers_str == NULL || strlen(controllers_str) == 0 || strcmp(controllers_str, "\n") == 0) {
-        free(controllers_str);
-        return true;
+    if (match == NULL) {
+        return get_value_ull(content, result);
     }
 
-    free(controllers_str);
-    return false;
-}
-#endif
-
-static int make_sure_cgroup2_isulad_path_exist()
-{
-    int ret = 0;
-
-    if (util_dir_exists(CGROUP_ISULAD_PATH)) {
-        return 0;
+    // match full string
+    match_with_space = util_string_append(" ", match);
+    if (match_with_space == NULL) {
+        ERROR("Failed to append string");
+        return -1;
     }
 
-    if (cgroup2_enable_all() != 0) {
+    lines = util_string_split(content, '\n');
+    if (lines == NULL) {
+        ERROR("Failed to split content %s", content);
         return -1;
     }
 
-#if defined (__ANDROID__) || defined(__MUSL__)
-    if (cgroup2_no_controller()) {
-        DEBUG("no cgroup controller found");
-        return 0;
+    for (worker = lines; worker && *worker; worker++) {
+        if (util_has_prefix(*worker, match_with_space)) {
+            break;
+        }
     }
-#endif
-
-    ret = mkdir(CGROUP_ISULAD_PATH, DEFAULT_CGROUP_DIR_MODE);
-    if (ret != 0 && (errno != EEXIST || !util_dir_exists(CGROUP_ISULAD_PATH))) {
+    if (*worker == NULL) {
+        ERROR("Cannot find match string %s", match);
         return -1;
     }
 
-    return ret;
-}
-
-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)
-{
-    int ret = 0;
-    int nret = 0;
-    char *size = NULL;
-    char path[PATH_MAX] = { 0 };
-
-    if (make_sure_cgroup2_isulad_path_exist() != 0) {
+    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);
 
-    // cpu cgroup
-    cpuinfo->cpu_shares = cgroup_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_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");
-
-    cpusetinfo->cpuset = cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_CPUS_EFFECTIVE) &&
-                         cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_CPUS) &&
-                         cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_MEMS_EFFECTIVE) &&
-                         cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_MEMS);
-    common_cgroup_do_log(quiet, !(cpusetinfo->cpuset), "Your kernel does not support cpuset");
-    if (cpusetinfo->cpuset) {
-        cpusetinfo->cpus = util_read_content_from_file(CGROUP2_CPUSET_CPUS_EFFECTIVE_PATH);
-        cpusetinfo->mems = util_read_content_from_file(CGROUP2_CPUSET_MEMS_EFFECTIVE_PATH);
-        if (cpusetinfo->cpus == NULL || cpusetinfo->mems == NULL) {
-            ERROR("read cpus or mems failed");
-            return -1;
-        }
-        cpusetinfo->cpus = util_trim_space(cpusetinfo->cpus);
-        cpusetinfo->mems = util_trim_space(cpusetinfo->mems);
-    }
-
-    // io cgroup
-    blkioinfo->blkio_weight = cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_IO_BFQ_WEIGHT) ||
-                              cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_IO_WEIGHT);
-    blkioinfo->blkio_weight_device = blkioinfo->blkio_weight;
-    common_cgroup_do_log(quiet, !(blkioinfo->blkio_weight), "Your kernel does not support cgroup2 io weight");
-
-    blkioinfo->blkio_read_bps_device = cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_IO_MAX);
-    blkioinfo->blkio_write_bps_device = blkioinfo->blkio_read_bps_device;
-    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_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_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_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_enabled(CGROUP_ISULAD_PATH, CGROUP2_PIDS_MAX);
-    common_cgroup_do_log(quiet, !(pidsinfo->pidslimit), "Your kernel does not support cgroup2 pids max");
-
-    // hugetlb cgroup
-    size = get_default_huge_page_size();
-    if (size != NULL) {
-        nret = snprintf(path, sizeof(path), CGROUP2_HUGETLB_MAX, size);
-        if (nret < 0 || (size_t)nret >= sizeof(path)) {
-            WARN("Failed to print hugetlb path");
-            ret = -1;
-            goto out;
-        }
-        hugetlbinfo->hugetlblimit = cgroup_enabled(CGROUP_ISULAD_PATH, path);
-        common_cgroup_do_log(quiet, !hugetlbinfo->hugetlblimit, "Your kernel does not support cgroup2 hugetlb limit");
-    } else {
-        WARN("Your kernel does not support cgroup2 hugetlb limit");
-    }
-
-    // files cgroup
-    filesinfo->fileslimit = cgroup_enabled(CGROUP_ISULAD_PATH, CGROUP2_FILES_LIMIT);
-    common_cgroup_do_log(quiet, !(filesinfo->fileslimit), "Your kernel does not support cgroup2 files limit");
-
-out:
-    free(size);
-
-    return ret;
-}
+    return get_value_ull(llu_string, result);
+}
\ No newline at end of file
diff --git a/src/daemon/common/cgroup.h b/src/daemon/common/cgroup.h
index fa20f42c..251e3a3d 100644
--- a/src/daemon/common/cgroup.h
+++ b/src/daemon/common/cgroup.h
@@ -31,6 +31,15 @@ extern "C" {
 #define CGROUP_MOUNTPOINT "/sys/fs/cgroup"
 #define CGROUP_ISULAD_PATH CGROUP_MOUNTPOINT"/isulad"
 
+struct cgfile_t {
+    char *name;
+    char *file;
+    char *match;
+    int (*get_value)(const char *content, const char *match, void *result);
+};
+
+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);
@@ -42,7 +51,6 @@ static inline void common_cgroup_do_log(bool quiet, bool do_log, const char *msg
     }
 }
 
-
 typedef struct {
     char **controllers;
     char *mountpoint;
@@ -140,6 +148,7 @@ typedef struct {
 } 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);
 
 char *common_get_init_cgroup(const char *subsystem);
 
diff --git a/src/daemon/common/cgroup_v1.c b/src/daemon/common/cgroup_v1.c
index e38fc03e..e34100bc 100644
--- a/src/daemon/common/cgroup_v1.c
+++ b/src/daemon/common/cgroup_v1.c
@@ -23,20 +23,8 @@
 
 #define CGROUP_HUGETLB_LIMIT "hugetlb.%s.limit_in_bytes"
 
-typedef struct {
-    char *match;
-} cgfile_callback_args_t;
-
-struct cgfile_t {
-    char *name;
-    char *file;
-    int (*get_value)(const char *content, const cgfile_callback_args_t *args, void *result);
-};
-
-static int get_value_ll(const char *content, const cgfile_callback_args_t *args, void *result);
-static int get_value_ull(const char *content, const cgfile_callback_args_t *args, void *result);
-static int get_match_value_ull(const char *content, const cgfile_callback_args_t *args, void *result);
-static int get_value_string(const char *content, const cgfile_callback_args_t *args, void *result);
+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);
 
 typedef enum {
     // CPU subsystem
@@ -63,46 +51,46 @@ typedef enum {
 
 static struct cgfile_t g_cgroup_v1_files[] = {
     // CPU subsystem
-    [CPU_RT_PERIOD]                 = {"cpu_rt_period",         "cpu.rt_period_us",                 get_value_ull},
-    [CPU_RT_RUNTIME]                = {"cpu_rt_runtime",        "cpu.rt_runtime_us",                get_value_ull},
-    [CPU_SHARES]                    = {"cpu_shares",            "cpu.shares",                       get_value_ull},
-    [CPU_CFS_PERIOD]                = {"cpu_cfs_period",        "cpu.cfs_period_us",                get_value_ull},
-    [CPU_CFS_QUOTA]                 = {"cpu_cfs_quota",         "cpu.cfs_quota_us",                 get_value_ll},
+    [CPU_RT_PERIOD]               = {"cpu_rt_period",         "cpu.rt_period_us",                 NULL,                    get_match_value_ull},
+    [CPU_RT_RUNTIME]              = {"cpu_rt_runtime",        "cpu.rt_runtime_us",                NULL,                    get_match_value_ull},
+    [CPU_SHARES]                  = {"cpu_shares",            "cpu.shares",                       NULL,                    get_match_value_ull},
+    [CPU_CFS_PERIOD]              = {"cpu_cfs_period",        "cpu.cfs_period_us",                NULL,                    get_match_value_ull},
+    [CPU_CFS_QUOTA]               = {"cpu_cfs_quota",         "cpu.cfs_quota_us",                 NULL,                    get_value_ll},
     // CPUSET subsystem
-    [CPUSET_CPUS]                   = {"cpuset_cpus",           "cpuset.cpus",                      get_value_string},
-    [CPUSET_MEMS]                   = {"cpuset_mems",           "cpuset.mems",                      get_value_string},
+    [CPUSET_CPUS]                 = {"cpuset_cpus",           "cpuset.cpus",                      NULL,                    get_value_string},
+    [CPUSET_MEMS]                 = {"cpuset_mems",           "cpuset.mems",                      NULL,                    get_value_string},
     // CPUACCT subsystem
-    [CPUACCT_USE_NANOS]             = {"cpu_use_nanos",         "cpuacct.usage",                    get_value_ull},
-    [CPUACCT_USE_USER]              = {"cpu_use_user",          "cpuacct.stat",                     get_match_value_ull},
-    [CPUACCT_USE_SYS]               = {"cpu_use_sys",           "cpuacct.stat",                     get_match_value_ull},
+    [CPUACCT_USE_NANOS]           = {"cpu_use_nanos",         "cpuacct.usage",                    NULL,                    get_match_value_ull},
+    [CPUACCT_USE_USER]            = {"cpu_use_user",          "cpuacct.stat",                     NULL,                    get_match_value_ull},
+    [CPUACCT_USE_SYS]             = {"cpu_use_sys",           "cpuacct.stat",                     NULL,                    get_match_value_ull},
     // MEMORY subsystem
-    [MEMORY_LIMIT]                  = {"mem_limit",             "memory.limit_in_bytes",            get_value_ull},
-    [MEMORY_USAGE]                  = {"mem_usage",             "memory.usage_in_bytes",            get_value_ull},
-    [MEMORY_SOFT_LIMIT]             = {"mem_soft_limit",        "memory.soft_limit_in_bytes",       get_value_ull},
-    [MEMORY_KMEM_LIMIT]             = {"kmem_limit",            "memory.kmem.limit_in_bytes",       get_value_ull},
-    [MEMORY_KMEM_USAGE]             = {"kmem_usage",            "memory.kmem.usage_in_bytes",       get_value_ull},
-    [MEMORY_SWAPPINESS]             = {"swappiness",            "memory.swappiness",                NULL},
-    [MEMORY_SW_LIMIT]               = {"memsw_limit",           "memory.memsw.limit_in_bytes",      get_value_ull},
-    [MEMORY_SW_USAGE]               = {"memsw_usage",           "memory.memsw.usage_in_bytes",      get_value_ull},
-    [MEMORY_CACHE]                  = {"cache",                 "memory.stat",                      get_match_value_ull},
-    [MEMORY_CACHE_TOTAL]            = {"cache_total",           "memory.stat",                      get_match_value_ull},
-    [MEMORY_TOTAL_RSS]              = {"total_rss",             "memory.stat",                      get_match_value_ull},
-    [MEMORY_TOTAL_PGFAULT]          = {"total_page_fault",      "memory.stat",                      get_match_value_ull},
-    [MEMORY_TOTAL_PGMAJFAULT]       = {"total_page_majfault",   "memory.stat",                      get_match_value_ull},
-    [MEMORY_TOTAL_INACTIVE_FILE]    = {"total_inactive_file",   "memory.stat",                      get_match_value_ull},
-    [MEMORY_OOM_CONTROL]            = {"oom_control",           "memory.oom_control",               NULL},
+    [MEMORY_LIMIT]                = {"mem_limit",             "memory.limit_in_bytes",            NULL,                    get_match_value_ull},
+    [MEMORY_USAGE]                = {"mem_usage",             "memory.usage_in_bytes",            NULL,                    get_match_value_ull},
+    [MEMORY_SOFT_LIMIT]           = {"mem_soft_limit",        "memory.soft_limit_in_bytes",       NULL,                    get_match_value_ull},
+    [MEMORY_KMEM_LIMIT]           = {"kmem_limit",            "memory.kmem.limit_in_bytes",       NULL,                    get_match_value_ull},
+    [MEMORY_KMEM_USAGE]           = {"kmem_usage",            "memory.kmem.usage_in_bytes",       NULL,                    get_match_value_ull},
+    [MEMORY_SWAPPINESS]           = {"swappiness",            "memory.swappiness",                NULL,                    NULL},
+    [MEMORY_SW_LIMIT]             = {"memsw_limit",           "memory.memsw.limit_in_bytes",      NULL,                    get_match_value_ull},
+    [MEMORY_SW_USAGE]             = {"memsw_usage",           "memory.memsw.usage_in_bytes",      NULL,                    get_match_value_ull},
+    [MEMORY_CACHE]                = {"cache",                 "memory.stat",                      NULL,                    get_match_value_ull},
+    [MEMORY_CACHE_TOTAL]          = {"cache_total",           "memory.stat",                      NULL,                    get_match_value_ull},
+    [MEMORY_TOTAL_RSS]            = {"total_rss",             "memory.stat",                      "total_rss",             get_match_value_ull},
+    [MEMORY_TOTAL_PGFAULT]        = {"total_page_fault",      "memory.stat",                      "total_pgfault",         get_match_value_ull},
+    [MEMORY_TOTAL_PGMAJFAULT]     = {"total_page_majfault",   "memory.stat",                      "total_pgmajfault",      get_match_value_ull},
+    [MEMORY_TOTAL_INACTIVE_FILE]  = {"total_inactive_file",   "memory.stat",                      "total_inactive_file",   get_match_value_ull},
+    [MEMORY_OOM_CONTROL]          = {"oom_control",           "memory.oom_control",               NULL,                    NULL},
     // BLKIO subsystem
-    [BLKIO_WEIGTH]                  = {"blkio_weigth",          "blkio.weight",                     NULL},
-    [BLKIO_WEIGTH_DEVICE]           = {"blkio_weigth_device",   "blkio.weight_device",              NULL},
-    [BLKIO_READ_BPS]                = {"blkio_read_bps",        "blkio.throttle.read_bps_device",   NULL},
-    [BLKIO_WRITE_BPS]               = {"blkio_write_bps",       "blkio.throttle.write_bps_device",  NULL},
-    [BLKIO_READ_IOPS]               = {"blkio_read_iops",       "blkio.throttle.read_iops_device",  NULL},
-    [BLKIO_WRITE_IOPS]              = {"blkio_write_iops",      "blkio.throttle.write_iops_device", NULL},
+    [BLKIO_WEIGTH]                = {"blkio_weigth",          "blkio.weight",                     NULL,                    NULL},
+    [BLKIO_WEIGTH_DEVICE]         = {"blkio_weigth_device",   "blkio.weight_device",              NULL,                    NULL},
+    [BLKIO_READ_BPS]              = {"blkio_read_bps",        "blkio.throttle.read_bps_device",   NULL,                    NULL},
+    [BLKIO_WRITE_BPS]             = {"blkio_write_bps",       "blkio.throttle.write_bps_device",  NULL,                    NULL},
+    [BLKIO_READ_IOPS]             = {"blkio_read_iops",       "blkio.throttle.read_iops_device",  NULL,                    NULL},
+    [BLKIO_WRITE_IOPS]            = {"blkio_write_iops",      "blkio.throttle.write_iops_device", NULL,                    NULL},
     // PIDS subsystem
-    [PIDS_CURRENT]                  = {"pids_current",          "pids.current",                     get_value_ull},
+    [PIDS_CURRENT]                = {"pids_current",          "pids.current",                     NULL,                    get_match_value_ull},
 };
 
-static int get_value_ll(const char *content, const cgfile_callback_args_t *args, void *result)
+static int get_value_ll(const char *content, const char *match, void *result)
 {
     long long ll_result = 0;
 
@@ -115,81 +103,7 @@ static int get_value_ll(const char *content, const cgfile_callback_args_t *args,
     return 0;
 }
 
-static int get_value_ull(const char *content, const cgfile_callback_args_t *args, 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;
-}
-
-static int get_match_value_ull(const char *content, const cgfile_callback_args_t *args, void *result)
-{
-    int ret = 0;
-    uint64_t llu_result = 0;
-    char *llu_string = NULL;
-    char *match_with_space = NULL;
-    char **lines = NULL;
-    char **worker = NULL;
-
-    if (args == NULL || args->match == NULL || strlen(args->match) == 0) {
-        ERROR("Invalid arguments");
-        return -1;
-    }
-
-    // match full string
-    match_with_space = util_string_append(" ", args->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);
-        ret = -1;
-        goto out;
-    }
-
-    for (worker = lines; worker && *worker; worker++) {
-        if (util_has_prefix(*worker, match_with_space)) {
-            break;
-        }
-    }
-    if (*worker == NULL) {
-        ERROR("Cannot find match string %s", args->match);
-        ret = -1;
-        goto out;
-    }
-
-    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");
-        ret = -1;
-        goto out;
-    }
-    llu_string = util_trim_space(llu_string);
-
-    ret = util_safe_uint64(llu_string, &llu_result);
-    if (ret != 0) {
-        ERROR("Failed to convert %s to uint64", llu_string);
-    } else {
-        *(uint64_t *)result = llu_result;
-    }
-
-out:
-    free(match_with_space);
-    free(llu_string);
-    util_free_array(lines);
-    return ret;
-}
-
-static int get_value_string(const char *content, const cgfile_callback_args_t *args, void *result)
+static int get_value_string(const char *content, const char *match, void *result)
 {
     *(char **)result = util_strdup_s(content);
     return 0;
@@ -228,7 +142,7 @@ static bool check_cgroup_v1_helper(const char *mountpoint, const cgroup_v1_files
 }
 
 static int get_cgroup_v1_value_helper(const char *path, const cgroup_v1_files_index index,
-                                      const cgfile_callback_args_t *args, void *result)
+                                      void *result)
 {
     int nret = 0;
     char file_path[PATH_MAX] = { 0 };
@@ -265,7 +179,7 @@ static int get_cgroup_v1_value_helper(const char *path, const cgroup_v1_files_in
     util_trim_newline(content);
     content = util_trim_space(content);
 
-    nret = g_cgroup_v1_files[index].get_value(content, args, result);
+    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);
     }
@@ -308,11 +222,11 @@ static void check_cgroup_v1_cpuset(const cgroup_layer_t *layers, const bool quie
         return;
     }
 
-    if (get_cgroup_v1_value_helper(mountpoint, CPUSET_CPUS, NULL, (void *)&cpusetinfo->cpus) != 0) {
+    if (get_cgroup_v1_value_helper(mountpoint, CPUSET_CPUS, (void *)&cpusetinfo->cpus) != 0) {
         ERROR("Failed to get cgroup cpuset.cpus data");
         return;
     }
-    if (get_cgroup_v1_value_helper(mountpoint, CPUSET_MEMS, NULL, (void *)&cpusetinfo->mems) != 0) {
+    if (get_cgroup_v1_value_helper(mountpoint, CPUSET_MEMS, (void *)&cpusetinfo->mems) != 0) {
         free(cpusetinfo->cpus);
         cpusetinfo->cpus = NULL;
         ERROR("Failed to get cgroup cpuset.cpus data");
@@ -463,7 +377,7 @@ static void get_cgroup_v1_metrics_cpu(const cgroup_layer_t *layers, const char *
         return;
     }
 
-    get_cgroup_v1_value_helper(path, CPUACCT_USE_NANOS, NULL, (void *)&cgroup_cpu_metrics->cpu_use_nanos);
+    get_cgroup_v1_value_helper(path, CPUACCT_USE_NANOS, (void *)&cgroup_cpu_metrics->cpu_use_nanos);
 }
 
 static void get_cgroup_v1_metrics_memory(const cgroup_layer_t *layers, const char *cgroup_path,
@@ -472,18 +386,6 @@ static void get_cgroup_v1_metrics_memory(const cgroup_layer_t *layers, const cha
     int nret = 0;
     char *mountpoint = NULL;
     char path[PATH_MAX] = { 0 };
-    const cgfile_callback_args_t total_inactive_file_arg = {
-        .match = "total_inactive_file",
-    };
-    const cgfile_callback_args_t total_rss_arg = {
-        .match = "total_rss",
-    };
-    const cgfile_callback_args_t total_pgfault_arg = {
-        .match = "total_pgfault",
-    };
-    const cgfile_callback_args_t total_pgmajfault_arg = {
-        .match = "total_pgmajfault",
-    };
 
     mountpoint = common_find_cgroup_subsystem_mountpoint(layers, "memory");
     if (mountpoint == NULL) {
@@ -497,14 +399,14 @@ static void get_cgroup_v1_metrics_memory(const cgroup_layer_t *layers, const cha
         return;
     }
 
-    get_cgroup_v1_value_helper(path, MEMORY_LIMIT, NULL, (void *)&cgroup_mem_metrics->mem_limit);
-    get_cgroup_v1_value_helper(path, MEMORY_USAGE, NULL, (void *)&cgroup_mem_metrics->mem_used);
-    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_RSS, &total_rss_arg, (void *)&cgroup_mem_metrics->total_rss);
-    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_PGFAULT, &total_pgfault_arg,
+    get_cgroup_v1_value_helper(path, MEMORY_LIMIT, (void *)&cgroup_mem_metrics->mem_limit);
+    get_cgroup_v1_value_helper(path, MEMORY_USAGE, (void *)&cgroup_mem_metrics->mem_used);
+    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_RSS, (void *)&cgroup_mem_metrics->total_rss);
+    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_PGFAULT,
                                (void *)&cgroup_mem_metrics->total_pgfault);
-    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_PGMAJFAULT, &total_pgmajfault_arg,
+    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_PGMAJFAULT,
                                (void *)&cgroup_mem_metrics->total_pgmajfault);
-    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_INACTIVE_FILE, &total_inactive_file_arg,
+    get_cgroup_v1_value_helper(path, MEMORY_TOTAL_INACTIVE_FILE,
                                (void *)&cgroup_mem_metrics->total_inactive_file);
 }
 
@@ -527,7 +429,7 @@ static void get_cgroup_v1_metrics_pid(const cgroup_layer_t *layers, const char *
         return;
     }
 
-    get_cgroup_v1_value_helper(path, PIDS_CURRENT, NULL, (void *)&cgroup_pids_metrics->pid_current);
+    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)
diff --git a/src/daemon/common/cgroup_v2.c b/src/daemon/common/cgroup_v2.c
new file mode 100644
index 00000000..25509bda
--- /dev/null
+++ b/src/daemon/common/cgroup_v2.c
@@ -0,0 +1,406 @@
+/******************************************************************************
+ * 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-01-16
+ * Description: provide cgroup v2 functions
+ ******************************************************************************/
+#include "cgroup.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <isula_libutils/auto_cleanup.h>
+
+#include "utils.h"
+#include "path.h"
+#include "sysinfo.h"
+
+// Cgroup V2 Item Definition
+#define CGROUP2_CPU_WEIGHT "cpu.weight"
+#define CGROUP2_CPU_MAX "cpu.max"
+#define CGROUP2_CPUSET_CPUS_EFFECTIVE "cpuset.cpus.effective"
+#define CGROUP2_CPUSET_MEMS_EFFECTIVE "cpuset.mems.effective"
+#define CGROUP2_CPUSET_CPUS "cpuset.cpus"
+#define CGROUP2_CPUSET_MEMS "cpuset.mems"
+#define CGROUP2_IO_WEIGHT "io.weight"
+#define CGROUP2_IO_BFQ_WEIGHT "io.bfq.weight"
+#define CGROUP2_IO_MAX "io.max"
+#define CGROUP2_MEMORY_MAX "memory.max"
+#define CGROUP2_MEMORY_LOW "memory.low"
+#define CGROUP2_MEMORY_SWAP_MAX "memory.swap.max"
+#define CGROUP2_HUGETLB_MAX "hugetlb.%s.max"
+#define CGROUP2_PIDS_MAX "pids.max"
+#define CGROUP2_FILES_LIMIT "files.limit"
+
+#define CGROUP2_CONTROLLERS_PATH CGROUP_MOUNTPOINT"/cgroup.controllers"
+#define CGROUP2_SUBTREE_CONTROLLER_PATH CGROUP_MOUNTPOINT"/cgroup.subtree_control"
+#define CGROUP2_CPUSET_CPUS_EFFECTIVE_PATH CGROUP_MOUNTPOINT"/cpuset.cpus.effective"
+#define CGROUP2_CPUSET_MEMS_EFFECTIVE_PATH CGROUP_MOUNTPOINT"/cpuset.mems.effective"
+
+#ifndef CGROUP2_SUPER_MAGIC
+#define CGROUP2_SUPER_MAGIC 0x63677270
+#endif
+
+static int get_value_ull_v2(const char *content, const char *match, void *result)
+{
+    uint64_t ull_result = 0;
+    __isula_auto_free char *tmp_str = util_strdup_s(content);
+
+    tmp_str = util_trim_space(tmp_str);
+    if (strcmp(tmp_str, "max") == 0) {
+        *(uint64_t *)result = UINT64_MAX;
+        return 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;
+}
+
+typedef enum {
+    // cpu
+    CPUACCT_USE_USER, CPUACCT_USE_SYS, CPUACCT_USE_NANOS,
+    // MEMORY subsystem
+    MEMORY_USAGE, MEMORY_LIMIT, MEMORY_ANON,
+    MEMORY_TOTAL_PGFAULT, MEMORY_TOTAL_INACTIVE_FILE, MEMORY_TOTAL_PGMAJFAULT,
+    MEMORY_CACHE, MEMORY_CACHE_TOTAL,
+    // BLKIO subsystem
+    BLKIO_READ_BPS, BLKIO_WRITE_BPS, BLKIO_READ_IOPS, BLKIO_WRITE_IOPS,
+    // PIDS subsystem
+    PIDS_CURRENT,
+    // MAX
+    CGROUP_V2_FILES_INDEX_MAXS
+} cgroup_v2_files_index;
+
+static struct cgfile_t g_cgroup_v2_files[] = {
+    // cpu
+    [CPUACCT_USE_USER]              = {"cpu_use_user",          "cpu.stat",        "user_usec",         get_match_value_ull},
+    [CPUACCT_USE_SYS]               = {"cpu_use_sys",           "cpu.stat",        "system_usec",       get_match_value_ull},
+    [CPUACCT_USE_NANOS]             = {"cpu_use_nanos",         "cpu.stat",        "usage_usec",        get_match_value_ull},
+    // memory
+    [MEMORY_USAGE]                  = {"mem_usage",             "memory.current",  NULL,                get_value_ull_v2},
+    [MEMORY_LIMIT]                  = {"mem_limit",             "memory.max",      NULL,                get_value_ull_v2},
+    [MEMORY_ANON]                   = {"mem_anon",              "memory.stat",     "anon",              get_match_value_ull},
+    [MEMORY_TOTAL_PGFAULT]          = {"total_page_fault",      "memory.stat",     "pgfault",           get_match_value_ull},
+    [MEMORY_TOTAL_PGMAJFAULT]       = {"total_page_majfault",   "memory.stat",     "pgmajfault",        get_match_value_ull},
+    [MEMORY_TOTAL_INACTIVE_FILE]    = {"total_inactive_file",   "memory.stat",     "inactive_file",     get_match_value_ull},
+    [MEMORY_CACHE]                  = {"cache",                 "memory.stat",     "file",              get_match_value_ull},
+    [MEMORY_CACHE_TOTAL]            = {"cache_total",           "memory.stat",     "file",              get_match_value_ull},
+    // pids
+    [PIDS_CURRENT]                  = {"pids_current",          "pids.current",    NULL,                get_value_ull_v2},
+};
+
+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;
+}
+
+static void get_cgroup_v2_metrics_cpu(const char *cgroup_path, cgroup_cpu_metrics_t *cgroup_cpu_metrics)
+{
+    int nret = 0;
+    char path[PATH_MAX] = { 0 };
+
+    nret = snprintf(path, sizeof(path), "%s/%s", CGROUP_MOUNTPOINT, cgroup_path);
+    if (nret < 0 || (size_t)nret >= sizeof(path)) {
+        ERROR("Failed to snprintf");
+        return;
+    }
+
+    get_cgroup_v2_value_helper(path, CPUACCT_USE_NANOS, (void *)&cgroup_cpu_metrics->cpu_use_nanos);
+}
+
+static void get_cgroup_v2_metrics_memory(const char *cgroup_path, cgroup_mem_metrics_t *cgroup_mem_metrics)
+{
+    int nret = 0;
+    char path[PATH_MAX] = { 0 };
+
+    nret = snprintf(path, sizeof(path), "%s/%s", CGROUP_MOUNTPOINT, cgroup_path);
+    if (nret < 0 || (size_t)nret >= sizeof(path)) {
+        ERROR("Failed to snprintf");
+        return;
+    }
+
+    get_cgroup_v2_value_helper(path, MEMORY_LIMIT, (void *)&cgroup_mem_metrics->mem_limit);
+    get_cgroup_v2_value_helper(path, MEMORY_USAGE, (void *)&cgroup_mem_metrics->mem_used);
+    // Use Anon memory for RSS as cAdvisor on cgroupv2
+    // see https://github.com/google/cadvisor/blob/a9858972e75642c2b1914c8d5428e33e6392c08a/container/libcontainer/handler.go#L799
+    get_cgroup_v2_value_helper(path, MEMORY_ANON, (void *)&cgroup_mem_metrics->total_rss);
+    get_cgroup_v2_value_helper(path, MEMORY_TOTAL_PGFAULT,
+                               (void *)&cgroup_mem_metrics->total_pgfault);
+    get_cgroup_v2_value_helper(path, MEMORY_TOTAL_PGMAJFAULT,
+                               (void *)&cgroup_mem_metrics->total_pgmajfault);
+    get_cgroup_v2_value_helper(path, MEMORY_TOTAL_INACTIVE_FILE,
+                               (void *)&cgroup_mem_metrics->total_inactive_file);
+}
+
+static void get_cgroup_v2_metrics_pid(const char *cgroup_path, cgroup_pids_metrics_t *cgroup_pids_metrics)
+{
+    int nret = 0;
+    char path[PATH_MAX] = { 0 };
+
+    nret = snprintf(path, sizeof(path), "%s/%s", CGROUP_MOUNTPOINT, cgroup_path);
+    if (nret < 0 || (size_t)nret >= sizeof(path)) {
+        ERROR("Failed to snprintf");
+        return;
+    }
+
+    get_cgroup_v2_value_helper(path, PIDS_CURRENT, (void *)&cgroup_pids_metrics->pid_current);
+}
+
+static int cgroup2_enable_all()
+{
+    int ret = 0;
+    int nret = 0;
+    int n = 0;
+    size_t i = 0;
+    const char *space = "";
+    __isula_auto_free char *controllers_str = NULL;
+    __isula_auto_free char *subtree_controller_str = NULL;
+    __isula_auto_array_t char **controllers = NULL;
+    char enable_controllers[PATH_MAX] = { 0 };
+
+    controllers_str = util_read_content_from_file(CGROUP2_CONTROLLERS_PATH);
+    if (controllers_str == NULL || strlen(controllers_str) == 0 || strcmp(controllers_str, "\n") == 0) {
+        WARN("no cgroup controller found");
+        return ret;
+    }
+
+    subtree_controller_str = util_read_content_from_file(CGROUP2_SUBTREE_CONTROLLER_PATH);
+    if (subtree_controller_str != NULL && strcmp(controllers_str, subtree_controller_str) == 0) {
+        return ret;
+    }
+
+    controllers = util_string_split(controllers_str, ' ');
+    if (controllers == NULL) {
+        ERROR("split %s failed", controllers_str);
+        return -1;
+    }
+
+    for (i = 0; i < util_array_len((const char **)controllers); i++) {
+        nret = snprintf(enable_controllers + n, PATH_MAX - n, "%s+%s", space, controllers[i]);
+        if (nret < 0 || (size_t)nret >= PATH_MAX - n) {
+            ERROR("Path is too long");
+            return -1;
+        }
+        n += nret;
+        space = " ";
+    }
+    ret = util_write_file(CGROUP2_SUBTREE_CONTROLLER_PATH, enable_controllers, strlen(enable_controllers),
+                          DEFAULT_CGROUP_FILE_MODE);
+    if (ret != 0) {
+        SYSERROR("write %s to %s failed", enable_controllers, CGROUP2_SUBTREE_CONTROLLER_PATH);
+        return ret;
+    }
+
+    return ret;
+}
+
+#if defined (__ANDROID__) || defined(__MUSL__)
+static bool cgroup2_no_controller()
+{
+    char *controllers_str = NULL;
+
+    controllers_str = util_read_content_from_file(CGROUP2_CONTROLLERS_PATH);
+    if (controllers_str == NULL || strlen(controllers_str) == 0 || strcmp(controllers_str, "\n") == 0) {
+        free(controllers_str);
+        return true;
+    }
+
+    free(controllers_str);
+    return false;
+}
+#endif
+
+static int make_sure_cgroup2_isulad_path_exist()
+{
+    int ret = 0;
+
+    if (util_dir_exists(CGROUP_ISULAD_PATH)) {
+        return 0;
+    }
+
+    if (cgroup2_enable_all() != 0) {
+        return -1;
+    }
+
+#if defined (__ANDROID__) || defined(__MUSL__)
+    if (cgroup2_no_controller()) {
+        DEBUG("no cgroup controller found");
+        return 0;
+    }
+#endif
+
+    ret = mkdir(CGROUP_ISULAD_PATH, DEFAULT_CGROUP_DIR_MODE);
+    if (ret != 0 && (errno != EEXIST || !util_dir_exists(CGROUP_ISULAD_PATH))) {
+        return -1;
+    }
+
+    return ret;
+}
+
+/* cgroup enabled */
+static bool cgroup_v2_enabled(const char *mountpoint, const char *name)
+{
+    char path[PATH_MAX] = { 0 };
+    int nret;
+
+    nret = snprintf(path, sizeof(path), "%s/%s", mountpoint, name);
+    if (nret < 0 || (size_t)nret >= sizeof(path)) {
+        ERROR("Path is too long");
+        return false;
+    }
+    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)
+{
+    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");
+
+    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) &&
+                         cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_CPUSET_MEMS);
+    common_cgroup_do_log(quiet, !(cpusetinfo->cpuset), "Your kernel does not support cpuset");
+    if (cpusetinfo->cpuset) {
+        cpusetinfo->cpus = util_read_content_from_file(CGROUP2_CPUSET_CPUS_EFFECTIVE_PATH);
+        cpusetinfo->mems = util_read_content_from_file(CGROUP2_CPUSET_MEMS_EFFECTIVE_PATH);
+        if (cpusetinfo->cpus == NULL || cpusetinfo->mems == NULL) {
+            ERROR("read cpus or mems failed");
+            return -1;
+        }
+        cpusetinfo->cpus = util_trim_space(cpusetinfo->cpus);
+        cpusetinfo->mems = util_trim_space(cpusetinfo->mems);
+    }
+
+    // io cgroup
+    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;
+    common_cgroup_do_log(quiet, !(blkioinfo->blkio_weight), "Your kernel does not support cgroup2 io weight");
+
+    blkioinfo->blkio_read_bps_device = cgroup_v2_enabled(CGROUP_ISULAD_PATH, CGROUP2_IO_MAX);
+    blkioinfo->blkio_write_bps_device = blkioinfo->blkio_read_bps_device;
+    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");
+
+    // hugetlb cgroup
+    size = get_default_huge_page_size();
+    if (size != NULL) {
+        nret = snprintf(path, sizeof(path), CGROUP2_HUGETLB_MAX, size);
+        if (nret < 0 || (size_t)nret >= sizeof(path)) {
+            WARN("Failed to print hugetlb path");
+            return -1;
+        }
+        hugetlbinfo->hugetlblimit = cgroup_v2_enabled(CGROUP_ISULAD_PATH, path);
+        common_cgroup_do_log(quiet, !hugetlbinfo->hugetlblimit, "Your kernel does not support cgroup2 hugetlb limit");
+    } else {
+        WARN("Your kernel does not support cgroup2 hugetlb limit");
+    }
+
+    // files cgroup
+    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)
+{
+    if (cgroup_path == NULL || strlen(cgroup_path) == 0 || cgroup_metrics == NULL) {
+        ERROR("Invalid arguments");
+        return -1;
+    }
+
+    get_cgroup_v2_metrics_cpu(cgroup_path, &cgroup_metrics->cgcpu_metrics);
+    get_cgroup_v2_metrics_memory(cgroup_path, &cgroup_metrics->cgmem_metrics);
+    get_cgroup_v2_metrics_pid(cgroup_path, &cgroup_metrics->cgpids_metrics);
+
+    return 0;
+}
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 76fa17bc..3bdc3af8 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
@@ -881,7 +881,7 @@ void PodSandboxManagerService::GetPodSandboxCgroupMetrics(const std::string &cgr
     if (cgroupVersion == CGROUP_VERSION_1) {
         nret = common_get_cgroup_v1_metrics(cgroupParent.c_str(), &cgroupMetrics);
     } else {
-        // todo: get cgroup v2 metrics
+        nret = common_get_cgroup_v2_metrics(cgroupParent.c_str(), &cgroupMetrics);
     }
 
     if (nret != 0) {
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 4d1d19eb..49a7ca54 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
@@ -1337,7 +1337,7 @@ void PodSandboxManagerService::GetPodSandboxCgroupMetrics(const container_inspec
     if (cgroupVersion == CGROUP_VERSION_1) {
         nret = common_get_cgroup_v1_metrics(cgroupParent, &cgroupMetrics);
     } else {
-        // todo: get cgroup v2 metrics
+        nret = common_get_cgroup_v2_metrics(cgroupParent, &cgroupMetrics);
     }
 
     if (nret != 0) {
diff --git a/src/utils/cutils/utils_array.h b/src/utils/cutils/utils_array.h
index 64f41496..1c084595 100644
--- a/src/utils/cutils/utils_array.h
+++ b/src/utils/cutils/utils_array.h
@@ -18,6 +18,7 @@
 
 #include <stdbool.h>
 #include <stddef.h>
+#include <isula_libutils/auto_cleanup.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -57,6 +58,11 @@ void util_free_sensitive_array(char **array);
 
 void util_free_sensitive_array_by_len(char **array, size_t len);
 
+// define auto free function callback for char *
+define_auto_cleanup_callback(util_free_array, char *);
+// define auto free macro for char *
+#define __isula_auto_array_t auto_cleanup_tag(util_free_array)
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.34.1

