forked from lix-project/lix
Clean up cgroup handling in getMaxCPU()
Also, don't assume in LocalDerivationGoal that cgroups are mounted on /sys/fs/cgroup.
This commit is contained in:
parent
1211e59a03
commit
1e6a5d1ff6
|
@ -409,12 +409,16 @@ void LocalDerivationGoal::startBuilder()
|
||||||
#if __linux__
|
#if __linux__
|
||||||
settings.requireExperimentalFeature(Xp::Cgroups);
|
settings.requireExperimentalFeature(Xp::Cgroups);
|
||||||
|
|
||||||
|
auto cgroupFS = getCgroupFS();
|
||||||
|
if (!cgroupFS)
|
||||||
|
throw Error("cannot determine the cgroups file system");
|
||||||
|
|
||||||
auto ourCgroups = getCgroups("/proc/self/cgroup");
|
auto ourCgroups = getCgroups("/proc/self/cgroup");
|
||||||
auto ourCgroup = ourCgroups[""];
|
auto ourCgroup = ourCgroups[""];
|
||||||
if (ourCgroup == "")
|
if (ourCgroup == "")
|
||||||
throw Error("cannot determine cgroup name from /proc/self/cgroup");
|
throw Error("cannot determine cgroup name from /proc/self/cgroup");
|
||||||
|
|
||||||
auto ourCgroupPath = canonPath("/sys/fs/cgroup/" + ourCgroup);
|
auto ourCgroupPath = canonPath(*cgroupFS + "/" + ourCgroup);
|
||||||
|
|
||||||
if (!pathExists(ourCgroupPath))
|
if (!pathExists(ourCgroupPath))
|
||||||
throw Error("expected cgroup directory '%s'", ourCgroupPath);
|
throw Error("expected cgroup directory '%s'", ourCgroupPath);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "cgroup.hh"
|
#include "cgroup.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
#include "finally.hh"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -10,9 +11,25 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <mntent.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
std::optional<Path> getCgroupFS()
|
||||||
|
{
|
||||||
|
static auto res = [&]() -> std::optional<Path> {
|
||||||
|
auto fp = fopen("/proc/mounts", "r");
|
||||||
|
if (!fp) return std::nullopt;
|
||||||
|
Finally delFP = [&]() { fclose(fp); };
|
||||||
|
while (auto ent = getmntent(fp))
|
||||||
|
if (std::string_view(ent->mnt_type) == "cgroup2")
|
||||||
|
return ent->mnt_dir;
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: obsolete, check for cgroup2
|
// FIXME: obsolete, check for cgroup2
|
||||||
std::map<std::string, std::string> getCgroups(const Path & cgroupFile)
|
std::map<std::string, std::string> getCgroups(const Path & cgroupFile)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
std::optional<Path> getCgroupFS();
|
||||||
|
|
||||||
std::map<std::string, std::string> getCgroups(const Path & cgroupFile);
|
std::map<std::string, std::string> getCgroups(const Path & cgroupFile);
|
||||||
|
|
||||||
struct CgroupStats
|
struct CgroupStats
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "sync.hh"
|
#include "sync.hh"
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "serialise.hh"
|
#include "serialise.hh"
|
||||||
|
#include "cgroup.hh"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
@ -36,7 +37,6 @@
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include <mntent.h>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -727,43 +727,24 @@ unsigned int getMaxCPU()
|
||||||
{
|
{
|
||||||
#if __linux__
|
#if __linux__
|
||||||
try {
|
try {
|
||||||
FILE *fp = fopen("/proc/mounts", "r");
|
auto cgroupFS = getCgroupFS();
|
||||||
if (!fp)
|
if (!cgroupFS) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
Strings cgPathParts;
|
if (!pathExists("/proc/self/cgroup")) return 0;
|
||||||
|
|
||||||
struct mntent *ent;
|
auto cgroups = getCgroups("/proc/self/cgroup");
|
||||||
while ((ent = getmntent(fp))) {
|
auto cgroup = cgroups[""];
|
||||||
std::string mountType, mountPath;
|
if (cgroup == "") return 0;
|
||||||
|
|
||||||
mountType = ent->mnt_type;
|
auto cpuFile = *cgroupFS + "/" + cgroup + "/cpu.max";
|
||||||
mountPath = ent->mnt_dir;
|
|
||||||
|
|
||||||
if (mountType == "cgroup2") {
|
if (pathExists(cpuFile)) {
|
||||||
cgPathParts.push_back(mountPath);
|
auto cpuMax = readFile(cpuFile);
|
||||||
break;
|
auto cpuMaxParts = tokenizeString<std::vector<std::string>>(cpuMax, " \n");
|
||||||
}
|
auto quota = cpuMaxParts[0];
|
||||||
}
|
auto period = cpuMaxParts[1];
|
||||||
|
if (quota != "max")
|
||||||
fclose(fp);
|
return std::ceil(std::stoi(quota) / std::stof(period));
|
||||||
|
|
||||||
if (cgPathParts.size() > 0 && pathExists("/proc/self/cgroup")) {
|
|
||||||
std::string currentCgroup = readFile("/proc/self/cgroup");
|
|
||||||
Strings cgValues = tokenizeString<Strings>(currentCgroup, ":");
|
|
||||||
cgPathParts.push_back(trim(cgValues.back(), "\n"));
|
|
||||||
cgPathParts.push_back("cpu.max");
|
|
||||||
std::string fullCgPath = canonPath(concatStringsSep("/", cgPathParts));
|
|
||||||
|
|
||||||
if (pathExists(fullCgPath)) {
|
|
||||||
std::string cpuMax = readFile(fullCgPath);
|
|
||||||
std::vector<std::string> cpuMaxParts = tokenizeString<std::vector<std::string>>(cpuMax, " ");
|
|
||||||
std::string quota = cpuMaxParts[0];
|
|
||||||
std::string period = trim(cpuMaxParts[1], "\n");
|
|
||||||
|
|
||||||
if (quota != "max")
|
|
||||||
return std::ceil(std::stoi(quota) / std::stof(period));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Error &) { ignoreException(); }
|
} catch (Error &) { ignoreException(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue