From 5d51e50bec794736e4d6c7e464557cc82480a8fe Mon Sep 17 00:00:00 2001 From: bin liu Date: Mon, 7 Sep 2020 17:50:02 +0800 Subject: [PATCH] get relative paths at new/load func default. Signed-off-by: bin liu --- src/cgroup.rs | 72 ++++++++++++++++++++++++++++++++----------------- tests/cgroup.rs | 21 +++++++++------ 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/src/cgroup.rs b/src/cgroup.rs index 429681a..899195c 100644 --- a/src/cgroup.rs +++ b/src/cgroup.rs @@ -1,6 +1,7 @@ //! This module handles cgroup operations. Start here! use crate::error::*; +use crate::error::ErrorKind::*; use crate::libc_rmdir; @@ -37,7 +38,7 @@ impl<'b> Cgroup<'b> { fn create(&self) { if self.hier.v2() { create_v2_cgroup(self.hier.root().clone(), &self.path); - }else{ + } else { for subsystem in &self.subsystems { subsystem.to_controller().create(); } @@ -55,9 +56,8 @@ impl<'b> Cgroup<'b> { /// Note that if the handle goes out of scope and is dropped, the control group is _not_ /// destroyed. pub fn new>(hier: Box<&'b dyn Hierarchy>, path: P) -> Cgroup<'b> { - let cg = Cgroup::load(hier, path); - cg.create(); - cg + let relative_paths = get_cgroups_relative_paths().unwrap(); + Cgroup::new_with_relative_paths(hier, path, relative_paths) } /// Create a handle for a control group in the hierarchy `hier`, with name `path`. @@ -68,30 +68,31 @@ impl<'b> Cgroup<'b> { /// Note that if the handle goes out of scope and is dropped, the control group is _not_ /// destroyed. pub fn load>(hier: Box<&'b dyn Hierarchy>, path: P) -> Cgroup<'b> { - let path = path.as_ref(); - let mut subsystems = hier.subsystems(); - if path.as_os_str() != "" { - subsystems = subsystems - .into_iter() - .map(|x| x.enter(path)) - .collect::>(); - } - - let cg = Cgroup { - subsystems: subsystems, - hier: hier, - path: path.to_str().unwrap().to_string(), - }; - - cg + let relative_paths = get_cgroups_relative_paths().unwrap(); + Cgroup::load_with_relative_paths(hier, path, relative_paths) } + /// Create a new control group in the hierarchy `hier`, with name `path`. + /// and relative paths from `/proc/self/cgroup` + /// + /// Returns a handle to the control group that can be used to manipulate it. + /// + /// Note that if the handle goes out of scope and is dropped, the control group is _not_ + /// destroyed. pub fn new_with_relative_paths>(hier: Box<&'b dyn Hierarchy>, path: P, relative_paths: HashMap) -> Cgroup<'b> { let cg = Cgroup::load_with_relative_paths(hier, path, relative_paths); cg.create(); cg } + /// Create a handle for a control group in the hierarchy `hier`, with name `path`, + /// and relative paths from `/proc/self/cgroup` + /// + /// Returns a handle to the control group (that possibly does not exist until `create()` has + /// been called on the cgroup. + /// + /// Note that if the handle goes out of scope and is dropped, the control group is _not_ + /// destroyed. pub fn load_with_relative_paths>(hier: Box<&'b dyn Hierarchy>, path: P, relative_paths: HashMap) -> Cgroup<'b> { let path = path.as_ref(); let mut subsystems = hier.subsystems(); @@ -206,7 +207,7 @@ impl<'b> Cgroup<'b> { if subsystems.len() > 0 { let c = subsystems[0].to_controller(); c.add_task(&pid) - } else{ + } else { Ok(()) } } else { @@ -252,7 +253,6 @@ fn enable_controllers(controllers: &Vec, path: &PathBuf) { f.push("cgroup.subtree_control"); for c in controllers{ let body = format!("+{}", c); - // FIXME set mode to 0644 let _rest = fs::write(f.as_path(), body.as_bytes()); } } @@ -265,7 +265,7 @@ fn supported_controllers(p: &PathBuf) -> Vec{ fn create_v2_cgroup(root: PathBuf, path: &str) -> Result<()> { // controler list ["memory", "cpu"] - let controllers = supported_controllers(&root); + let controllers = supported_controllers(&root); let mut fp = root; // enable for root @@ -279,7 +279,6 @@ fn create_v2_cgroup(root: PathBuf, path: &str) -> Result<()> { fp.push(ele); // create dir, need not check if is a file or directory if !fp.exists(){ - // FIXME set mode to 0755 match ::std::fs::create_dir(fp.clone()) { Err(e) => return Err(Error::with_cause(ErrorKind::FsError, e)), Ok(_) => {}, @@ -293,4 +292,27 @@ fn create_v2_cgroup(root: PathBuf, path: &str) -> Result<()> { } Ok(()) -} \ No newline at end of file +} + +pub fn get_cgroups_relative_paths() -> Result> { + let mut m = HashMap::new(); + let content = fs::read_to_string("/proc/self/cgroup").map_err(|e| Error::with_cause(ReadFailed, e))?; + for l in content.lines() { + let fl: Vec<&str> = l.split(':').collect(); + if fl.len() != 3 { + continue; + } + + let keys: Vec<&str> = fl[1].split(',').collect(); + for key in &keys { + // this is a workaround, cgroup file are using `name=systemd`, + // but if file system the name is `systemd` + if *key == "name=systemd" { + m.insert("systemd".to_string(), fl[2].to_string()); + } else { + m.insert(key.to_string(), fl[2].to_string()); + } + } + } + Ok(m) +} diff --git a/tests/cgroup.rs b/tests/cgroup.rs index c5c2949..f78c20b 100644 --- a/tests/cgroup.rs +++ b/tests/cgroup.rs @@ -39,22 +39,27 @@ fn test_cgroup_with_relative_paths() { return } let h = cgroups::hierarchies::auto(); + let cgroup_root = h.root(); let h = Box::new(&*h); let mut relative_paths = HashMap::new(); - relative_paths.insert("memory".to_string(), "/mmm/abc/def".to_string()); - let cg = Cgroup::new_with_relative_paths(h, String::from("test_cgroup_with_prefix"), relative_paths); + let mem_relative_path = "/mmm/abc/def"; + relative_paths.insert("memory".to_string(), mem_relative_path.to_string()); + let cgroup_name = "test_cgroup_with_relative_paths"; + + let cg = Cgroup::new_with_relative_paths(h, String::from(cgroup_name), relative_paths); { let subsystems = cg.subsystems(); subsystems.into_iter().for_each(|sub| match sub { Subsystem::Pid(c) => { - let p = c.path().to_str().unwrap(); - let rel_path = p.trim_start_matches("/sys/fs/cgroup/pids"); - assert_eq!(rel_path, "/test_cgroup_with_prefix") + let cgroup_path = c.path().to_str().unwrap(); + let relative_path = "/pids/"; + // cgroup_path = cgroup_root + relative_path + cgroup_name + assert_eq!(cgroup_path, format!("{}{}{}", cgroup_root.to_str().unwrap(), relative_path, cgroup_name)); }, Subsystem::Mem(c) => { - let p = c.path().to_str().unwrap(); - let rel_path = p.trim_start_matches("/sys/fs/cgroup/memory"); - assert_eq!(rel_path, "/mmm/abc/def/test_cgroup_with_prefix") + let cgroup_path = c.path().to_str().unwrap(); + // cgroup_path = cgroup_root + relative_path + cgroup_name + assert_eq!(cgroup_path, format!("{}/memory{}/{}", cgroup_root.to_str().unwrap(), mem_relative_path, cgroup_name)); }, _ => {}, });