From 2149e1c0c48c55d90397f279bcef0f17c345462c Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Thu, 4 Oct 2018 00:45:43 +0900 Subject: [PATCH] Run rustfmt --- src/blkio.rs | 491 +++++++++++++++++++++++++++------------------ src/cgroup.rs | 66 +++--- src/cpu.rs | 76 ++++--- src/cpuacct.rs | 83 +++++--- src/cpuset.rs | 263 ++++++++++++++---------- src/devices.rs | 89 ++++++-- src/freezer.rs | 32 ++- src/hierarchies.rs | 31 ++- src/hugetlb.rs | 39 ++-- src/lib.rs | 103 +++++----- src/memory.rs | 389 +++++++++++++++++++++++------------ src/net_cls.rs | 45 +++-- src/net_prio.rs | 80 +++++--- src/perf_event.rs | 22 +- src/pid.rs | 47 +++-- src/rdma.rs | 29 ++- tests/cgroup.rs | 4 +- tests/cpuset.rs | 2 +- tests/devices.rs | 30 ++- tests/pids.rs | 22 +- tests/resources.rs | 2 +- 21 files changed, 1208 insertions(+), 737 deletions(-) diff --git a/src/blkio.rs b/src/blkio.rs index 7036f1d..38863b3 100644 --- a/src/blkio.rs +++ b/src/blkio.rs @@ -1,13 +1,15 @@ //! This module contains the implementation of the `blkio` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/blkio-controller.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt) -use std::path::PathBuf; -use std::io::{Read, Write}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, BlkIoResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; use CgroupError::*; +use { + BlkIoResources, CgroupError, ControllIdentifier, Controller, Controllers, Resources, Subsystem, +}; /// A controller that allows controlling the `blkio` subsystem of a Cgroup. /// @@ -102,35 +104,31 @@ fn parse_io_service_total(s: String) -> Result { } fn parse_blkio_data(s: String) -> Result, CgroupError> { - let r = s.chars() + let r = s + .chars() .map(|x| if x == ':' { ' ' } else { x }) .collect::(); - let r = r.lines() + let r = r + .lines() .flat_map(|x| x.split_whitespace()) .collect::>(); - let r = r.chunks(3) - .collect::>(); + let r = r.chunks(3).collect::>(); let mut res = Vec::new(); - let err = r.iter() - .try_for_each(|x| - match x { - [major, minor, data] => { - res.push(BlkIoData { - major: major.parse::().unwrap(), - minor: minor.parse::().unwrap(), - data: data.parse::().unwrap(), - }); - Ok(()) - }, - _ => { - Err(CgroupError::ParseError) - } - } - ); + let err = r.iter().try_for_each(|x| match x { + [major, minor, data] => { + res.push(BlkIoData { + major: major.parse::().unwrap(), + minor: minor.parse::().unwrap(), + data: data.parse::().unwrap(), + }); + Ok(()) + } + _ => Err(CgroupError::ParseError), + }); if err.is_err() { return Err(CgroupError::ParseError); @@ -256,10 +254,18 @@ pub struct BlkIo { } impl Controller for BlkIoController { - fn control_type(&self) -> Controllers { Controllers::BlkIo } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::BlkIo + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -308,7 +314,7 @@ impl<'a> From<&'a Subsystem> for &'a BlkIoController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -345,172 +351,216 @@ impl BlkIoController { /// group's tasks. pub fn blkio(&self) -> BlkIo { BlkIo { - io_merged: self.open_path("blkio.io_merged", false) + io_merged: self + .open_path("blkio.io_merged", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_merged_total: self.open_path("blkio.io_merged", false) + io_merged_total: self + .open_path("blkio.io_merged", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_merged_recursive: self.open_path("blkio.io_merged_recursive", false) + io_merged_recursive: self + .open_path("blkio.io_merged_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_merged_recursive_total: self.open_path("blkio.io_merged_recursive", false) + io_merged_recursive_total: self + .open_path("blkio.io_merged_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_queued: self.open_path("blkio.io_queued", false) + io_queued: self + .open_path("blkio.io_queued", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_queued_total: self.open_path("blkio.io_queued", false) + io_queued_total: self + .open_path("blkio.io_queued", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_queued_recursive: self.open_path("blkio.io_queued_recursive", false) + io_queued_recursive: self + .open_path("blkio.io_queued_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_queued_recursive_total: self.open_path("blkio.io_queued_recursive", false) + io_queued_recursive_total: self + .open_path("blkio.io_queued_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_service_bytes: self.open_path("blkio.io_service_bytes", false) + io_service_bytes: self + .open_path("blkio.io_service_bytes", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_service_bytes_total: self.open_path("blkio.io_service_bytes", false) + io_service_bytes_total: self + .open_path("blkio.io_service_bytes", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_service_bytes_recursive: self.open_path("blkio.io_service_bytes_recursive", false) + io_service_bytes_recursive: self + .open_path("blkio.io_service_bytes_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_service_bytes_recursive_total: self.open_path("blkio.io_service_bytes_recursive", false) + io_service_bytes_recursive_total: self + .open_path("blkio.io_service_bytes_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_serviced: self.open_path("blkio.io_serviced", false) + io_serviced: self + .open_path("blkio.io_serviced", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_serviced_total: self.open_path("blkio.io_serviced", false) + io_serviced_total: self + .open_path("blkio.io_serviced", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_serviced_recursive: self.open_path("blkio.io_serviced_recursive", false) + io_serviced_recursive: self + .open_path("blkio.io_serviced_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_serviced_recursive_total: self.open_path("blkio.io_serviced_recursive", false) + io_serviced_recursive_total: self + .open_path("blkio.io_serviced_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_service_time: self.open_path("blkio.io_service_time", false) + io_service_time: self + .open_path("blkio.io_service_time", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_service_time_total: self.open_path("blkio.io_service_time", false) + io_service_time_total: self + .open_path("blkio.io_service_time", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_service_time_recursive: self.open_path("blkio.io_service_time_recursive", false) + io_service_time_recursive: self + .open_path("blkio.io_service_time_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_service_time_recursive_total: self.open_path("blkio.io_service_time_recursive", false) + io_service_time_recursive_total: self + .open_path("blkio.io_service_time_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_wait_time: self.open_path("blkio.io_wait_time", false) + io_wait_time: self + .open_path("blkio.io_wait_time", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_wait_time_total: self.open_path("blkio.io_wait_time", false) + io_wait_time_total: self + .open_path("blkio.io_wait_time", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_wait_time_recursive: self.open_path("blkio.io_wait_time_recursive", false) + io_wait_time_recursive: self + .open_path("blkio.io_wait_time_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_wait_time_recursive_total: self.open_path("blkio.io_wait_time_recursive", false) + io_wait_time_recursive_total: self + .open_path("blkio.io_wait_time_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - leaf_weight: self.open_path("blkio.leaf_weight", false).and_then(|file| { - read_u64_from(file) - }).unwrap_or(0u64), - leaf_weight_device: self.open_path("blkio.leaf_weight_device", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), - sectors: self.open_path("blkio.sectors", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), - sectors_recursive: self.open_path("blkio.sectors_recursive", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), + leaf_weight: self + .open_path("blkio.leaf_weight", false) + .and_then(|file| read_u64_from(file)) + .unwrap_or(0u64), + leaf_weight_device: self + .open_path("blkio.leaf_weight_device", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + sectors: self + .open_path("blkio.sectors", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + sectors_recursive: self + .open_path("blkio.sectors_recursive", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), throttle: BlkIoThrottle { - io_service_bytes: self.open_path("blkio.throttle.io_service_bytes", false) - .and_then(read_string_from) - .and_then(parse_io_service) - .unwrap_or(Vec::new()), - io_service_bytes_total: self.open_path("blkio.throttle.io_service_bytes", false) - .and_then(read_string_from) - .and_then(parse_io_service_total) - .unwrap_or(0), - io_service_bytes_recursive: self.open_path("blkio.throttle.io_service_bytes_recursive", false) + io_service_bytes: self + .open_path("blkio.throttle.io_service_bytes", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_service_bytes_recursive_total: self.open_path("blkio.throttle.io_service_bytes_recursive", false) + io_service_bytes_total: self + .open_path("blkio.throttle.io_service_bytes", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_serviced: self.open_path("blkio.throttle.io_serviced", false) + io_service_bytes_recursive: self + .open_path("blkio.throttle.io_service_bytes_recursive", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_serviced_total: self.open_path("blkio.throttle.io_serviced", false) + io_service_bytes_recursive_total: self + .open_path("blkio.throttle.io_service_bytes_recursive", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - io_serviced_recursive: self.open_path("blkio.throttle.io_serviced_recursive", false) + io_serviced: self + .open_path("blkio.throttle.io_serviced", false) .and_then(read_string_from) .and_then(parse_io_service) .unwrap_or(Vec::new()), - io_serviced_recursive_total: self.open_path("blkio.throttle.io_serviced_recursive", false) + io_serviced_total: self + .open_path("blkio.throttle.io_serviced", false) .and_then(read_string_from) .and_then(parse_io_service_total) .unwrap_or(0), - read_bps_device: self.open_path("blkio.throttle.read_bps_device", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), - read_iops_device: self.open_path("blkio.throttle.read_iops_device", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), - write_bps_device: self.open_path("blkio.throttle.write_bps_device", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), - write_iops_device: self.open_path("blkio.throttle.write_iops_device", false).and_then(|file| { - read_string_from(file) - }).unwrap_or("".to_string()), + io_serviced_recursive: self + .open_path("blkio.throttle.io_serviced_recursive", false) + .and_then(read_string_from) + .and_then(parse_io_service) + .unwrap_or(Vec::new()), + io_serviced_recursive_total: self + .open_path("blkio.throttle.io_serviced_recursive", false) + .and_then(read_string_from) + .and_then(parse_io_service_total) + .unwrap_or(0), + read_bps_device: self + .open_path("blkio.throttle.read_bps_device", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + read_iops_device: self + .open_path("blkio.throttle.read_iops_device", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + write_bps_device: self + .open_path("blkio.throttle.write_bps_device", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + write_iops_device: self + .open_path("blkio.throttle.write_iops_device", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), }, - time: self.open_path("blkio.time", false) + time: self + .open_path("blkio.time", false) .and_then(read_string_from) .and_then(parse_blkio_data) .unwrap_or(Vec::new()), - time_recursive: self.open_path("blkio.time_recursive", false) + time_recursive: self + .open_path("blkio.time_recursive", false) .and_then(read_string_from) .and_then(parse_blkio_data) .unwrap_or(Vec::new()), - weight: self.open_path("blkio.weight", false).and_then(|file| { - read_u64_from(file) - }).unwrap_or(0u64), - weight_device: self.open_path("blkio.weight_device", false) + weight: self + .open_path("blkio.weight", false) + .and_then(|file| read_u64_from(file)) + .unwrap_or(0u64), + weight_device: self + .open_path("blkio.weight_device", false) .and_then(read_string_from) .and_then(parse_blkio_data) .unwrap_or(Vec::new()), @@ -520,77 +570,116 @@ impl BlkIoController { /// Set the leaf weight on the control group's tasks, i.e., how are they weighted against the /// descendant control groups' tasks. pub fn set_leaf_weight(&self, w: u64) -> Result<(), CgroupError> { - self.open_path("blkio.leaf_weight", true).and_then(|mut file| { - file.write_all(w.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("blkio.leaf_weight", true) + .and_then(|mut file| { + file.write_all(w.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Same as `set_leaf_weight()`, but settable per each block device. pub fn set_leaf_weight_for_device(&self, d: String) -> Result<(), CgroupError> { - self.open_path("blkio.leaf_weight_device", true).and_then(|mut file| { - file.write_all(d.as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("blkio.leaf_weight_device", true) + .and_then(|mut file| file.write_all(d.as_ref()).map_err(CgroupError::WriteError)) } /// Reset the statistics the kernel has gathered so far and start fresh. pub fn reset_stats(&self) -> Result<(), CgroupError> { - self.open_path("blkio.leaf_weight_device", true).and_then(|mut file| { - file.write_all("1".to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("blkio.leaf_weight_device", true) + .and_then(|mut file| { + file.write_all("1".to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Throttle the bytes per second rate of read operation affecting the block device /// `major:minor` to `bps`. - pub fn throttle_read_bps_for_device(&self, major: u64, minor: u64, bps: u64) -> Result<(), CgroupError> { - self.open_path("blkio.throttle.read_bps_device", true).and_then(|mut file| { - file.write_all(format!("{}:{} {}", major, minor, bps).to_string().as_ref()).map_err(CgroupError::WriteError) - }) + pub fn throttle_read_bps_for_device( + &self, + major: u64, + minor: u64, + bps: u64, + ) -> Result<(), CgroupError> { + self.open_path("blkio.throttle.read_bps_device", true) + .and_then(|mut file| { + file.write_all(format!("{}:{} {}", major, minor, bps).to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Throttle the I/O operations per second rate of read operation affecting the block device /// `major:minor` to `bps`. - pub fn throttle_read_iops_for_device(&self, major: u64, minor: u64, iops: u64) -> Result<(), CgroupError> { - self.open_path("blkio.throttle.read_iops_device", true).and_then(|mut file| { - file.write_all(format!("{}:{} {}", major, minor, iops).to_string().as_ref()).map_err(CgroupError::WriteError) - }) + pub fn throttle_read_iops_for_device( + &self, + major: u64, + minor: u64, + iops: u64, + ) -> Result<(), CgroupError> { + self.open_path("blkio.throttle.read_iops_device", true) + .and_then(|mut file| { + file.write_all(format!("{}:{} {}", major, minor, iops).to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Throttle the bytes per second rate of write operation affecting the block device /// `major:minor` to `bps`. - pub fn throttle_write_bps_for_device(&self, major: u64, minor: u64, bps: u64) -> Result<(), CgroupError> { - self.open_path("blkio.throttle.write_bps_device", true).and_then(|mut file| { - file.write_all(format!("{}:{} {}", major, minor, bps).to_string().as_ref()).map_err(CgroupError::WriteError) - }) + pub fn throttle_write_bps_for_device( + &self, + major: u64, + minor: u64, + bps: u64, + ) -> Result<(), CgroupError> { + self.open_path("blkio.throttle.write_bps_device", true) + .and_then(|mut file| { + file.write_all(format!("{}:{} {}", major, minor, bps).to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Throttle the I/O operations per second rate of write operation affecting the block device /// `major:minor` to `bps`. - pub fn throttle_write_iops_for_device(&self, major: u64, minor: u64, iops: u64) -> Result<(), CgroupError> { - self.open_path("blkio.throttle.write_iops_device", true).and_then(|mut file| { - file.write_all(format!("{}:{} {}", major, minor, iops).to_string().as_ref()).map_err(CgroupError::WriteError) - }) + pub fn throttle_write_iops_for_device( + &self, + major: u64, + minor: u64, + iops: u64, + ) -> Result<(), CgroupError> { + self.open_path("blkio.throttle.write_iops_device", true) + .and_then(|mut file| { + file.write_all(format!("{}:{} {}", major, minor, iops).to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Set the weight of the control group's tasks. pub fn set_weight(&self, w: u64) -> Result<(), CgroupError> { - self.open_path("blkio.leaf_weight", true).and_then(|mut file| { - file.write_all(w.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("blkio.leaf_weight", true) + .and_then(|mut file| { + file.write_all(w.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Same as `set_weight()`, but settable per each block device. - pub fn set_weight_for_device(&self, major: u64, minor: u64, weight: u64) -> Result<(), CgroupError> { - self.open_path("blkio.weight_device", true).and_then(|mut file| { - file.write_all(format!("{}:{} {}", major, minor, weight).as_ref()) - .map_err(CgroupError::WriteError) - }) + pub fn set_weight_for_device( + &self, + major: u64, + minor: u64, + weight: u64, + ) -> Result<(), CgroupError> { + self.open_path("blkio.weight_device", true) + .and_then(|mut file| { + file.write_all(format!("{}:{} {}", major, minor, weight).as_ref()) + .map_err(CgroupError::WriteError) + }) } } #[cfg(test)] mod test { - use blkio::{IoService, parse_io_service, parse_io_service_total}; - use blkio::{BlkIoData, parse_blkio_data}; - use ::CgroupError; + use blkio::{parse_blkio_data, BlkIoData}; + use blkio::{parse_io_service, parse_io_service_total, IoService}; + use CgroupError; const test_value: &str = "\ 8:32 Read 4280320 @@ -645,75 +734,87 @@ Total 61823067136 #[test] fn test_parse_io_service_total() { - assert_eq!(parse_io_service_total(test_value.to_string()), Ok(61823067136)); + assert_eq!( + parse_io_service_total(test_value.to_string()), + Ok(61823067136) + ); } #[test] fn test_parse_io_service() { - assert_eq!(parse_io_service(test_value.to_string()), Ok(vec![ - IoService { - major: 8, - minor: 32, - read: 4280320, - write: 0, - sync: 4280320, - async: 0, - total: 4280320, - }, - IoService { - major: 8, - minor: 48, - read: 5705479168, - write: 56096055296, - sync: 11213923328, - async: 50587611136, - total: 61801534464, - }, - IoService { - major: 8, - minor: 16, - read: 10059776, - write: 0, - sync: 10059776, - async: 0, - total: 10059776, - }, - IoService { - major: 8, - minor: 0 , - read: 7192576, - write: 0, - sync: 7192576, - async: 0, - total: 7192576, - } - ])); - assert_eq!(parse_io_service(test_wrong_value.to_string()), Err(CgroupError::ParseError)); + assert_eq!( + parse_io_service(test_value.to_string()), + Ok(vec![ + IoService { + major: 8, + minor: 32, + read: 4280320, + write: 0, + sync: 4280320, + async: 0, + total: 4280320, + }, + IoService { + major: 8, + minor: 48, + read: 5705479168, + write: 56096055296, + sync: 11213923328, + async: 50587611136, + total: 61801534464, + }, + IoService { + major: 8, + minor: 16, + read: 10059776, + write: 0, + sync: 10059776, + async: 0, + total: 10059776, + }, + IoService { + major: 8, + minor: 0, + read: 7192576, + write: 0, + sync: 7192576, + async: 0, + total: 7192576, + } + ]) + ); + assert_eq!( + parse_io_service(test_wrong_value.to_string()), + Err(CgroupError::ParseError) + ); } #[test] fn test_parse_blkio_data() { - assert_eq!(parse_blkio_data(test_blkio_data.to_string()), Ok(vec![ - BlkIoData { - major: 8, - minor: 48, - data: 454480833999, - }, - BlkIoData { - major: 8, - minor: 32, - data: 228392923193, - }, - BlkIoData { - major: 8, - minor: 16, - data: 772456885, - }, - BlkIoData { - major: 8, - minor: 0, - data: 559583764, - } - ])); + assert_eq!( + parse_blkio_data(test_blkio_data.to_string()), + Ok(vec![ + BlkIoData { + major: 8, + minor: 48, + data: 454480833999, + }, + BlkIoData { + major: 8, + minor: 32, + data: 228392923193, + }, + BlkIoData { + major: 8, + minor: 16, + data: 772456885, + }, + BlkIoData { + major: 8, + minor: 0, + data: 559583764, + } + ]) + ); } } diff --git a/src/cgroup.rs b/src/cgroup.rs index 7e46f0f..33260fc 100644 --- a/src/cgroup.rs +++ b/src/cgroup.rs @@ -1,16 +1,15 @@ //! This module handles cgroup operations. Start here! -use {CgroupError, CgroupPid, Resources, ControllIdentifier, Controller, Hierarchy, Subsystem}; +use {CgroupError, CgroupPid, ControllIdentifier, Controller, Hierarchy, Resources, Subsystem}; use std::convert::From; - /// A control group is the central structure to this crate. /// /// /// # What are control groups? /// -/// Lifting over from the Linux kernel sources: +/// Lifting over from the Linux kernel sources: /// /// > Control Groups provide a mechanism for aggregating/partitioning sets of /// > tasks, and all their future children, into hierarchical groups with @@ -26,7 +25,6 @@ pub struct Cgroup<'b> { } impl<'b> Cgroup<'b> { - /// Create this control group. fn create(&self) { for subsystem in &self.subsystems { @@ -55,8 +53,11 @@ impl<'b> Cgroup<'b> { /// destroyed. pub fn load(hier: &Hierarchy, path: String) -> Cgroup { let mut subsystems = hier.subsystems(); - if path != "" { - subsystems = subsystems.into_iter().map(|x| x.enter(&path)).collect::>(); + if path != "" { + subsystems = subsystems + .into_iter() + .map(|x| x.enter(&path)) + .collect::>(); } let cg = Cgroup { @@ -79,28 +80,28 @@ impl<'b> Cgroup<'b> { /// actually removed, and remove the descendants first if not. In the future, this behavior /// will change. pub fn delete(self) { - self.subsystems.into_iter().for_each(|sub| { - match sub { - Subsystem::Pid(pidc) => pidc.delete(), - Subsystem::Mem(c) => c.delete(), - Subsystem::CpuSet(c) => c.delete(), - Subsystem::CpuAcct(c) => c.delete(), - Subsystem::Cpu(c) => c.delete(), - Subsystem::Devices(c) => c.delete(), - Subsystem::Freezer(c) => c.delete(), - Subsystem::NetCls(c) => c.delete(), - Subsystem::BlkIo(c) => c.delete(), - Subsystem::PerfEvent(c) => c.delete(), - Subsystem::NetPrio(c) => c.delete(), - Subsystem::HugeTlb(c) => c.delete(), - Subsystem::Rdma(c) => c.delete(), - } + self.subsystems.into_iter().for_each(|sub| match sub { + Subsystem::Pid(pidc) => pidc.delete(), + Subsystem::Mem(c) => c.delete(), + Subsystem::CpuSet(c) => c.delete(), + Subsystem::CpuAcct(c) => c.delete(), + Subsystem::Cpu(c) => c.delete(), + Subsystem::Devices(c) => c.delete(), + Subsystem::Freezer(c) => c.delete(), + Subsystem::NetCls(c) => c.delete(), + Subsystem::BlkIo(c) => c.delete(), + Subsystem::PerfEvent(c) => c.delete(), + Subsystem::NetPrio(c) => c.delete(), + Subsystem::HugeTlb(c) => c.delete(), + Subsystem::Rdma(c) => c.delete(), }); } /// Apply a set of resource limits to the control group. pub fn apply(&self, res: &Resources) -> Result<(), CgroupError> { - self.subsystems.iter().try_fold((), |_, e| e.to_controller().apply(res)) + self.subsystems + .iter() + .try_fold((), |_, e| e.to_controller().apply(res)) } /// Retrieve a container based on type inference. @@ -114,8 +115,9 @@ impl<'b> Cgroup<'b> { /// .expect("No cpu controller attached!"); /// ``` pub fn controller_of<'a, T>(self: &'a Self) -> Option<&'a T> - where &'a T: From<&'a Subsystem>, - T: Controller + ControllIdentifier, + where + &'a T: From<&'a Subsystem>, + T: Controller + ControllIdentifier, { for i in &self.subsystems { if i.to_controller().control_type() == T::controller_type() { @@ -139,19 +141,25 @@ impl<'b> Cgroup<'b> { /// Attach a task to the control group. pub fn add_task(&self, pid: CgroupPid) -> Result<(), CgroupError> { - self.subsystems().iter().try_for_each(|sub| sub.to_controller().add_task(&pid)) + self.subsystems() + .iter() + .try_for_each(|sub| sub.to_controller().add_task(&pid)) } /// Returns an Iterator that can be used to iterate over the tasks that are currently in the /// control group. pub fn tasks(&self) -> Vec { /* Collect the tasks from all subsystems */ - let mut v = self.subsystems().iter() + let mut v = self + .subsystems() + .iter() .map(|x| x.to_controller().tasks()) - .fold(vec![], |mut acc, mut x| { acc.append(&mut x); acc }); + .fold(vec![], |mut acc, mut x| { + acc.append(&mut x); + acc + }); v.sort(); v.dedup(); v } - } diff --git a/src/cpu.rs b/src/cpu.rs index eb6ccf7..6af7b7f 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,21 +1,23 @@ //! This module contains the implementation of the `cpu` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/scheduler/sched-design-CFS.txt](https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt) //! paragraph 7 ("GROUP SCHEDULER EXTENSIONS TO CFS"). -use std::path::PathBuf; -use std::io::{Read, Write}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, CpuResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; +use { + CgroupError, ControllIdentifier, Controller, Controllers, CpuResources, Resources, Subsystem, +}; /// A controller that allows controlling the `cpu` subsystem of a Cgroup. -/// +/// /// In essence, it allows gathering information about how much the tasks inside the control group /// are using the CPU and creating rules that limit their usage. Note that this crate does not yet /// support managing realtime tasks. #[derive(Debug, Clone)] -pub struct CpuController{ +pub struct CpuController { base: PathBuf, path: PathBuf, } @@ -30,10 +32,18 @@ pub struct Cpu { } impl Controller for CpuController { - fn control_type(&self) -> Controllers { Controllers::Cpu} - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::Cpu + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -74,7 +84,7 @@ impl<'a> From<&'a Subsystem> for &'a CpuController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -102,42 +112,46 @@ impl CpuController { /// Returns CPU time statistics based on the processes in the control group. pub fn cpu(&self) -> Cpu { Cpu { - stat: self.open_path("cpu.stat", false).and_then(|mut file| { - let mut s = String::new(); - let res = file.read_to_string(&mut s); - match res { - Ok(_) => Ok(s), - Err(e) => Err(CgroupError::ReadError(e)), - } - }).unwrap_or("".to_string()), + stat: self + .open_path("cpu.stat", false) + .and_then(|mut file| { + let mut s = String::new(); + let res = file.read_to_string(&mut s); + match res { + Ok(_) => Ok(s), + Err(e) => Err(CgroupError::ReadError(e)), + } + }).unwrap_or("".to_string()), } } /// Configures the CPU bandwidth (in relative relation to other control groups and this control /// group's parent). - /// + /// /// For example, setting control group `A`'s `shares` to `100`, and control group `B`'s /// `shares` to `200` ensures that control group `B` receives twice as much as CPU bandwidth. /// (Assuming both `A` and `B` are of the same parent) pub fn set_shares(&self, shares: u64) -> Result<(), CgroupError> { self.open_path("cpu.shares", true).and_then(|mut file| { - file.write_all(shares.to_string().as_ref()).map_err(CgroupError::WriteError) + file.write_all(shares.to_string().as_ref()) + .map_err(CgroupError::WriteError) }) } /// 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) -> Result { - self.open_path("cpu.shares", false) - .and_then(read_u64_from) + 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, us: u64) -> Result<(), CgroupError> { - self.open_path("cpu.cfs_period_us", true).and_then(|mut file| { - file.write_all(us.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("cpu.cfs_period_us", true) + .and_then(|mut file| { + file.write_all(us.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Retrieve the period of time of how often this cgroup's access to the CPU should be @@ -150,11 +164,13 @@ impl CpuController { /// 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, us: u64) -> Result<(), CgroupError> { - self.open_path("cpu.cfs_quota_us", true).and_then(|mut file| { - file.write_all(us.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("cpu.cfs_quota_us", true) + .and_then(|mut file| { + 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) -> Result { diff --git a/src/cpuacct.rs b/src/cpuacct.rs index 53d5a82..b379bcb 100644 --- a/src/cpuacct.rs +++ b/src/cpuacct.rs @@ -1,12 +1,12 @@ //! This module contains the implementation of the `cpuacct` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/cpuacct.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt) -use std::path::PathBuf; -use std::io::{Read, Write}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, Controllers, Resources, Subsystem, ControllIdentifier, Controller}; +use {CgroupError, ControllIdentifier, Controller, Controllers, Resources, Subsystem}; /// A controller that allows controlling the `cpuacct` subsystem of a Cgroup. /// @@ -50,10 +50,18 @@ pub struct CpuAcct { } impl Controller for CpuAcctController { - fn control_type(&self) -> Controllers { Controllers::CpuAcct } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::CpuAcct + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, _res: &Resources) -> Result<(), CgroupError> { Ok(()) @@ -74,7 +82,7 @@ impl<'a> From<&'a Subsystem> for &'a CpuAcctController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -101,7 +109,6 @@ 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; @@ -115,32 +122,44 @@ impl CpuAcctController { /// Gathers the statistics that are available in the control group into a `CpuAcct` structure. pub fn cpuacct(&self) -> CpuAcct { CpuAcct { - stat: self.open_path("cpuacct.stat", false) - .and_then(|file| read_string_from(file)).unwrap_or("".to_string()), - usage: self.open_path("cpuacct.usage", false) - .and_then(|file| read_u64_from(file)) - .unwrap_or(0), - usage_all: self.open_path("cpuacct.usage_all", false) - .and_then(|file| read_string_from(file)).unwrap_or("".to_string()), - usage_percpu: self.open_path("cpuacct.usage_percpu", false) - .and_then(|file| read_string_from(file)).unwrap_or("".to_string()), - usage_percpu_sys: self.open_path("cpuacct.usage_percpu_sys", false) - .and_then(|file| read_string_from(file)).unwrap_or("".to_string()), - usage_percpu_user: self.open_path("cpuacct.usage_percpu_user", false) - .and_then(|file| read_string_from(file)).unwrap_or("".to_string()), - usage_sys: self.open_path("cpuacct.usage_sys", false) - .and_then(|file| read_u64_from(file)) - .unwrap_or(0), - usage_user: self.open_path("cpuacct.usage_user", false) - .and_then(|file| read_u64_from(file)) - .unwrap_or(0), + stat: self + .open_path("cpuacct.stat", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + usage: self + .open_path("cpuacct.usage", false) + .and_then(|file| read_u64_from(file)) + .unwrap_or(0), + usage_all: self + .open_path("cpuacct.usage_all", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + usage_percpu: self + .open_path("cpuacct.usage_percpu", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + usage_percpu_sys: self + .open_path("cpuacct.usage_percpu_sys", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + usage_percpu_user: self + .open_path("cpuacct.usage_percpu_user", false) + .and_then(|file| read_string_from(file)) + .unwrap_or("".to_string()), + usage_sys: self + .open_path("cpuacct.usage_sys", false) + .and_then(|file| read_u64_from(file)) + .unwrap_or(0), + usage_user: self + .open_path("cpuacct.usage_user", false) + .and_then(|file| read_u64_from(file)) + .unwrap_or(0), } } /// Reset the statistics the kernel has gathered about the control group. pub fn reset(&self) -> Result<(), CgroupError> { - self.open_path("cpuacct.usage", true).and_then(|mut file| { - file.write_all(b"0").map_err(CgroupError::WriteError) - }) + self.open_path("cpuacct.usage", true) + .and_then(|mut file| file.write_all(b"0").map_err(CgroupError::WriteError)) } } diff --git a/src/cpuset.rs b/src/cpuset.rs index d39a3c4..7b6dc7c 100644 --- a/src/cpuset.rs +++ b/src/cpuset.rs @@ -1,16 +1,18 @@ //! This module contains the implementation of the `cpuset` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/cpusets.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt) -use std::path::PathBuf; -use std::io::{Read, Write}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, CpuResources, Resources, Controller, ControllIdentifier, Subsystem, Controllers}; use CgroupError::*; +use { + CgroupError, ControllIdentifier, Controller, Controllers, CpuResources, Resources, Subsystem, +}; /// A controller that allows controlling the `cpuset` subsystem of a Cgroup. -/// +/// /// In essence, this controller is responsible for restricting the tasks in the control group to a /// set of CPUs and/or memory nodes. #[derive(Debug, Clone)] @@ -50,11 +52,11 @@ pub struct CpuSet { /// the memory pressure for control groups or not. pub memory_pressure_enabled: Option, /// If true, filesystem buffers are spread across evenly between the nodes specified in `mems`. - pub memory_spread_page: bool, + pub memory_spread_page: bool, /// If true, kernel slab caches for file I/O are spread across evenly between the nodes /// specified in `mems`. - pub memory_spread_slab: bool, - /// The list of memory nodes the tasks of the control group can use. + pub memory_spread_slab: bool, + /// The list of memory nodes the tasks of the control group can use. /// /// The format is the same as the `cpus`, `effective_cpus` and `effective_mems` fields. pub mems: Vec<(u64, u64)>, @@ -73,14 +75,21 @@ pub struct CpuSet { /// | 5 | Immediately balance the load between CPUs even if the system is NUMA | /// | 6 | Immediately balance the load between all CPUs | pub sched_relax_domain_level: u64, - } impl Controller for CpuSetController { - fn control_type(&self) -> Controllers { Controllers::CpuSet } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::CpuSet + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -109,7 +118,7 @@ impl<'a> From<&'a Subsystem> for &'a CpuSetController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -184,13 +193,16 @@ impl CpuSetController { pub fn cpuset(&self) -> CpuSet { CpuSet { cpu_exclusive: { - self.open_path("cpuset.cpu_exclusive", false).and_then(|file| { - read_u64_from(file) - }).map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.cpu_exclusive", false) + .and_then(|file| read_u64_from(file)) + .map(|x| x == 1) + .unwrap_or(false) }, cpus: { - self.open_path("cpuset.cpus", false).and_then(read_string_from) - .and_then(parse_range).unwrap_or(Vec::new()) + self.open_path("cpuset.cpus", false) + .and_then(read_string_from) + .and_then(parse_range) + .unwrap_or(Vec::new()) }, effective_cpus: { self.open_path("cpuset.effective_cpus", false) @@ -205,31 +217,45 @@ impl CpuSetController { .unwrap_or(Vec::new()) }, mem_exclusive: { - self.open_path("cpuset.mem_exclusive", false).and_then(read_u64_from) - .map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.mem_exclusive", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .unwrap_or(false) }, mem_hardwall: { - self.open_path("cpuset.mem_hardwall", false).and_then(read_u64_from) - .map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.mem_hardwall", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .unwrap_or(false) }, memory_migrate: { - self.open_path("cpuset.memory_migrate", false).and_then(read_u64_from) - .map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.memory_migrate", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .unwrap_or(false) }, memory_pressure: { - self.open_path("cpuset.memory_pressure", false).and_then(read_u64_from).unwrap_or(0) + self.open_path("cpuset.memory_pressure", false) + .and_then(read_u64_from) + .unwrap_or(0) }, memory_pressure_enabled: { - self.open_path("cpuset.memory_pressure_enabled", false).and_then(read_u64_from) - .map(|x| x == 1).ok() + self.open_path("cpuset.memory_pressure_enabled", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .ok() }, memory_spread_page: { - self.open_path("cpuset.memory_spread_page", false).and_then(read_u64_from) - .map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.memory_spread_page", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .unwrap_or(false) }, memory_spread_slab: { - self.open_path("cpuset.memory_spread_slab", false).and_then(read_u64_from) - .map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.memory_spread_slab", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .unwrap_or(false) }, mems: { self.open_path("cpuset.mems", false) @@ -238,11 +264,14 @@ impl CpuSetController { .unwrap_or(Vec::new()) }, sched_load_balance: { - self.open_path("cpuset.sched_load_balance", false).and_then(read_u64_from) - .map(|x| x == 1).unwrap_or(false) + self.open_path("cpuset.sched_load_balance", false) + .and_then(read_u64_from) + .map(|x| x == 1) + .unwrap_or(false) }, sched_relax_domain_level: { - self.open_path("cpuset.sched_relax_domain_level", false).and_then(read_u64_from) + self.open_path("cpuset.sched_relax_domain_level", false) + .and_then(read_u64_from) .unwrap_or(0) }, } @@ -251,25 +280,27 @@ impl CpuSetController { /// Control whether the CPUs selected via `set_cpus()` should be exclusive to this control /// group or not. pub fn set_cpu_exclusive(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.cpu_exclusive", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.cpu_exclusive", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Control whether the memory nodes selected via `set_memss()` should be exclusive to this control /// group or not. pub fn set_mem_exclusive(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.mem_exclusive", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.mem_exclusive", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Set the CPUs that the tasks in this control group can run on. @@ -278,7 +309,8 @@ impl CpuSetController { /// be represented via dashes. pub fn set_cpus(&self, cpus: &String) -> Result<(), CgroupError> { self.open_path("cpuset.cpus", true).and_then(|mut file| { - file.write_all(cpus.as_ref()).map_err(CgroupError::WriteError) + file.write_all(cpus.as_ref()) + .map_err(CgroupError::WriteError) }) } @@ -287,7 +319,8 @@ impl CpuSetController { /// Syntax is the same as with `set_cpus()`. pub fn set_mems(&self, mems: &String) -> Result<(), CgroupError> { self.open_path("cpuset.mems", true).and_then(|mut file| { - file.write_all(mems.as_ref()).map_err(CgroupError::WriteError) + file.write_all(mems.as_ref()) + .map_err(CgroupError::WriteError) }) } @@ -297,70 +330,77 @@ impl CpuSetController { /// Note that some kernel allocations, most notably those that are made in interrupt handlers /// may disregard this. pub fn set_hardwall(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.mem_hardwall", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.mem_hardwall", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Controls whether the kernel should attempt to rebalance the load between the CPUs specified in the /// `cpus` field of this control group. pub fn set_load_balancing(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.sched_load_balance", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.sched_load_balance", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Contorl how much effort the kernel should invest in rebalacing the control group. /// /// See @CpuSet 's similar field for more information. pub fn set_rebalance_relax_domain_level(&self, i: i64) -> Result<(), CgroupError> { - self.open_path("cpuset.sched_relax_domain_level", true).and_then(|mut file| { - file.write_all(i.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("cpuset.sched_relax_domain_level", true) + .and_then(|mut file| { + file.write_all(i.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Control whether when using `set_mems()` the existing memory used by the tasks should be /// migrated over to the now-selected nodes. pub fn set_memory_migration(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.memory_migrate", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.memory_migrate", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Control whether filesystem buffers should be evenly split across the nodes selected via /// `set_mems()`. pub fn set_memory_spread_page(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.memory_spread_page", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.memory_spread_page", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Control whether the kernel's slab cache for file I/O should be evenly split across the /// nodes selected via `set_mems()`. pub fn set_memory_spread_slab(&self, b: bool) -> Result<(), CgroupError> { - self.open_path("cpuset.memory_spread_slab", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.memory_spread_slab", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } /// Control whether the kernel should collect information to calculate memory pressure for @@ -372,13 +412,14 @@ impl CpuSetController { if !self.path_exists("cpuset.memory_pressure_enabled") { return Err(CgroupError::InvalidOperation); } - self.open_path("cpuset.memory_pressure_enabled", true).and_then(|mut file| { - if b { - file.write_all(b"1").map_err(CgroupError::WriteError) - } else { - file.write_all(b"0").map_err(CgroupError::WriteError) - } - }) + self.open_path("cpuset.memory_pressure_enabled", true) + .and_then(|mut file| { + if b { + file.write_all(b"1").map_err(CgroupError::WriteError) + } else { + file.write_all(b"0").map_err(CgroupError::WriteError) + } + }) } } @@ -387,20 +428,22 @@ mod tests { use cpuset; #[test] fn test_parse_range() { - let test_cases = vec!["1,2,4-6,9".to_string(), - "".to_string(), - "1".to_string(), - "1-111".to_string(), - "1,2,3,4".to_string(), - "1-5,6-7,8-9".to_string() - ]; - let expecteds = vec![vec![(1, 1), (2, 2), (4, 6), (9, 9)], - vec![], - vec![(1, 1)], - vec![(1, 111)], - vec![(1, 1), (2, 2), (3, 3), (4, 4)], - vec![(1, 5), (6, 7), (8, 9)] - ]; + let test_cases = vec![ + "1,2,4-6,9".to_string(), + "".to_string(), + "1".to_string(), + "1-111".to_string(), + "1,2,3,4".to_string(), + "1-5,6-7,8-9".to_string(), + ]; + let expecteds = vec![ + vec![(1, 1), (2, 2), (4, 6), (9, 9)], + vec![], + vec![(1, 1)], + vec![(1, 111)], + vec![(1, 1), (2, 2), (3, 3), (4, 4)], + vec![(1, 5), (6, 7), (8, 9)], + ]; for (i, case) in test_cases.into_iter().enumerate() { let range = cpuset::parse_range(case.clone()); diff --git a/src/devices.rs b/src/devices.rs index e15fed0..341a0ae 100644 --- a/src/devices.rs +++ b/src/devices.rs @@ -1,18 +1,21 @@ //! This module contains the implementation of the `devices` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/devices.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/devices.txt) -use std::path::PathBuf; use std::io::{Read, Write}; +use std::path::PathBuf; -use {DeviceResource, CgroupError, DeviceResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; +use { + CgroupError, ControllIdentifier, Controller, Controllers, DeviceResource, DeviceResources, + Resources, Subsystem, +}; /// A controller that allows controlling the `devices` subsystem of a Cgroup. /// /// In essence, using the devices controller, it is possible to allow or disallow sets of devices to /// be used by the control group's tasks. #[derive(Debug, Clone)] -pub struct DevicesController{ +pub struct DevicesController { base: PathBuf, path: PathBuf, } @@ -29,7 +32,9 @@ pub enum DeviceType { } impl Default for DeviceType { - fn default() -> Self { DeviceType::All } + fn default() -> Self { + DeviceType::All + } } impl DeviceType { @@ -124,10 +129,18 @@ impl DevicePermissions { } impl Controller for DevicesController { - fn control_type(&self) -> Controllers { Controllers::Devices } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::Devices + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -161,7 +174,7 @@ impl<'a> From<&'a Subsystem> for &'a DevicesController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -182,13 +195,31 @@ impl DevicesController { /// /// When `-1` is passed as `major` or `minor`, the kernel interprets that value as "any", /// meaning that it will match any device. - pub fn allow_device(&self, devtype: DeviceType, major: i64, minor: i64, perm: &Vec) -> Result<(), CgroupError> { - let perms = perm.iter().map(DevicePermissions::to_char).collect::(); - let minor = if minor == -1 { "*".to_string() } else { format!("{}", minor) }; - let major = if major == -1 { "*".to_string() } else { format!("{}", major) }; + pub fn allow_device( + &self, + devtype: DeviceType, + major: i64, + minor: i64, + perm: &Vec, + ) -> Result<(), CgroupError> { + let perms = perm + .iter() + .map(DevicePermissions::to_char) + .collect::(); + let minor = if minor == -1 { + "*".to_string() + } else { + format!("{}", minor) + }; + let major = if major == -1 { + "*".to_string() + } else { + format!("{}", major) + }; let final_str = format!("{} {}:{} {}", devtype.to_char(), major, minor, perms); self.open_path("devices.allow", true).and_then(|mut file| { - file.write_all(final_str.as_ref()).map_err(CgroupError::WriteError) + file.write_all(final_str.as_ref()) + .map_err(CgroupError::WriteError) }) } @@ -196,13 +227,31 @@ impl DevicesController { /// /// When `-1` is passed as `major` or `minor`, the kernel interprets that value as "any", /// meaning that it will match any device. - pub fn deny_device(&self, devtype: DeviceType, major: i64, minor: i64, perm: &Vec) -> Result<(), CgroupError> { - let perms = perm.iter().map(DevicePermissions::to_char).collect::(); - let minor = if minor == -1 { "*".to_string() } else { format!("{}", minor) }; - let major = if major == -1 { "*".to_string() } else { format!("{}", major) }; + pub fn deny_device( + &self, + devtype: DeviceType, + major: i64, + minor: i64, + perm: &Vec, + ) -> Result<(), CgroupError> { + let perms = perm + .iter() + .map(DevicePermissions::to_char) + .collect::(); + let minor = if minor == -1 { + "*".to_string() + } else { + format!("{}", minor) + }; + let major = if major == -1 { + "*".to_string() + } else { + format!("{}", major) + }; let final_str = format!("{} {}:{} {}", devtype.to_char(), major, minor, perms); self.open_path("devices.deny", true).and_then(|mut file| { - file.write_all(final_str.as_ref()).map_err(CgroupError::WriteError) + file.write_all(final_str.as_ref()) + .map_err(CgroupError::WriteError) }) } diff --git a/src/freezer.rs b/src/freezer.rs index 44725c3..3e4556a 100644 --- a/src/freezer.rs +++ b/src/freezer.rs @@ -1,11 +1,11 @@ //! This module contains the implementation of the `freezer` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/freezer-subsystem.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/freezer-subsystem.txt) -use std::path::PathBuf; use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; +use {CgroupError, ControllIdentifier, Controller, Controllers, Resources, Subsystem}; /// A controller that allows controlling the `freezer` subsystem of a Cgroup. /// @@ -16,7 +16,7 @@ use {CgroupError, Controllers, Controller, Resources, ControllIdentifier, Subsys /// Note that if the control group is currently in the `Frozen` or `Freezing` state, then no /// processes can be added to it. #[derive(Debug, Clone)] -pub struct FreezerController{ +pub struct FreezerController { base: PathBuf, path: PathBuf, } @@ -32,10 +32,18 @@ pub enum FreezerState { } impl Controller for FreezerController { - fn control_type(&self) -> Controllers { Controllers::Freezer } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::Freezer + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, _res: &Resources) -> Result<(), CgroupError> { Ok(()) @@ -56,7 +64,7 @@ impl<'a> From<&'a Subsystem> for &'a FreezerController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -76,14 +84,16 @@ impl FreezerController { /// Freezes the processes in the control group. pub fn freeze(&self) -> Result<(), CgroupError> { self.open_path("freezer.state", true).and_then(|mut file| { - file.write_all("FROZEN".to_string().as_ref()).map_err(CgroupError::WriteError) + file.write_all("FROZEN".to_string().as_ref()) + .map_err(CgroupError::WriteError) }) } /// Thaws, that is, unfreezes the processes in the control group. pub fn thaw(&self) -> Result<(), CgroupError> { self.open_path("freezer.state", true).and_then(|mut file| { - file.write_all("THAWED".to_string().as_ref()).map_err(CgroupError::WriteError) + file.write_all("THAWED".to_string().as_ref()) + .map_err(CgroupError::WriteError) }) } diff --git a/src/hierarchies.rs b/src/hierarchies.rs index 3f305db..9f3ebcd 100644 --- a/src/hierarchies.rs +++ b/src/hierarchies.rs @@ -3,28 +3,27 @@ //! Currently, we only support the cgroupv1 hierarchy, but in the future we will add support for //! the Unified Hierarchy. +use std::fs::File; use std::io::BufRead; use std::io::BufReader; -use std::fs::File; use std::path::{Path, PathBuf}; +use blkio::BlkIoController; +use cpu::CpuController; +use cpuacct::CpuAcctController; +use cpuset::CpuSetController; +use devices::DevicesController; +use freezer::FreezerController; +use hugetlb::HugeTlbController; +use memory::MemController; +use net_cls::NetClsController; +use net_prio::NetPrioController; +use perf_event::PerfEventController; +use pid::PidController; +use rdma::RdmaController; use {Controllers, Hierarchy, Subsystem}; -use ::pid::PidController; -use ::memory::MemController; -use ::cpuset::CpuSetController; -use ::cpuacct::CpuAcctController; -use ::cpu::CpuController; -use ::freezer::FreezerController; -use ::devices::DevicesController; -use ::net_cls::NetClsController; -use ::blkio::BlkIoController; -use ::perf_event::PerfEventController; -use ::net_prio::NetPrioController; -use ::hugetlb::HugeTlbController; -use ::rdma::RdmaController; - -use ::cgroup::Cgroup; +use cgroup::Cgroup; /// The standard, original cgroup implementation. Often referred to as "cgroupv1". pub struct V1 { diff --git a/src/hugetlb.rs b/src/hugetlb.rs index db63844..6411205 100644 --- a/src/hugetlb.rs +++ b/src/hugetlb.rs @@ -1,14 +1,16 @@ //! This module contains the implementation of the `hugetlb` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/hugetlb.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt) -use std::path::PathBuf; use std::fs::File; -use std::io::{Write, Read}; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, HugePageResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; use CgroupError::*; - +use { + CgroupError, ControllIdentifier, Controller, Controllers, HugePageResources, Resources, + Subsystem, +}; /// A controller that allows controlling the `hugetlb` subsystem of a Cgroup. /// @@ -21,10 +23,18 @@ pub struct HugeTlbController { } impl Controller for HugeTlbController { - fn control_type(&self) -> Controllers { Controllers::HugeTlb } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::HugeTlb + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -56,7 +66,7 @@ impl<'a> From<&'a Subsystem> for &'a HugeTlbController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -110,8 +120,10 @@ impl HugeTlbController { /// Get the maximum observed usage of memory that is backed by hugepages of a certain size /// (`hugetlb_size`). pub fn max_usage_in_bytes(&self, hugetlb_size: &String) -> Result { - self.open_path(&format!("hugetlb.{}.max_usage_in_bytes", hugetlb_size), false) - .and_then(read_u64_from) + self.open_path( + &format!("hugetlb.{}.max_usage_in_bytes", hugetlb_size), + false, + ).and_then(read_u64_from) } /// Set the limit (in bytes) of how much memory can be backed by hugepages of a certain size @@ -119,7 +131,8 @@ impl HugeTlbController { pub fn set_limit_in_bytes(&self, hugetlb_size: &String, limit: u64) -> Result<(), CgroupError> { self.open_path(&format!("hugetlb.{}.limit_in_bytes", hugetlb_size), false) .and_then(|mut file| { - file.write_all(limit.to_string().as_ref()).map_err(CgroupError::WriteError) + file.write_all(limit.to_string().as_ref()) + .map_err(CgroupError::WriteError) }) } } diff --git a/src/lib.rs b/src/lib.rs index 35cb6a5..47c5f68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,35 +1,35 @@ -use std::path::PathBuf; use std::fs::File; use std::io::{BufRead, BufReader, Write}; +use std::path::PathBuf; -pub mod hierarchies; -pub mod pid; -pub mod memory; -pub mod cpuset; -pub mod cpuacct; -pub mod cpu; -pub mod devices; -pub mod cgroup; -pub mod freezer; -pub mod net_cls; pub mod blkio; -pub mod perf_event; -pub mod net_prio; +pub mod cgroup; +pub mod cpu; +pub mod cpuacct; +pub mod cpuset; +pub mod devices; +pub mod freezer; +pub mod hierarchies; pub mod hugetlb; +pub mod memory; +pub mod net_cls; +pub mod net_prio; +pub mod perf_event; +pub mod pid; pub mod rdma; -use pid::PidController; -use memory::MemController; -use cpuset::CpuSetController; -use cpuacct::CpuAcctController; -use cpu::CpuController; -use freezer::FreezerController; -use devices::DevicesController; -use net_cls::NetClsController; use blkio::BlkIoController; -use perf_event::PerfEventController; -use net_prio::NetPrioController; +use cpu::CpuController; +use cpuacct::CpuAcctController; +use cpuset::CpuSetController; +use devices::DevicesController; +use freezer::FreezerController; use hugetlb::HugeTlbController; +use memory::MemController; +use net_cls::NetClsController; +use net_prio::NetPrioController; +use perf_event::PerfEventController; +use pid::PidController; use rdma::RdmaController; pub use cgroup::Cgroup; @@ -95,22 +95,34 @@ impl PartialEq for CgroupError { match self { CgroupError::WriteError(_) => if let CgroupError::WriteError(_) = other { return true; - } else { return false }, + } else { + return false; + }, CgroupError::ReadError(_) => if let CgroupError::ReadError(_) = other { return true; - } else { return false }, + } else { + return false; + }, CgroupError::ParseError => if let CgroupError::ParseError = other { return true; - } else { return false }, + } else { + return false; + }, CgroupError::InvalidOperation => if let CgroupError::InvalidOperation = other { return true; - } else { return false }, + } else { + return false; + }, CgroupError::InvalidPath => if let CgroupError::InvalidPath = other { return true; - } else { return false }, + } else { + return false; + }, CgroupError::Unknown => if let CgroupError::Unknown = other { return true; - } else { return false }, + } else { + return false; + }, } } } @@ -232,23 +244,25 @@ pub trait Controller { /// Attach a task to this controller. fn add_task(&self, pid: &CgroupPid) -> Result<(), CgroupError> { self.open_path("tasks", true).and_then(|mut file| { - file.write_all(pid.pid.to_string().as_ref()).map_err(CgroupError::WriteError) + file.write_all(pid.pid.to_string().as_ref()) + .map_err(CgroupError::WriteError) }) } /// Get the list of tasks that this controller has. fn tasks(&self) -> Vec { - self.open_path("tasks", false).and_then(|file| { - let bf = BufReader::new(file); - let mut v = Vec::new(); - for line in bf.lines() { - if let Ok(line) = line { - let n = line.trim().parse().unwrap_or(0u64); - v.push(n); + self.open_path("tasks", false) + .and_then(|file| { + let bf = BufReader::new(file); + let mut v = Vec::new(); + for line in bf.lines() { + if let Ok(line) = line { + let n = line.trim().parse().unwrap_or(0u64); + v.push(n); + } } - } - Ok(v.into_iter().map(CgroupPid::from).collect()) - }).unwrap_or(vec![]) + Ok(v.into_iter().map(CgroupPid::from).collect()) + }).unwrap_or(vec![]) } } @@ -479,21 +493,16 @@ pub struct CgroupPid { impl From for CgroupPid { fn from(u: u64) -> CgroupPid { - CgroupPid { - pid: u, - } + CgroupPid { pid: u } } } impl<'a> From<&'a std::process::Child> for CgroupPid { fn from(u: &std::process::Child) -> CgroupPid { - CgroupPid { - pid: u.id() as u64, - } + CgroupPid { pid: u.id() as u64 } } } - impl Subsystem { fn enter(self, path: &String) -> Self { match self { diff --git a/src/memory.rs b/src/memory.rs index 3aae959..13d9a2b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,13 +1,15 @@ //! This module contains the implementation of the `memory` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/memory.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt) -use std::path::PathBuf; -use std::io::{Write, Read}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, Resources, MemoryResources, Controller, Controllers, Subsystem, ControllIdentifier}; use CgroupError::*; +use { + CgroupError, ControllIdentifier, Controller, Controllers, MemoryResources, Resources, Subsystem, +}; /// A controller that allows controlling the `memory` subsystem of a Cgroup. /// @@ -15,7 +17,7 @@ use CgroupError::*; /// of the tasks in the control group. Additonally, one can also set powerful limits on their /// memory usage. #[derive(Debug, Clone)] -pub struct MemController{ +pub struct MemController { base: PathBuf, path: PathBuf, } @@ -83,55 +85,127 @@ fn parse_numa_stat(s: String) -> Result { // Parse the number of nodes let nodes = (s.split_whitespace().collect::>().len() - 8) / 8; let mut ls = s.lines(); - let total_line = ls.next().unwrap(); - let file_line = ls.next().unwrap(); - let anon_line = ls.next().unwrap(); + let total_line = ls.next().unwrap(); + let file_line = ls.next().unwrap(); + let anon_line = ls.next().unwrap(); let unevict_line = ls.next().unwrap(); - let hier_total_line = ls.next().unwrap(); - let hier_file_line = ls.next().unwrap(); - let hier_anon_line = ls.next().unwrap(); + let hier_total_line = ls.next().unwrap(); + let hier_file_line = ls.next().unwrap(); + let hier_anon_line = ls.next().unwrap(); let hier_unevict_line = ls.next().unwrap(); Ok(NumaStat { - total_pages: total_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + total_pages: total_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), total_pages_per_node: { let spl = &total_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - file_pages: file_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + file_pages: file_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), file_pages_per_node: { let spl = &file_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - anon_pages: anon_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + anon_pages: anon_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), anon_pages_per_node: { let spl = &anon_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - unevictable_pages: unevict_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + unevictable_pages: unevict_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), unevictable_pages_per_node: { let spl = &unevict_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - hierarchical_total_pages: hier_total_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_total_pages: hier_total_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), hierarchical_total_pages_per_node: { let spl = &hier_total_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - hierarchical_file_pages: hier_file_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_file_pages: hier_file_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), hierarchical_file_pages_per_node: { let spl = &hier_file_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - hierarchical_anon_pages: hier_anon_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_anon_pages: hier_anon_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), hierarchical_anon_pages_per_node: { let spl = &hier_anon_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, - hierarchical_unevictable_pages: hier_unevict_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_unevictable_pages: hier_unevict_line + .split(|x| x == ' ' || x == '=') + .collect::>()[1] + .parse::() + .unwrap_or(0), hierarchical_unevictable_pages_per_node: { let spl = &hier_unevict_line.split(" ").collect::>()[1..]; - spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + spl.iter() + .map(|x| { + x.split("=").collect::>()[1] + .parse::() + .unwrap_or(0) + }).collect() }, }) } @@ -177,9 +251,10 @@ pub struct MemoryStat { } fn parse_memory_stat(s: String) -> Result { - let sp: Vec<&str> = s.split_whitespace() - .filter(|x| x.parse::().is_ok()) - .collect(); + let sp: Vec<&str> = s + .split_whitespace() + .filter(|x| x.parse::().is_ok()) + .collect(); let mut spl = sp.iter(); Ok(MemoryStat { @@ -317,10 +392,18 @@ pub struct Kmem { } impl Controller for MemController { - fn control_type(&self) -> Controllers { Controllers::Mem } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::Mem + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -357,53 +440,79 @@ impl MemController { /// kernel Documentation and/or sources. pub fn memory_stat(&self) -> Memory { Memory { - fail_cnt: self.open_path("memory.failcnt", false) - .and_then(read_u64_from).unwrap_or(0), - limit_in_bytes: self.open_path("memory.limit_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - usage_in_bytes: self.open_path("memory.usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - max_usage_in_bytes: self.open_path("memory.max_usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - move_charge_at_immigrate: self.open_path("memory.move_charge_at_immigrate", false) - .and_then(read_u64_from).unwrap_or(0), - numa_stat: self.open_path("memory.numa_stat", false) - .and_then(read_string_from) - .and_then(parse_numa_stat) - .unwrap_or(NumaStat::default()), - oom_control: self.open_path("memory.oom_control", false) - .and_then(read_string_from) - .and_then(parse_oom_control) - .unwrap_or(OomControl::default()), - soft_limit_in_bytes: self.open_path("memory.soft_limit_in_bytes", false) - .and_then(read_u64_from) - .unwrap_or(0), - stat: self.open_path("memory.stat", false) - .and_then(read_string_from) - .and_then(parse_memory_stat) - .unwrap_or(MemoryStat::default()), - swappiness: self.open_path("memory.swappiness", false) - .and_then(read_u64_from) - .unwrap_or(0), - use_hierarchy: self.open_path("memory.use_hierarchy", false) - .and_then(read_u64_from) - .unwrap_or(0) + fail_cnt: self + .open_path("memory.failcnt", false) + .and_then(read_u64_from) + .unwrap_or(0), + limit_in_bytes: self + .open_path("memory.limit_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + usage_in_bytes: self + .open_path("memory.usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + max_usage_in_bytes: self + .open_path("memory.max_usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + move_charge_at_immigrate: self + .open_path("memory.move_charge_at_immigrate", false) + .and_then(read_u64_from) + .unwrap_or(0), + numa_stat: self + .open_path("memory.numa_stat", false) + .and_then(read_string_from) + .and_then(parse_numa_stat) + .unwrap_or(NumaStat::default()), + oom_control: self + .open_path("memory.oom_control", false) + .and_then(read_string_from) + .and_then(parse_oom_control) + .unwrap_or(OomControl::default()), + soft_limit_in_bytes: self + .open_path("memory.soft_limit_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + stat: self + .open_path("memory.stat", false) + .and_then(read_string_from) + .and_then(parse_memory_stat) + .unwrap_or(MemoryStat::default()), + swappiness: self + .open_path("memory.swappiness", false) + .and_then(read_u64_from) + .unwrap_or(0), + use_hierarchy: self + .open_path("memory.use_hierarchy", false) + .and_then(read_u64_from) + .unwrap_or(0), } } /// Gathers information about the kernel memory usage of the control group's tasks. pub fn kmem_stat(&self) -> Kmem { Kmem { - fail_cnt: self.open_path("memory.kmem.failcnt", false) - .and_then(read_u64_from).unwrap_or(0), - limit_in_bytes: self.open_path("memory.kmem.limit_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - usage_in_bytes: self.open_path("memory.kmem.usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - max_usage_in_bytes: self.open_path("memory.kmem.max_usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - slabinfo: self.open_path("memory.kmem.slabinfo", false) - .and_then(read_string_from).unwrap_or("".to_string()), + fail_cnt: self + .open_path("memory.kmem.failcnt", false) + .and_then(read_u64_from) + .unwrap_or(0), + limit_in_bytes: self + .open_path("memory.kmem.limit_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + usage_in_bytes: self + .open_path("memory.kmem.usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + max_usage_in_bytes: self + .open_path("memory.kmem.max_usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + slabinfo: self + .open_path("memory.kmem.slabinfo", false) + .and_then(read_string_from) + .unwrap_or("".to_string()), } } @@ -411,14 +520,22 @@ impl MemController { /// TCP-related. pub fn kmem_tcp_stat(&self) -> Tcp { Tcp { - fail_cnt: self.open_path("memory.kmem.tcp.failcnt", false) - .and_then(read_u64_from).unwrap_or(0), - limit_in_bytes: self.open_path("memory.kmem.tcp.limit_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - usage_in_bytes: self.open_path("memory.kmem.tcp.usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - max_usage_in_bytes: self.open_path("memory.kmem.tcp.max_usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), + fail_cnt: self + .open_path("memory.kmem.tcp.failcnt", false) + .and_then(read_u64_from) + .unwrap_or(0), + limit_in_bytes: self + .open_path("memory.kmem.tcp.limit_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + usage_in_bytes: self + .open_path("memory.kmem.tcp.usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + max_usage_in_bytes: self + .open_path("memory.kmem.tcp.max_usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), } } @@ -426,65 +543,83 @@ impl MemController { /// (if any). pub fn memswap(&self) -> MemSwap { MemSwap { - fail_cnt: self.open_path("memory.memsw.failcnt", false) - .and_then(read_u64_from).unwrap_or(0), - limit_in_bytes: self.open_path("memory.memsw.limit_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - usage_in_bytes: self.open_path("memory.memsw.usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), - max_usage_in_bytes: self.open_path("memory.memsw.max_usage_in_bytes", false) - .and_then(read_u64_from).unwrap_or(0), + fail_cnt: self + .open_path("memory.memsw.failcnt", false) + .and_then(read_u64_from) + .unwrap_or(0), + limit_in_bytes: self + .open_path("memory.memsw.limit_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + usage_in_bytes: self + .open_path("memory.memsw.usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), + max_usage_in_bytes: self + .open_path("memory.memsw.max_usage_in_bytes", false) + .and_then(read_u64_from) + .unwrap_or(0), } } /// Set the memory usage limit of the control group, in bytes. pub fn set_limit(&self, limit: u64) -> Result<(), CgroupError> { - self.open_path("memory.limit_in_bytes", true).and_then(|mut file| { - file.write_all(limit.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("memory.limit_in_bytes", true) + .and_then(|mut file| { + file.write_all(limit.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Set the kernel memory limit of the control group, in bytes. pub fn set_kmem_limit(&self, limit: u64) -> Result<(), CgroupError> { - self.open_path("memory.kmem.limit_in_bytes", true).and_then(|mut file| { - file.write_all(limit.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("memory.kmem.limit_in_bytes", true) + .and_then(|mut file| { + file.write_all(limit.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Set the memory+swap limit of the control group, in bytes. pub fn set_memswap_limit(&self, limit: u64) -> Result<(), CgroupError> { - self.open_path("memory.memsw.limit_in_bytes", true).and_then(|mut file| { - file.write_all(limit.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("memory.memsw.limit_in_bytes", true) + .and_then(|mut file| { + file.write_all(limit.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } /// Set how much kernel memory can be used for TCP-related buffers by the control group. pub fn set_tcp_limit(&self, limit: u64) -> Result<(), CgroupError> { - self.open_path("memory.kmem.tcp.limit_in_bytes", true).and_then(|mut file| { - file.write_all(limit.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("memory.kmem.tcp.limit_in_bytes", true) + .and_then(|mut file| { + file.write_all(limit.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } - /// Set the soft limit of the control group, in bytes. /// /// This limit is enforced when the system is nearing OOM conditions. Contrast this with the /// hard limit, which is _always_ enforced. pub fn set_soft_limit(&self, limit: u64) -> Result<(), CgroupError> { - self.open_path("memory.soft_limit_in_bytes", true).and_then(|mut file| { - file.write_all(limit.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("memory.soft_limit_in_bytes", true) + .and_then(|mut file| { + file.write_all(limit.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } - /// Set how likely the kernel is to swap out parts of the address space used by the control /// group. /// /// Note that a value of zero does not imply that the process will not be swapped out. pub fn set_swappiness(&self, swp: u64) -> Result<(), CgroupError> { - self.open_path("memory.swappiness", true).and_then(|mut file| { - file.write_all(swp.to_string().as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("memory.swappiness", true) + .and_then(|mut file| { + file.write_all(swp.to_string().as_ref()) + .map_err(CgroupError::WriteError) + }) } } @@ -502,7 +637,7 @@ impl<'a> From<&'a Subsystem> for &'a MemController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -526,7 +661,9 @@ fn read_string_from(mut file: File) -> Result { #[cfg(test)] mod tests { - use memory::{MemoryStat, parse_memory_stat, NumaStat, parse_oom_control, OomControl, parse_numa_stat}; + use memory::{ + parse_memory_stat, parse_numa_stat, parse_oom_control, MemoryStat, NumaStat, OomControl, + }; const good_value: &str = "\ total=51189 N0=51189 N1=123 file=50175 N0=50175 N1=123 @@ -585,7 +722,8 @@ total_unevictable 81920 #[test] fn test_parse_numa_stat() { - assert_eq!(parse_numa_stat(good_value.to_string()), + assert_eq!( + parse_numa_stat(good_value.to_string()), Ok(NumaStat { total_pages: 51189, total_pages_per_node: vec![51189, 123], @@ -604,22 +742,26 @@ total_unevictable 81920 hierarchical_anon_pages_per_node: vec![770402, 123], hierarchical_unevictable_pages: 20, hierarchical_unevictable_pages_per_node: vec![20, 123], - })); + }) + ); } #[test] fn test_parse_oom_control() { - assert_eq!(parse_oom_control(good_oomcontrol_val.to_string()), - Ok(OomControl { - oom_kill_disable: false, - under_oom: true, - oom_kill: 1337, - })); + assert_eq!( + parse_oom_control(good_oomcontrol_val.to_string()), + Ok(OomControl { + oom_kill_disable: false, + under_oom: true, + oom_kill: 1337, + }) + ); } #[test] fn test_parse_memory_stat() { - assert_eq!(parse_memory_stat(good_memorystat_val.to_string()), + assert_eq!( + parse_memory_stat(good_memorystat_val.to_string()), Ok(MemoryStat { cache: 178880512, rss: 4206592, @@ -657,6 +799,7 @@ total_unevictable 81920 total_inactive_file: 1272135680, total_active_file: 2338816000, total_unevictable: 81920, - })); + }) + ); } } diff --git a/src/net_cls.rs b/src/net_cls.rs index 0f9ef38..2b9234a 100644 --- a/src/net_cls.rs +++ b/src/net_cls.rs @@ -1,13 +1,16 @@ //! This module contains the implementation of the `net_cls` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/net_cls.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.txt) -use std::path::PathBuf; -use std::io::{Read, Write}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, NetworkResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; use CgroupError::*; +use { + CgroupError, ControllIdentifier, Controller, Controllers, NetworkResources, Resources, + Subsystem, +}; /// A controller that allows controlling the `net_cls` subsystem of a Cgroup. /// @@ -21,10 +24,18 @@ pub struct NetClsController { } impl Controller for NetClsController { - fn control_type(&self) -> Controllers { Controllers::NetCls } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::NetCls + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -54,7 +65,7 @@ impl<'a> From<&'a Subsystem> for &'a NetClsController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -78,19 +89,19 @@ impl NetClsController { path: root, } } - + /// Set the network class id of the outgoing packets of the control group's tasks. pub fn set_class(&self, class: u64) -> Result<(), CgroupError> { - self.open_path("net_cls.classid", true).and_then(|mut file| { - let s = format!("{:#08X}", class); - file.write_all(s.as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("net_cls.classid", true) + .and_then(|mut file| { + let s = format!("{:#08X}", class); + file.write_all(s.as_ref()).map_err(CgroupError::WriteError) + }) } /// Get the network class id of the outgoing packets of the control group's tasks. pub fn get_class(&self) -> Result { - self.open_path("net_cls.classid", false).and_then(|file| { - read_u64_from(file) - }) + self.open_path("net_cls.classid", false) + .and_then(|file| read_u64_from(file)) } } diff --git a/src/net_prio.rs b/src/net_prio.rs index 9b16962..2d126da 100644 --- a/src/net_prio.rs +++ b/src/net_prio.rs @@ -1,14 +1,17 @@ //! This module contains the implementation of the `net_prio` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/net_prio.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/net_prio.txt) -use std::path::PathBuf; -use std::io::{BufReader, BufRead, Write, Read}; -use std::fs::File; use std::collections::HashMap; +use std::fs::File; +use std::io::{BufRead, BufReader, Read, Write}; +use std::path::PathBuf; -use {CgroupError, NetworkResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; use CgroupError::*; +use { + CgroupError, ControllIdentifier, Controller, Controllers, NetworkResources, Resources, + Subsystem, +}; /// A controller that allows controlling the `net_prio` subsystem of a Cgroup. /// @@ -22,10 +25,18 @@ pub struct NetPrioController { } impl Controller for NetPrioController { - fn control_type(&self) -> Controllers { Controllers::NetPrio } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::NetPrio + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -55,7 +66,7 @@ impl<'a> From<&'a Subsystem> for &'a NetPrioController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -89,38 +100,41 @@ impl NetPrioController { /// A map of priorities for each network interface. pub fn ifpriomap(&self) -> Result, CgroupError> { - self.open_path("net_prio.ifpriomap", false) .and_then(|file| { - let bf = BufReader::new(file); - bf.lines().fold(Ok(HashMap::new()), |acc, line| { - if acc.is_err() { - acc - } else { - let mut acc = acc.unwrap(); - let l = line.unwrap(); - let mut sp = l.split_whitespace(); - let ifname = sp.nth(0); - let ifprio = sp.nth(1); - if ifname.is_none() || ifprio.is_none() { - Err(CgroupError::ParseError) + self.open_path("net_prio.ifpriomap", false) + .and_then(|file| { + let bf = BufReader::new(file); + bf.lines().fold(Ok(HashMap::new()), |acc, line| { + if acc.is_err() { + acc } else { - let ifname = ifname.unwrap(); - let ifprio = ifprio.unwrap().trim().parse(); - if ifprio.is_err() { + let mut acc = acc.unwrap(); + let l = line.unwrap(); + let mut sp = l.split_whitespace(); + let ifname = sp.nth(0); + let ifprio = sp.nth(1); + if ifname.is_none() || ifprio.is_none() { Err(CgroupError::ParseError) } else { - acc.insert(ifname.to_string(), ifprio.unwrap()); - Ok(acc) + let ifname = ifname.unwrap(); + let ifprio = ifprio.unwrap().trim().parse(); + if ifprio.is_err() { + Err(CgroupError::ParseError) + } else { + acc.insert(ifname.to_string(), ifprio.unwrap()); + Ok(acc) + } } } - } + }) }) - }) } /// Set the priority of the network traffic on `eif` to be `prio`. pub fn set_if_prio(&self, eif: &String, prio: u64) -> Result<(), CgroupError> { - self.open_path("net_prio.ifpriomap", true).and_then(|mut file| { - file.write_all(format!("{} {}", eif, prio).as_ref()).map_err(CgroupError::WriteError) - }) + self.open_path("net_prio.ifpriomap", true) + .and_then(|mut file| { + file.write_all(format!("{} {}", eif, prio).as_ref()) + .map_err(CgroupError::WriteError) + }) } } diff --git a/src/perf_event.rs b/src/perf_event.rs index 78fe793..314dd94 100644 --- a/src/perf_event.rs +++ b/src/perf_event.rs @@ -1,10 +1,10 @@ //! This module contains the implementation of the `perf_event` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [tools/perf/Documentation/perf-record.txt](https://raw.githubusercontent.com/torvalds/linux/master/tools/perf/Documentation/perf-record.txt) use std::path::PathBuf; -use {CgroupError, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; +use {CgroupError, ControllIdentifier, Controller, Controllers, Resources, Subsystem}; /// A controller that allows controlling the `perf_event` subsystem of a Cgroup. /// @@ -17,10 +17,18 @@ pub struct PerfEventController { } impl Controller for PerfEventController { - fn control_type(&self) -> Controllers { Controllers::PerfEvent } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::PerfEvent + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, _res: &Resources) -> Result<(), CgroupError> { Ok(()) @@ -41,7 +49,7 @@ impl<'a> From<&'a Subsystem> for &'a PerfEventController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } diff --git a/src/pid.rs b/src/pid.rs index f535444..3aa21bc 100644 --- a/src/pid.rs +++ b/src/pid.rs @@ -1,13 +1,15 @@ //! This module contains the implementation of the `pids` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroups-v1/pids.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/pids.txt) -use std::path::PathBuf; -use std::io::{Write, Read}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, Resources, PidResources, Controller, ControllIdentifier, Subsystem, Controllers}; use CgroupError::*; +use { + CgroupError, ControllIdentifier, Controller, Controllers, PidResources, Resources, Subsystem, +}; /// A controller that allows controlling the `pids` subsystem of a Cgroup. #[derive(Debug, Clone)] @@ -33,10 +35,18 @@ impl Default for PidMax { } impl Controller for PidController { - fn control_type(&self) -> Controllers { Controllers::Pids } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::Pids + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, res: &Resources) -> Result<(), CgroupError> { /* get the resources that apply to this controller */ @@ -45,7 +55,7 @@ impl Controller for PidController { 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(()); @@ -78,7 +88,7 @@ impl<'a> From<&'a Subsystem> for &'a PidController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -109,14 +119,12 @@ impl PidController { self.open_path("pids.events", false).and_then(|mut file| { let mut string = String::new(); match file.read_to_string(&mut string) { - Ok(_) => { - match string.split_whitespace().nth(1) { - Some(elem) => match elem.parse() { - Ok(val) => Ok(val), - Err(_) => Err(CgroupError::ParseError), - }, - None => Err(CgroupError::ParseError), - } + Ok(_) => match string.split_whitespace().nth(1) { + Some(elem) => match elem.parse() { + Ok(val) => Ok(val), + Err(_) => Err(CgroupError::ParseError), + }, + None => Err(CgroupError::ParseError), }, Err(e) => Err(CgroupError::ReadError(e)), } @@ -125,7 +133,8 @@ impl PidController { /// The number of processes currently. pub fn get_pid_current(&self) -> Result { - self.open_path("pids.current", false).and_then(read_u64_from) + self.open_path("pids.current", false) + .and_then(read_u64_from) } /// The maximum number of processes that can exist at one time in the control group. diff --git a/src/rdma.rs b/src/rdma.rs index b973818..8163164 100644 --- a/src/rdma.rs +++ b/src/rdma.rs @@ -1,12 +1,12 @@ //! This module contains the implementation of the `rdma` cgroup subsystem. -//! +//! //! See the Kernel's documentation for more information about this subsystem, found at: //! [Documentation/cgroup-v1/rdma.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/rdma.txt) -use std::path::PathBuf; -use std::io::{Write, Read}; use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; -use {CgroupError, Controllers, Controller, Resources, ControllIdentifier, Subsystem}; +use {CgroupError, ControllIdentifier, Controller, Controllers, Resources, Subsystem}; /// A controller that allows controlling the `rdma` subsystem of a Cgroup. /// @@ -19,10 +19,18 @@ pub struct RdmaController { } impl Controller for RdmaController { - fn control_type(&self) -> Controllers { Controllers::Rdma } - fn get_path(&self) -> &PathBuf { &self.path } - fn get_path_mut(&mut self) -> &mut PathBuf { &mut self.path } - fn get_base(&self) -> &PathBuf { &self.base } + fn control_type(&self) -> Controllers { + Controllers::Rdma + } + fn get_path(&self) -> &PathBuf { + &self.path + } + fn get_path_mut(&mut self) -> &mut PathBuf { + &mut self.path + } + fn get_base(&self) -> &PathBuf { + &self.base + } fn apply(&self, _res: &Resources) -> Result<(), CgroupError> { Ok(()) @@ -43,7 +51,7 @@ impl<'a> From<&'a Subsystem> for &'a RdmaController { _ => { assert_eq!(1, 0); ::std::mem::uninitialized() - }, + } } } } @@ -77,7 +85,8 @@ impl RdmaController { /// Set a maximum usage for each RDMA/IB resource. pub fn set_max(&self, max: &String) -> Result<(), CgroupError> { self.open_path("rdma.max", true).and_then(|mut file| { - file.write_all(max.as_ref()).map_err(CgroupError::WriteError) + file.write_all(max.as_ref()) + .map_err(CgroupError::WriteError) }) } } diff --git a/tests/cgroup.rs b/tests/cgroup.rs index 413fca7..c11caa9 100644 --- a/tests/cgroup.rs +++ b/tests/cgroup.rs @@ -2,8 +2,8 @@ extern crate cgroups; use cgroups::{Cgroup, CgroupPid}; -extern crate nix; extern crate libc; +extern crate nix; #[test] fn test_tasks_iterator() { @@ -17,7 +17,7 @@ fn test_tasks_iterator() { // Verify that the task is indeed in the control group assert_eq!(tasks.next(), Some(CgroupPid::from(pid))); assert_eq!(tasks.next(), None); - + // Now, try removing it. cg.remove_task(CgroupPid::from(pid)); tasks = cg.tasks().into_iter(); diff --git a/tests/cpuset.rs b/tests/cpuset.rs index 4595b2d..b456415 100644 --- a/tests/cpuset.rs +++ b/tests/cpuset.rs @@ -1,7 +1,7 @@ extern crate cgroups; -use cgroups::{Cgroup, CgroupError}; use cgroups::cpuset::CpuSetController; +use cgroups::{Cgroup, CgroupError}; #[test] fn test_cpuset_memory_pressure_root_cg() { diff --git a/tests/devices.rs b/tests/devices.rs index b34ea6a..7e43a17 100644 --- a/tests/devices.rs +++ b/tests/devices.rs @@ -1,8 +1,8 @@ //! Integration tests about the devices subsystem extern crate cgroups; +use cgroups::devices::{DevicePermissions, DeviceType, DevicesController}; use cgroups::{Cgroup, DeviceResource}; -use cgroups::devices::{DevicesController, DevicePermissions, DeviceType}; #[test] fn test_devices_parsing() { @@ -12,7 +12,16 @@ fn test_devices_parsing() { let devices: &DevicesController = cg.controller_of().unwrap(); // Deny access to all devices first - devices.deny_device(DeviceType::All, -1, -1, &vec![DevicePermissions::Read, DevicePermissions::Write, DevicePermissions::MkNod]); + devices.deny_device( + DeviceType::All, + -1, + -1, + &vec![ + DevicePermissions::Read, + DevicePermissions::Write, + DevicePermissions::MkNod, + ], + ); // Acquire the list of allowed devices after we denied all let allowed_devices = devices.allowed_devices(); // Verify that there are no devices that we can access. @@ -25,13 +34,16 @@ fn test_devices_parsing() { assert!(allowed_devices.is_ok()); let allowed_devices = allowed_devices.unwrap(); assert_eq!(allowed_devices.len(), 1); - assert_eq!(allowed_devices[0], DeviceResource { - allow: true, - devtype: DeviceType::Char, - major: 1, - minor: 3, - access: vec![DevicePermissions::MkNod], - }); + assert_eq!( + allowed_devices[0], + DeviceResource { + allow: true, + devtype: DeviceType::Char, + major: 1, + minor: 3, + access: vec![DevicePermissions::MkNod], + } + ); // Now deny, this device explicitly. devices.deny_device(DeviceType::Char, 1, 3, &DevicePermissions::all()); diff --git a/tests/pids.rs b/tests/pids.rs index 4262e55..c892150 100644 --- a/tests/pids.rs +++ b/tests/pids.rs @@ -1,12 +1,12 @@ //! Integration tests about the pids subsystem extern crate cgroups; -use cgroups::{CgroupError, CgroupPid, Cgroup, Resources, PidResources}; use cgroups::pid::{PidController, PidMax}; use cgroups::Controller; +use cgroups::{Cgroup, CgroupError, CgroupPid, PidResources, Resources}; extern crate nix; -use nix::unistd::{Pid, fork, ForkResult}; use nix::sys::wait::{waitpid, WaitStatus}; +use nix::unistd::{fork, ForkResult, Pid}; extern crate libc; use libc::pid_t; @@ -86,16 +86,14 @@ fn test_pid_events_is_not_zero() { let events = pids.get_pid_events(); assert!(events.is_ok()); assert_eq!(events.unwrap(), before + 1); - }, - Ok(ForkResult::Child) => { - loop { - let pids_max = pids.get_pid_max(); - if pids_max.is_ok() && pids_max.unwrap() == PidMax::Value(1) { - if let Err(_) = fork() { - unsafe { libc::exit(0) }; - } else { - unsafe { libc::exit(1) }; - } + } + Ok(ForkResult::Child) => loop { + let pids_max = pids.get_pid_max(); + if pids_max.is_ok() && pids_max.unwrap() == PidMax::Value(1) { + if let Err(_) = fork() { + unsafe { libc::exit(0) }; + } else { + unsafe { libc::exit(1) }; } } }, diff --git a/tests/resources.rs b/tests/resources.rs index 72d2494..31021f2 100644 --- a/tests/resources.rs +++ b/tests/resources.rs @@ -1,8 +1,8 @@ //! Integration test about setting resources using `apply()` extern crate cgroups; -use cgroups::{Cgroup, Resources, PidResources}; use cgroups::pid::{PidController, PidMax}; +use cgroups::{Cgroup, PidResources, Resources}; #[test] fn pid_resources() {