diff --git a/src/cpu.rs b/src/cpu.rs index 535de66..9f34911 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -18,8 +18,8 @@ use crate::error::*; use crate::{parse_max_value, read_i64_from}; use crate::{ - ControllIdentifier, ControllerInternal, Controllers, CpuResources, MaxValue, Resources, - Subsystem, + ControllIdentifier, ControllerInternal, Controllers, CpuResources, CustomizedAttribute, + MaxValue, Resources, Subsystem, }; /// A controller that allows controlling the `cpu` subsystem of a Cgroup. @@ -91,6 +91,10 @@ impl ControllerInternal for CpuController { return Err(Error::new(ErrorKind::Other)); } + res.attrs.iter().for_each(|(k, v)| { + let _ = self.set(k, v); + }) + // TODO: rt properties (CONFIG_RT_GROUP_SCHED) are not yet supported } @@ -306,6 +310,8 @@ impl CpuController { } } +impl CustomizedAttribute for CpuController {} + fn parse_cfs_quota_and_period(mut file: File) -> Result { let mut content = String::new(); file.read_to_string(&mut content) diff --git a/src/lib.rs b/src/lib.rs index c94f73e..d1aa71f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -189,9 +189,22 @@ mod sealed { std::path::Path::new(p).exists() } } + + pub trait CustomizedAttribute: ControllerInternal { + fn set(&self, key: &str, value: &str) -> Result<()> { + self.open_path(key, true).and_then(|mut file| { + file.write_all(value.as_ref()) + .map_err(|e| Error::with_cause(WriteFailed, e)) + }) + } + + fn get(&self, key: &str) -> Result { + self.open_path(key, false).and_then(read_str_from) + } + } } -pub(crate) use crate::sealed::ControllerInternal; +pub(crate) use crate::sealed::{ControllerInternal, CustomizedAttribute}; /// A Controller is a subsystem attached to the control group. /// @@ -363,6 +376,14 @@ pub struct MemoryResources { /// Note, however, that a value of zero does not mean the process is never swapped out. Use the /// traditional `mlock(2)` system call for that purpose. pub swappiness: u64, + /// Customized key-value attributes + /// + /// # Usage: + /// ``` + /// let resource = &mut cgroups::Resources::default(); + /// resource.memory.attrs.insert("memory.numa_balancing", "true".to_string()); + /// // apply here + pub attrs: std::collections::HashMap<&'static str, String>, } /// Resources limits on the number of processes. @@ -402,6 +423,14 @@ pub struct CpuResources { pub realtime_runtime: i64, /// This is currently a no-operation. pub realtime_period: u64, + /// Customized key-value attributes + /// # Usage: + /// ``` + /// let resource = &mut cgroups::Resources::default(); + /// resource.cpu.attrs.insert("cpu.cfs_init_buffer_us", "10".to_string()); + /// // apply here + /// ``` + pub attrs: std::collections::HashMap<&'static str, String>, } /// A device resource that can be allowed or denied access to. @@ -791,3 +820,11 @@ pub fn read_i64_from(mut file: File) -> Result { Err(e) => Err(Error::with_cause(ReadFailed, e)), } } + +pub fn read_str_from(mut file: File) -> Result { + let mut string = String::new(); + match file.read_to_string(&mut string) { + Ok(_) => Ok(string.trim().to_owned()), + Err(e) => Err(Error::with_cause(ReadFailed, e)), + } +} diff --git a/src/memory.rs b/src/memory.rs index 9b1e804..0e3ea8c 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -21,8 +21,8 @@ use crate::events; use crate::flat_keyed_to_hashmap; use crate::{ - ControllIdentifier, ControllerInternal, Controllers, MaxValue, MemoryResources, Resources, - Subsystem, + ControllIdentifier, ControllerInternal, Controllers, CustomizedAttribute, MaxValue, + MemoryResources, Resources, Subsystem, }; /// A controller that allows controlling the `memory` subsystem of a Cgroup. @@ -834,6 +834,8 @@ impl ControllIdentifier for MemController { } } +impl CustomizedAttribute for MemController {} + impl<'a> From<&'a Subsystem> for &'a MemController { fn from(sub: &'a Subsystem) -> &'a MemController { unsafe {