1
0
Fork 0
mirror of https://github.com/containers/youki synced 2024-05-10 17:46:15 +02:00
youki/src/cgroups/manager.rs

107 lines
3.5 KiB
Rust

use std::{collections::HashMap, path::PathBuf};
use std::{fs::remove_dir, path::Path};
use anyhow::Result;
use nix::unistd::Pid;
use procfs::process::Process;
use crate::{cgroups::ControllerType, spec::LinuxResources, utils::PathBufExt};
use super::{
blkio::Blkio, devices::Devices, hugetlb::Hugetlb, memory::Memory,
network_classifier::NetworkClassifier, network_priority::NetworkPriority, pids::Pids,
Controller,
};
const CONTROLLERS: &[ControllerType] = &[
ControllerType::Devices,
ControllerType::HugeTlb,
ControllerType::Memory,
ControllerType::Pids,
ControllerType::Blkio,
ControllerType::NetworkPriority,
ControllerType::NetworkClassifier,
];
pub struct Manager {
subsystems: HashMap<String, PathBuf>,
}
impl Manager {
pub fn new(cgroup_path: PathBuf) -> Result<Self> {
let mut subsystems = HashMap::<String, PathBuf>::new();
for subsystem in CONTROLLERS.iter().map(|c| c.to_string()) {
subsystems.insert(
subsystem.to_owned(),
Self::get_subsystem_path(&cgroup_path, &subsystem)?,
);
}
Ok(Manager { subsystems })
}
pub fn apply(&self, linux_resources: &LinuxResources, pid: Pid) -> Result<()> {
for subsys in &self.subsystems {
match subsys.0.as_str() {
"devices" => Devices::apply(linux_resources, &subsys.1, pid)?,
"hugetlb" => Hugetlb::apply(linux_resources, &subsys.1, pid)?,
"memory" => Memory::apply(linux_resources, &subsys.1, pid)?,
"pids" => Pids::apply(linux_resources, &subsys.1, pid)?,
"blkio" => Blkio::apply(linux_resources, &subsys.1, pid)?,
"net_prio" => NetworkPriority::apply(linux_resources, &subsys.1, pid)?,
"net_cls" => NetworkClassifier::apply(linux_resources, &subsys.1, pid)?,
_ => continue,
}
}
Ok(())
}
pub fn remove(&self) -> Result<()> {
for cgroup_path in &self.subsystems {
if cgroup_path.1.exists() {
log::debug!("remove cgroup {:?}", cgroup_path.1);
remove_dir(&cgroup_path.1)?;
}
}
Ok(())
}
fn get_subsystem_path(cgroup_path: &Path, subsystem: &str) -> anyhow::Result<PathBuf> {
log::debug!("Get path for subsystem: {}", subsystem);
let mount = Process::myself()?
.mountinfo()?
.into_iter()
.find(|m| {
if m.fs_type == "cgroup" {
// Some systems mount net_prio and net_cls in the same directory
// other systems mount them in their own diretories. This
// should handle both cases.
if subsystem == "net_cls" || subsystem == "net_prio" {
return m.mount_point.ends_with("net_cls,net_prio")
|| m.mount_point.ends_with("net_prio,net_cls");
}
}
m.mount_point.ends_with(subsystem)
})
.unwrap();
let cgroup = Process::myself()?
.cgroups()?
.into_iter()
.find(|c| c.controllers.contains(&subsystem.to_owned()))
.unwrap();
let p = if cgroup_path.to_string_lossy().into_owned().is_empty() {
mount
.mount_point
.join_absolute_path(Path::new(&cgroup.pathname))?
} else {
mount.mount_point.join_absolute_path(&cgroup_path)?
};
Ok(p)
}
}