summaryrefslogtreecommitdiff
path: root/0012-fix-cpu-rt-disable-after-reboot-machine.patch
diff options
context:
space:
mode:
Diffstat (limited to '0012-fix-cpu-rt-disable-after-reboot-machine.patch')
-rw-r--r--0012-fix-cpu-rt-disable-after-reboot-machine.patch823
1 files changed, 823 insertions, 0 deletions
diff --git a/0012-fix-cpu-rt-disable-after-reboot-machine.patch b/0012-fix-cpu-rt-disable-after-reboot-machine.patch
new file mode 100644
index 0000000..5ae07d1
--- /dev/null
+++ b/0012-fix-cpu-rt-disable-after-reboot-machine.patch
@@ -0,0 +1,823 @@
+From 166edf2093b2c35fe4e479ca4b6568be8c98f907 Mon Sep 17 00:00:00 2001
+From: haozi007 <liuhao27@huawei.com>
+Date: Wed, 15 Feb 2023 17:47:12 +0800
+Subject: [PATCH 12/53] fix cpu-rt disable after reboot machine
+
+1. ensure parent cgroup cpu-rt of container, should do in start container;
+2. current do in create container, will cause failed of start container with cpu-rt after reboot machine
+
+Signed-off-by: haozi007 <liuhao27@huawei.com>
+---
+ src/daemon/common/sysinfo.c | 46 +++-
+ src/daemon/common/sysinfo.h | 2 +
+ src/daemon/executor/container_cb/execution.c | 158 ++++++++++++-
+ .../executor/container_cb/execution_create.c | 222 +-----------------
+ src/daemon/modules/api/specs_api.h | 2 +-
+ src/daemon/modules/spec/specs.c | 84 ++++---
+ test/specs/specs/specs_ut.cc | 40 ++--
+ 7 files changed, 280 insertions(+), 274 deletions(-)
+
+diff --git a/src/daemon/common/sysinfo.c b/src/daemon/common/sysinfo.c
+index 38416db4..7559d653 100644
+--- a/src/daemon/common/sysinfo.c
++++ b/src/daemon/common/sysinfo.c
+@@ -24,8 +24,10 @@
+ #include <linux/magic.h>
+ #include <sys/stat.h>
+
++#include <isula_libutils/auto_cleanup.h>
++#include <isula_libutils/log.h>
++
+ #include "err_msg.h"
+-#include "isula_libutils/log.h"
+ #include "utils.h"
+ #include "utils_array.h"
+ #include "utils_file.h"
+@@ -1627,3 +1629,45 @@ free_out:
+ }
+ return minfos;
+ }
++
++char *sysinfo_cgroup_controller_cpurt_mnt_path()
++{
++ int nret = 0;
++ __isula_auto_free char *mnt = NULL;
++ __isula_auto_free char *root = NULL;
++ char fpath[PATH_MAX] = { 0 };
++ sysinfo_t *sysinfo = NULL;
++
++ sysinfo = get_sys_info(true);
++ if (sysinfo == NULL) {
++ ERROR("Can not get system info");
++ return NULL;
++ }
++
++ if (!(sysinfo->cgcpuinfo.cpu_rt_period)) {
++ ERROR("Daemon-scoped cpu-rt-period and cpu-rt-runtime are not supported by kernel");
++ isulad_set_error_message("Daemon-scoped cpu-rt-period and cpu-rt-runtime are not supported by kernel");
++ return NULL;
++ }
++
++ nret = find_cgroup_mountpoint_and_root("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'");
++ return NULL;
++ }
++
++ // When iSulad is run inside docker, the root is based of the host cgroup.
++ // Replace root to "/"
++ if (strncmp(root, "/docker/", strlen("/docker/")) == 0) {
++ root[1] = '\0';
++ }
++
++ nret = snprintf(fpath, sizeof(fpath), "%s/%s", mnt, root);
++ if (nret < 0 || (size_t)nret >= sizeof(fpath)) {
++ ERROR("Failed to print string");
++ return NULL;
++ }
++
++ return util_strdup_s(fpath);
++}
+\ No newline at end of file
+diff --git a/src/daemon/common/sysinfo.h b/src/daemon/common/sysinfo.h
+index 8468e00a..bbb3c6b5 100644
+--- a/src/daemon/common/sysinfo.h
++++ b/src/daemon/common/sysinfo.h
+@@ -139,6 +139,8 @@ 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();
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/src/daemon/executor/container_cb/execution.c b/src/daemon/executor/container_cb/execution.c
+index 7b18a8e1..ed70fc14 100644
+--- a/src/daemon/executor/container_cb/execution.c
++++ b/src/daemon/executor/container_cb/execution.c
+@@ -18,6 +18,12 @@
+ #include <pthread.h>
+ #include <malloc.h>
+ #include <sys/eventfd.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++#include <libgen.h>
++
+ #include <isula_libutils/container_config.h>
+ #include <isula_libutils/container_config_v2.h>
+ #include <isula_libutils/container_delete_request.h>
+@@ -34,13 +40,13 @@
+ #include <isula_libutils/container_stop_request.h>
+ #include <isula_libutils/container_stop_response.h>
+ #include <isula_libutils/json_common.h>
+-#include <stdbool.h>
+-#include <stdint.h>
+-#include <stdlib.h>
+-#include <string.h>
++#include <isula_libutils/auto_cleanup.h>
++#include <isula_libutils/log.h>
+
+-#include "isula_libutils/log.h"
++#include "isulad_config.h"
++#include "sysinfo.h"
+ #include "container_api.h"
++#include "specs_api.h"
+ #include "execution_extend.h"
+ #include "execution_information.h"
+ #include "execution_stream.h"
+@@ -302,6 +308,135 @@ static void pack_start_response(container_start_response *response, uint32_t cc,
+ }
+ }
+
++static int do_init_cpurt_cgroups_path(const char *path, int recursive_depth, const char *mnt_root,
++ int64_t cpu_rt_period, int64_t cpu_rt_runtime);
++
++/* maybe create cpu realtime file */
++static int maybe_create_cpu_realtime_file(int64_t value, const char *file, const char *path)
++{
++ int ret;
++ __isula_auto_close int fd = -1;
++ ssize_t nwrite;
++ char fpath[PATH_MAX] = { 0 };
++ char buf[ISULAD_NUMSTRLEN64] = { 0 };
++
++ if (value == 0) {
++ return 0;
++ }
++
++ ret = util_mkdir_p(path, CONFIG_DIRECTORY_MODE);
++ if (ret != 0) {
++ ERROR("Failed to mkdir: %s", path);
++ return -1;
++ }
++
++ ret = snprintf(fpath, sizeof(fpath), "%s/%s", path, file);
++ if (ret < 0 || ret >= sizeof(fpath)) {
++ ERROR("Failed to print string");
++ return -1;
++ }
++ ret = snprintf(buf, sizeof(buf), "%lld", (long long int)value);
++ if (ret < 0 || (size_t)ret >= sizeof(buf)) {
++ ERROR("Failed to print string");
++ return -1;
++ }
++
++ fd = util_open(fpath, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0700);
++ if (fd < 0) {
++ ERROR("Failed to open file: %s: %s", fpath, strerror(errno));
++ isulad_set_error_message("Failed to open file: %s: %s", fpath, strerror(errno));
++ return -1;
++ }
++ nwrite = util_write_nointr(fd, buf, strlen(buf));
++ if (nwrite < 0 || nwrite != strlen(buf)) {
++ ERROR("Failed to write %s to %s: %s", buf, fpath, strerror(errno));
++ isulad_set_error_message("Failed to write '%s' to '%s': %s", buf, fpath, strerror(errno));
++ return -1;
++ }
++
++ return 0;
++}
++
++static int recursively_create_cgroup(const char *path, const char *mnt_root, int recursive_depth, int64_t cpu_rt_period,
++ int64_t cpu_rt_runtime)
++{
++ int ret = 0;
++ __isula_auto_free char *dup = NULL;
++ char *dirpath = NULL;
++ char fpath[PATH_MAX] = { 0 };
++
++ dup = util_strdup_s(path);
++ dirpath = dirname(dup);
++ ret = do_init_cpurt_cgroups_path(dirpath, (recursive_depth + 1), mnt_root, cpu_rt_period, cpu_rt_runtime);
++ if (ret != 0) {
++ return ret;
++ }
++
++ int nret = snprintf(fpath, sizeof(fpath), "%s/%s", mnt_root, path);
++ if (nret < 0 || (size_t)nret >= sizeof(fpath)) {
++ ERROR("Failed to print string");
++ return ret;
++ }
++
++ ret = maybe_create_cpu_realtime_file(cpu_rt_period, "cpu.rt_period_us", fpath);
++ if (ret != 0) {
++ return ret;
++ }
++
++ return maybe_create_cpu_realtime_file(cpu_rt_runtime, "cpu.rt_runtime_us", fpath);
++}
++
++/* init cgroups path */
++static int do_init_cpurt_cgroups_path(const char *path, int recursive_depth, const char *mnt_root,
++ int64_t cpu_rt_period, int64_t cpu_rt_runtime)
++{
++ if ((recursive_depth + 1) > MAX_PATH_DEPTH) {
++ ERROR("Reach the max cgroup depth:%s", path);
++ return -1;
++ }
++
++ if (path == NULL || strcmp(path, "/") == 0 || strcmp(path, ".") == 0) {
++ return 0;
++ }
++
++ // Recursively create cgroup to ensure that the system and all parent cgroups have values set
++ // for the period and runtime as this limits what the children can be set to.
++ return recursively_create_cgroup(path, mnt_root, recursive_depth, cpu_rt_period, cpu_rt_runtime);
++}
++
++// TODO: maybe we should adapt to cgroup v2
++static int cpurt_controller_init(const char *id, const host_config *host_spec)
++{
++ __isula_auto_free char *mnt_root = NULL;
++ __isula_auto_free char *cgroups_path = NULL;
++ char *dirpath = NULL;
++ int64_t cpu_rt_period = 0;
++ int64_t cpu_rt_runtime = 0;
++
++ cgroups_path = merge_container_cgroups_path(id, host_spec);
++ if (cgroups_path == NULL || strcmp(cgroups_path, "/") == 0 || strcmp(cgroups_path, ".") == 0) {
++ return 0;
++ }
++
++ if (conf_get_cgroup_cpu_rt(&cpu_rt_period, &cpu_rt_runtime)) {
++ return -1;
++ }
++
++ if (cpu_rt_period == 0 && cpu_rt_runtime == 0) {
++ return 0;
++ }
++
++ mnt_root = sysinfo_cgroup_controller_cpurt_mnt_path();
++ if (mnt_root == NULL) {
++ ERROR("Failed to get cpu rt controller mnt root path");
++ return -1;
++ }
++
++ dirpath = dirname(cgroups_path);
++
++ return do_init_cpurt_cgroups_path(dirpath, 0, mnt_root, cpu_rt_period, cpu_rt_runtime);
++}
++
+ static int container_start_prepare(container_t *cont, const container_start_request *request, int stdinfd,
+ struct io_write_wrapper *stdout_handler, struct io_write_wrapper *stderr_handler,
+ char **fifopath, char *fifos[], int *sync_fd, pthread_t *thread_id)
+@@ -314,6 +449,19 @@ static int container_start_prepare(container_t *cont, const container_start_requ
+ return -1;
+ }
+
++ // init cgroup path for cpu_rt_runtime and cpu_rt_period
++ // we should do this in start container, not create container
++ // because, in scenarios:
++ // 1. enable cpu-rt of isulad;
++ // 2. then run container with --cpu-rt-runtime
++ // 3. then reboot machine;
++ // 4. finally, start before container, it will failed...
++ // cause of no one to set value into cgroup/isulad/cpu-rt-runtime and cpu-rt-period.
++ if (cpurt_controller_init(id, cont->hostconfig) != 0) {
++ isulad_set_error_message("Failed to init controller of cpu-rt for container \"%s\".", id);
++ return -1;
++ }
++
+ if (prepare_start_io(cont, request, fifopath, fifos, stdinfd, stdout_handler, stderr_handler, sync_fd, thread_id) !=
+ 0) {
+ return -1;
+diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c
+index 4cc333fd..4abc89c7 100644
+--- a/src/daemon/executor/container_cb/execution_create.c
++++ b/src/daemon/executor/container_cb/execution_create.c
+@@ -19,6 +19,14 @@
+ #include <errno.h>
+ #include <sys/stat.h>
+ #include <malloc.h>
++#include <limits.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <isula_libutils/log.h>
++#include <isula_libutils/auto_cleanup.h>
+ #include <isula_libutils/container_config.h>
+ #include <isula_libutils/container_config_v2.h>
+ #include <isula_libutils/defs.h>
+@@ -26,14 +34,7 @@
+ #include <isula_libutils/isulad_daemon_configs.h>
+ #include <isula_libutils/json_common.h>
+ #include <isula_libutils/oci_runtime_spec.h>
+-#include <limits.h>
+-#include <stdbool.h>
+-#include <stdint.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <libgen.h>
+
+-#include "isula_libutils/log.h"
+ #include "isulad_config.h"
+ #include "specs_api.h"
+ #include "verify.h"
+@@ -58,9 +59,6 @@
+ #include "opt_log.h"
+ #include "runtime_api.h"
+
+-static int do_init_cpurt_cgroups_path(const char *path, int recursive_depth, const char *mnt_root,
+- int64_t cpu_rt_period, int64_t cpu_rt_runtime);
+-
+ static int create_request_check(const container_create_request *request)
+ {
+ int ret = 0;
+@@ -1323,203 +1321,6 @@ static int save_container_config_before_create(const char *id, const char *runti
+ return 0;
+ }
+
+-/* maybe create cpu realtime file */
+-static int maybe_create_cpu_realtime_file(int64_t value, const char *file, const char *path)
+-{
+- int ret;
+- int fd = -1;
+- ssize_t nwrite;
+- char fpath[PATH_MAX] = { 0 };
+- char buf[ISULAD_NUMSTRLEN64] = { 0 };
+-
+- if (value == 0) {
+- return 0;
+- }
+-
+- ret = util_mkdir_p(path, CONFIG_DIRECTORY_MODE);
+- if (ret != 0) {
+- ERROR("Failed to mkdir: %s", path);
+- return -1;
+- }
+-
+- ret = snprintf(fpath, sizeof(fpath), "%s/%s", path, file);
+- if (ret < 0 || ret >= sizeof(fpath)) {
+- ERROR("Failed to print string");
+- return -1;
+- }
+- ret = snprintf(buf, sizeof(buf), "%lld", (long long int)value);
+- if (ret < 0 || (size_t)ret >= sizeof(buf)) {
+- ERROR("Failed to print string");
+- return -1;
+- }
+-
+- fd = util_open(fpath, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0700);
+- if (fd < 0) {
+- ERROR("Failed to open file: %s: %s", fpath, strerror(errno));
+- isulad_set_error_message("Failed to open file: %s: %s", fpath, strerror(errno));
+- return -1;
+- }
+- nwrite = util_write_nointr(fd, buf, strlen(buf));
+- if (nwrite < 0) {
+- ERROR("Failed to write %s to %s: %s", buf, fpath, strerror(errno));
+- isulad_set_error_message("Failed to write '%s' to '%s': %s", buf, fpath, strerror(errno));
+- close(fd);
+- return -1;
+- }
+- close(fd);
+-
+- return 0;
+-}
+-
+-static int recursively_create_cgroup(const char *path, const char *mnt_root, int recursive_depth, int64_t cpu_rt_period,
+- int64_t cpu_rt_runtime)
+-{
+- int ret = 0;
+- char *dup = NULL;
+- char *dirpath = NULL;
+- char fpath[PATH_MAX] = { 0 };
+-
+- dup = util_strdup_s(path);
+- dirpath = dirname(dup);
+- ret = do_init_cpurt_cgroups_path(dirpath, (recursive_depth + 1), mnt_root, cpu_rt_period, cpu_rt_runtime);
+- free(dup);
+- if (ret != 0) {
+- return ret;
+- }
+-
+- int nret = snprintf(fpath, sizeof(fpath), "%s/%s", mnt_root, path);
+- if (nret < 0 || (size_t)nret >= sizeof(fpath)) {
+- ERROR("Failed to print string");
+- ret = -1;
+- goto out;
+- }
+-
+- ret = maybe_create_cpu_realtime_file(cpu_rt_period, "cpu.rt_period_us", fpath);
+- if (ret != 0) {
+- goto out;
+- }
+-
+- ret = maybe_create_cpu_realtime_file(cpu_rt_runtime, "cpu.rt_runtime_us", fpath);
+- if (ret != 0) {
+- goto out;
+- }
+-
+-out:
+- return ret;
+-}
+-
+-/* init cgroups path */
+-static int do_init_cpurt_cgroups_path(const char *path, int recursive_depth, const char *mnt_root,
+- int64_t cpu_rt_period, int64_t cpu_rt_runtime)
+-{
+- if ((recursive_depth + 1) > MAX_PATH_DEPTH) {
+- ERROR("Reach the max cgroup depth:%s", path);
+- return -1;
+- }
+-
+- if (path == NULL || strcmp(path, "/") == 0 || strcmp(path, ".") == 0) {
+- return 0;
+- }
+-
+- // Recursively create cgroup to ensure that the system and all parent cgroups have values set
+- // for the period and runtime as this limits what the children can be set to.
+- if (recursively_create_cgroup(path, mnt_root, recursive_depth, cpu_rt_period, cpu_rt_runtime)) {
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-static char *get_cpurt_controller_mnt_path()
+-{
+- char *res = NULL;
+- int nret = 0;
+- char *mnt = NULL;
+- char *root = NULL;
+- char fpath[PATH_MAX] = { 0 };
+-
+- nret = find_cgroup_mountpoint_and_root("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'");
+- goto out;
+- }
+-
+- // When iSulad is run inside docker, the root is based of the host cgroup.
+- // Replace root to "/"
+- if (strncmp(root, "/docker/", strlen("/docker/")) == 0) {
+- root[1] = '\0';
+- }
+-
+- nret = snprintf(fpath, sizeof(fpath), "%s/%s", mnt, root);
+- if (nret < 0 || (size_t)nret >= sizeof(fpath)) {
+- ERROR("Failed to print string");
+- goto out;
+- }
+-
+- res = util_strdup_s(fpath);
+-
+-out:
+- free(mnt);
+- free(root);
+- return res;
+-}
+-
+-static int cpurt_controller_init(const char *cgroups_path)
+-{
+- int ret = 0;
+- char *dup = NULL;
+- char *dirpath = NULL;
+- int64_t cpu_rt_period = 0;
+- int64_t cpu_rt_runtime = 0;
+- sysinfo_t *sysinfo = NULL;
+- char *mnt_root = NULL;
+-
+- if (cgroups_path == NULL || strcmp(cgroups_path, "/") == 0 || strcmp(cgroups_path, ".") == 0) {
+- return 0;
+- }
+-
+- if (conf_get_cgroup_cpu_rt(&cpu_rt_period, &cpu_rt_runtime)) {
+- return -1;
+- }
+-
+- if (cpu_rt_period == 0 && cpu_rt_runtime == 0) {
+- return 0;
+- }
+-
+- sysinfo = get_sys_info(true);
+- if (sysinfo == NULL) {
+- ERROR("Can not get system info");
+- ret = -1;
+- goto out;
+- }
+-
+- if (!(sysinfo->cgcpuinfo.cpu_rt_period)) {
+- ERROR("Daemon-scoped cpu-rt-period and cpu-rt-runtime are not supported by kernel");
+- isulad_set_error_message("Daemon-scoped cpu-rt-period and cpu-rt-runtime are not supported by kernel");
+- ret = -1;
+- goto out;
+- }
+-
+- mnt_root = get_cpurt_controller_mnt_path();
+- if (mnt_root == NULL) {
+- ERROR("Failed to get cpu rt controller mnt root path");
+- isulad_set_error_message("Failed to get cpu rt controller mnt root path");
+- ret = -1;
+- goto out;
+- }
+-
+- dup = util_strdup_s(cgroups_path);
+- dirpath = dirname(dup);
+-
+- ret = do_init_cpurt_cgroups_path(dirpath, 0, mnt_root, cpu_rt_period, cpu_rt_runtime);
+-
+-out:
+- free(mnt_root);
+- free(dup);
+- return ret;
+-}
+-
+ /*
+ * request -> host_spec + container_spec
+ * container_spec + image config
+@@ -1680,13 +1481,6 @@ int container_create_cb(const container_create_request *request, container_creat
+ goto umount_channel;
+ }
+
+- // init cgroup path for cpu_rt_runtime and cpu_rt_period
+- if (cpurt_controller_init(oci_spec->linux->cgroups_path) != 0) {
+- ERROR("Unable to init CPU RT controller %s", oci_spec->linux->cgroups_path);
+- cc = ISULAD_ERR_EXEC;
+- goto umount_channel;
+- }
+-
+ if (container_v2_spec_merge_contaner_spec(v2_spec) != 0) {
+ ERROR("Failed to merge container settings");
+ cc = ISULAD_ERR_EXEC;
+diff --git a/src/daemon/modules/api/specs_api.h b/src/daemon/modules/api/specs_api.h
+index 4c132108..e0a73f55 100644
+--- a/src/daemon/modules/api/specs_api.h
++++ b/src/daemon/modules/api/specs_api.h
+@@ -28,7 +28,7 @@ extern "C" {
+
+ int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_config_v2_common_config *v2_spec,
+ oci_runtime_spec *oci_spec);
+-int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, const host_config *host_spec);
++char *merge_container_cgroups_path(const char *id, const host_config *host_spec);
+ int merge_global_config(oci_runtime_spec *oci_spec);
+ oci_runtime_spec *load_oci_config(const char *rootpath, const char *name);
+ oci_runtime_spec *default_spec(bool system_container);
+diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c
+index 12d9b96d..857fc3dc 100644
+--- a/src/daemon/modules/spec/specs.c
++++ b/src/daemon/modules/spec/specs.c
+@@ -26,6 +26,7 @@
+ #include <isula_libutils/oci_runtime_hooks.h>
+ #include <isula_libutils/host_config.h>
+ #include <isula_libutils/log.h>
++#include <isula_libutils/auto_cleanup.h>
+ #include <limits.h>
+ #include <stdint.h>
+
+@@ -165,36 +166,43 @@ out:
+ return ret;
+ }
+
+-static int make_annotations_cgroup_dir(const container_config *container_spec, const host_config *host_spec)
++static char *do_get_container_cgroup_path(const host_config *host_spec)
+ {
+- int ret = 0;
+- char cleaned[PATH_MAX] = { 0 };
+- char *default_cgroup_parent = NULL;
+ char *path = NULL;
+
+- default_cgroup_parent = conf_get_isulad_cgroup_parent();
+ if (host_spec->cgroup_parent != NULL) {
+- path = host_spec->cgroup_parent;
+- } else if (default_cgroup_parent != NULL) {
+- path = default_cgroup_parent;
++ // first, use user setting
++ path = util_strdup_s(host_spec->cgroup_parent);
++ } else {
++ // second, if user donot set, use setting from daemon config
++ path = conf_get_isulad_cgroup_parent();
+ }
++
+ if (path == NULL) {
+- path = "/isulad";
++ // third, all faild, just use default '/isulad'
++ path = util_strdup_s("/isulad");
+ }
++
++ return path;
++}
++
++static int make_annotations_cgroup_dir(const container_config *container_spec, const host_config *host_spec)
++{
++ char cleaned[PATH_MAX] = { 0 };
++ __isula_auto_free char *path = NULL;
++
++ path = do_get_container_cgroup_path(host_spec);
+ if (util_clean_path(path, cleaned, sizeof(cleaned)) == NULL) {
+ ERROR("Failed to clean path: %s", path);
+- ret = -1;
+- goto out;
++ return -1;
+ }
++
+ if (append_json_map_string_string(container_spec->annotations, "cgroup.dir", cleaned)) {
+ ERROR("Realloc annotations failed");
+- ret = -1;
+- goto out;
++ return -1;
+ }
+
+-out:
+- free(default_cgroup_parent);
+- return ret;
++ return 0;
+ }
+
+ static int make_annotations_oom_score_adj(const container_config *container_spec, const host_config *host_spec)
+@@ -2058,42 +2066,40 @@ out:
+ return ret;
+ }
+
+-int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, const host_config *host_spec)
++char *merge_container_cgroups_path(const char *id, const host_config *host_spec)
+ {
+- int ret = 0;
+- char *default_cgroup_parent = NULL;
+- char *path = NULL;
++ __isula_auto_free char *path = NULL;
+
++ if (id == NULL || host_spec == NULL) {
++ ERROR("Invalid arguments");
++ return NULL;
++ }
++
++ path = do_get_container_cgroup_path(host_spec);
++
++ return util_path_join(path, id);
++}
++
++static int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, const host_config *host_spec)
++{
+ if (id == NULL || oci_spec == NULL || host_spec == NULL) {
+ ERROR("Invalid arguments");
+- ret = -1;
+- goto out;
++ return -1;
+ }
+
+ if (make_sure_oci_spec_linux(oci_spec) != 0) {
+ ERROR("Failed to make oci spec linux");
+- ret = -1;
+- goto out;
++ return -1;
+ }
+
+- default_cgroup_parent = conf_get_isulad_cgroup_parent();
+- path = default_cgroup_parent;
+- if (host_spec->cgroup_parent != NULL) {
+- path = host_spec->cgroup_parent;
+- }
++ free(oci_spec->linux->cgroups_path);
++ oci_spec->linux->cgroups_path = merge_container_cgroups_path(id, host_spec);
+
+- if (path == NULL) {
+- free(oci_spec->linux->cgroups_path);
+- oci_spec->linux->cgroups_path = util_path_join("/isulad", id);
+- return 0;
++ if (oci_spec->linux->cgroups_path == NULL) {
++ WARN("OCI spec cgroups path is NULL");
+ }
+
+- free(oci_spec->linux->cgroups_path);
+- oci_spec->linux->cgroups_path = util_path_join(path, id);
+-
+-out:
+- free(default_cgroup_parent);
+- return ret;
++ return 0;
+ }
+
+ int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_config_v2_common_config *v2_spec,
+diff --git a/test/specs/specs/specs_ut.cc b/test/specs/specs/specs_ut.cc
+index c4014e2e..96aa1c63 100644
+--- a/test/specs/specs/specs_ut.cc
++++ b/test/specs/specs/specs_ut.cc
+@@ -232,15 +232,16 @@ char *invoke_conf_get_isulad_cgroup_parent()
+ return util_strdup_s("/var/lib/isulad/engines/lcr");
+ }
+
+-TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_1)
++TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_1)
+ {
+- ASSERT_EQ(merge_oci_cgroups_path(nullptr, nullptr, nullptr), -1);
++ ASSERT_EQ(merge_container_cgroups_path(nullptr, nullptr), nullptr);
+ }
+
+-TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_2)
++TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_2)
+ {
+ oci_runtime_spec *oci_spec = nullptr;
+ host_config *host_spec = nullptr;
++ char *merged_cp = nullptr;
+
+ oci_spec = (oci_runtime_spec *)util_common_calloc_s(sizeof(oci_runtime_spec));
+ ASSERT_TRUE(oci_spec != nullptr);
+@@ -250,20 +251,23 @@ TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_2)
+
+ EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent_null));
+
+- ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0);
++ merged_cp = merge_container_cgroups_path("123", host_spec);
++ ASSERT_NE(merged_cp, nullptr);
+
+- ASSERT_STREQ(oci_spec->linux->cgroups_path, "/isulad/123");
++ ASSERT_STREQ(merged_cp, "/isulad/123");
+
+ free_oci_runtime_spec(oci_spec);
+ free_host_config(host_spec);
++ free(merged_cp);
+
+ testing::Mock::VerifyAndClearExpectations(&m_isulad_conf);
+ }
+
+-TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_3)
++TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_3)
+ {
+ oci_runtime_spec *oci_spec = nullptr;
+ host_config *host_spec = nullptr;
++ char *merged_cp = nullptr;
+
+ oci_spec = (oci_runtime_spec *)util_common_calloc_s(sizeof(oci_runtime_spec));
+ ASSERT_TRUE(oci_spec != nullptr);
+@@ -275,20 +279,23 @@ TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_3)
+
+ EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent_null));
+
+- ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0);
++ merged_cp = merge_container_cgroups_path("123", host_spec);
++ ASSERT_NE(merged_cp, nullptr);
+
+- ASSERT_STREQ(oci_spec->linux->cgroups_path, "/test/123");
++ ASSERT_STREQ(merged_cp, "/test/123");
+
+ free_oci_runtime_spec(oci_spec);
+ free_host_config(host_spec);
++ free(merged_cp);
+
+ testing::Mock::VerifyAndClearExpectations(&m_isulad_conf);
+ }
+
+-TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_4)
++TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_4)
+ {
+ oci_runtime_spec *oci_spec = nullptr;
+ host_config *host_spec = nullptr;
++ char *merged_cp = nullptr;
+
+ oci_spec = (oci_runtime_spec *)util_common_calloc_s(sizeof(oci_runtime_spec));
+ ASSERT_TRUE(oci_spec != nullptr);
+@@ -298,20 +305,23 @@ TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_4)
+
+ EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent));
+
+- ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0);
++ merged_cp = merge_container_cgroups_path("123", host_spec);
++ ASSERT_NE(merged_cp, nullptr);
+
+- ASSERT_STREQ(oci_spec->linux->cgroups_path, "/var/lib/isulad/engines/lcr/123");
++ ASSERT_STREQ(merged_cp, "/var/lib/isulad/engines/lcr/123");
+
+ free_oci_runtime_spec(oci_spec);
+ free_host_config(host_spec);
++ free(merged_cp);
+
+ testing::Mock::VerifyAndClearExpectations(&m_isulad_conf);
+ }
+
+-TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_5)
++TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_5)
+ {
+ oci_runtime_spec *oci_spec = nullptr;
+ host_config *host_spec = nullptr;
++ char *merged_cp = nullptr;
+
+ oci_spec = (oci_runtime_spec *)util_common_calloc_s(sizeof(oci_runtime_spec));
+ ASSERT_TRUE(oci_spec != nullptr);
+@@ -323,12 +333,14 @@ TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_5)
+
+ EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent));
+
+- ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0);
++ merged_cp = merge_container_cgroups_path("123", host_spec);
++ ASSERT_NE(merged_cp, nullptr);
+
+- ASSERT_STREQ(oci_spec->linux->cgroups_path, "/test/123");
++ ASSERT_STREQ(merged_cp, "/test/123");
+
+ free_oci_runtime_spec(oci_spec);
+ free_host_config(host_spec);
++ free(merged_cp);
+
+ testing::Mock::VerifyAndClearExpectations(&m_isulad_conf);
+ }
+--
+2.25.1
+