From 1f188be40593cfed0b0b56173aeb4c13258e58ce Mon Sep 17 00:00:00 2001 From: Tim Zhang Date: Thu, 12 Nov 2020 20:06:03 +0800 Subject: [PATCH] Detect subsystems and get root from /proc/self/mountinfo Delete check_support and stop detecting subsystems by finding in the root folders because the detecting method is not accurate. Signed-off-by: Tim Zhang --- Cargo.toml | 1 + src/blkio.rs | 8 +-- src/cpu.rs | 8 +-- src/cpuacct.rs | 6 +- src/cpuset.rs | 8 +-- src/devices.rs | 6 +- src/freezer.rs | 8 +-- src/hierarchies.rs | 154 ++++++++++++++++----------------------------- src/hugetlb.rs | 8 +-- src/lib.rs | 8 +-- src/memory.rs | 8 +-- src/net_cls.rs | 6 +- src/net_prio.rs | 6 +- src/perf_event.rs | 6 +- src/pid.rs | 8 +-- src/rdma.rs | 6 +- src/systemd.rs | 8 +-- 17 files changed, 83 insertions(+), 180 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 156a69f..5bdbbe6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ log = "0.4" regex = "1.1" nix = "0.18.0" libc = "0.2" +procinfo = "0.4.2" [dev-dependencies] libc = "0.2.76" diff --git a/src/blkio.rs b/src/blkio.rs index b0f78a2..7e21faf 100644 --- a/src/blkio.rs +++ b/src/blkio.rs @@ -421,12 +421,8 @@ fn read_u64_from(mut file: File) -> Result { } impl BlkIoController { - /// Constructs a new `BlkIoController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Constructs a new `BlkIoController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root, diff --git a/src/cpu.rs b/src/cpu.rs index 105a438..bcf9206 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -122,12 +122,8 @@ fn read_u64_from(mut file: File) -> Result { } impl CpuController { - /// Contructs a new `CpuController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Contructs a new `CpuController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root, diff --git a/src/cpuacct.rs b/src/cpuacct.rs index 0924d95..6efde64 100644 --- a/src/cpuacct.rs +++ b/src/cpuacct.rs @@ -118,10 +118,8 @@ fn read_string_from(mut file: File) -> Result { } impl CpuAcctController { - /// Contructs a new `CpuAcctController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf) -> Self { - let mut root = oroot; - root.push(Self::controller_type().to_string()); + /// Contructs a new `CpuAcctController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf) -> Self { Self { base: root.clone(), path: root, diff --git a/src/cpuset.rs b/src/cpuset.rs index 4d4427d..cef4679 100644 --- a/src/cpuset.rs +++ b/src/cpuset.rs @@ -261,12 +261,8 @@ fn parse_range(s: String) -> Result> { } impl CpuSetController { - /// Contructs a new `CpuSetController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Contructs a new `CpuSetController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root, diff --git a/src/devices.rs b/src/devices.rs index 5a78a2e..838d17e 100644 --- a/src/devices.rs +++ b/src/devices.rs @@ -189,10 +189,8 @@ impl<'a> From<&'a Subsystem> for &'a DevicesController { } impl DevicesController { - /// Constructs a new `DevicesController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf) -> Self { - let mut root = oroot; - root.push(Self::controller_type().to_string()); + /// Constructs a new `DevicesController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf) -> Self { Self { base: root.clone(), path: root, diff --git a/src/freezer.rs b/src/freezer.rs index c9da379..93a0185 100644 --- a/src/freezer.rs +++ b/src/freezer.rs @@ -82,12 +82,8 @@ impl<'a> From<&'a Subsystem> for &'a FreezerController { } impl FreezerController { - /// Contructs a new `FreezerController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Contructs a new `FreezerController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root, diff --git a/src/hierarchies.rs b/src/hierarchies.rs index c0ca8b0..4e0742f 100644 --- a/src/hierarchies.rs +++ b/src/hierarchies.rs @@ -9,12 +9,9 @@ //! Currently, we only support the cgroupv1 hierarchy, but in the future we will add support for //! the Unified Hierarchy. -use std::fs::{self, File}; -use std::io::BufRead; -use std::io::BufReader; -use std::path::{Path, PathBuf}; - -use log::*; +use procinfo::pid::{mountinfo_self, Mountinfo}; +use std::fs; +use std::path::PathBuf; use crate::blkio::BlkIoController; use crate::cpu::CpuController; @@ -36,7 +33,7 @@ use crate::cgroup::Cgroup; /// The standard, original cgroup implementation. Often referred to as "cgroupv1". pub struct V1 { - mount_point: String, + mountinfo: Vec, } pub struct V2 { @@ -54,56 +51,47 @@ impl Hierarchy for V1 { // The cgroup writeback feature requires cooperation between memcgs and blkcgs // To avoid exceptions, we should add_task for blkcg before memcg(push BlkIo before Mem) // For more Information: https://www.alibabacloud.com/help/doc-detail/155509.htm - if self.check_support(Controllers::BlkIo) { - subs.push(Subsystem::BlkIo(BlkIoController::new(self.root(), false))); + if let Some(root) = self.get_mount_point(Controllers::BlkIo) { + subs.push(Subsystem::BlkIo(BlkIoController::new(root, false))); } - if self.check_support(Controllers::Mem) { - subs.push(Subsystem::Mem(MemController::new(self.root(), false))); + if let Some(root) = self.get_mount_point(Controllers::Mem) { + subs.push(Subsystem::Mem(MemController::new(root, false))); } - if self.check_support(Controllers::Pids) { - subs.push(Subsystem::Pid(PidController::new(self.root(), false))); + if let Some(root) = self.get_mount_point(Controllers::Pids) { + subs.push(Subsystem::Pid(PidController::new(root, false))); } - if self.check_support(Controllers::CpuSet) { - subs.push(Subsystem::CpuSet(CpuSetController::new(self.root(), false))); + if let Some(root) = self.get_mount_point(Controllers::CpuSet) { + subs.push(Subsystem::CpuSet(CpuSetController::new(root, false))); } - if self.check_support(Controllers::CpuAcct) { - subs.push(Subsystem::CpuAcct(CpuAcctController::new(self.root()))); + if let Some(root) = self.get_mount_point(Controllers::CpuAcct) { + subs.push(Subsystem::CpuAcct(CpuAcctController::new(root))); } - if self.check_support(Controllers::Cpu) { - subs.push(Subsystem::Cpu(CpuController::new(self.root(), false))); + if let Some(root) = self.get_mount_point(Controllers::Cpu) { + subs.push(Subsystem::Cpu(CpuController::new(root, false))); } - if self.check_support(Controllers::Devices) { - subs.push(Subsystem::Devices(DevicesController::new(self.root()))); + if let Some(root) = self.get_mount_point(Controllers::Devices) { + subs.push(Subsystem::Devices(DevicesController::new(root))); } - if self.check_support(Controllers::Freezer) { - subs.push(Subsystem::Freezer(FreezerController::new( - self.root(), - false, - ))); + if let Some(root) = self.get_mount_point(Controllers::Freezer) { + subs.push(Subsystem::Freezer(FreezerController::new(root, false))); } - if self.check_support(Controllers::NetCls) { - subs.push(Subsystem::NetCls(NetClsController::new(self.root()))); + if let Some(root) = self.get_mount_point(Controllers::NetCls) { + subs.push(Subsystem::NetCls(NetClsController::new(root))); } - if self.check_support(Controllers::PerfEvent) { - subs.push(Subsystem::PerfEvent(PerfEventController::new(self.root()))); + if let Some(root) = self.get_mount_point(Controllers::PerfEvent) { + subs.push(Subsystem::PerfEvent(PerfEventController::new(root))); } - if self.check_support(Controllers::NetPrio) { - subs.push(Subsystem::NetPrio(NetPrioController::new(self.root()))); + if let Some(root) = self.get_mount_point(Controllers::NetPrio) { + subs.push(Subsystem::NetPrio(NetPrioController::new(root))); } - if self.check_support(Controllers::HugeTlb) { - subs.push(Subsystem::HugeTlb(HugeTlbController::new( - self.root(), - false, - ))); + if let Some(root) = self.get_mount_point(Controllers::HugeTlb) { + subs.push(Subsystem::HugeTlb(HugeTlbController::new(root, false))); } - if self.check_support(Controllers::Rdma) { - subs.push(Subsystem::Rdma(RdmaController::new(self.root()))); + if let Some(root) = self.get_mount_point(Controllers::Rdma) { + subs.push(Subsystem::Rdma(RdmaController::new(root))); } - if self.check_support(Controllers::Systemd) { - subs.push(Subsystem::Systemd(SystemdController::new( - self.root(), - false, - ))); + if let Some(root) = self.get_mount_point(Controllers::Systemd) { + subs.push(Subsystem::Systemd(SystemdController::new(root, false))); } subs @@ -114,20 +102,17 @@ impl Hierarchy for V1 { Cgroup::load(&*b, "".to_string()) } - fn check_support(&self, sub: Controllers) -> bool { - let root = self.root().read_dir().unwrap(); - for entry in root { - if let Ok(entry) = entry { - if entry.file_name().into_string().unwrap() == sub.to_string() { - return true; - } - } - } - return false; - } - fn root(&self) -> PathBuf { - PathBuf::from(self.mount_point.clone()) + self.mountinfo + .iter() + .find_map(|m| { + if m.fs_type.0 == "cgroup" { + return Some(m.mount_point.parent().unwrap()); + } + None + }) + .unwrap() + .to_path_buf() } } @@ -189,10 +174,6 @@ impl Hierarchy for V2 { Cgroup::load(&*b, "".to_string()) } - fn check_support(&self, _sub: Controllers) -> bool { - return false; - } - fn root(&self) -> PathBuf { PathBuf::from(self.root.clone()) } @@ -202,11 +183,19 @@ impl V1 { /// Finds where control groups are mounted to and returns a hierarchy in which control groups /// can be created. pub fn new() -> V1 { - let mount_point = find_v1_mount().unwrap(); V1 { - mount_point: mount_point, + mountinfo: mountinfo_self().unwrap(), } } + + pub fn get_mount_point(&self, controller: Controllers) -> Option { + self.mountinfo.iter().find_map(|m| { + if m.fs_type.0 == "cgroup" && m.super_opts.contains(&controller.to_string()) { + return Some(m.mount_point.clone()); + } + None + }) + } } impl V2 { @@ -225,7 +214,7 @@ pub const UNIFIED_MOUNTPOINT: &'static str = "/sys/fs/cgroup"; pub fn is_cgroup2_unified_mode() -> bool { use nix::sys::statfs; - let path = Path::new(UNIFIED_MOUNTPOINT); + let path = std::path::Path::new(UNIFIED_MOUNTPOINT); let fs_stat = statfs::statfs(path); if fs_stat.is_err() { return false; @@ -264,40 +253,3 @@ pub fn auto() -> Box { Box::new(V1::new()) } } - -pub fn find_v1_mount() -> Option { - // Open mountinfo so we can get a parseable mount list - let mountinfo_path = Path::new("/proc/self/mountinfo"); - - // If /proc isn't mounted, or something else happens, then bail out - if mountinfo_path.exists() == false { - return None; - } - - let mountinfo_file = File::open(mountinfo_path).unwrap(); - let mountinfo_reader = BufReader::new(&mountinfo_file); - for _line in mountinfo_reader.lines() { - let line = _line.unwrap(); - let mut fields = line.split_whitespace(); - let index = line.find(" - ").unwrap(); - let more_fields = line[index + 3..].split_whitespace().collect::>(); - if more_fields.len() == 0 { - continue; - } - if more_fields[0] == "cgroup" { - if more_fields.len() < 3 { - continue; - } - let cgroups_mount = fields.nth(4).unwrap(); - if let Some(parent) = std::path::Path::new(cgroups_mount).parent() { - if let Some(path) = parent.as_os_str().to_str() { - debug!("found cgroups {:?} from {:?}", path, cgroups_mount); - return Some(path.to_string()); - } - } - continue; - } - } - - None -} diff --git a/src/hugetlb.rs b/src/hugetlb.rs index d9e8d3c..686a599 100644 --- a/src/hugetlb.rs +++ b/src/hugetlb.rs @@ -98,12 +98,8 @@ fn read_u64_from(mut file: File) -> Result { } impl HugeTlbController { - /// Constructs a new `HugeTlbController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Constructs a new `HugeTlbController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { let sizes = get_hugepage_sizes().unwrap(); Self { base: root.clone(), diff --git a/src/lib.rs b/src/lib.rs index 117e88e..fe5c0c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,7 +137,7 @@ impl Controllers { Controllers::NetPrio => return "net_prio".to_string(), Controllers::HugeTlb => return "hugetlb".to_string(), Controllers::Rdma => return "rdma".to_string(), - Controllers::Systemd => return "systemd".to_string(), + Controllers::Systemd => return "name=systemd".to_string(), } } } @@ -367,12 +367,6 @@ pub trait Hierarchy { fn root_control_group(&self) -> Cgroup; fn v2(&self) -> bool; - - /// Checks whether a certain subsystem is supported in the hierarchy. - /// - /// This is an internal function and should not be used. - #[doc(hidden)] - fn check_support(&self, sub: Controllers) -> bool; } /// Resource limits for the memory subsystem. diff --git a/src/memory.rs b/src/memory.rs index 9dcea22..314de66 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -465,12 +465,8 @@ impl ControllerInternal for MemController { } impl MemController { - /// Contructs a new `MemController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Contructs a new `MemController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root, diff --git a/src/net_cls.rs b/src/net_cls.rs index ad2af39..5328eb1 100644 --- a/src/net_cls.rs +++ b/src/net_cls.rs @@ -86,10 +86,8 @@ fn read_u64_from(mut file: File) -> Result { } impl NetClsController { - /// Constructs a new `NetClsController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf) -> Self { - let mut root = oroot; - root.push(Self::controller_type().to_string()); + /// Constructs a new `NetClsController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf) -> Self { Self { base: root.clone(), path: root, diff --git a/src/net_prio.rs b/src/net_prio.rs index 3728796..d1bbbde 100644 --- a/src/net_prio.rs +++ b/src/net_prio.rs @@ -89,10 +89,8 @@ fn read_u64_from(mut file: File) -> Result { } impl NetPrioController { - /// Constructs a new `NetPrioController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf) -> Self { - let mut root = oroot; - root.push(Self::controller_type().to_string()); + /// Constructs a new `NetPrioController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf) -> Self { Self { base: root.clone(), path: root, diff --git a/src/perf_event.rs b/src/perf_event.rs index 09eefc6..f0e9240 100644 --- a/src/perf_event.rs +++ b/src/perf_event.rs @@ -64,10 +64,8 @@ impl<'a> From<&'a Subsystem> for &'a PerfEventController { } impl PerfEventController { - /// Constructs a new `PerfEventController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf) -> Self { - let mut root = oroot; - root.push(Self::controller_type().to_string()); + /// Constructs a new `PerfEventController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf) -> Self { Self { base: root.clone(), path: root, diff --git a/src/pid.rs b/src/pid.rs index e9c4869..1955828 100644 --- a/src/pid.rs +++ b/src/pid.rs @@ -101,13 +101,9 @@ fn read_u64_from(mut file: File) -> Result { } impl PidController { - /// Constructors a new `PidController` instance, with `oroot` serving as the controller's root + /// Constructors a new `PidController` instance, with `root` serving as the controller's root /// directory. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root, diff --git a/src/rdma.rs b/src/rdma.rs index 9d366d2..8066c15 100644 --- a/src/rdma.rs +++ b/src/rdma.rs @@ -75,10 +75,8 @@ fn read_string_from(mut file: File) -> Result { } impl RdmaController { - /// Constructs a new `RdmaController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf) -> Self { - let mut root = oroot; - root.push(Self::controller_type().to_string()); + /// Constructs a new `RdmaController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf) -> Self { Self { base: root.clone(), path: root, diff --git a/src/systemd.rs b/src/systemd.rs index 545c411..3fe0262 100644 --- a/src/systemd.rs +++ b/src/systemd.rs @@ -61,12 +61,8 @@ impl<'a> From<&'a Subsystem> for &'a SystemdController { } impl SystemdController { - /// Constructs a new `SystemdController` with `oroot` serving as the root of the control group. - pub fn new(oroot: PathBuf, v2: bool) -> Self { - let mut root = oroot; - if !v2 { - root.push(Self::controller_type().to_string()); - } + /// Constructs a new `SystemdController` with `root` serving as the root of the control group. + pub fn new(root: PathBuf, v2: bool) -> Self { Self { base: root.clone(), path: root,