Skip to content
Open
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
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ log = "0.4"
nix = { version = "0.25.0", default-features = false, features = ["event", "fs", "process"] }
libc = "0.2"
serde = { version = "1.0", features = ["derive"], optional = true }
serde_json = { version = "1.0", optional = true }
thiserror = "1"
oci-spec = { version = "0.8.1", optional = true }
zbus = "5.8"
Expand All @@ -28,4 +29,4 @@ nix = "0.25"

[features]
default = []
oci = ["oci-spec"]
oci = ["oci-spec", "serde", "serde_json"]
24 changes: 23 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub enum FreezerState {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct CgroupPid {
/// The process identifier
pub pid: u64,
pid: u64,
}

impl From<u64> for CgroupPid {
Expand All @@ -49,6 +49,28 @@ impl From<&std::process::Child> for CgroupPid {
}
}

impl From<u32> for CgroupPid {
fn from(u: u32) -> CgroupPid {
CgroupPid { pid: u as u64 }
}
}

impl From<i32> for CgroupPid {
fn from(u: i32) -> CgroupPid {
CgroupPid { pid: u as u64 }
}
}

impl CgroupPid {
pub fn set(&mut self, pid: u64) {
self.pid = pid;
}

pub fn as_raw(&self) -> u64 {
self.pid
}
}

#[cfg(test)]
pub mod tests {
use std::fs;
Expand Down
3 changes: 3 additions & 0 deletions src/manager/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ pub enum Error {

#[error("systemd dbus error: {0}")]
SystemdDbus(#[from] SystemdDbusError),

#[error("serialization error: {0}")]
Serialization(#[from] serde_json::Error),
}
107 changes: 89 additions & 18 deletions src/manager/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use oci_spec::runtime::{
LinuxBlockIo, LinuxCpu, LinuxDeviceCgroup, LinuxHugepageLimit, LinuxMemory, LinuxNetwork,
LinuxPids, LinuxResources,
};
use serde::{Deserialize, Serialize};

use crate::fs::blkio::{BlkIoController, BlkIoData, IoService, IoStat};
use crate::fs::cgroup::UNIFIED_MOUNTPOINT;
Expand All @@ -31,7 +32,8 @@ use crate::manager::error::Error;
use crate::manager::{conv, Manager, Result};
use crate::stats::{
BlkioCgroupStats, BlkioStat, CpuAcctStats, CpuCgroupStats, CpuThrottlingStats,
HugeTlbCgroupStats, HugeTlbStat, MemoryCgroupStats, MemoryStats, PidsCgroupStats,
DeviceCgroupStat, DevicesCgroupStats, HugeTlbCgroupStats, HugeTlbStat, MemoryCgroupStats,
MemoryStats, PidsCgroupStats,
};
use crate::{CgroupPid, CgroupStats, FreezerState};

Expand All @@ -42,7 +44,7 @@ const MOUNTINFO_PATH: &str = "/proc/self/mountinfo";
///
/// This manager deals with `LinuxResources` conformed to the OCI runtime
/// specification, so that it allows users not to do type conversions.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FsManager {
/// Cgroup subsystem paths read from `/proc/self/cgroup`
/// - cgroup v1: <subsystem> -> <path>
Expand All @@ -55,6 +57,7 @@ pub struct FsManager {
/// - cgroup v2: "/sys/fs/cgroup/<base>"
base: String,
/// Cgroup managed by this manager.
#[serde(skip)]
cgroup: Cgroup,
}

Expand Down Expand Up @@ -83,7 +86,7 @@ impl FsManager {

impl FsManager {
/// Create the cgroups if they are not created yet.
pub(crate) fn create_cgroups(&mut self) -> Result<()> {
pub fn create_cgroups(&mut self) -> Result<()> {
if self.exists() {
return Ok(());
}
Expand Down Expand Up @@ -128,7 +131,10 @@ impl FsManager {
}

fn set_cpuset(&self, linux_cpu: &LinuxCpu) -> Result<()> {
let controller: &CpuSetController = self.controller()?;
let controller: &CpuSetController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

if let Some(cpus) = linux_cpu.cpus() {
controller.set_cpus(cpus)?;
Expand All @@ -142,7 +148,10 @@ impl FsManager {
}

fn set_cpu(&self, linux_cpu: &LinuxCpu) -> Result<()> {
let controller: &CpuController = self.controller()?;
let controller: &CpuController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

if let Some(shares) = linux_cpu.shares() {
let shares = if self.v2() {
Expand Down Expand Up @@ -210,7 +219,10 @@ impl FsManager {
}

fn set_memory_v1(&self, linux_memory: &LinuxMemory) -> Result<()> {
let controller: &MemController = self.controller()?;
let controller: &MemController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

let mem_limit = linux_memory.limit().unwrap_or(0);
let memswap_limit = linux_memory.swap().unwrap_or(0);
Expand All @@ -237,7 +249,10 @@ impl FsManager {
}

fn set_memory_v2(&self, linux_memory: &LinuxMemory) -> Result<()> {
let controller: &MemController = self.controller()?;
let controller: &MemController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

if linux_memory.reservation().is_none()
&& linux_memory.limit().is_none()
Expand Down Expand Up @@ -297,7 +312,11 @@ impl FsManager {
}

fn set_pids(&self, pids: &LinuxPids) -> Result<()> {
let controller: &PidController = self.controller()?;
let controller: &PidController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

let value = if pids.limit() > 0 {
MaxValue::Value(pids.limit())
} else {
Expand All @@ -309,7 +328,10 @@ impl FsManager {
}

fn set_blkio(&self, blkio: &LinuxBlockIo) -> Result<()> {
let controller: &BlkIoController = self.controller()?;
let controller: &BlkIoController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

if let Some(weight) = blkio.weight() {
controller.set_weight(weight as u64)?;
Expand Down Expand Up @@ -372,7 +394,10 @@ impl FsManager {
}

fn set_hugepages(&self, hugepage_limits: &[LinuxHugepageLimit]) -> Result<()> {
let controller: &HugeTlbController = self.controller()?;
let controller: &HugeTlbController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

for limit in hugepage_limits.iter() {
// ignore not supported page size
Expand All @@ -389,24 +414,29 @@ impl FsManager {

fn set_network(&self, network: &LinuxNetwork) -> Result<()> {
if let Some(class_id) = network.class_id() {
let controller: &NetClsController = self.controller()?;
controller.set_class(class_id as u64)?;
if let Ok(controller) = self.controller::<NetClsController>() {
controller.set_class(class_id as u64)?;
}
}

if let Some(priorities) = network.priorities() {
let controller: &NetPrioController = self.controller()?;
for priority in priorities.iter() {
let eif = priority.name();
let prio = priority.priority() as u64;
controller.set_if_prio(eif, prio)?;
if let Ok(controller) = self.controller::<NetPrioController>() {
for priority in priorities.iter() {
let eif = priority.name();
let prio = priority.priority() as u64;
controller.set_if_prio(eif, prio)?;
}
}
}

Ok(())
}

fn set_devices(&self, devices: &[LinuxDeviceCgroup]) -> Result<()> {
let controller: &DevicesController = self.controller()?;
let controller: &DevicesController = match self.controller() {
Ok(c) => c,
Err(_) => return Ok(()),
};

for device in devices.iter() {
let devtype =
Expand Down Expand Up @@ -725,6 +755,41 @@ impl FsManager {
})
.collect()
}

fn devices_cgroup_stats(&self) -> DevicesCgroupStats {
let controller: &DevicesController = match self.controller() {
Ok(controller) => controller,
Err(_) => return DevicesCgroupStats::default(),
};

let list = controller
.allowed_devices()
.map(|devs| {
devs.iter()
.map(|dev| DeviceCgroupStat {
dev_type: dev.devtype.to_char().to_string(),
major: dev.major,
minor: dev.minor,
access: {
let mut access = String::new();
if dev.access.contains(&DevicePermissions::Read) {
access.push('r');
}
if dev.access.contains(&DevicePermissions::Write) {
access.push('w');
}
if dev.access.contains(&DevicePermissions::MkNod) {
access.push('m');
}
access
},
})
.collect::<Vec<_>>()
})
.unwrap_or_default();

DevicesCgroupStats { list }
}
}

impl Manager for FsManager {
Expand Down Expand Up @@ -860,6 +925,7 @@ impl Manager for FsManager {
pids: self.pids_cgroup_stats(),
blkio: self.blkio_cgroup_stats(),
hugetlb: self.huge_tlb_cgroup_stats(),
devices: self.devices_cgroup_stats(),
}
}

Expand All @@ -871,6 +937,11 @@ impl Manager for FsManager {
&self.mounts
}

fn serialize(&self) -> Result<String> {
let json = serde_json::to_string(self)?;
Ok(json)
}

fn systemd(&self) -> bool {
false
}
Expand Down
10 changes: 7 additions & 3 deletions src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
//

mod error;
use std::collections::HashMap;

pub use error::{Error, Result};
mod fs;
pub use fs::FsManager;
mod systemd;
pub use systemd::SystemdManager;
mod conv;

use std::collections::HashMap;
use std::fmt::Debug;

use oci_spec::runtime::LinuxResources;

use crate::systemd::SLICE_SUFFIX;
Expand All @@ -25,7 +26,7 @@ pub fn is_systemd_cgroup(cgroups_path: &str) -> bool {
}

/// Manage cgroups designed for OCI containers.
pub trait Manager: Send + Sync {
pub trait Manager: Send + Sync + Debug {
/// Add a process specified by its tgid.
fn add_proc(&mut self, tgid: CgroupPid) -> Result<()>;

Expand Down Expand Up @@ -78,6 +79,9 @@ pub trait Manager: Send + Sync {
/// mappings of relative paths see "paths()".
fn mounts(&self) -> &HashMap<String, String>;

/// Serialize the cgroup manager to a string in the format of JSON.
fn serialize(&self) -> Result<String>;

/// Indicate whether the cgroup manager is using systemd.
fn systemd(&self) -> bool;

Expand Down
Loading
Loading