提交 70db2e4e 编写于 作者: L lifeng68

cputrt: add support cpurt runtime period

Signed-off-by: Nlifeng68 <lifeng68@huawei.com>
上级 82846737
......@@ -443,7 +443,21 @@ extern "C" {
0, \
&(cmdargs).custom_conf.blkio_throttle_write_iops_device, \
"Limit write rate (IO per second) to a device (format: <device-path>:<number>),number is unsigned 64 bytes integer.", \
command_append_array },
command_append_array }, \
{ CMD_OPT_TYPE_CALLBACK, \
false, \
"cpu-rt-period", \
0, \
&((cmdargs).cr).cpu_rt_period, \
"Limit CPU real-time period in microseconds.", \
command_convert_llong }, \
{ CMD_OPT_TYPE_CALLBACK, \
false, \
"cpu-rt-runtime", \
0, \
&((cmdargs).cr).cpu_rt_runtime, \
"Limit CPU real-time runtime in microseconds.", \
command_convert_llong },
#define CREATE_EXTEND_OPTIONS(cmdargs) \
{ CMD_OPT_TYPE_BOOL, \
......
......@@ -45,6 +45,10 @@ static int pack_update_request(const struct client_arguments *args, struct isula
request->updateconfig->cr->cpu_quota = args->cr.cpu_quota;
request->updateconfig->cr->cpu_realtime_period = args->cr.cpu_rt_period;
request->updateconfig->cr->cpu_realtime_runtime = args->cr.cpu_rt_runtime;
request->updateconfig->cr->cpuset_cpus = args->cr.cpuset_cpus;
request->updateconfig->cr->cpuset_mems = args->cr.cpuset_mems;
......
......@@ -92,7 +92,21 @@ extern "C" {
0, \
&(cmdargs).cr.blkio_weight, \
"Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)", \
command_convert_u16 },
command_convert_u16 }, \
{ CMD_OPT_TYPE_CALLBACK, \
false, \
"cpu-rt-period", \
0, \
&((cmdargs).cr).cpu_rt_period, \
"Limit CPU real-time period in microseconds.", \
command_convert_llong }, \
{ CMD_OPT_TYPE_CALLBACK, \
false, \
"cpu-rt-runtime", \
0, \
&((cmdargs).cr).cpu_rt_runtime, \
"Limit CPU real-time runtime in microseconds.", \
command_convert_llong },
extern const char g_cmd_update_desc[];
extern const char g_cmd_update_usage[];
......
......@@ -1398,11 +1398,6 @@ int main(int argc, char **argv)
goto failure;
}
if (init_cgroups_path("/lxc", 0)) {
msg = g_isulad_errmsg ? g_isulad_errmsg : "Failed to init cgroups path";
goto failure;
}
if (add_sighandler()) {
msg = "Failed to add sig handlers";
goto failure;
......
......@@ -223,6 +223,30 @@ free_out:
return epath;
}
int conf_get_cgroup_cpu_rt(int64_t *cpu_rt_period, int64_t *cpu_rt_runtime)
{
struct service_arguments *conf = NULL;
if (isulad_server_conf_rdlock() != 0) {
return -1;
}
conf = conf_get_server_conf();
if (conf == NULL) {
(void)isulad_server_conf_unlock();
return -1;
}
*cpu_rt_period = conf->json_confs->cpu_rt_period;
*cpu_rt_runtime = conf->json_confs->cpu_rt_runtime;
if (isulad_server_conf_unlock() != 0) {
return -1;
}
return 0;
}
/* conf get graph checked flag file path */
char *conf_get_graph_check_flag_file()
{
......@@ -1202,172 +1226,6 @@ out:
return ret;
}
/* maybe create cpu realtime file */
static int maybe_create_cpu_realtime_file(bool present, int64_t value, const char *file, const char *path)
{
int ret;
int fd = 0;
ssize_t nwrite;
char fpath[PATH_MAX] = { 0 };
char buf[ISULAD_NUMSTRLEN64] = { 0 };
if (!present || value == 0) {
return 0;
}
ret = util_mkdir_p(path, CONFIG_DIRECTORY_MODE);
if (ret != 0) {
ERROR("Failed to mkdir: %s", path);
return -1;
}
int nret = snprintf(fpath, sizeof(fpath), "%s/%s", path, file);
if (nret < 0 || nret >= sizeof(fpath)) {
ERROR("Failed to print string");
return -1;
}
nret = snprintf(buf, sizeof(buf), "%lld", (long long int)value);
if (nret < 0 || (size_t)nret >= 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 get_cgroup_cpu_rt(int64_t *cpu_rt_period, int64_t *cpu_rt_runtime)
{
struct service_arguments *conf = NULL;
if (isulad_server_conf_rdlock() != 0) {
return -1;
}
conf = conf_get_server_conf();
if (conf == NULL) {
(void)isulad_server_conf_unlock();
return -1;
}
*cpu_rt_period = conf->json_confs->cpu_rt_period;
*cpu_rt_runtime = conf->json_confs->cpu_rt_runtime;
if (isulad_server_conf_unlock() != 0) {
return -1;
}
return 0;
}
static int recursively_create_cgroup(const char *path, int recursive_depth, int64_t cpu_rt_period,
int64_t cpu_rt_runtime)
{
int ret = 0;
sysinfo_t *sysinfo = NULL;
char *dup = NULL;
char *dirpath = NULL;
char *mnt = NULL;
char *root = NULL;
char fpath[PATH_MAX] = { 0 };
dup = util_strdup_s(path);
dirpath = dirname(dup);
ret = init_cgroups_path(dirpath, (recursive_depth + 1));
free(dup);
if (ret != 0) {
return ret;
}
ret = find_cgroup_mountpoint_and_root("cpu", &mnt, &root);
if (ret != 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'");
ret = -1;
goto out;
}
// When iSulad is run inside iSulad/docker, the root is based of the host cgroup.
// Replace root to "/"
if (strncmp(root, "/lxc/", strlen("/lxc/")) != 0) {
root[1] = '\0';
}
int nret = snprintf(fpath, sizeof(fpath), "%s/%s/%s", mnt, root, path);
if (nret < 0 || (size_t)nret >= sizeof(fpath)) {
ERROR("Failed to print string");
ret = -1;
goto out;
}
sysinfo = get_sys_info(true);
if (sysinfo == NULL) {
ERROR("Can not get system info");
ret = -1;
goto out;
}
ret = maybe_create_cpu_realtime_file(sysinfo->cgcpuinfo.cpu_rt_period, cpu_rt_period, "cpu.rt_period_us", fpath);
if (ret != 0) {
goto out;
}
ret = maybe_create_cpu_realtime_file(sysinfo->cgcpuinfo.cpu_rt_runtime, cpu_rt_runtime, "cpu.rt_runtime_us", fpath);
if (ret != 0) {
goto out;
}
out:
free(mnt);
free(root);
free_sysinfo(sysinfo);
return ret;
}
/* init cgroups path */
int init_cgroups_path(const char *path, int recursive_depth)
{
int64_t cpu_rt_period = 0;
int64_t cpu_rt_runtime = 0;
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;
}
if (get_cgroup_cpu_rt(&cpu_rt_period, &cpu_rt_runtime)) {
return -1;
}
if (cpu_rt_period == 0 && cpu_rt_runtime == 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, recursive_depth, cpu_rt_period, cpu_rt_runtime)) {
return -1;
}
return 0;
}
#define OVERRIDE_STRING_VALUE(dst, src) \
do { \
if ((src) != NULL && strlen((src)) != 0) { \
......
......@@ -49,6 +49,8 @@ char *conf_get_isulad_logdriver();
int conf_get_daemon_log_config(char **loglevel, char **logdriver, char **engine_log_path);
char *conf_get_isulad_log_gather_fifo_path();
int conf_get_cgroup_cpu_rt(int64_t *cpu_rt_period, int64_t *cpu_rt_runtime);
char *conf_get_isulad_log_file();
char *conf_get_engine_log_file();
char *conf_get_enable_plugins();
......@@ -74,8 +76,6 @@ int conf_get_isulad_default_ulimit(host_config_ulimits_element ***ulimit);
unsigned int conf_get_start_timeout();
int init_cgroups_path(const char *path, int recursive_depth);
char **conf_get_insecure_registry_list();
char **conf_get_registry_list();
......
......@@ -33,6 +33,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include "isula_libutils/log.h"
#include "isulad_config.h"
......@@ -57,6 +58,9 @@
#include "utils_verify.h"
#include "selinux_label.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 runtime_check(const char *name, bool *runtime_res)
{
int ret = 0;
......@@ -1022,6 +1026,204 @@ 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 = 0;
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;
}
int nret = snprintf(fpath, sizeof(fpath), "%s/%s", path, file);
if (nret < 0 || nret >= sizeof(fpath)) {
ERROR("Failed to print string");
return -1;
}
nret = snprintf(buf, sizeof(buf), "%lld", (long long int)value);
if (nret < 0 || (size_t)nret >= 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_sysinfo(sysinfo);
free(mnt_root);
free(dup);
return ret;
}
/*
* request -> host_spec + container_spec
* container_spec + image config
......@@ -1127,11 +1329,6 @@ int container_create_cb(const container_create_request *request, container_creat
goto umount_shm;
}
ret = merge_oci_cgroups_path(id, oci_spec, host_spec);
if (ret < 0) {
goto umount_shm;
}
if (merge_config_for_syscontainer(request, host_spec, v2_spec->config, oci_spec) != 0) {
ERROR("Failed to merge config for syscontainer");
cc = ISULAD_ERR_EXEC;
......@@ -1165,6 +1362,13 @@ 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;
......
......@@ -853,6 +853,12 @@ static void update_container_cpu(const host_config *hostconfig, host_config *cho
free(chostconfig->cpuset_mems);
chostconfig->cpuset_mems = util_strdup_s(hostconfig->cpuset_mems);
}
if (hostconfig->cpu_realtime_period != 0) {
chostconfig->cpu_realtime_period = hostconfig->cpu_realtime_period;
}
if (hostconfig->cpu_realtime_runtime != 0) {
chostconfig->cpu_realtime_runtime = hostconfig->cpu_realtime_runtime;
}
}
static int update_container_memory(const char *id, const host_config *hostconfig, host_config *chostconfig)
......
......@@ -40,6 +40,8 @@ struct engine_cgroup_resources {
uint64_t memory_swap;
uint64_t memory_reservation;
uint64_t kernel_memory_limit;
int64_t cpurt_runtime;
int64_t cpurt_period;
};
typedef struct _engine_start_request_t {
......
......@@ -94,6 +94,8 @@ static bool lcr_update_container(const char *name, const char *lcrpath, const st
lcr_cr.memory_swap = cr->memory_swap;
lcr_cr.memory_reservation = cr->memory_reservation;
lcr_cr.kernel_memory_limit = cr->kernel_memory_limit;
lcr_cr.cpurt_period = cr->cpurt_period;
lcr_cr.cpurt_runtime = cr->cpurt_runtime;
return g_lcr_update_op(name, lcrpath, &lcr_cr);
}
......
......@@ -518,6 +518,8 @@ static void to_engine_resources(const host_config *hostconfig, struct engine_cgr
cr->memory_swap = (uint64_t)hostconfig->memory_swap;
cr->memory_reservation = (uint64_t)hostconfig->memory_reservation;
cr->kernel_memory_limit = (uint64_t)hostconfig->kernel_memory;
cr->cpurt_period = hostconfig->cpu_realtime_period;
cr->cpurt_runtime = hostconfig->cpu_realtime_runtime;
}
int rt_lcr_update(const char *id, const char *runtime, const rt_update_params_t *params)
......
......@@ -1962,6 +1962,44 @@ out:
return ret;
}
int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, const host_config *host_spec)
{
int ret = 0;
char *default_cgroup_parent = NULL;
char *path = NULL;
if (id == NULL || oci_spec == NULL || host_spec == NULL) {
ERROR("Invalid arguments");
ret = -1;
goto out;
}
if (make_sure_oci_spec_linux(oci_spec) != 0) {
ERROR("Failed to make oci spec linux");
ret = -1;
goto out;
}
default_cgroup_parent = conf_get_isulad_cgroup_parent();
path = default_cgroup_parent;
if (host_spec->cgroup_parent != NULL) {
path = host_spec->cgroup_parent;
}
if (path == NULL) {
free(oci_spec->linux->cgroups_path);
oci_spec->linux->cgroups_path = util_path_join("/isulad", id);
return 0;
}
free(oci_spec->linux->cgroups_path);
oci_spec->linux->cgroups_path = util_path_join(path, id);
out:
free(default_cgroup_parent);
return ret;
}
int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_config_v2_common_config *v2_spec,
oci_runtime_spec *oci_spec)
{
......@@ -2029,45 +2067,13 @@ int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_c
goto out;
}
out:
return ret;
}
int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, const host_config *host_spec)
{
int ret = 0;
char *default_cgroup_parent = NULL;
char *path = NULL;
if (id == NULL || oci_spec == NULL || host_spec == NULL) {
ERROR("Invalid arguments");
ret = -1;
goto out;
}
if (make_sure_oci_spec_linux(oci_spec) != 0) {
ERROR("Failed to make oci spec linux");
ret = -1;
ret = merge_oci_cgroups_path(v2_spec->id, oci_spec, host_spec);
if (ret != 0) {
ERROR("Failed to make cgroup parent");
goto out;
}
default_cgroup_parent = conf_get_isulad_cgroup_parent();
path = default_cgroup_parent;
if (host_spec->cgroup_parent != NULL) {
path = host_spec->cgroup_parent;
}
if (path == NULL) {
free(oci_spec->linux->cgroups_path);
oci_spec->linux->cgroups_path = util_path_join("/isulad", id);
return 0;
}
free(oci_spec->linux->cgroups_path);
oci_spec->linux->cgroups_path = util_path_join(path, id);
out:
UTIL_FREE_AND_SET_NULL(default_cgroup_parent);
return ret;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册