Skip to content

Commit 9162c5a

Browse files
committed
Initial work
Signed-off-by: Levente Kurusa <[email protected]>
1 parent 6951e92 commit 9162c5a

18 files changed

+2343
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ Cargo.lock
88

99
# These are backup files generated by rustfmt
1010
**/*.rs.bk
11+
12+
/target
13+
**/*.rs.bk
14+
Cargo.lock

Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "cgroups-rs"
3+
version = "0.1.0"
4+
authors = ["Levente Kurusa <[email protected]>"]
5+
6+
[dependencies]

src/blkio.rs

+274
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
/* block IO controller */
2+
use std::path::PathBuf;
3+
use std::io::{Read, Write};
4+
use std::fs::File;
5+
6+
use {BlkIoResources, Controllers, Controller, Resources, ControllIdentifier, Subsystem};
7+
8+
#[derive(Debug, Clone)]
9+
pub struct BlkIoController {
10+
base: PathBuf,
11+
path: PathBuf,
12+
}
13+
14+
#[derive(Debug)]
15+
pub struct BlkIoThrottle {
16+
pub io_service_bytes: String,
17+
pub io_service_bytes_recursive: String,
18+
pub io_serviced: String,
19+
pub io_serviced_recursive: String,
20+
pub read_bps_device: String,
21+
pub read_iops_device: String,
22+
pub write_bps_device: String,
23+
pub write_iops_device: String,
24+
}
25+
26+
#[derive(Debug)]
27+
pub struct BlkIo {
28+
pub io_merged: String,
29+
pub io_merged_recursive: String,
30+
pub io_queued: String,
31+
pub io_queued_recursive: String,
32+
pub io_service_bytes: String,
33+
pub io_service_bytes_recursive: String,
34+
pub io_serviced: String,
35+
pub io_serviced_recursive: String,
36+
pub io_service_time: String,
37+
pub io_service_time_recursive: String,
38+
pub io_wait_time: String,
39+
pub io_wait_time_recursive: String,
40+
pub leaf_weight: u64,
41+
pub leaf_weight_device: String,
42+
pub sectors: String,
43+
pub sectors_recursive: String,
44+
pub throttle: BlkIoThrottle,
45+
pub time: String,
46+
pub time_recursive: String,
47+
pub weight: u64,
48+
pub weight_device: String,
49+
}
50+
51+
impl Controller for BlkIoController {
52+
fn control_type(self: &Self) -> Controllers { Controllers::BlkIo }
53+
fn get_path<'a>(self: &'a Self) -> &'a PathBuf { &self.path }
54+
fn get_path_mut<'a>(self: &'a mut Self) -> &'a mut PathBuf { &mut self.path }
55+
fn get_base<'a>(self: &'a Self) -> &'a PathBuf { &self.base }
56+
57+
fn apply(self: &Self, res: &Resources) {
58+
/* get the resources that apply to this controller */
59+
let res: &BlkIoResources = &res.blkio;
60+
61+
if res.update_values {
62+
self.set_weight(res.weight as u64);
63+
self.set_leaf_weight(res.leaf_weight as u64);
64+
65+
for dev in &res.weight_device {
66+
self.set_weight_for_device(format!("{}:{} {}",
67+
dev.major, dev.minor, dev.weight));
68+
}
69+
70+
for dev in &res.throttle_read_bps_device {
71+
self.throttle_read_bps_for_device(dev.major, dev.minor, dev.rate);
72+
}
73+
74+
for dev in &res.throttle_write_bps_device {
75+
self.throttle_write_bps_for_device(dev.major, dev.minor, dev.rate);
76+
}
77+
78+
for dev in &res.throttle_read_iops_device {
79+
self.throttle_read_iops_for_device(dev.major, dev.minor, dev.rate);
80+
}
81+
82+
for dev in &res.throttle_write_iops_device {
83+
self.throttle_write_iops_for_device(dev.major, dev.minor, dev.rate);
84+
}
85+
}
86+
}
87+
}
88+
89+
impl ControllIdentifier for BlkIoController {
90+
fn controller_type() -> Controllers {
91+
Controllers::BlkIo
92+
}
93+
}
94+
95+
impl<'a> From<&'a Subsystem> for &'a BlkIoController {
96+
fn from(sub: &'a Subsystem) -> &'a BlkIoController {
97+
unsafe {
98+
match sub {
99+
Subsystem::BlkIo(c) => c,
100+
_ => {
101+
assert_eq!(1, 0);
102+
::std::mem::uninitialized()
103+
},
104+
}
105+
}
106+
}
107+
}
108+
109+
fn read_string_from(mut file: File) -> Option<String> {
110+
let mut string = String::new();
111+
let _ = file.read_to_string(&mut string);
112+
Some(string.trim().to_string())
113+
}
114+
115+
fn read_u64_from(mut file: File) -> Option<u64> {
116+
let mut string = String::new();
117+
let _ = file.read_to_string(&mut string);
118+
string.trim().parse().ok()
119+
}
120+
121+
impl BlkIoController {
122+
pub fn new(oroot: PathBuf) -> Self {
123+
let mut root = oroot;
124+
root.push(Self::controller_type().to_string());
125+
Self {
126+
base: root.clone(),
127+
path: root,
128+
}
129+
}
130+
pub fn blkio(self: &Self) -> BlkIo {
131+
BlkIo {
132+
io_merged: self.open_path("blkio.io_merged", false).and_then(|file| {
133+
read_string_from(file)
134+
}).unwrap_or("".to_string()),
135+
io_merged_recursive: self.open_path("blkio.io_merged_recursive", false).and_then(|file| {
136+
read_string_from(file)
137+
}).unwrap_or("".to_string()),
138+
io_queued: self.open_path("blkio.io_queued", false).and_then(|file| {
139+
read_string_from(file)
140+
}).unwrap_or("".to_string()),
141+
io_queued_recursive: self.open_path("blkio.io_queued_recursive", false).and_then(|file| {
142+
read_string_from(file)
143+
}).unwrap_or("".to_string()),
144+
io_service_bytes: self.open_path("blkio.io_service_bytes", false).and_then(|file| {
145+
read_string_from(file)
146+
}).unwrap_or("".to_string()),
147+
io_service_bytes_recursive: self.open_path("blkio.io_service_bytes_recursive", false).and_then(|file| {
148+
read_string_from(file)
149+
}).unwrap_or("".to_string()),
150+
io_serviced: self.open_path("blkio.io_serviced", false).and_then(|file| {
151+
read_string_from(file)
152+
}).unwrap_or("".to_string()),
153+
io_serviced_recursive: self.open_path("blkio.io_serviced_recursive", false).and_then(|file| {
154+
read_string_from(file)
155+
}).unwrap_or("".to_string()),
156+
io_service_time: self.open_path("blkio.io_service_time", false).and_then(|file| {
157+
read_string_from(file)
158+
}).unwrap_or("".to_string()),
159+
io_service_time_recursive: self.open_path("blkio.io_service_time_recursive", false).and_then(|file| {
160+
read_string_from(file)
161+
}).unwrap_or("".to_string()),
162+
io_wait_time: self.open_path("blkio.io_wait_time", false).and_then(|file| {
163+
read_string_from(file)
164+
}).unwrap_or("".to_string()),
165+
io_wait_time_recursive: self.open_path("blkio.io_wait_time_recursive", false).and_then(|file| {
166+
read_string_from(file)
167+
}).unwrap_or("".to_string()),
168+
leaf_weight: self.open_path("blkio.leaf_weight", false).and_then(|file| {
169+
read_u64_from(file)
170+
}).unwrap_or(0u64),
171+
leaf_weight_device: self.open_path("blkio.leaf_weight_device", false).and_then(|file| {
172+
read_string_from(file)
173+
}).unwrap_or("".to_string()),
174+
sectors: self.open_path("blkio.sectors", false).and_then(|file| {
175+
read_string_from(file)
176+
}).unwrap_or("".to_string()),
177+
sectors_recursive: self.open_path("blkio.sectors_recursive", false).and_then(|file| {
178+
read_string_from(file)
179+
}).unwrap_or("".to_string()),
180+
throttle: BlkIoThrottle {
181+
io_service_bytes: self.open_path("blkio.throttle.io_service_bytes", false).and_then(|file| {
182+
read_string_from(file)
183+
}).unwrap_or("".to_string()),
184+
io_service_bytes_recursive: self.open_path("blkio.throttle.io_service_bytes_recursive", false).and_then(|file| {
185+
read_string_from(file)
186+
}).unwrap_or("".to_string()),
187+
io_serviced: self.open_path("blkio.throttle.io_serviced", false).and_then(|file| {
188+
read_string_from(file)
189+
}).unwrap_or("".to_string()),
190+
io_serviced_recursive: self.open_path("blkio.throttle.io_serviced_recursive", false).and_then(|file| {
191+
read_string_from(file)
192+
}).unwrap_or("".to_string()),
193+
read_bps_device: self.open_path("blkio.throttle.read_bps_device", false).and_then(|file| {
194+
read_string_from(file)
195+
}).unwrap_or("".to_string()),
196+
read_iops_device: self.open_path("blkio.throttle.read_iops_device", false).and_then(|file| {
197+
read_string_from(file)
198+
}).unwrap_or("".to_string()),
199+
write_bps_device: self.open_path("blkio.throttle.write_bps_device", false).and_then(|file| {
200+
read_string_from(file)
201+
}).unwrap_or("".to_string()),
202+
write_iops_device: self.open_path("blkio.throttle.write_iops_device", false).and_then(|file| {
203+
read_string_from(file)
204+
}).unwrap_or("".to_string()),
205+
},
206+
time: self.open_path("blkio.time", false).and_then(|file| {
207+
read_string_from(file)
208+
}).unwrap_or("".to_string()),
209+
time_recursive: self.open_path("blkio.time_recursive", false).and_then(|file| {
210+
read_string_from(file)
211+
}).unwrap_or("".to_string()),
212+
weight: self.open_path("blkio.weight", false).and_then(|file| {
213+
read_u64_from(file)
214+
}).unwrap_or(0u64),
215+
weight_device: self.open_path("blkio.weight_device", false).and_then(|file| {
216+
read_string_from(file)
217+
}).unwrap_or("".to_string()),
218+
}
219+
}
220+
221+
pub fn set_leaf_weight(self: &Self, w: u64) {
222+
self.open_path("blkio.leaf_weight", true).and_then(|mut file| {
223+
file.write_all(w.to_string().as_ref()).ok()
224+
});
225+
}
226+
227+
pub fn set_leaf_weight_for_device(self: &Self, d: String) {
228+
self.open_path("blkio.leaf_weight_device", true).and_then(|mut file| {
229+
file.write_all(d.as_ref()).ok()
230+
});
231+
}
232+
233+
pub fn reset_stats(self: &Self) {
234+
self.open_path("blkio.leaf_weight_device", true).and_then(|mut file| {
235+
file.write_all("1".to_string().as_ref()).ok()
236+
});
237+
}
238+
239+
pub fn throttle_read_bps_for_device(self: &Self, major: u64, minor: u64, bps: u64) {
240+
self.open_path("blkio.throttle.read_bps_device", true).and_then(|mut file| {
241+
file.write_all(format!("{}:{} {}", major, minor, bps).to_string().as_ref()).ok()
242+
});
243+
}
244+
245+
pub fn throttle_read_iops_for_device(self: &Self, major: u64, minor: u64, iops: u64) {
246+
self.open_path("blkio.throttle.read_iops_device", true).and_then(|mut file| {
247+
file.write_all(format!("{}:{} {}", major, minor, iops).to_string().as_ref()).ok()
248+
});
249+
}
250+
251+
pub fn throttle_write_bps_for_device(self: &Self, major: u64, minor: u64, bps: u64) {
252+
self.open_path("blkio.throttle.write_bps_device", true).and_then(|mut file| {
253+
file.write_all(format!("{}:{} {}", major, minor, bps).to_string().as_ref()).ok()
254+
});
255+
}
256+
257+
pub fn throttle_write_iops_for_device(self: &Self, major: u64, minor: u64, iops: u64) {
258+
self.open_path("blkio.throttle.write_iops_device", true).and_then(|mut file| {
259+
file.write_all(format!("{}:{} {}", major, minor, iops).to_string().as_ref()).ok()
260+
});
261+
}
262+
263+
pub fn set_weight(self: &Self, w: u64) {
264+
self.open_path("blkio.leaf_weight", true).and_then(|mut file| {
265+
file.write_all(w.to_string().as_ref()).ok()
266+
});
267+
}
268+
269+
pub fn set_weight_for_device(self: &Self, d: String) {
270+
self.open_path("blkio.weight_device", true).and_then(|mut file| {
271+
file.write_all(d.as_ref()).ok()
272+
});
273+
}
274+
}

src/cgroup.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use {CgroupPid, Resources, ControllIdentifier, Controller, Hierarchy, Subsystem};
2+
3+
use std::convert::From;
4+
5+
6+
/* Describe a cgroup in a simple fashion */
7+
pub struct Cgroup {
8+
/// Name of the cgroup
9+
//name: String,
10+
/// The list of subsystems that control this cgroup
11+
subsystems: Vec<Subsystem>,
12+
}
13+
14+
impl Cgroup {
15+
fn create(self: &Self) {
16+
for subsystem in &self.subsystems {
17+
subsystem.to_controller().create();
18+
}
19+
}
20+
21+
pub fn new(hier: &Hierarchy, path: String, _resources: i64) -> Cgroup {
22+
let mut subsystems = hier.subsystems();
23+
subsystems = subsystems.into_iter().map(|x| x.enter(&path)).collect::<Vec<_>>();
24+
25+
let cg = Cgroup {
26+
//name: path,
27+
subsystems: subsystems,
28+
};
29+
30+
cg.create();
31+
cg
32+
}
33+
34+
pub fn subsystems(self: &Self) -> &Vec<Subsystem> {
35+
&self.subsystems
36+
}
37+
38+
pub fn delete(self: Self) {
39+
self.subsystems.into_iter().for_each(|sub| {
40+
match sub {
41+
Subsystem::Pid(pidc) => pidc.delete(),
42+
Subsystem::Mem(c) => c.delete(),
43+
Subsystem::CpuSet(c) => c.delete(),
44+
Subsystem::CpuAcct(c) => c.delete(),
45+
Subsystem::Cpu(c) => c.delete(),
46+
Subsystem::Devices(c) => c.delete(),
47+
Subsystem::Freezer(c) => c.delete(),
48+
Subsystem::NetCls(c) => c.delete(),
49+
Subsystem::BlkIo(c) => c.delete(),
50+
Subsystem::PerfEvent(c) => c.delete(),
51+
Subsystem::NetPrio(c) => c.delete(),
52+
Subsystem::HugeTlb(c) => c.delete(),
53+
Subsystem::Rdma(c) => c.delete(),
54+
}
55+
});
56+
}
57+
58+
pub fn apply(self: &Self, res: &Resources) {
59+
for subsystem in &self.subsystems {
60+
subsystem.to_controller().apply(res);
61+
}
62+
}
63+
64+
pub fn controller_of<'a, T>(self: &'a Self) -> Option<&'a T>
65+
where &'a T: From<&'a Subsystem>,
66+
T: Controller + ControllIdentifier,
67+
{
68+
for i in &self.subsystems {
69+
if i.to_controller().control_type() == T::controller_type() {
70+
/*
71+
* N.B.:
72+
* https://play.rust-lang.org/?gist=978b2846bacebdaa00be62374f4f4334&version=stable&mode=debug&edition=2015
73+
*/
74+
return Some(i.into());
75+
}
76+
}
77+
None
78+
}
79+
80+
pub fn add_task(self: &Self, pid: CgroupPid) {
81+
self.subsystems().iter().for_each(|sub| sub.to_controller().add_task(&pid));
82+
}
83+
}

0 commit comments

Comments
 (0)