mirror of
https://github.com/kata-containers/cgroups-rs.git
synced 2026-08-05 02:13:23 +00:00
controllers: verify that resource application went ok or not
Signed-off-by: Levente Kurusa <lkurusa@acm.org>
This commit is contained in:
12
src/blkio.rs
12
src/blkio.rs
@@ -101,7 +101,7 @@ impl Controller for BlkIoController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &BlkIoResources = &res.blkio;
|
||||
|
||||
@@ -110,8 +110,7 @@ impl Controller for BlkIoController {
|
||||
let _ = self.set_leaf_weight(res.leaf_weight as u64);
|
||||
|
||||
for dev in &res.weight_device {
|
||||
let _ = self.set_weight_for_device(format!("{}:{} {}",
|
||||
dev.major, dev.minor, dev.weight));
|
||||
let _ = self.set_weight_for_device(dev.major, dev.minor, dev.weight as u64);
|
||||
}
|
||||
|
||||
for dev in &res.throttle_read_bps_device {
|
||||
@@ -130,6 +129,8 @@ impl Controller for BlkIoController {
|
||||
let _ = self.throttle_write_iops_for_device(dev.major, dev.minor, dev.rate);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,9 +335,10 @@ impl BlkIoController {
|
||||
}
|
||||
|
||||
/// Same as `set_weight()`, but settable per each block device.
|
||||
pub fn set_weight_for_device(self: &Self, d: String) -> Result<(), CgroupError> {
|
||||
pub fn set_weight_for_device(self: &Self, major: u64, minor: u64, weight: u64) -> Result<(), CgroupError> {
|
||||
self.open_path("blkio.weight_device", true).and_then(|mut file| {
|
||||
file.write_all(d.as_ref()).map_err(CgroupError::WriteError)
|
||||
file.write_all(format!("{}:{} {}", major, minor, weight).as_ref())
|
||||
.map_err(CgroupError::WriteError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,10 +99,8 @@ impl<'b> Cgroup<'b> {
|
||||
}
|
||||
|
||||
/// Apply a set of resource limits to the control group.
|
||||
pub fn apply(self: &Self, res: &Resources) {
|
||||
for subsystem in &self.subsystems {
|
||||
subsystem.to_controller().apply(res);
|
||||
}
|
||||
pub fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
self.subsystems.iter().try_fold((), |_, e| e.to_controller().apply(res))
|
||||
}
|
||||
|
||||
/// Retrieve a container based on type inference.
|
||||
|
||||
43
src/cpu.rs
43
src/cpu.rs
@@ -5,6 +5,7 @@
|
||||
//! paragraph 7 ("GROUP SCHEDULER EXTENSIONS TO CFS").
|
||||
use std::path::PathBuf;
|
||||
use std::io::{Read, Write};
|
||||
use std::fs::File;
|
||||
|
||||
use {CgroupError, CpuResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem};
|
||||
|
||||
@@ -34,17 +35,28 @@ impl Controller for CpuController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &CpuResources = &res.cpu;
|
||||
|
||||
if res.update_values {
|
||||
/* apply pid_max */
|
||||
let _ = self.set_shares(res.shares);
|
||||
if self.shares() != Ok(res.shares as u64) {
|
||||
return Err(CgroupError::Unknown);
|
||||
}
|
||||
let _ = self.set_cfs_period(res.period);
|
||||
if self.cfs_period() != Ok(res.period as u64) {
|
||||
return Err(CgroupError::Unknown);
|
||||
}
|
||||
let _ = self.set_cfs_quota(res.quota as u64);
|
||||
if self.cfs_quota() != Ok(res.quota as u64) {
|
||||
return Err(CgroupError::Unknown);
|
||||
}
|
||||
/* TODO: rt properties (CONFIG_RT_GROUP_SCHED) are not yet supported */
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +80,14 @@ impl<'a> From<&'a Subsystem> for &'a CpuController {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_u64_from(mut file: File) -> Result<u64, CgroupError> {
|
||||
let mut string = String::new();
|
||||
match file.read_to_string(&mut string) {
|
||||
Ok(_) => string.trim().parse().map_err(|_| CgroupError::ParseError),
|
||||
Err(e) => Err(CgroupError::ReadError(e)),
|
||||
}
|
||||
}
|
||||
|
||||
impl CpuController {
|
||||
/// Contructs a new `CpuController` with `oroot` serving as the root of the control group.
|
||||
pub fn new(oroot: PathBuf) -> Self {
|
||||
@@ -105,6 +125,13 @@ impl CpuController {
|
||||
})
|
||||
}
|
||||
|
||||
/// Retrieve the CPU bandwidth that this control group (relative to other control groups and
|
||||
/// this control group's parent) can use.
|
||||
pub fn shares(self: &Self) -> Result<u64, CgroupError> {
|
||||
self.open_path("cpu.shares", false)
|
||||
.and_then(read_u64_from)
|
||||
}
|
||||
|
||||
/// Specify a period (when using the CFS scheduler) of time in microseconds for how often this
|
||||
/// control group's access to the CPU should be reallocated.
|
||||
pub fn set_cfs_period(self: &Self, us: u64) -> Result<(), CgroupError> {
|
||||
@@ -113,6 +140,13 @@ impl CpuController {
|
||||
})
|
||||
}
|
||||
|
||||
/// Retrieve the period of time of how often this cgroup's access to the CPU should be
|
||||
/// reallocated in microseconds.
|
||||
pub fn cfs_period(self: &Self) -> Result<u64, CgroupError> {
|
||||
self.open_path("cpu.cfs_period_us", false)
|
||||
.and_then(read_u64_from)
|
||||
}
|
||||
|
||||
/// Specify a quota (when using the CFS scheduler) of time in microseconds for which all tasks
|
||||
/// in this control group can run during one period (see: `set_cfs_period()`).
|
||||
pub fn set_cfs_quota(self: &Self, us: u64) -> Result<(), CgroupError> {
|
||||
@@ -120,4 +154,11 @@ impl CpuController {
|
||||
file.write_all(us.to_string().as_ref()).map_err(CgroupError::WriteError)
|
||||
})
|
||||
}
|
||||
|
||||
/// Retrieve the quota of time for which all tasks in this cgroup can run during one period, in
|
||||
/// microseconds.
|
||||
pub fn cfs_quota(self: &Self) -> Result<u64, CgroupError> {
|
||||
self.open_path("cpu.cfs_quota_us", false)
|
||||
.and_then(read_u64_from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ impl Controller for CpuAcctController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, _res: &Resources) {
|
||||
fn apply(self: &Self, _res: &Resources) -> Result<(), CgroupError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,15 +82,16 @@ impl Controller for CpuSetController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &CpuResources = &res.cpu;
|
||||
|
||||
if res.update_values {
|
||||
/* apply pid_max */
|
||||
let _ = self.set_cpus(&res.cpus);
|
||||
let _ = self.set_mems(&res.mems);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ impl Controller for DevicesController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &DeviceResources = &res.devices;
|
||||
|
||||
@@ -142,6 +142,8 @@ impl Controller for DevicesController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ impl Controller for FreezerController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, _res: &Resources) {
|
||||
fn apply(self: &Self, _res: &Resources) -> Result<(), CgroupError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,15 +26,19 @@ impl Controller for HugeTlbController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &HugePageResources = &res.hugepages;
|
||||
|
||||
if res.update_values {
|
||||
for i in &res.limits {
|
||||
let _ = self.set_limit_in_bytes(&i.size, i.limit);
|
||||
if self.limit_in_bytes(&i.size) != Ok(i.limit) {
|
||||
return Err(CgroupError::Unknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ pub enum CgroupError {
|
||||
/// This could be caused by trying to escape the control group filesystem via a string of "..".
|
||||
/// This crate checks against this and operations will fail with this error.
|
||||
InvalidPath,
|
||||
/// An unknown error has occured.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl PartialEq for CgroupError {
|
||||
@@ -106,6 +108,9 @@ impl PartialEq for CgroupError {
|
||||
CgroupError::InvalidPath => if let CgroupError::InvalidPath = other {
|
||||
return true;
|
||||
} else { return false },
|
||||
CgroupError::Unknown => if let CgroupError::Unknown = other {
|
||||
return true;
|
||||
} else { return false },
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,7 +159,7 @@ impl Controllers {
|
||||
pub trait Controller {
|
||||
/// Apply a set of resources to the Controller, invoking its internal functions to pass the
|
||||
/// kernel the information.
|
||||
fn apply(self: &Self, res: &Resources);
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError>;
|
||||
|
||||
/* meta stuff */
|
||||
#[doc(hidden)]
|
||||
|
||||
@@ -121,7 +121,7 @@ impl Controller for MemController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let memres: &MemoryResources = &res.memory;
|
||||
|
||||
@@ -133,6 +133,8 @@ impl Controller for MemController {
|
||||
let _ = self.set_tcp_limit(memres.kernel_tcp_memory_limit);
|
||||
let _ = self.set_swappiness(memres.swappiness);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +26,17 @@ impl Controller for NetClsController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &NetworkResources = &res.network;
|
||||
|
||||
if res.update_values {
|
||||
let _ = self.set_class(res.class_id);
|
||||
if self.get_class() != Ok(res.class_id) {
|
||||
return Err(CgroupError::Unknown);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ impl Controller for NetPrioController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let res: &NetworkResources = &res.network;
|
||||
|
||||
@@ -36,6 +36,8 @@ impl Controller for NetPrioController {
|
||||
let _ = self.set_if_prio(&i.name, i.priority);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! [tools/perf/Documentation/perf-record.txt](https://raw.githubusercontent.com/torvalds/linux/master/tools/perf/Documentation/perf-record.txt)
|
||||
use std::path::PathBuf;
|
||||
|
||||
use {Controllers, Controller, Resources, ControllIdentifier, Subsystem};
|
||||
use {CgroupError, Controllers, Controller, Resources, ControllIdentifier, Subsystem};
|
||||
|
||||
/// A controller that allows controlling the `perf_event` subsystem of a Cgroup.
|
||||
///
|
||||
@@ -22,7 +22,8 @@ impl Controller for PerfEventController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, _res: &Resources) {
|
||||
fn apply(self: &Self, _res: &Resources) -> Result<(), CgroupError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
src/pid.rs
11
src/pid.rs
@@ -38,14 +38,23 @@ impl Controller for PidController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, res: &Resources) {
|
||||
fn apply(self: &Self, res: &Resources) -> Result<(), CgroupError> {
|
||||
/* get the resources that apply to this controller */
|
||||
let pidres: &PidResources = &res.pid;
|
||||
|
||||
if pidres.update_values {
|
||||
/* apply pid_max */
|
||||
let _ = self.set_pid_max(pidres.maximum_number_of_processes);
|
||||
|
||||
/* now, verify */
|
||||
if self.get_pid_max() == Ok(pidres.maximum_number_of_processes) {
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(CgroupError::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ impl Controller for RdmaController {
|
||||
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
|
||||
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
|
||||
|
||||
fn apply(self: &Self, _res: &Resources) {
|
||||
fn apply(self: &Self, _res: &Resources) -> Result<(), CgroupError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user