Support the basic configfs
This commit is contained in:
parent
537f08d7cf
commit
fc69af3e95
|
|
@ -617,10 +617,10 @@ macro_rules! inherit_sys_branch_node {
|
|||
}
|
||||
}
|
||||
|
||||
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> {
|
||||
fn child(&self, name: &str) -> Option<Arc<dyn $crate::SysObj>> {
|
||||
self.$field
|
||||
.child(name)
|
||||
.map(|child| child as Arc<dyn SysObj>)
|
||||
.map(|child| child as Arc<dyn $crate::SysObj>)
|
||||
}
|
||||
|
||||
fn create_child(&self, name: &str) -> $crate::Result<alloc::sync::Arc<dyn $crate::SysObj>> {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use aster_block::BlockDevice;
|
||||
use aster_systree::SysNode;
|
||||
use spin::Once;
|
||||
|
||||
use super::inode::ConfigInode;
|
||||
use crate::{
|
||||
fs::{
|
||||
configfs::systree_node::ConfigRootNode,
|
||||
registry::{FsProperties, FsType},
|
||||
utils::{systree_inode::SysTreeInodeTy, FileSystem, FsFlags, Inode, SuperBlock},
|
||||
Result,
|
||||
},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
/// A file system that provides a user-space interface for configuring kernel objects.
|
||||
///
|
||||
/// `ConfigFs` is a RAM-based file system that allows user-space applications to create,
|
||||
/// configure, and manage kernel objects through a virtual file system interface.
|
||||
/// Unlike sysfs which is primarily read-only and represents existing kernel state,
|
||||
/// `ConfigFs` is designed for dynamic creation and configuration of kernel objects.
|
||||
pub struct ConfigFs {
|
||||
sb: SuperBlock,
|
||||
root: Arc<dyn Inode>,
|
||||
}
|
||||
|
||||
// Magic number for `ConfigFs` (taken from Linux).
|
||||
const MAGIC_NUMBER: u64 = 0x62656570;
|
||||
const BLOCK_SIZE: usize = 4096;
|
||||
const NAME_MAX: usize = 255;
|
||||
|
||||
impl ConfigFs {
|
||||
/// Returns the `CgroupFs` singleton.
|
||||
pub(super) fn singleton() -> &'static Arc<ConfigFs> {
|
||||
static SINGLETON: Once<Arc<ConfigFs>> = Once::new();
|
||||
|
||||
SINGLETON.call_once(|| Self::new(ConfigRootNode::singleton().clone()))
|
||||
}
|
||||
|
||||
fn new(root_node: Arc<ConfigRootNode>) -> Arc<Self> {
|
||||
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX);
|
||||
let root_inode = ConfigInode::new_root(root_node);
|
||||
|
||||
Arc::new(Self {
|
||||
sb,
|
||||
root: root_inode,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FileSystem for ConfigFs {
|
||||
fn sync(&self) -> Result<()> {
|
||||
// `ConfigFs` is volatile, sync is a no-op
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn root_inode(&self) -> Arc<dyn Inode> {
|
||||
self.root.clone()
|
||||
}
|
||||
|
||||
fn sb(&self) -> SuperBlock {
|
||||
self.sb.clone()
|
||||
}
|
||||
|
||||
fn flags(&self) -> FsFlags {
|
||||
FsFlags::empty()
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct ConfigFsType;
|
||||
|
||||
impl FsType for ConfigFsType {
|
||||
fn name(&self) -> &'static str {
|
||||
"configfs"
|
||||
}
|
||||
|
||||
fn properties(&self) -> FsProperties {
|
||||
FsProperties::empty()
|
||||
}
|
||||
|
||||
fn create(
|
||||
&self,
|
||||
_args: Option<CString>,
|
||||
_disk: Option<Arc<dyn BlockDevice>>,
|
||||
) -> Result<Arc<dyn FileSystem>> {
|
||||
Ok(ConfigFs::singleton().clone() as _)
|
||||
}
|
||||
|
||||
fn sysnode(&self) -> Option<Arc<dyn SysNode>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
|
||||
use ostd::sync::RwLock;
|
||||
|
||||
use crate::{
|
||||
fs::{
|
||||
configfs::fs::ConfigFs,
|
||||
utils::{
|
||||
systree_inode::{SysTreeInodeTy, SysTreeNodeKind},
|
||||
FileSystem, Inode, InodeMode, Metadata,
|
||||
},
|
||||
},
|
||||
Result,
|
||||
};
|
||||
|
||||
/// An inode abstraction used in the `ConfigFs`.
|
||||
pub struct ConfigInode {
|
||||
/// The corresponding node in the SysTree.
|
||||
node_kind: SysTreeNodeKind,
|
||||
/// The metadata of this inode.
|
||||
metadata: Metadata,
|
||||
/// The file mode (permissions) of this inode, protected by a lock.
|
||||
mode: RwLock<InodeMode>,
|
||||
/// Weak reference to the parent inode.
|
||||
parent: Weak<ConfigInode>,
|
||||
/// Weak self-reference for cyclic data structures.
|
||||
this: Weak<ConfigInode>,
|
||||
}
|
||||
|
||||
impl SysTreeInodeTy for ConfigInode {
|
||||
fn new_arc(
|
||||
node_kind: SysTreeNodeKind,
|
||||
metadata: Metadata,
|
||||
mode: InodeMode,
|
||||
parent: Weak<Self>,
|
||||
) -> Arc<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Arc::new_cyclic(|this| Self {
|
||||
node_kind,
|
||||
metadata,
|
||||
mode: RwLock::new(mode),
|
||||
parent,
|
||||
this: this.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn node_kind(&self) -> &SysTreeNodeKind {
|
||||
&self.node_kind
|
||||
}
|
||||
|
||||
fn metadata(&self) -> &Metadata {
|
||||
&self.metadata
|
||||
}
|
||||
|
||||
fn mode(&self) -> Result<InodeMode> {
|
||||
Ok(*self.mode.read())
|
||||
}
|
||||
|
||||
fn set_mode(&self, mode: InodeMode) -> Result<()> {
|
||||
*self.mode.write() = mode;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parent(&self) -> &Weak<Self> {
|
||||
&self.parent
|
||||
}
|
||||
|
||||
fn this(&self) -> Arc<Self> {
|
||||
self.this.upgrade().expect("Weak ref invalid")
|
||||
}
|
||||
}
|
||||
|
||||
impl Inode for ConfigInode {
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
ConfigFs::singleton().clone()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use aster_systree::{EmptyNode, SysBranchNode};
|
||||
use systree_node::ConfigRootNode;
|
||||
|
||||
use crate::{fs::configfs::fs::ConfigFsType, prelude::*};
|
||||
|
||||
mod fs;
|
||||
mod inode;
|
||||
mod systree_node;
|
||||
#[cfg(ktest)]
|
||||
mod test;
|
||||
|
||||
// This method should be called during kernel file system initialization,
|
||||
// _after_ `aster_systree::init`.
|
||||
pub(super) fn init() {
|
||||
let config_kernel_sysnode = EmptyNode::new("config".into());
|
||||
super::sysfs::register_kernel_sysnode(config_kernel_sysnode).unwrap();
|
||||
|
||||
super::registry::register(&ConfigFsType).unwrap();
|
||||
}
|
||||
|
||||
/// Registers a subsystem `SysTree` node under the root node of [`ConfigFs`].
|
||||
///
|
||||
/// If a subsystem with the same name has already been registered,
|
||||
/// this function returns an error.
|
||||
pub fn register_subsystem(subsystem: Arc<dyn SysBranchNode>) -> Result<()> {
|
||||
ConfigRootNode::singleton().add_child(subsystem)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unregisters a subsystem from the root node of [`ConfigFs`] by its name.
|
||||
///
|
||||
/// If no subsystem with the given name exists, this function returns an error.
|
||||
#[expect(dead_code)]
|
||||
pub fn unregister_subsystem(name: &str) -> Result<()> {
|
||||
ConfigRootNode::singleton().remove_child(name)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(ktest)]
|
||||
pub fn init_for_ktest() {
|
||||
aster_systree::init_for_ktest();
|
||||
super::registry::init();
|
||||
super::sysfs::init();
|
||||
init();
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use core::fmt::Debug;
|
||||
|
||||
use aster_systree::{
|
||||
inherit_sys_branch_node, BranchNodeFields, Result, SysAttrSet, SysBranchNode, SysObj, SysPerms,
|
||||
SysStr,
|
||||
};
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
use spin::Once;
|
||||
|
||||
/// The `SysTree` node that represents the root node of the `ConfigFs`.
|
||||
#[derive(Debug)]
|
||||
pub struct ConfigRootNode {
|
||||
fields: BranchNodeFields<dyn SysObj, Self>,
|
||||
}
|
||||
|
||||
#[inherit_methods(from = "self.fields")]
|
||||
impl ConfigRootNode {
|
||||
/// Returns the `ConfigRootNode` singleton.
|
||||
pub(super) fn singleton() -> &'static Arc<ConfigRootNode> {
|
||||
static SINGLETON: Once<Arc<ConfigRootNode>> = Once::new();
|
||||
|
||||
SINGLETON.call_once(Self::new)
|
||||
}
|
||||
|
||||
fn new() -> Arc<Self> {
|
||||
let name = SysStr::from("config");
|
||||
|
||||
let attrs = SysAttrSet::new_empty();
|
||||
Arc::new_cyclic(|weak_self| {
|
||||
let fields = BranchNodeFields::new(name, attrs, weak_self.clone());
|
||||
ConfigRootNode { fields }
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a child node.
|
||||
pub fn add_child(&self, new_child: Arc<dyn SysObj>) -> Result<()>;
|
||||
}
|
||||
|
||||
inherit_sys_branch_node!(ConfigRootNode, 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 perms(&self) -> SysPerms {
|
||||
SysPerms::DEFAULT_RW_PERMS
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
pub mod cgroupfs;
|
||||
pub mod configfs;
|
||||
pub mod device;
|
||||
pub mod devpts;
|
||||
pub mod epoll;
|
||||
|
|
@ -60,6 +61,7 @@ pub fn init() {
|
|||
sysfs::init();
|
||||
procfs::init();
|
||||
cgroupfs::init();
|
||||
configfs::init();
|
||||
ramfs::init();
|
||||
tmpfs::init();
|
||||
devpts::init();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use aster_systree::{
|
||||
inherit_sys_branch_node, BranchNodeFields, Error, Result, SysAttrSetBuilder, SysBranchNode,
|
||||
SysNode, SysPerms, SysStr,
|
||||
};
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
use ostd::mm::{VmReader, VmWriter};
|
||||
use spin::Once;
|
||||
|
||||
/// Registers a new kernel `SysNode`.
|
||||
pub(super) fn register(config_obj: Arc<dyn SysNode>) -> crate::Result<()> {
|
||||
KERNEL_SYS_NODE_ROOT.get().unwrap().add_child(config_obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unregisters a kernel `SysNode`.
|
||||
pub(super) fn unregister(name: &str) -> crate::Result<()> {
|
||||
let _ = KERNEL_SYS_NODE_ROOT.get().unwrap().remove_child(name)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn init() {
|
||||
KERNEL_SYS_NODE_ROOT.call_once(|| {
|
||||
let singleton = KernelSysNodeRoot::new();
|
||||
super::systree_singleton()
|
||||
.root()
|
||||
.add_child(singleton.clone())
|
||||
.unwrap();
|
||||
|
||||
singleton
|
||||
});
|
||||
}
|
||||
|
||||
static KERNEL_SYS_NODE_ROOT: Once<Arc<KernelSysNodeRoot>> = Once::new();
|
||||
|
||||
/// A systree node representing the `/sys/kernel` directory.
|
||||
///
|
||||
/// This node serves as the root for all kernel-related sysfs entries,
|
||||
/// including kernel parameters, debugging interfaces, and various
|
||||
/// kernel subsystem information. It corresponds to the `/kernel`
|
||||
/// directory in the sysfs filesystem.
|
||||
#[derive(Debug)]
|
||||
pub struct KernelSysNodeRoot {
|
||||
fields: BranchNodeFields<dyn SysNode, Self>,
|
||||
}
|
||||
|
||||
#[inherit_methods(from = "self.fields")]
|
||||
impl KernelSysNodeRoot {
|
||||
/// Creates a new `KernelSysNodeRoot` instance.
|
||||
fn new() -> Arc<Self> {
|
||||
let name = SysStr::from("kernel");
|
||||
let builder = SysAttrSetBuilder::new();
|
||||
// TODO: Add more kernel-specific attributes.
|
||||
let attrs = builder
|
||||
.build()
|
||||
.expect("Failed to build kernel attribute set");
|
||||
Arc::new_cyclic(|weak_self| {
|
||||
let fields = BranchNodeFields::new(name, attrs, weak_self.clone());
|
||||
KernelSysNodeRoot { fields }
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a kernel `SysNode` to this node.
|
||||
fn add_child(&self, new_child: Arc<dyn SysNode>) -> Result<()>;
|
||||
}
|
||||
|
||||
inherit_sys_branch_node!(KernelSysNodeRoot, 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
|
||||
}
|
||||
});
|
||||
|
|
@ -2,14 +2,31 @@
|
|||
|
||||
mod fs;
|
||||
mod inode;
|
||||
mod kernel;
|
||||
#[cfg(ktest)]
|
||||
mod test;
|
||||
|
||||
pub use aster_systree::primary_tree as systree_singleton;
|
||||
use aster_systree::SysNode;
|
||||
use fs::SysFsType;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
// This method should be called during kernel file system initialization,
|
||||
// _after_ `aster_systree::init`.
|
||||
pub fn init() {
|
||||
super::registry::register(&SysFsType).unwrap();
|
||||
|
||||
kernel::init();
|
||||
}
|
||||
|
||||
/// Registers a new kernel `SysNode`.
|
||||
pub fn register_kernel_sysnode(config_obj: Arc<dyn SysNode>) -> Result<()> {
|
||||
kernel::register(config_obj)
|
||||
}
|
||||
|
||||
/// Unregisters a kernel `SysNode`.
|
||||
#[expect(dead_code)]
|
||||
pub fn unregister_kernel_sysnode(name: &str) -> Result<()> {
|
||||
kernel::unregister(name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@
|
|||
# a generic init process. It should later be replaced by the actual init process.
|
||||
mount -t sysfs none /sys
|
||||
mount -t proc none /proc
|
||||
mount -t cgroup2 none /sys/fs/cgroup
|
||||
mount -t cgroup2 none /sys/fs/cgroup
|
||||
mount -t configfs none /sys/kernel/config
|
||||
Loading…
Reference in New Issue