Backport #66237 to 24.3: Fix detection of number of CPUs in containers

This commit is contained in:
robot-clickhouse 2024-07-16 16:11:12 +00:00
parent d9c08c4bbe
commit cbab31ce7c
5 changed files with 21 additions and 19 deletions

View File

@ -3,7 +3,7 @@
#include <base/defines.h> #include <base/defines.h>
#include <fstream> #include <fstream>
#include <sstream> #include <string>
bool cgroupsV2Enabled() bool cgroupsV2Enabled()
@ -40,7 +40,7 @@ bool cgroupsV2MemoryControllerEnabled()
#endif #endif
} }
std::string cgroupV2OfProcess() std::filesystem::path cgroupV2PathOfProcess()
{ {
#if defined(OS_LINUX) #if defined(OS_LINUX)
chassert(cgroupsV2Enabled()); chassert(cgroupsV2Enabled());
@ -48,17 +48,18 @@ std::string cgroupV2OfProcess()
/// A simpler way to get the membership is: /// A simpler way to get the membership is:
std::ifstream cgroup_name_file("/proc/self/cgroup"); std::ifstream cgroup_name_file("/proc/self/cgroup");
if (!cgroup_name_file.is_open()) if (!cgroup_name_file.is_open())
return ""; return {};
/// With cgroups v2, there will be a *single* line with prefix "0::/" /// With cgroups v2, there will be a *single* line with prefix "0::/"
/// (see https://docs.kernel.org/admin-guide/cgroup-v2.html) /// (see https://docs.kernel.org/admin-guide/cgroup-v2.html)
std::string cgroup; std::string cgroup;
std::getline(cgroup_name_file, cgroup); std::getline(cgroup_name_file, cgroup);
static const std::string v2_prefix = "0::/"; static const std::string v2_prefix = "0::/";
if (!cgroup.starts_with(v2_prefix)) if (!cgroup.starts_with(v2_prefix))
return ""; return {};
cgroup = cgroup.substr(v2_prefix.length()); cgroup = cgroup.substr(v2_prefix.length());
return cgroup; /// Note: The 'root' cgroup can have an empty cgroup name, this is valid
return default_cgroups_mount / cgroup;
#else #else
return ""; return {};
#endif #endif
} }

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include <string>
#if defined(OS_LINUX) #if defined(OS_LINUX)
/// I think it is possible to mount the cgroups hierarchy somewhere else (e.g. when in containers). /// I think it is possible to mount the cgroups hierarchy somewhere else (e.g. when in containers).
@ -16,7 +15,7 @@ bool cgroupsV2Enabled();
/// Assumes that cgroupsV2Enabled() is enabled. /// Assumes that cgroupsV2Enabled() is enabled.
bool cgroupsV2MemoryControllerEnabled(); bool cgroupsV2MemoryControllerEnabled();
/// Which cgroup does the process belong to? /// Detects which cgroup v2 the process belongs to and returns the filesystem path to the cgroup.
/// Returns an empty string if the cgroup cannot be determined. /// Returns an empty path the cgroup cannot be determined.
/// Assumes that cgroupsV2Enabled() is enabled. /// Assumes that cgroupsV2Enabled() is enabled.
std::string cgroupV2OfProcess(); std::filesystem::path cgroupV2PathOfProcess();

View File

@ -23,8 +23,9 @@ std::optional<uint64_t> getCgroupsV2MemoryLimit()
if (!cgroupsV2MemoryControllerEnabled()) if (!cgroupsV2MemoryControllerEnabled())
return {}; return {};
std::string cgroup = cgroupV2OfProcess(); std::filesystem::path current_cgroup = cgroupV2PathOfProcess();
auto current_cgroup = cgroup.empty() ? default_cgroups_mount : (default_cgroups_mount / cgroup); if (current_cgroup.empty())
return {};
/// Open the bottom-most nested memory limit setting file. If there is no such file at the current /// Open the bottom-most nested memory limit setting file. If there is no such file at the current
/// level, try again at the parent level as memory settings are inherited. /// level, try again at the parent level as memory settings are inherited.

View File

@ -125,8 +125,9 @@ std::optional<std::string> getCgroupsV2FileName()
if (!cgroupsV2MemoryControllerEnabled()) if (!cgroupsV2MemoryControllerEnabled())
return {}; return {};
String cgroup = cgroupV2OfProcess(); std::filesystem::path current_cgroup = cgroupV2PathOfProcess();
auto current_cgroup = cgroup.empty() ? default_cgroups_mount : (default_cgroups_mount / cgroup); if (current_cgroup.empty())
return {};
/// Return the bottom-most nested current memory file. If there is no such file at the current /// Return the bottom-most nested current memory file. If there is no such file at the current
/// level, try again at the parent level as memory settings are inherited. /// level, try again at the parent level as memory settings are inherited.

View File

@ -37,12 +37,12 @@ uint32_t getCGroupLimitedCPUCores(unsigned default_cpu_count)
/// cgroupsv2 /// cgroupsv2
if (cgroupsV2Enabled()) if (cgroupsV2Enabled())
{ {
/// First, we identify the cgroup the process belongs /// First, we identify the path of the cgroup the process belongs
std::string cgroup = cgroupV2OfProcess(); std::filesystem::path cgroup_path = cgroupV2PathOfProcess();
if (cgroup.empty()) if (cgroup_path.empty())
return default_cpu_count; return default_cpu_count;
auto current_cgroup = cgroup.empty() ? default_cgroups_mount : (default_cgroups_mount / cgroup); auto current_cgroup = cgroup_path;
// Looking for cpu.max in directories from the current cgroup to the top level // Looking for cpu.max in directories from the current cgroup to the top level
// It does not stop on the first time since the child could have a greater value than parent // It does not stop on the first time since the child could have a greater value than parent
@ -62,7 +62,7 @@ uint32_t getCGroupLimitedCPUCores(unsigned default_cpu_count)
} }
current_cgroup = current_cgroup.parent_path(); current_cgroup = current_cgroup.parent_path();
} }
current_cgroup = default_cgroups_mount / cgroup; current_cgroup = cgroup_path;
// Looking for cpuset.cpus.effective in directories from the current cgroup to the top level // Looking for cpuset.cpus.effective in directories from the current cgroup to the top level
while (current_cgroup != default_cgroups_mount.parent_path()) while (current_cgroup != default_cgroups_mount.parent_path())
{ {