From d92f388ae17c49e832ce661b308d803faae9820b Mon Sep 17 00:00:00 2001 From: Chen Chengjun Date: Wed, 10 Dec 2025 06:34:07 +0000 Subject: [PATCH] Provide dummy supports for some cgroup attributes required by Podman --- kernel/src/fs/cgroupfs/controller/cpuset.rs | 25 +++++++-- kernel/src/fs/cgroupfs/controller/pids.rs | 59 ++++++++++++++++++--- kernel/src/fs/cgroupfs/systree_node.rs | 15 +++++- 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/kernel/src/fs/cgroupfs/controller/cpuset.rs b/kernel/src/fs/cgroupfs/controller/cpuset.rs index d81f04574..10764fb94 100644 --- a/kernel/src/fs/cgroupfs/controller/cpuset.rs +++ b/kernel/src/fs/cgroupfs/controller/cpuset.rs @@ -3,7 +3,11 @@ use alloc::sync::Arc; use aster_systree::{Error, Result, SysAttrSetBuilder, SysPerms, SysStr}; -use ostd::mm::{VmReader, VmWriter}; +use aster_util::printer::VmPrinter; +use ostd::{ + cpu::num_cpus, + mm::{VmReader, VmWriter}, +}; /// A sub-controller responsible for CPU resource management in the cgroup subsystem. pub struct CpuSetController { @@ -29,8 +33,23 @@ impl CpuSetController { } impl super::SubControl for CpuSetController { - fn read_attr_at(&self, _name: &str, _offset: usize, _writer: &mut VmWriter) -> Result { - Err(Error::AttributeError) + fn read_attr_at(&self, name: &str, offset: usize, writer: &mut VmWriter) -> Result { + let mut printer = VmPrinter::new_skip(writer, offset); + match name { + "cpuset.cpus.effective" => { + let num_cpus = num_cpus(); + if num_cpus == 1 { + writeln!(printer, "0")?; + } else { + writeln!(printer, "0-{}", num_cpus - 1)?; + } + } + // Currently we only support a single memory node. + "cpuset.mems.effective" => writeln!(printer, "0")?, + _ => return Err(Error::AttributeError), + } + + Ok(printer.bytes_written()) } fn write_attr(&self, _name: &str, _reader: &mut VmReader) -> Result { diff --git a/kernel/src/fs/cgroupfs/controller/pids.rs b/kernel/src/fs/cgroupfs/controller/pids.rs index a105e4616..2ac2ca3aa 100644 --- a/kernel/src/fs/cgroupfs/controller/pids.rs +++ b/kernel/src/fs/cgroupfs/controller/pids.rs @@ -1,15 +1,19 @@ // SPDX-License-Identifier: MPL-2.0 use alloc::sync::Arc; +use core::sync::atomic::{AtomicU32, Ordering}; -use aster_systree::{Error, Result, SysAttrSetBuilder, SysPerms, SysStr}; +use aster_systree::{Error, MAX_ATTR_SIZE, Result, SysAttrSetBuilder, SysPerms, SysStr}; +use aster_util::printer::VmPrinter; use ostd::mm::{VmReader, VmWriter}; +use crate::{process::posix_thread::PID_MAX, util::ReadCString}; + /// A sub-controller responsible for PID resource management in the cgroup subsystem. /// /// This controller will only provide interfaces in non-root cgroup nodes. pub struct PidsController { - _private: (), + max_pid: AtomicU32, } impl PidsController { @@ -21,18 +25,59 @@ impl PidsController { } impl super::SubControl for PidsController { - fn read_attr_at(&self, _name: &str, _offset: usize, _writer: &mut VmWriter) -> Result { - Err(Error::AttributeError) + fn read_attr_at(&self, name: &str, offset: usize, writer: &mut VmWriter) -> Result { + let mut printer = VmPrinter::new_skip(writer, offset); + match name { + "pids.max" => { + let max_pid = self.max_pid.load(Ordering::Relaxed); + if max_pid == u32::MAX { + writeln!(printer, "max")?; + } else { + writeln!(printer, "{}", max_pid)?; + } + } + _ => return Err(Error::AttributeError), + } + + Ok(printer.bytes_written()) } - fn write_attr(&self, _name: &str, _reader: &mut VmReader) -> Result { - Err(Error::AttributeError) + fn write_attr(&self, name: &str, reader: &mut VmReader) -> Result { + match name { + "pids.max" => { + let (content, len) = reader + .read_cstring_until_end(MAX_ATTR_SIZE) + .map_err(|_| Error::PageFault)?; + let value = content + .to_str() + .map_err(|_| Error::InvalidOperation)? + .trim(); + let value = if value == "max" { + u32::MAX + } else if let Ok(value) = value.parse::() { + if value >= PID_MAX { + return Err(Error::InvalidOperation); + } + log::warn!("The cgroup's PID limit '{}' will not be enforced", value); + value + } else { + return Err(Error::InvalidOperation); + }; + + self.max_pid.store(value, Ordering::Relaxed); + + Ok(len) + } + _ => Err(Error::AttributeError), + } } } impl super::SubControlStatic for PidsController { fn new(_is_root: bool) -> Self { - Self { _private: () } + Self { + max_pid: AtomicU32::new(u32::MAX), + } } fn type_() -> super::SubCtrlType { diff --git a/kernel/src/fs/cgroupfs/systree_node.rs b/kernel/src/fs/cgroupfs/systree_node.rs index e51fe19d2..fc7a86172 100644 --- a/kernel/src/fs/cgroupfs/systree_node.rs +++ b/kernel/src/fs/cgroupfs/systree_node.rs @@ -350,6 +350,10 @@ impl CgroupNode { SysStr::from("cgroup.events"), SysPerms::DEFAULT_RO_ATTR_PERMS, ); + builder.add( + SysStr::from("cgroup.freeze"), + SysPerms::DEFAULT_RW_ATTR_PERMS, + ); Controller::init_attr_set(&mut builder, false); @@ -597,8 +601,8 @@ inherit_sys_branch_node!(CgroupNode, fields, { }; writeln!(printer, "populated {}", res)?; - // Currently we have not enabled the "frozen" attribute - // so the "frozen" field is always zero. + // Currently we have not enabled writing to the "cgroup.freeze" + // attribute so the "frozen" field is always zero. writeln!(printer, "frozen {}", 0)?; Ok::(printer.bytes_written()) @@ -627,6 +631,13 @@ inherit_sys_branch_node!(CgroupNode, fields, { }) .ok_or(Error::IsDead)? } + "cgroup.freeze" => self + .with_inner(|_| { + writeln!(printer, "0")?; + + Ok::(printer.bytes_written()) + }) + .ok_or(Error::IsDead)?, // TODO: Add support for reading other attributes. _ => self // This read may target a stale controller if the cgroup's sub-controllers