Adjust the attributes-related APIs of SysNode
This commit is contained in:
parent
e648528c46
commit
dda8161bef
|
|
@ -130,8 +130,19 @@ pub trait SysBranchNode: SysNode {
|
|||
/// In particular, every "normal" node may have associated attributes.
|
||||
pub trait SysNode: SysObj {
|
||||
/// Returns the attribute set of a `SysNode`.
|
||||
///
|
||||
/// The attribute set returned by this method contains all possible attributes
|
||||
/// that this node may have. For nodes with dynamically changing attributes, it is
|
||||
/// necessary to additionally use the [`SysNode::is_attr_absent`] method to confirm
|
||||
/// whether an attribute is currently present.
|
||||
fn node_attrs(&self) -> &SysAttrSet;
|
||||
|
||||
/// Returns whether an attribute with the given name is absent.
|
||||
///
|
||||
/// If the node does not have the attribute with the given name,
|
||||
/// the return value is unspecified.
|
||||
fn is_attr_absent(&self, _name: &str) -> bool;
|
||||
|
||||
/// Reads the value of an attribute.
|
||||
fn read_attr(&self, name: &str, writer: &mut VmWriter) -> Result<usize>;
|
||||
|
||||
|
|
|
|||
|
|
@ -277,6 +277,10 @@ macro_rules! _inner_impl_sys_node {
|
|||
self.$field.attr_set()
|
||||
}
|
||||
|
||||
fn is_attr_absent(&self, name: &str) -> bool {
|
||||
<_ as $helper_trait>::is_attr_absent(self, name)
|
||||
}
|
||||
|
||||
fn read_attr(
|
||||
&self,
|
||||
name: &str,
|
||||
|
|
@ -331,6 +335,10 @@ pub trait _InheritSysLeafNode<T: SysNode> {
|
|||
self.field().init_parent(parent);
|
||||
}
|
||||
|
||||
fn is_attr_absent(&self, _name: &str) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn read_attr(&self, name: &str, writer: &mut VmWriter) -> Result<usize> {
|
||||
self.read_attr_at(name, 0, writer)
|
||||
}
|
||||
|
|
@ -371,6 +379,7 @@ pub trait _InheritSysLeafNode<T: SysNode> {
|
|||
/// - Methods with default implementations that users can override:
|
||||
/// - [`SysObj::is_root`]
|
||||
/// - [`SysObj::init_parent`]
|
||||
/// - [`SysNode::is_attr_absent`]
|
||||
/// - [`SysNode::read_attr`]
|
||||
/// - [`SysNode::write_attr`]
|
||||
/// - [`SysNode::read_attr_at`]
|
||||
|
|
@ -471,6 +480,10 @@ pub trait _InheritSysBranchNode<T: SysBranchNode> {
|
|||
self.field().init_parent(parent);
|
||||
}
|
||||
|
||||
fn is_attr_absent(&self, _name: &str) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn read_attr(&self, name: &str, writer: &mut VmWriter) -> Result<usize> {
|
||||
self.read_attr_at(name, 0, writer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,6 +190,9 @@ pub(in crate::fs) trait SysTreeInodeTy: Send + Sync + 'static {
|
|||
}
|
||||
} else {
|
||||
// If no child node found, try finding an attribute of the current branch node
|
||||
if sysnode.is_attr_absent(name) {
|
||||
return_errno_with_message!(Errno::ENOENT, "attribute is not present");
|
||||
}
|
||||
let Some(attr) = sysnode.node_attrs().get(name) else {
|
||||
return_errno_with_message!(Errno::ENOENT, "child node or attribute not found");
|
||||
};
|
||||
|
|
@ -198,10 +201,10 @@ pub(in crate::fs) trait SysTreeInodeTy: Send + Sync + 'static {
|
|||
SysTreeNodeKind::Branch(branch_arc) => branch_arc.clone(),
|
||||
// This case shouldn't happen if lookup_node_or_attr is called correctly
|
||||
_ => {
|
||||
return Err(Error::with_message(
|
||||
return_errno_with_message!(
|
||||
Errno::EIO,
|
||||
"lookup_node_or_attr called on non-branch inode",
|
||||
))
|
||||
"lookup_node_or_attr called on non-branch inode"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -215,18 +218,18 @@ pub(in crate::fs) trait SysTreeInodeTy: Send + Sync + 'static {
|
|||
Self: Sized + 'static,
|
||||
{
|
||||
// This function is called when the current inode is a Leaf directory
|
||||
if sysnode.is_attr_absent(name) {
|
||||
return_errno_with_message!(Errno::ENOENT, "attribute is not present");
|
||||
}
|
||||
let Some(attr) = sysnode.node_attrs().get(name) else {
|
||||
return Err(Error::new(Errno::ENOENT));
|
||||
return_errno_with_message!(Errno::ENOENT, "child node or attribute not found");
|
||||
};
|
||||
|
||||
let leaf_node_arc: Arc<dyn SysNode> = match &self.node_kind() {
|
||||
SysTreeNodeKind::Leaf(leaf_arc) => leaf_arc.clone(),
|
||||
// This case shouldn't happen if lookup_attr is called correctly
|
||||
_ => {
|
||||
return Err(Error::with_message(
|
||||
Errno::EIO,
|
||||
"lookup_attr called on non-leaf inode",
|
||||
))
|
||||
return_errno_with_message!(Errno::EIO, "lookup_attr called on non-leaf inode");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -240,22 +243,30 @@ pub(in crate::fs) trait SysTreeInodeTy: Send + Sync + 'static {
|
|||
{
|
||||
match &self.node_kind() {
|
||||
SysTreeNodeKind::Branch(branch_node) => {
|
||||
let attrs = branch_node.node_attrs().iter().cloned().collect();
|
||||
let attr_iter = AttrDentryIter::new(attrs, self.metadata().ino, min_ino);
|
||||
let attrs = branch_node.node_attrs();
|
||||
let attr_iter = AttrDentryIter::new(
|
||||
Some((attrs.iter(), branch_node.as_ref())),
|
||||
self.metadata().ino,
|
||||
min_ino,
|
||||
);
|
||||
let child_objs = branch_node.children();
|
||||
let node_iter = NodeDentryIter::new(child_objs, min_ino);
|
||||
let special_iter = ThisAndParentDentryIter::new(self, min_ino);
|
||||
attr_iter.chain(node_iter).chain(special_iter)
|
||||
}
|
||||
SysTreeNodeKind::Leaf(leaf_node) => {
|
||||
let attrs = leaf_node.node_attrs().iter().cloned().collect();
|
||||
let attr_iter = AttrDentryIter::new(attrs, self.metadata().ino, min_ino);
|
||||
let attrs = leaf_node.node_attrs();
|
||||
let attr_iter = AttrDentryIter::new(
|
||||
Some((attrs.iter(), leaf_node.as_ref())),
|
||||
self.metadata().ino,
|
||||
min_ino,
|
||||
);
|
||||
let node_iter = NodeDentryIter::new(Vec::new(), min_ino);
|
||||
let special_iter = ThisAndParentDentryIter::new(self, min_ino);
|
||||
attr_iter.chain(node_iter).chain(special_iter)
|
||||
}
|
||||
SysTreeNodeKind::Attr(_, _) | SysTreeNodeKind::Symlink(_) => {
|
||||
let attr_iter = AttrDentryIter::new(Vec::new(), self.metadata().ino, min_ino);
|
||||
let attr_iter = AttrDentryIter::new(None, self.metadata().ino, min_ino);
|
||||
let node_iter = NodeDentryIter::new(Vec::new(), min_ino);
|
||||
let special_iter = ThisAndParentDentryIter::new(self, min_ino);
|
||||
attr_iter.chain(node_iter).chain(special_iter)
|
||||
|
|
@ -456,7 +467,7 @@ impl<KInode: SysTreeInodeTy + Send + Sync + 'static> Inode for KInode {
|
|||
|
||||
default fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>> {
|
||||
if self.type_() != InodeType::Dir {
|
||||
return Err(Error::new(Errno::ENOTDIR));
|
||||
return_errno_with_message!(Errno::ENOTDIR, "not a directory inode");
|
||||
}
|
||||
|
||||
if name == "." {
|
||||
|
|
@ -530,7 +541,7 @@ impl<KInode: SysTreeInodeTy + Send + Sync + 'static> Inode for KInode {
|
|||
|
||||
if res.is_err() {
|
||||
if count == 0 {
|
||||
return Err(Error::new(Errno::EINVAL));
|
||||
return_errno_with_message!(Errno::EINVAL, "dirent visitor error");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -588,31 +599,33 @@ impl<KInode: SysTreeInodeTy + Send + Sync + 'static> Inode for KInode {
|
|||
}
|
||||
|
||||
// Update AttrDentryIter to filter by min_ino
|
||||
struct AttrDentryIter {
|
||||
attrs: Vec<SysAttr>,
|
||||
struct AttrDentryIter<'a, I: Iterator<Item = &'a SysAttr>> {
|
||||
attrs_and_node: Option<(I, &'a dyn SysNode)>,
|
||||
dir_ino: Ino,
|
||||
min_ino: Ino,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl AttrDentryIter {
|
||||
fn new(attrs: Vec<SysAttr>, dir_ino: Ino, min_ino: Ino) -> Self {
|
||||
impl<'a, I: Iterator<Item = &'a SysAttr>> AttrDentryIter<'a, I> {
|
||||
fn new(attrs_and_node: Option<(I, &'a dyn SysNode)>, dir_ino: Ino, min_ino: Ino) -> Self {
|
||||
Self {
|
||||
attrs,
|
||||
attrs_and_node,
|
||||
dir_ino,
|
||||
min_ino,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for AttrDentryIter {
|
||||
impl<'a, I: Iterator<Item = &'a SysAttr>> Iterator for AttrDentryIter<'a, I> {
|
||||
type Item = Dentry;
|
||||
|
||||
fn next(&mut self) -> Option<Dentry> {
|
||||
while self.index < self.attrs.len() {
|
||||
let attr = &self.attrs[self.index];
|
||||
self.index += 1;
|
||||
let (iter, sys_node) = self.attrs_and_node.as_mut()?;
|
||||
|
||||
for attr in iter {
|
||||
if sys_node.is_attr_absent(attr.name()) {
|
||||
continue; // Skip hidden attributes
|
||||
}
|
||||
|
||||
let attr_ino = ino::from_dir_ino_and_attr_id(self.dir_ino, attr.id());
|
||||
|
||||
if attr_ino >= self.min_ino {
|
||||
|
|
|
|||
Loading…
Reference in New Issue