Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seperate adding tasks to cgroups and applying resource restrictions #111

Merged
merged 3 commits into from
Jun 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/cgroups/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ pub const CGROUP_PROCS: &str = "cgroup.procs";
pub const DEFAULT_CGROUP_ROOT: &str = "/sys/fs/cgroup";

pub trait CgroupManager {
fn apply(&self, linux_resources: &LinuxResources, pid: Pid) -> Result<()>;
/// Adds a task specified by its pid to the cgroup
fn add_task(&self, pid: Pid) -> Result<()>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is slightly out of the scope of this PR, However Could you provide comments on each function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// Applies resource restrictions to the cgroup
fn apply(&self, linux_resources: &LinuxResources) -> Result<()>;
/// Removes the cgroup
fn remove(&self) -> Result<()>;
}

Expand Down
25 changes: 8 additions & 17 deletions src/cgroups/v1/blkio.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
use std::{
fs::{self},
path::Path,
};

use crate::cgroups::{
common::{self, CGROUP_PROCS},
v1::Controller,
};
use std::path::Path;

use crate::cgroups::{common, v1::Controller};
use anyhow::Result;
use oci_spec::{LinuxBlockIo, LinuxResources};

const CGROUP_BLKIO_THROTTLE_READ_BPS: &str = "blkio.throttle.read_bps_device";
Expand All @@ -17,25 +12,19 @@ const CGROUP_BLKIO_THROTTLE_WRITE_IOPS: &str = "blkio.throttle.write_iops_device
pub struct Blkio {}

impl Controller for Blkio {
fn apply(
linux_resources: &LinuxResources,
cgroup_root: &Path,
pid: nix::unistd::Pid,
) -> anyhow::Result<()> {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path) -> Result<()> {
log::debug!("Apply blkio cgroup config");
fs::create_dir_all(cgroup_root)?;

if let Some(blkio) = &linux_resources.block_io {
Self::apply(cgroup_root, blkio)?;
}

common::write_cgroup_file(cgroup_root.join(CGROUP_PROCS), pid)?;
Ok(())
}
}

impl Blkio {
fn apply(root_path: &Path, blkio: &LinuxBlockIo) -> anyhow::Result<()> {
fn apply(root_path: &Path, blkio: &LinuxBlockIo) -> Result<()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

for trbd in &blkio.blkio_throttle_read_bps_device {
common::write_cgroup_file_str(
&root_path.join(CGROUP_BLKIO_THROTTLE_READ_BPS),
Expand Down Expand Up @@ -70,6 +59,8 @@ impl Blkio {

#[cfg(test)]
mod tests {
use std::fs;

use super::*;
use crate::cgroups::test::setup;
use oci_spec::{LinuxBlockIo, LinuxThrottleDevice};
Expand Down
12 changes: 10 additions & 2 deletions src/cgroups/v1/controller.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::path::Path;
use std::{fs, path::Path};

use anyhow::Result;
use nix::unistd::Pid;

use oci_spec::LinuxResources;

use crate::cgroups::common::{self, CGROUP_PROCS};

pub trait Controller {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path, pid: Pid) -> Result<()>;
fn add_task(pid: Pid, cgroup_path: &Path) -> Result<()> {
fs::create_dir_all(cgroup_path)?;
common::write_cgroup_file(cgroup_path.join(CGROUP_PROCS), pid)?;
Ok(())
}

fn apply(linux_resources: &LinuxResources, cgroup_root: &Path) -> Result<()>;
}
1 change: 1 addition & 0 deletions src/cgroups/v1/controller_type.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt::Display;

#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub enum ControllerType {
Cpu,
CpuAcct,
Expand Down
10 changes: 4 additions & 6 deletions src/cgroups/v1/cpu.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::{fs, path::Path};
use std::path::Path;

use anyhow::Result;
use nix::unistd::Pid;
use oci_spec::{LinuxCpu, LinuxResources};

use crate::cgroups::common::{self, CGROUP_PROCS};
use crate::cgroups::common;

use super::Controller;

Expand All @@ -17,14 +16,13 @@ const CGROUP_CPU_RT_PERIOD: &str = "cpu.rt_period_us";
pub struct Cpu {}

impl Controller for Cpu {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path, pid: Pid) -> Result<()> {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path) -> Result<()> {
log::debug!("Apply Cpu cgroup config");
fs::create_dir_all(cgroup_root)?;

if let Some(cpu) = &linux_resources.cpu {
Self::apply(cgroup_root, cpu)?;
}

common::write_cgroup_file(cgroup_root.join(CGROUP_PROCS), pid)?;
Ok(())
}
}
Expand Down
22 changes: 9 additions & 13 deletions src/cgroups/v1/cpuacct.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
use std::{fs, path::Path};
use std::path::Path;

use anyhow::Result;
use nix::unistd::Pid;
use oci_spec::LinuxResources;

use crate::cgroups::common::{self, CGROUP_PROCS};

use super::Controller;

pub struct CpuAcct {}

impl Controller for CpuAcct {
fn apply(_linux_resources: &LinuxResources, cgroup_path: &Path, pid: Pid) -> Result<()> {
log::debug!("Apply cpuacct cgroup config");
fs::create_dir_all(cgroup_path)?;

common::write_cgroup_file(cgroup_path.join(CGROUP_PROCS), pid)?;
fn apply(_linux_resources: &LinuxResources, _cgroup_path: &Path) -> Result<()> {
Ok(())
}
}

#[cfg(test)]
mod tests {
use std::fs;

use nix::unistd::Pid;

use super::*;
use crate::cgroups::test::setup;
use crate::cgroups::{common::CGROUP_PROCS, test::setup};

#[test]
fn test_apply() {
fn test_add_task() {
let (tmp, procs) = setup("test_cpuacct_apply", CGROUP_PROCS);
let resource = LinuxResources::default();
let pid = Pid::from_raw(1000);

CpuAcct::apply(&resource, &tmp, pid).expect("apply cpuacct");
CpuAcct::add_task(pid, &tmp).expect("apply cpuacct");

let content = fs::read_to_string(&procs)
.unwrap_or_else(|_| panic!("read {} file content", CGROUP_PROCS));
Expand Down
14 changes: 10 additions & 4 deletions src/cgroups/v1/cpuset.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::{fs, path::Path};

use anyhow::{bail, Result};
use nix::unistd::Pid;
use nix::unistd;
use oci_spec::{LinuxCpu, LinuxResources};
use unistd::Pid;

use crate::cgroups::common::{self, CGROUP_PROCS};

Expand All @@ -14,18 +15,23 @@ const CGROUP_CPUSET_MEMS: &str = "cpuset.mems";
pub struct CpuSet {}

impl Controller for CpuSet {
fn apply(linux_resources: &LinuxResources, cgroup_path: &Path, pid: Pid) -> Result<()> {
log::debug!("Apply CpuSet cgroup config");
fn add_task(pid: Pid, cgroup_path: &Path) -> Result<()> {
fs::create_dir_all(cgroup_path)?;

Self::ensure_not_empty(cgroup_path, CGROUP_CPUSET_CPUS)?;
Self::ensure_not_empty(cgroup_path, CGROUP_CPUSET_MEMS)?;

common::write_cgroup_file(cgroup_path.join(CGROUP_PROCS), pid)?;
Ok(())
}

fn apply(linux_resources: &LinuxResources, cgroup_path: &Path) -> Result<()> {
log::debug!("Apply CpuSet cgroup config");

if let Some(cpuset) = &linux_resources.cpu {
Self::apply(cgroup_path, cpuset)?;
}

common::write_cgroup_file(cgroup_path.join(CGROUP_PROCS), pid)?;
Ok(())
}
}
Expand Down
9 changes: 3 additions & 6 deletions src/cgroups/v1/devices.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
use std::{fs::create_dir_all, path::Path};
use std::path::Path;

use anyhow::Result;
use nix::unistd::Pid;

use crate::cgroups::common::{self, CGROUP_PROCS};
use crate::cgroups::common;
use crate::{cgroups::v1::Controller, rootfs::default_devices};
use oci_spec::{LinuxDeviceCgroup, LinuxDeviceType, LinuxResources};

pub struct Devices {}

impl Controller for Devices {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path, pid: Pid) -> Result<()> {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path) -> Result<()> {
log::debug!("Apply Devices cgroup config");
create_dir_all(&cgroup_root)?;

for d in &linux_resources.devices {
Self::apply_device(d, cgroup_root)?;
Expand All @@ -27,7 +25,6 @@ impl Controller for Devices {
Self::apply_device(&d, &cgroup_root)?;
}

common::write_cgroup_file(cgroup_root.join(CGROUP_PROCS), pid)?;
Ok(())
}
}
Expand Down
43 changes: 21 additions & 22 deletions src/cgroups/v1/freezer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use std::{
};

use anyhow::{Result, *};
use nix::unistd::Pid;

use crate::cgroups::common::{self, CGROUP_PROCS};
use crate::cgroups::common;
use crate::cgroups::v1::Controller;
use oci_spec::{FreezerState, LinuxResources};

Expand All @@ -20,15 +19,14 @@ const FREEZER_STATE_FREEZING: &str = "FREEZING";
pub struct Freezer {}

impl Controller for Freezer {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path, pid: Pid) -> Result<()> {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path) -> Result<()> {
log::debug!("Apply Freezer cgroup config");
create_dir_all(&cgroup_root)?;

if let Some(freezer_state) = linux_resources.freezer {
Self::apply(freezer_state, cgroup_root)?;
}

common::write_cgroup_file(cgroup_root.join(CGROUP_PROCS), pid)?;
Ok(())
}
}
Expand Down Expand Up @@ -116,8 +114,10 @@ impl Freezer {
#[cfg(test)]
mod tests {
use super::*;
use crate::cgroups::common::CGROUP_PROCS;
use crate::cgroups::test::set_fixture;
use crate::utils::create_temp_dir;
use nix::unistd::Pid;
use oci_spec::FreezerState;

#[test]
Expand Down Expand Up @@ -160,10 +160,9 @@ mod tests {
}

#[test]
fn test_apply() {
let tmp =
create_temp_dir("test_set_freezer_state").expect("create temp directory for test");
set_fixture(&tmp, CGROUP_FREEZER_STATE, "").expect("Set fixure for freezer state");
fn test_add_and_apply() {
let tmp = create_temp_dir("test_add_task").expect("create temp directory for test");
set_fixture(&tmp, CGROUP_FREEZER_STATE, "").expect("set fixure for freezer state");
set_fixture(&tmp, CGROUP_PROCS, "").expect("set fixture for proc file");

// set Thawed state.
Expand All @@ -182,13 +181,13 @@ mod tests {
};

let pid = Pid::from_raw(1000);
let _ =
<Freezer as Controller>::apply(&linux_resources, &tmp, pid).expect("freezer apply");
Freezer::add_task(pid, &tmp).expect("freezer add task");
<Freezer as Controller>::apply(&linux_resources, &tmp).expect("freezer apply");
let state_content =
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("Read to string");
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("read to string");
assert_eq!(FREEZER_STATE_THAWED, state_content);
let pid_content =
std::fs::read_to_string(tmp.join(CGROUP_PROCS)).expect("Read to string");
std::fs::read_to_string(tmp.join(CGROUP_PROCS)).expect("read to string");
assert_eq!(pid_content, "1000");
}

Expand All @@ -208,13 +207,13 @@ mod tests {
};

let pid = Pid::from_raw(1001);
let _ =
<Freezer as Controller>::apply(&linux_resources, &tmp, pid).expect("freezer apply");
Freezer::add_task(pid, &tmp).expect("freezer add task");
<Freezer as Controller>::apply(&linux_resources, &tmp).expect("freezer apply");
let state_content =
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("Read to string");
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("read to string");
assert_eq!(FREEZER_STATE_FROZEN, state_content);
let pid_content =
std::fs::read_to_string(tmp.join(CGROUP_PROCS)).expect("Read to string");
std::fs::read_to_string(tmp.join(CGROUP_PROCS)).expect("read to string");
assert_eq!(pid_content, "1001");
}

Expand All @@ -233,16 +232,16 @@ mod tests {
freezer: Some(FreezerState::Undefined),
};

let old_state_content =
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("Read to string");
let pid = Pid::from_raw(1002);
let _ =
<Freezer as Controller>::apply(&linux_resources, &tmp, pid).expect("freezer apply");
let old_state_content =
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("read to string");
Freezer::add_task(pid, &tmp).expect("freezer add task");
<Freezer as Controller>::apply(&linux_resources, &tmp).expect("freezer apply");
let state_content =
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("Read to string");
std::fs::read_to_string(tmp.join(CGROUP_FREEZER_STATE)).expect("read to string");
assert_eq!(old_state_content, state_content);
let pid_content =
std::fs::read_to_string(tmp.join(CGROUP_PROCS)).expect("Read to string");
std::fs::read_to_string(tmp.join(CGROUP_PROCS)).expect("read to string");
assert_eq!(pid_content, "1002");
}
}
Expand Down
Loading