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 <tim@hyper.sh>
This commit is contained in:
Tim Zhang
2020-11-12 20:06:03 +08:00
parent fbd7164c29
commit 1f188be405
17 changed files with 83 additions and 180 deletions

View File

@@ -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"

View File

@@ -421,12 +421,8 @@ fn read_u64_from(mut file: File) -> Result<u64> {
}
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,

View File

@@ -122,12 +122,8 @@ fn read_u64_from(mut file: File) -> Result<u64> {
}
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,

View File

@@ -118,10 +118,8 @@ fn read_string_from(mut file: File) -> Result<String> {
}
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,

View File

@@ -261,12 +261,8 @@ fn parse_range(s: String) -> Result<Vec<(u64, u64)>> {
}
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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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<Mountinfo>,
}
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<PathBuf> {
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<dyn Hierarchy> {
Box::new(V1::new())
}
}
pub fn find_v1_mount() -> Option<String> {
// 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::<Vec<_>>();
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
}

View File

@@ -98,12 +98,8 @@ fn read_u64_from(mut file: File) -> Result<u64> {
}
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(),

View File

@@ -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.

View File

@@ -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,

View File

@@ -86,10 +86,8 @@ fn read_u64_from(mut file: File) -> Result<u64> {
}
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,

View File

@@ -89,10 +89,8 @@ fn read_u64_from(mut file: File) -> Result<u64> {
}
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,

View File

@@ -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,

View File

@@ -101,13 +101,9 @@ fn read_u64_from(mut file: File) -> Result<u64> {
}
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,

View File

@@ -75,10 +75,8 @@ fn read_string_from(mut file: File) -> Result<String> {
}
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,

View File

@@ -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,