mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-11 06:16:49 +00:00
Re-organize some systree-related code
This commit is contained in:
parent
a67bd8cdc9
commit
c56aee92f4
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -268,6 +268,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"component",
|
"component",
|
||||||
|
"inherit-methods-macro",
|
||||||
"ostd",
|
"ostd",
|
||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
@ -9,6 +9,7 @@ edition = "2021"
|
|||||||
bitflags = "2.5"
|
bitflags = "2.5"
|
||||||
ostd = { path = "../../../ostd" }
|
ostd = { path = "../../../ostd" }
|
||||||
component = { path = "../../libs/comp-sys/component" }
|
component = { path = "../../libs/comp-sys/component" }
|
||||||
|
inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e"}
|
||||||
spin = "0.9"
|
spin = "0.9"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
|
@ -37,9 +37,6 @@ pub struct SysAttr {
|
|||||||
name: SysStr,
|
name: SysStr,
|
||||||
/// Flags defining the behavior and permissions of the attribute.
|
/// Flags defining the behavior and permissions of the attribute.
|
||||||
flags: SysAttrFlags,
|
flags: SysAttrFlags,
|
||||||
// Potentially add read/write handler functions or trait objects later
|
|
||||||
// read_handler: fn(...) -> Result<usize>,
|
|
||||||
// write_handler: fn(...) -> Result<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysAttr {
|
impl SysAttr {
|
||||||
|
@ -7,7 +7,7 @@ use core::{
|
|||||||
sync::atomic::{AtomicU64, Ordering},
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ostd::mm::{VmReader, VmWriter};
|
use ostd::mm::{FallibleVmWrite, VmReader, VmWriter};
|
||||||
|
|
||||||
use super::{Error, Result, SysAttrSet, SysStr};
|
use super::{Error, Result, SysAttrSet, SysStr};
|
||||||
|
|
||||||
@ -16,9 +16,9 @@ pub const MAX_ATTR_SIZE: usize = 4096;
|
|||||||
/// The three types of nodes in a `SysTree`.
|
/// The three types of nodes in a `SysTree`.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum SysNodeType {
|
pub enum SysNodeType {
|
||||||
/// A branching node is one that may contain child nodes.
|
/// A branching node is one that can have child nodes.
|
||||||
Branch,
|
Branch,
|
||||||
/// A leaf node is one that may not contain child nodes.
|
/// A leaf node is one that cannot have child nodes.
|
||||||
Leaf,
|
Leaf,
|
||||||
/// A symlink node,
|
/// A symlink node,
|
||||||
/// which ia a special kind of leaf node that points to another node,
|
/// which ia a special kind of leaf node that points to another node,
|
||||||
@ -27,6 +27,7 @@ pub enum SysNodeType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A trait that represents a branching node in a `SysTree`.
|
/// A trait that represents a branching node in a `SysTree`.
|
||||||
|
#[expect(clippy::type_complexity)]
|
||||||
pub trait SysBranchNode: SysNode {
|
pub trait SysBranchNode: SysNode {
|
||||||
/// Visits a child node with the given name using a closure.
|
/// Visits a child node with the given name using a closure.
|
||||||
///
|
///
|
||||||
@ -49,7 +50,7 @@ pub trait SysBranchNode: SysNode {
|
|||||||
/// So the caller should do as little as possible inside the closure.
|
/// So the caller should do as little as possible inside the closure.
|
||||||
/// In particular, the caller should _not_ invoke other methods
|
/// In particular, the caller should _not_ invoke other methods
|
||||||
/// on this object as this might cause deadlock.
|
/// on this object as this might cause deadlock.
|
||||||
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>));
|
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
|
||||||
|
|
||||||
/// Visits child nodes with a minimum ID using a closure.
|
/// Visits child nodes with a minimum ID using a closure.
|
||||||
///
|
///
|
||||||
@ -75,7 +76,7 @@ pub trait SysBranchNode: SysNode {
|
|||||||
fn visit_children_with(
|
fn visit_children_with(
|
||||||
&self,
|
&self,
|
||||||
min_id: u64,
|
min_id: u64,
|
||||||
f: &mut dyn for<'a> FnMut(&'a Arc<(dyn SysObj + 'static)>) -> Option<()>,
|
f: &mut dyn for<'a> FnMut(&'a Arc<(dyn SysObj)>) -> Option<()>,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns a child with a specified name.
|
/// Returns a child with a specified name.
|
||||||
@ -182,18 +183,18 @@ pub trait SysObj: Any + Send + Sync + Debug + 'static {
|
|||||||
/// Returns a reference to this object as `Any` for downcasting.
|
/// Returns a reference to this object as `Any` for downcasting.
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
|
||||||
/// Attempts to get an Arc to this object as a `SysSymlink`.
|
/// Casts this object to a trait object of `SysTree` symlink.
|
||||||
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
|
fn cast_to_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to get an Arc to this object as a `SysNode`.
|
/// Casts this object to a trait object of a `SysTree` node.
|
||||||
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
|
fn cast_to_node(&self) -> Option<Arc<dyn SysNode>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to get an Arc to this object as a `SysBranchNode`.
|
/// Casts this object to a trait object of a `SysTree` branch node.
|
||||||
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
|
fn cast_to_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +211,7 @@ pub trait SysObj: Any + Send + Sync + Debug + 'static {
|
|||||||
///
|
///
|
||||||
/// The root node of a `SysTree` has an empty name.
|
/// The root node of a `SysTree` has an empty name.
|
||||||
/// All other inodes must have an non-empty name.
|
/// All other inodes must have an non-empty name.
|
||||||
fn name(&self) -> SysStr;
|
fn name(&self) -> &SysStr;
|
||||||
|
|
||||||
/// Returns whether a node is the root of a `SysTree`.
|
/// Returns whether a node is the root of a `SysTree`.
|
||||||
fn is_root(&self) -> bool {
|
fn is_root(&self) -> bool {
|
||||||
|
@ -6,22 +6,24 @@ use alloc::{
|
|||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{any::Any, fmt::Debug};
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
use inherit_methods_macro::inherit_methods;
|
||||||
use ostd::{
|
use ostd::{
|
||||||
mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter},
|
mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter},
|
||||||
prelude::ktest,
|
prelude::ktest,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Error, Result, SysAttrFlags, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields,
|
impl_cast_methods_for_branch, impl_cast_methods_for_symlink, Error, Result, SysAttrFlags,
|
||||||
SysNode, SysNodeId, SysNodeType, SysObj, SysStr, SysSymlink, SysTree,
|
SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, SysNode, SysNodeId,
|
||||||
|
SysNodeType, SysObj, SysStr, SysSymlink, SysTree,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DeviceNode {
|
struct DeviceNode {
|
||||||
fields: SysBranchNodeFields<dyn SysObj>,
|
fields: SysBranchNodeFields<dyn SysObj>,
|
||||||
self_ref: Weak<Self>,
|
weak_self: Weak<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceNode {
|
impl DeviceNode {
|
||||||
@ -41,38 +43,20 @@ impl DeviceNode {
|
|||||||
|
|
||||||
Arc::new_cyclic(|weak_self| DeviceNode {
|
Arc::new_cyclic(|weak_self| DeviceNode {
|
||||||
fields,
|
fields,
|
||||||
self_ref: weak_self.clone(),
|
weak_self: weak_self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysObj for DeviceNode {
|
impl SysObj for DeviceNode {
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl_cast_methods_for_branch!();
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysNode>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysBranchNode>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> &SysNodeId {
|
fn id(&self) -> &SysNodeId {
|
||||||
self.fields.id()
|
self.fields.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_(&self) -> SysNodeType {
|
fn name(&self) -> &SysStr {
|
||||||
SysNodeType::Branch
|
self.fields.name()
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> SysStr {
|
|
||||||
self.fields.name().to_string().into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,45 +113,13 @@ impl SysNode for DeviceNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inherit_methods(from = "self.fields")]
|
||||||
impl SysBranchNode for DeviceNode {
|
impl SysBranchNode for DeviceNode {
|
||||||
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)) {
|
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
|
||||||
let children = self.fields.children.read();
|
|
||||||
children
|
|
||||||
.get(name)
|
|
||||||
.map(|child| {
|
|
||||||
child
|
|
||||||
.arc_as_node()
|
|
||||||
.map(|node| f(Some(node.as_ref())))
|
|
||||||
.unwrap_or_else(|| f(None))
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| f(None));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>) {
|
fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>);
|
||||||
let children = self.fields.children.read();
|
|
||||||
for child in children
|
|
||||||
.values()
|
|
||||||
.filter(|child| child.id().as_u64() >= min_id)
|
|
||||||
{
|
|
||||||
if f(child).is_none() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> {
|
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>>;
|
||||||
let children = self.fields.children.read();
|
|
||||||
children.get(name).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn children(&self) -> Vec<Arc<dyn SysObj>> {
|
|
||||||
let children = self.fields.children.read();
|
|
||||||
children.values().cloned().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_children(&self) -> usize {
|
|
||||||
self.fields.children.read().len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -175,7 +127,7 @@ struct SymlinkNode {
|
|||||||
id: SysNodeId,
|
id: SysNodeId,
|
||||||
name: SysStr,
|
name: SysStr,
|
||||||
target: String,
|
target: String,
|
||||||
self_ref: Weak<Self>,
|
weak_self: Weak<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymlinkNode {
|
impl SymlinkNode {
|
||||||
@ -184,32 +136,20 @@ impl SymlinkNode {
|
|||||||
id: SysNodeId::new(),
|
id: SysNodeId::new(),
|
||||||
name: name.to_string().into(),
|
name: name.to_string().into(),
|
||||||
target: target.to_string(),
|
target: target.to_string(),
|
||||||
self_ref: weak_self.clone(),
|
weak_self: weak_self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysObj for SymlinkNode {
|
impl SysObj for SymlinkNode {
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl_cast_methods_for_symlink!();
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysSymlink>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> &SysNodeId {
|
fn id(&self) -> &SysNodeId {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_(&self) -> SysNodeType {
|
fn name(&self) -> &SysStr {
|
||||||
SysNodeType::Symlink
|
&self.name
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> SysStr {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +170,7 @@ fn systree_singleton() {
|
|||||||
// Check if root node exists
|
// Check if root node exists
|
||||||
assert!(root.is_root());
|
assert!(root.is_root());
|
||||||
assert_eq!(root.name(), "");
|
assert_eq!(root.name(), "");
|
||||||
assert_eq!(root.type_(), SysNodeType::Leaf);
|
assert_eq!(root.type_(), SysNodeType::Branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ktest]
|
#[ktest]
|
||||||
@ -309,7 +249,7 @@ fn symlinks() {
|
|||||||
|
|
||||||
// Verify symlink was added correctly
|
// Verify symlink was added correctly
|
||||||
let symlink_obj = device.child("device_link").unwrap();
|
let symlink_obj = device.child("device_link").unwrap();
|
||||||
let symlink_node = symlink_obj.arc_as_symlink().unwrap();
|
let symlink_node = symlink_obj.cast_to_symlink().unwrap();
|
||||||
assert_eq!(symlink_node.target_path(), "/sys/devices/device");
|
assert_eq!(symlink_node.target_path(), "/sys/devices/device");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,22 +4,18 @@
|
|||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::BTreeMap,
|
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
|
||||||
};
|
};
|
||||||
use core::any::Any;
|
|
||||||
|
|
||||||
use ostd::{
|
use inherit_methods_macro::inherit_methods;
|
||||||
mm::{VmReader, VmWriter},
|
use ostd::mm::{VmReader, VmWriter};
|
||||||
sync::RwLock,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
attr::SysAttrSet,
|
attr::SysAttrSet,
|
||||||
node::{SysBranchNode, SysNode, SysNodeId, SysNodeType, SysObj, SysSymlink},
|
node::{SysBranchNode, SysNode, SysNodeId, SysNodeType, SysObj},
|
||||||
Error, Result, SysStr,
|
Error, Result, SysStr,
|
||||||
};
|
};
|
||||||
|
use crate::{impl_cast_methods_for_branch, SysBranchNodeFields};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SysTree {
|
pub struct SysTree {
|
||||||
@ -32,12 +28,13 @@ impl SysTree {
|
|||||||
/// and standard subdirectories like "devices", "block", "kernel".
|
/// and standard subdirectories like "devices", "block", "kernel".
|
||||||
/// This is intended to be called once for the singleton.
|
/// This is intended to be called once for the singleton.
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
|
let name = ""; // Only the root has an empty name
|
||||||
|
let attr_set = SysAttrSet::new_empty(); // The root has no attributes
|
||||||
|
let fields = SysBranchNodeFields::new(SysStr::from(name), attr_set);
|
||||||
|
|
||||||
let root_node = Arc::new_cyclic(|weak_self| RootNode {
|
let root_node = Arc::new_cyclic(|weak_self| RootNode {
|
||||||
id: SysNodeId::new(),
|
fields,
|
||||||
name: "".into(),
|
weak_self: weak_self.clone(),
|
||||||
attrs: SysAttrSet::new_empty(),
|
|
||||||
children: RwLock::new(BTreeMap::new()),
|
|
||||||
self_ref: weak_self.clone(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Self { root: root_node }
|
Self { root: root_node }
|
||||||
@ -49,22 +46,22 @@ impl SysTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The root node in the `SysTree`.
|
||||||
|
///
|
||||||
|
/// A `RootNode` can work like a branching node, allowing to add additional nodes
|
||||||
|
/// as its children.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RootNode {
|
pub struct RootNode {
|
||||||
id: SysNodeId,
|
fields: SysBranchNodeFields<dyn SysObj>,
|
||||||
name: SysStr,
|
weak_self: Weak<Self>,
|
||||||
attrs: SysAttrSet,
|
|
||||||
children: RwLock<BTreeMap<SysStr, Arc<dyn SysObj>>>,
|
|
||||||
self_ref: Weak<Self>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RootNode {
|
impl RootNode {
|
||||||
/// Adds a child node. This was part of the concrete RootNode impl in lib.rs.
|
/// Adds a child node to this `RootNode`.
|
||||||
/// It's not part of the SysBranchNode trait definition.
|
|
||||||
pub fn add_child(&self, new_child: Arc<dyn SysObj>) -> Result<()> {
|
pub fn add_child(&self, new_child: Arc<dyn SysObj>) -> Result<()> {
|
||||||
let name = new_child.name();
|
let name = new_child.name();
|
||||||
let mut children_guard = self.children.write();
|
let mut children_guard = self.fields.children.write();
|
||||||
if children_guard.contains_key(&name) {
|
if children_guard.contains_key(name) {
|
||||||
return Err(Error::PermissionDenied);
|
return Err(Error::PermissionDenied);
|
||||||
}
|
}
|
||||||
children_guard.insert(name.clone(), new_child);
|
children_guard.insert(name.clone(), new_child);
|
||||||
@ -72,41 +69,13 @@ impl RootNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inherit_methods(from = "self.fields")]
|
||||||
impl SysObj for RootNode {
|
impl SysObj for RootNode {
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl_cast_methods_for_branch!();
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
|
fn id(&self) -> &SysNodeId;
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
|
fn name(&self) -> &SysStr;
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysNode>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysBranchNode>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> &SysNodeId {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_(&self) -> SysNodeType {
|
|
||||||
if self.children.read().is_empty() {
|
|
||||||
return SysNodeType::Leaf;
|
|
||||||
}
|
|
||||||
SysNodeType::Branch
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> SysStr {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_root(&self) -> bool {
|
fn is_root(&self) -> bool {
|
||||||
true
|
true
|
||||||
@ -119,7 +88,7 @@ impl SysObj for RootNode {
|
|||||||
|
|
||||||
impl SysNode for RootNode {
|
impl SysNode for RootNode {
|
||||||
fn node_attrs(&self) -> &SysAttrSet {
|
fn node_attrs(&self) -> &SysAttrSet {
|
||||||
&self.attrs
|
self.fields.attr_set()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
|
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
|
||||||
@ -131,35 +100,11 @@ impl SysNode for RootNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inherit_methods(from = "self.fields")]
|
||||||
impl SysBranchNode for RootNode {
|
impl SysBranchNode for RootNode {
|
||||||
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)) {
|
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
|
||||||
let children_guard = self.children.read();
|
|
||||||
children_guard
|
|
||||||
.get(name)
|
|
||||||
.map(|child| {
|
|
||||||
if let Some(node_ref) = child.arc_as_node().as_deref() {
|
|
||||||
f(Some(node_ref));
|
|
||||||
} else {
|
|
||||||
f(None);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| f(None));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_children_with(&self, _min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>) {
|
fn visit_children_with(&self, _min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>);
|
||||||
let children_guard = self.children.read();
|
|
||||||
for child_arc in children_guard.values() {
|
|
||||||
if f(child_arc).is_none() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> {
|
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>>;
|
||||||
self.children.read().get(name).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn children(&self) -> Vec<Arc<dyn SysObj>> {
|
|
||||||
self.children.read().values().cloned().collect()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
//! Utility definitions and helper structs for implementing `SysTree` nodes.
|
//! Utility definitions and helper structs for implementing `SysTree` nodes.
|
||||||
|
|
||||||
use alloc::{collections::BTreeMap, string::String, sync::Arc};
|
use alloc::{collections::BTreeMap, string::String, sync::Arc};
|
||||||
use core::ops::Deref;
|
|
||||||
|
|
||||||
use ostd::sync::RwLock;
|
use ostd::sync::RwLock;
|
||||||
|
|
||||||
@ -31,8 +30,8 @@ impl SysObjFields {
|
|||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &SysStr {
|
||||||
self.name.deref()
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ impl SysNormalNodeFields {
|
|||||||
self.base.id()
|
self.base.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &SysStr {
|
||||||
self.base.name()
|
self.base.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ impl<C: SysObj + ?Sized> SysBranchNodeFields<C> {
|
|||||||
self.base.id()
|
self.base.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &SysStr {
|
||||||
self.base.name()
|
self.base.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +96,7 @@ impl<C: SysObj + ?Sized> SysBranchNodeFields<C> {
|
|||||||
pub fn add_child(&self, new_child: Arc<C>) -> Result<()> {
|
pub fn add_child(&self, new_child: Arc<C>) -> Result<()> {
|
||||||
let mut children = self.children.write();
|
let mut children = self.children.write();
|
||||||
let name = new_child.name();
|
let name = new_child.name();
|
||||||
if children.contains_key(name.deref()) {
|
if children.contains_key(name) {
|
||||||
return Err(Error::PermissionDenied);
|
return Err(Error::PermissionDenied);
|
||||||
}
|
}
|
||||||
children.insert(name.clone(), new_child);
|
children.insert(name.clone(), new_child);
|
||||||
@ -108,6 +107,29 @@ impl<C: SysObj + ?Sized> SysBranchNodeFields<C> {
|
|||||||
let mut children = self.children.write();
|
let mut children = self.children.write();
|
||||||
children.remove(child_name)
|
children.remove(child_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<C>>)) {
|
||||||
|
let children_guard = self.children.read();
|
||||||
|
f(children_guard.get(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<C>) -> Option<()>) {
|
||||||
|
let children_guard = self.children.read();
|
||||||
|
for child_arc in children_guard.values() {
|
||||||
|
if child_arc.id().as_u64() < min_id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if f(child_arc).is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn child(&self, name: &str) -> Option<Arc<C>> {
|
||||||
|
let children = self.children.read();
|
||||||
|
children.get(name).cloned()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -128,7 +150,7 @@ impl SymlinkNodeFields {
|
|||||||
self.base.id()
|
self.base.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &SysStr {
|
||||||
self.base.name()
|
self.base.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ impl SysFsInode {
|
|||||||
match child_type {
|
match child_type {
|
||||||
SysNodeType::Branch => {
|
SysNodeType::Branch => {
|
||||||
let child_branch = child_sysnode
|
let child_branch = child_sysnode
|
||||||
.arc_as_branch()
|
.cast_to_branch()
|
||||||
.ok_or(Error::new(Errno::EIO))?;
|
.ok_or(Error::new(Errno::EIO))?;
|
||||||
let inode = Self::new_branch_dir(
|
let inode = Self::new_branch_dir(
|
||||||
self.systree,
|
self.systree,
|
||||||
@ -202,7 +202,7 @@ impl SysFsInode {
|
|||||||
}
|
}
|
||||||
SysNodeType::Leaf => {
|
SysNodeType::Leaf => {
|
||||||
let child_leaf_node =
|
let child_leaf_node =
|
||||||
child_sysnode.arc_as_node().ok_or(Error::new(Errno::EIO))?;
|
child_sysnode.cast_to_node().ok_or(Error::new(Errno::EIO))?;
|
||||||
let inode = Self::new_leaf_dir(
|
let inode = Self::new_leaf_dir(
|
||||||
self.systree,
|
self.systree,
|
||||||
InnerNode::Leaf(child_leaf_node),
|
InnerNode::Leaf(child_leaf_node),
|
||||||
@ -212,7 +212,7 @@ impl SysFsInode {
|
|||||||
}
|
}
|
||||||
SysNodeType::Symlink => {
|
SysNodeType::Symlink => {
|
||||||
let child_symlink = child_sysnode
|
let child_symlink = child_sysnode
|
||||||
.arc_as_symlink()
|
.cast_to_symlink()
|
||||||
.ok_or(Error::new(Errno::EIO))?;
|
.ok_or(Error::new(Errno::EIO))?;
|
||||||
let inode = Self::new_symlink(
|
let inode = Self::new_symlink(
|
||||||
self.systree,
|
self.systree,
|
||||||
@ -646,7 +646,7 @@ impl Iterator for NodeDentryIter {
|
|||||||
};
|
};
|
||||||
return Some(Dentry {
|
return Some(Dentry {
|
||||||
ino: obj_ino,
|
ino: obj_ino,
|
||||||
name: obj.name(),
|
name: obj.name().clone(),
|
||||||
type_,
|
type_,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,15 @@ use alloc::{
|
|||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{any::Any, fmt::Debug};
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use aster_systree::{
|
use aster_systree::{
|
||||||
|
impl_cast_methods_for_branch, impl_cast_methods_for_node, impl_cast_methods_for_symlink,
|
||||||
init_for_ktest, singleton as systree_singleton, Error as SysTreeError, Result as SysTreeResult,
|
init_for_ktest, singleton as systree_singleton, Error as SysTreeError, Result as SysTreeResult,
|
||||||
SysAttrFlags, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, SysNode,
|
SysAttrFlags, SysAttrSet, SysAttrSetBuilder, SysBranchNode, SysBranchNodeFields, SysNode,
|
||||||
SysNodeId, SysNodeType, SysNormalNodeFields, SysObj, SysStr, SysSymlink, SysTree,
|
SysNodeId, SysNodeType, SysNormalNodeFields, SysObj, SysStr, SysSymlink, SysTree,
|
||||||
};
|
};
|
||||||
|
use inherit_methods_macro::inherit_methods;
|
||||||
use ostd::{
|
use ostd::{
|
||||||
mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter},
|
mm::{FallibleVmRead, FallibleVmWrite, VmReader, VmWriter},
|
||||||
prelude::ktest,
|
prelude::ktest,
|
||||||
@ -40,7 +42,7 @@ use crate::{
|
|||||||
struct MockLeafNode {
|
struct MockLeafNode {
|
||||||
fields: SysNormalNodeFields,
|
fields: SysNormalNodeFields,
|
||||||
data: RwLock<BTreeMap<String, String>>, // Store attribute data
|
data: RwLock<BTreeMap<String, String>>, // Store attribute data
|
||||||
self_ref: Weak<Self>,
|
weak_self: Weak<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockLeafNode {
|
impl MockLeafNode {
|
||||||
@ -67,28 +69,20 @@ impl MockLeafNode {
|
|||||||
Arc::new_cyclic(|weak_self| MockLeafNode {
|
Arc::new_cyclic(|weak_self| MockLeafNode {
|
||||||
fields,
|
fields,
|
||||||
data: RwLock::new(data),
|
data: RwLock::new(data),
|
||||||
self_ref: weak_self.clone(),
|
weak_self: weak_self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysObj for MockLeafNode {
|
impl SysObj for MockLeafNode {
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl_cast_methods_for_node!();
|
||||||
self
|
|
||||||
}
|
|
||||||
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysNode>)
|
|
||||||
}
|
|
||||||
fn id(&self) -> &SysNodeId {
|
fn id(&self) -> &SysNodeId {
|
||||||
self.fields.id()
|
self.fields.id()
|
||||||
}
|
}
|
||||||
fn type_(&self) -> SysNodeType {
|
|
||||||
SysNodeType::Leaf
|
fn name(&self) -> &SysStr {
|
||||||
}
|
self.fields.name()
|
||||||
fn name(&self) -> SysStr {
|
|
||||||
Cow::Owned(self.fields.name().to_string()) // Convert to Cow::Owned
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +137,7 @@ impl SysNode for MockLeafNode {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct MockBranchNode {
|
struct MockBranchNode {
|
||||||
fields: SysBranchNodeFields<dyn SysObj>,
|
fields: SysBranchNodeFields<dyn SysObj>,
|
||||||
self_ref: Weak<Self>,
|
weak_self: Weak<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockBranchNode {
|
impl MockBranchNode {
|
||||||
@ -160,7 +154,7 @@ impl MockBranchNode {
|
|||||||
|
|
||||||
Arc::new_cyclic(|weak_self| MockBranchNode {
|
Arc::new_cyclic(|weak_self| MockBranchNode {
|
||||||
fields,
|
fields,
|
||||||
self_ref: weak_self.clone(),
|
weak_self: weak_self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,27 +164,14 @@ impl MockBranchNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SysObj for MockBranchNode {
|
impl SysObj for MockBranchNode {
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl_cast_methods_for_branch!();
|
||||||
self
|
|
||||||
}
|
|
||||||
fn arc_as_node(&self) -> Option<Arc<dyn SysNode>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysNode>)
|
|
||||||
}
|
|
||||||
fn arc_as_branch(&self) -> Option<Arc<dyn SysBranchNode>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysBranchNode>)
|
|
||||||
}
|
|
||||||
fn id(&self) -> &SysNodeId {
|
fn id(&self) -> &SysNodeId {
|
||||||
self.fields.id()
|
self.fields.id()
|
||||||
}
|
}
|
||||||
fn type_(&self) -> SysNodeType {
|
|
||||||
SysNodeType::Branch
|
fn name(&self) -> &SysStr {
|
||||||
}
|
self.fields.name()
|
||||||
fn name(&self) -> SysStr {
|
|
||||||
Cow::Owned(self.fields.name().to_string()) // Convert to Cow::Owned
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,41 +213,13 @@ impl SysNode for MockBranchNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inherit_methods(from = "self.fields")]
|
||||||
impl SysBranchNode for MockBranchNode {
|
impl SysBranchNode for MockBranchNode {
|
||||||
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&dyn SysNode>)) {
|
fn visit_child_with(&self, name: &str, f: &mut dyn FnMut(Option<&Arc<dyn SysObj>>));
|
||||||
self.fields
|
|
||||||
.children
|
|
||||||
.read()
|
|
||||||
.get(name)
|
|
||||||
.map(|child| {
|
|
||||||
child
|
|
||||||
.arc_as_node()
|
|
||||||
.map(|node| f(Some(node.as_ref())))
|
|
||||||
.unwrap_or_else(|| f(None));
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| f(None));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>) {
|
fn visit_children_with(&self, min_id: u64, f: &mut dyn FnMut(&Arc<dyn SysObj>) -> Option<()>);
|
||||||
let children = self.fields.children.read();
|
|
||||||
for child in children
|
|
||||||
.values()
|
|
||||||
.filter(|child| child.id().as_u64() >= min_id)
|
|
||||||
{
|
|
||||||
if f(child).is_none() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>> {
|
fn child(&self, name: &str) -> Option<Arc<dyn SysObj>>;
|
||||||
let children = self.fields.children.read();
|
|
||||||
children.get(name).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn children(&self) -> Vec<Arc<dyn SysObj>> {
|
|
||||||
self.fields.children.read().values().cloned().collect()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock Symlink
|
// Mock Symlink
|
||||||
@ -275,7 +228,7 @@ struct MockSymlinkNode {
|
|||||||
id: SysNodeId,
|
id: SysNodeId,
|
||||||
name: SysStr,
|
name: SysStr,
|
||||||
target: String,
|
target: String,
|
||||||
self_ref: Weak<Self>,
|
weak_self: Weak<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockSymlinkNode {
|
impl MockSymlinkNode {
|
||||||
@ -284,28 +237,20 @@ impl MockSymlinkNode {
|
|||||||
id: SysNodeId::new(),
|
id: SysNodeId::new(),
|
||||||
name: name.to_string().into(),
|
name: name.to_string().into(),
|
||||||
target: target.to_string(),
|
target: target.to_string(),
|
||||||
self_ref: weak_self.clone(),
|
weak_self: weak_self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SysObj for MockSymlinkNode {
|
impl SysObj for MockSymlinkNode {
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl_cast_methods_for_symlink!();
|
||||||
self
|
|
||||||
}
|
|
||||||
fn arc_as_symlink(&self) -> Option<Arc<dyn SysSymlink>> {
|
|
||||||
self.self_ref
|
|
||||||
.upgrade()
|
|
||||||
.map(|arc_self| arc_self as Arc<dyn SysSymlink>)
|
|
||||||
}
|
|
||||||
fn id(&self) -> &SysNodeId {
|
fn id(&self) -> &SysNodeId {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
fn type_(&self) -> SysNodeType {
|
|
||||||
SysNodeType::Symlink
|
fn name(&self) -> &SysStr {
|
||||||
}
|
&self.name
|
||||||
fn name(&self) -> SysStr {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user