mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-17 02:26:46 +00:00
Optimize the DirEntry
of RamInode
This commit is contained in:
parent
f194514100
commit
22b04ceae4
@ -8,6 +8,7 @@ use core::{
|
|||||||
use aster_block::bio::BioWaiter;
|
use aster_block::bio::BioWaiter;
|
||||||
use aster_rights::Full;
|
use aster_rights::Full;
|
||||||
use aster_util::slot_vec::SlotVec;
|
use aster_util::slot_vec::SlotVec;
|
||||||
|
use hashbrown::HashMap;
|
||||||
use ostd::{
|
use ostd::{
|
||||||
mm::{Frame, VmIo},
|
mm::{Frame, VmIo},
|
||||||
sync::RwMutexWriteGuard,
|
sync::RwMutexWriteGuard,
|
||||||
@ -242,13 +243,13 @@ impl InodeMeta {
|
|||||||
pub fn new_dir(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
pub fn new_dir(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
||||||
let now = now();
|
let now = now();
|
||||||
Self {
|
Self {
|
||||||
size: 2,
|
size: NUM_SPECIAL_ENTRIES,
|
||||||
blocks: 1,
|
blocks: 1,
|
||||||
atime: now,
|
atime: now,
|
||||||
mtime: now,
|
mtime: now,
|
||||||
ctime: now,
|
ctime: now,
|
||||||
mode,
|
mode,
|
||||||
nlinks: 2,
|
nlinks: NUM_SPECIAL_ENTRIES,
|
||||||
uid,
|
uid,
|
||||||
gid,
|
gid,
|
||||||
}
|
}
|
||||||
@ -316,16 +317,22 @@ impl Inner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a directory entry within a `RamInode`.
|
||||||
struct DirEntry {
|
struct DirEntry {
|
||||||
children: SlotVec<(CStr256, Arc<RamInode>)>,
|
children: SlotVec<(CStr256, Arc<RamInode>)>,
|
||||||
|
idx_map: HashMap<CStr256, usize>, // Used to accelerate indexing in `children`
|
||||||
this: Weak<RamInode>,
|
this: Weak<RamInode>,
|
||||||
parent: Weak<RamInode>,
|
parent: Weak<RamInode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Every directory has two special entries: "." and "..".
|
||||||
|
const NUM_SPECIAL_ENTRIES: usize = 2;
|
||||||
|
|
||||||
impl DirEntry {
|
impl DirEntry {
|
||||||
fn new(this: Weak<RamInode>, parent: Weak<RamInode>) -> Self {
|
fn new(this: Weak<RamInode>, parent: Weak<RamInode>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
children: SlotVec::new(),
|
children: SlotVec::new(),
|
||||||
|
idx_map: HashMap::new(),
|
||||||
this,
|
this,
|
||||||
parent,
|
parent,
|
||||||
}
|
}
|
||||||
@ -339,9 +346,7 @@ impl DirEntry {
|
|||||||
if name == "." || name == ".." {
|
if name == "." || name == ".." {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
self.children
|
self.idx_map.contains_key(name.as_bytes())
|
||||||
.iter()
|
|
||||||
.any(|(child, _)| child.as_str().unwrap() == name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,20 +356,31 @@ impl DirEntry {
|
|||||||
} else if name == ".." {
|
} else if name == ".." {
|
||||||
Some((1, self.parent.upgrade().unwrap()))
|
Some((1, self.parent.upgrade().unwrap()))
|
||||||
} else {
|
} else {
|
||||||
self.children
|
let idx = *self.idx_map.get(name.as_bytes())?;
|
||||||
.idxes_and_items()
|
let target_inode = self
|
||||||
.find(|(_, (child, _))| child.as_str().unwrap() == name)
|
.children
|
||||||
.map(|(idx, (_, inode))| (idx + 2, inode.clone()))
|
.get(idx)
|
||||||
|
.map(|(name_cstr256, inode)| {
|
||||||
|
debug_assert_eq!(name, name_cstr256.as_str().unwrap());
|
||||||
|
inode.clone()
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
Some((idx + NUM_SPECIAL_ENTRIES, target_inode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_entry(&mut self, name: &str, inode: Arc<RamInode>) -> usize {
|
fn append_entry(&mut self, name: &str, inode: Arc<RamInode>) -> usize {
|
||||||
self.children.put((CStr256::from(name), inode))
|
let name = CStr256::from(name);
|
||||||
|
let idx = self.children.put((name, inode));
|
||||||
|
self.idx_map.insert(name, idx);
|
||||||
|
idx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_entry(&mut self, idx: usize) -> Option<(CStr256, Arc<RamInode>)> {
|
fn remove_entry(&mut self, idx: usize) -> Option<(CStr256, Arc<RamInode>)> {
|
||||||
assert!(idx >= 2);
|
assert!(idx >= NUM_SPECIAL_ENTRIES);
|
||||||
self.children.remove(idx - 2)
|
let removed = self.children.remove(idx - NUM_SPECIAL_ENTRIES)?;
|
||||||
|
self.idx_map.remove(&removed.0);
|
||||||
|
Some(removed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn substitute_entry(
|
fn substitute_entry(
|
||||||
@ -372,8 +388,15 @@ impl DirEntry {
|
|||||||
idx: usize,
|
idx: usize,
|
||||||
new_entry: (CStr256, Arc<RamInode>),
|
new_entry: (CStr256, Arc<RamInode>),
|
||||||
) -> Option<(CStr256, Arc<RamInode>)> {
|
) -> Option<(CStr256, Arc<RamInode>)> {
|
||||||
assert!(idx >= 2);
|
assert!(idx >= NUM_SPECIAL_ENTRIES);
|
||||||
self.children.put_at(idx - 2, new_entry)
|
let new_name = new_entry.0;
|
||||||
|
let idx_children = idx - NUM_SPECIAL_ENTRIES;
|
||||||
|
|
||||||
|
let substitute = self.children.put_at(idx_children, new_entry)?;
|
||||||
|
let removed = self.idx_map.remove(&substitute.0);
|
||||||
|
debug_assert_eq!(removed.unwrap(), idx_children);
|
||||||
|
self.idx_map.insert(new_name, idx_children);
|
||||||
|
Some(substitute)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_entry(&self, idx: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
fn visit_entry(&self, idx: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
@ -391,12 +414,12 @@ impl DirEntry {
|
|||||||
}
|
}
|
||||||
// Read the normal child entries.
|
// Read the normal child entries.
|
||||||
let start_idx = *idx;
|
let start_idx = *idx;
|
||||||
for (offset, (name, child)) in self
|
for (offset_children, (name, child)) in self
|
||||||
.children
|
.children
|
||||||
.idxes_and_items()
|
.idxes_and_items()
|
||||||
.map(|(offset, (name, child))| (offset + 2, (name, child)))
|
.skip_while(|(offset, _)| offset + NUM_SPECIAL_ENTRIES < start_idx)
|
||||||
.skip_while(|(offset, _)| offset < &start_idx)
|
|
||||||
{
|
{
|
||||||
|
let offset = offset_children + NUM_SPECIAL_ENTRIES;
|
||||||
visitor.visit(name.as_str().unwrap(), child.ino, child.typ, offset)?;
|
visitor.visit(name.as_str().unwrap(), child.ino, child.typ, offset)?;
|
||||||
*idx = offset + 1;
|
*idx = offset + 1;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@ mod random_test;
|
|||||||
mod range_lock;
|
mod range_lock;
|
||||||
mod status_flags;
|
mod status_flags;
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
borrow::Borrow,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||||
@ -188,6 +193,18 @@ impl<'a, const N: usize> From<&'a str> for FixedStr<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Borrow<[u8]> for FixedCStr<N> {
|
||||||
|
fn borrow(&self) -> &[u8] {
|
||||||
|
self.as_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Hash for FixedCStr<N> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.as_bytes().hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<const N: usize> Default for FixedStr<N> {
|
impl<const N: usize> Default for FixedStr<N> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self([0u8; N])
|
Self([0u8; N])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user