asterinas/kernel/src/fs/cgroupfs/systree_node.rs

170 lines
5.0 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
use alloc::{
string::ToString,
sync::{Arc, Weak},
};
use core::fmt::Debug;
use aster_systree::{
inherit_sys_branch_node, BranchNodeFields, Error, Result, SysAttrSetBuilder, SysBranchNode,
SysObj, SysPerms, SysStr,
};
use inherit_methods_macro::inherit_methods;
use ostd::mm::{VmReader, VmWriter};
use spin::Once;
/// The root of a cgroup hierarchy, serving as the entry point to
/// the entire cgroup control system.
///
/// The cgroup system provides v2 unified hierarchy, and is also used as a root
/// node in the cgroup systree.
#[derive(Debug)]
pub(super) struct CgroupSystem {
fields: BranchNodeFields<CgroupNode, Self>,
}
/// A control group node in the cgroup systree.
///
/// Each node can bind a group of processes together for purpose of resource
/// management. Except for the root node, all nodes in the cgroup tree are of
/// this type.
#[derive(Debug)]
struct CgroupNode {
fields: BranchNodeFields<CgroupNode, Self>,
}
#[inherit_methods(from = "self.fields")]
impl CgroupSystem {
/// Adds a child node.
fn add_child(&self, new_child: Arc<CgroupNode>) -> Result<()>;
}
#[inherit_methods(from = "self.fields")]
impl CgroupNode {
/// Adds a child node.
fn add_child(&self, new_child: Arc<CgroupNode>) -> Result<()>;
}
impl CgroupSystem {
/// Returns the `CgroupSystem` singleton.
pub(super) fn singleton() -> &'static Arc<CgroupSystem> {
static SINGLETON: Once<Arc<CgroupSystem>> = Once::new();
SINGLETON.call_once(Self::new)
}
fn new() -> Arc<Self> {
let name = SysStr::from("cgroup");
let mut builder = SysAttrSetBuilder::new();
// TODO: Add more attributes as needed.
builder.add(
SysStr::from("cgroup.controllers"),
SysPerms::DEFAULT_RO_ATTR_PERMS,
);
builder.add(
SysStr::from("cgroup.max.depth"),
SysPerms::DEFAULT_RW_ATTR_PERMS,
);
builder.add(
SysStr::from("cgroup.threads"),
SysPerms::DEFAULT_RW_ATTR_PERMS,
);
builder.add(
SysStr::from("cpu.pressure"),
SysPerms::DEFAULT_RW_ATTR_PERMS,
);
builder.add(SysStr::from("cpu.stat"), SysPerms::DEFAULT_RO_ATTR_PERMS);
let attrs = builder.build().expect("Failed to build attribute set");
Arc::new_cyclic(|weak_self| {
let fields = BranchNodeFields::new(name, attrs, weak_self.clone());
CgroupSystem { fields }
})
}
}
impl CgroupNode {
pub(self) fn new(name: SysStr) -> Arc<Self> {
let mut builder = SysAttrSetBuilder::new();
// TODO: Add more attributes as needed. The normal cgroup node may have
// more attributes than the unified one.
builder.add(
SysStr::from("cgroup.controllers"),
SysPerms::DEFAULT_RO_ATTR_PERMS,
);
builder.add(
SysStr::from("cgroup.max.depth"),
SysPerms::DEFAULT_RW_ATTR_PERMS,
);
builder.add(
SysStr::from("cgroup.threads"),
SysPerms::DEFAULT_RW_ATTR_PERMS,
);
builder.add(
SysStr::from("cpu.pressure"),
SysPerms::DEFAULT_RW_ATTR_PERMS,
);
builder.add(SysStr::from("cpu.stat"), SysPerms::DEFAULT_RO_ATTR_PERMS);
let attrs = builder.build().expect("Failed to build attribute set");
Arc::new_cyclic(|weak_self| {
let fields = BranchNodeFields::new(name, attrs, weak_self.clone());
CgroupNode { fields }
})
}
}
inherit_sys_branch_node!(CgroupSystem, fields, {
fn is_root(&self) -> bool {
true
}
fn init_parent(&self, _parent: Weak<dyn SysBranchNode>) {
// This method should be a no-op for `RootNode`.
}
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
// TODO: Add support for reading attributes.
Err(Error::AttributeError)
}
fn write_attr(&self, _name: &str, _reader: &mut VmReader) -> Result<usize> {
// TODO: Add support for writing attributes.
Err(Error::AttributeError)
}
fn perms(&self) -> SysPerms {
SysPerms::DEFAULT_RW_PERMS
}
fn create_child(&self, name: &str) -> Result<Arc<dyn SysObj>> {
let new_child = CgroupNode::new(name.to_string().into());
self.add_child(new_child.clone())?;
Ok(new_child)
}
});
inherit_sys_branch_node!(CgroupNode, fields, {
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
// TODO: Add support for reading attributes.
Err(Error::AttributeError)
}
fn write_attr(&self, _name: &str, _reader: &mut VmReader) -> Result<usize> {
// TODO: Add support for writing attributes.
Err(Error::AttributeError)
}
fn perms(&self) -> SysPerms {
SysPerms::DEFAULT_RW_PERMS
}
fn create_child(&self, name: &str) -> Result<Arc<dyn SysObj>> {
let new_child = CgroupNode::new(name.to_string().into());
self.add_child(new_child.clone())?;
Ok(new_child)
}
});