From fd125947c9db0b33761414e65e919f73d9bf1815 Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Thu, 30 Nov 2023 12:01:11 -0800 Subject: Refactor workspace --- ayafs-core/src/memory/dir_entry.rs | 305 +++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 ayafs-core/src/memory/dir_entry.rs (limited to 'ayafs-core/src/memory/dir_entry.rs') diff --git a/ayafs-core/src/memory/dir_entry.rs b/ayafs-core/src/memory/dir_entry.rs new file mode 100644 index 0000000..55c67bd --- /dev/null +++ b/ayafs-core/src/memory/dir_entry.rs @@ -0,0 +1,305 @@ +use crate::disk::block::{DirectoryBlock, DirectoryEntry}; +use crate::disk::inode::Inode; +use crate::AyaFS; +use indexmap::map::Entry::Occupied; +use indexmap::IndexMap; +use libc::{c_int, ENOENT, ENOSPC}; +use log::debug; +use std::ffi::{OsStr, OsString}; +use std::os::unix::ffi::OsStrExt; + +impl AyaFS { + pub(crate) fn init_direntry_map(&mut self, index: usize) { + let direntry_map: IndexMap = IndexMap::new(); + if let Some((old_inode_index, old_dir_entry_map)) = + self.dir_entry_map.push(index, direntry_map) + { + if let Some(old_inode) = self.get_inode(old_inode_index) { + let mut old_inode = old_inode.clone(); + self.write_back_direntry(old_inode_index, &mut old_inode, old_dir_entry_map) + .unwrap(); + self.update_inode(old_inode_index, old_inode); + } + } + } + + pub(crate) fn load_direntry_map(&mut self, index: usize, inode: &Inode) -> Result<(), c_int> { + if self.dir_entry_map.contains(&index) { + debug!("load_direntry_map(ino: {}) already in cache", index); + return Ok(()); + } + + debug!("load_direntry_map(ino: {}) loading", index); + let mut dir_entry_map: IndexMap = IndexMap::new(); + let mut entry_index: usize = 0; + loop { + let block_index_within_inode = entry_index / 15; + let entry_index_within_block = entry_index % 15; + + match self.access_block::(inode, block_index_within_inode) { + Some(directory_block) => { + if directory_block.block.query(entry_index_within_block) { + let dir_entry = &directory_block.block.entries[entry_index_within_block]; + let name = dir_entry.name(); + dir_entry_map.insert(name, dir_entry.clone()); + } else { + break; + } + } + None => break, + } + entry_index += 1; + } + + if let Some((old_inode_index, old_dir_entry_map)) = + self.dir_entry_map.push(index, dir_entry_map) + { + if let Some(old_inode) = self.get_inode(old_inode_index) { + let mut old_inode = old_inode.clone(); + self.write_back_direntry(old_inode_index, &mut old_inode, old_dir_entry_map)?; + self.update_inode(old_inode_index, old_inode); + } + } + + Ok(()) + } + + pub(crate) fn write_back_direntry( + &mut self, + _parent_index: usize, + parent_inode: &mut Inode, + dir_entry_map: IndexMap, + ) -> Result<(), c_int> { + for (entry_index, (_, dir_entry)) in dir_entry_map.into_iter().enumerate() { + let block_index_within_inode = entry_index / 15; + let entry_index_within_block = entry_index % 15; + // 不够就新分配 + if self + .get_block_index(parent_inode, block_index_within_inode) + .is_none() + { + match self.allocate_block_for(parent_inode) { + Some((_, block_index_within)) => { + assert_eq!(block_index_within, block_index_within_inode); + } + None => { + return Err(ENOSPC); + } + } + } + match self.access_block_mut::(parent_inode, block_index_within_inode) { + Some(directory_block) => { + directory_block.block.allocate(entry_index_within_block); + directory_block.block.entries[entry_index_within_block] = dir_entry; + } + None => { + return Err(ENOENT); + } + } + } + Ok(()) + } + + pub(crate) fn exchange_direntry>( + &mut self, + parent_index: usize, + parent_inode: &mut Inode, + name: T, + new_parent_index: usize, + new_parent_inode: &mut Inode, + new_name: T, + ) -> Result<(), c_int> { + self.load_direntry_map(parent_index, parent_inode)?; + self.load_direntry_map(new_parent_index, new_parent_inode)?; + + let dir_entry = self + .dir_entry_map + .get(&parent_index) + .ok_or(ENOENT)? + .get(name.as_ref()) + .cloned() + .ok_or(ENOENT)?; + let new_dir_entry = self + .dir_entry_map + .get(&new_parent_index) + .ok_or(ENOENT)? + .get(new_name.as_ref()) + .cloned() + .ok_or(ENOENT)?; + + let name: &OsStr = name.as_ref(); + let new_name: &OsStr = new_name.as_ref(); + + self.dir_entry_map + .get_mut(&parent_index) + .map(|dir_entry_map| { + if let Occupied(mut entry) = dir_entry_map.entry(name.to_os_string()) { + *entry.get_mut() = new_dir_entry.clone(); + } + }) + .ok_or(ENOENT)?; + self.dir_entry_map + .get_mut(&new_parent_index) + .map(|new_dir_entry_map| { + if let Occupied(mut entry) = new_dir_entry_map.entry(new_name.to_os_string()) { + *entry.get_mut() = dir_entry.clone(); + } + }) + .ok_or(ENOENT)?; + + Ok(()) + } + + /// 删除第 entry_index 个 dir entry + pub(crate) fn remove_direntry>( + &mut self, + parent_index: usize, + parent_inode: &mut Inode, + name: T, + _entry_index: u32, + ) -> Result<(), c_int> { + self.load_direntry_map(parent_index, parent_inode)?; + if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) { + debug!(" remove_direntry(ino: {}) using hashmap", parent_index); + if dir_entry_map.shift_remove(name.as_ref()).is_some() { + Ok(()) + } else { + Err(ENOENT) + } + } else { + Err(ENOENT) + } + } + + pub(crate) fn add_direntry_2>( + &mut self, + parent_index: usize, + parent_inode: &mut Inode, + child_inode_name: T, + dir_entry: DirectoryEntry, + ) -> Result { + let child_inode_name = child_inode_name.as_ref(); + self.load_direntry_map(parent_index, parent_inode)?; + if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) { + let (entry_index, _) = + dir_entry_map.insert_full(child_inode_name.to_os_string(), dir_entry); + debug!( + " add_direntry(ino: {}) using hashmap, entry {}", + parent_index, entry_index + ); + parent_inode.size += 1; + Ok(entry_index as u32) + } else { + Err(ENOENT) + } + } + + pub(crate) fn add_direntry>( + &mut self, + parent_index: usize, + parent_inode: &mut Inode, + child_inode_index: usize, + child_inode_name: T, + file_type: u8, + ) -> Result { + let child_inode_name = child_inode_name.as_ref(); + self.load_direntry_map(parent_index, parent_inode)?; + if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) { + let name_len = child_inode_name.len() as u8; + let mut name = [0u8; 256]; + (&mut name[0..child_inode_name.len()]).copy_from_slice(child_inode_name.as_bytes()); + + let dir_entry = DirectoryEntry { + inode: child_inode_index as u32, + record_len: 264, + name_len, + file_type, + name, + }; + + let (entry_index, _) = + dir_entry_map.insert_full(child_inode_name.to_os_string(), dir_entry); + debug!( + " add_direntry(ino: {}) using hashmap, entry {}", + parent_index, entry_index + ); + parent_inode.size += 1; + Ok(entry_index as u32) + } else { + Err(ENOENT) + } + } + + pub(crate) fn get_direntry_by_name>( + &mut self, + parent_index: usize, + parent_inode: &Inode, + name: T, + ) -> Result { + self.load_direntry_map(parent_index, parent_inode)?; + if let Some(dir_entry_map) = self.dir_entry_map.get(&parent_index) { + debug!( + " get_direntry(ino: {}, name: {:?}) using hashmap", + parent_index, + name.as_ref() + ); + dir_entry_map.get(name.as_ref()).cloned().ok_or(ENOENT) + } else { + Err(ENOENT) + } + } + + pub(crate) fn get_direntry( + &mut self, + parent_index: usize, + parent_inode: &Inode, + entry_index: u32, + ) -> Result { + self.load_direntry_map(parent_index, parent_inode)?; + if let Some(dir_entry_map) = self.dir_entry_map.get(&parent_index) { + debug!( + " get_direntry(ino: {}, entry_index: {}) using hashmap", + parent_index, entry_index + ); + dir_entry_map + .iter() + .skip(entry_index as usize) + .next() + .map(|entry| entry.1.clone()) + .ok_or(ENOENT) + } else { + Err(ENOENT) + } + } + + /// 返回 inode_index, inode 在 parent 里的 index, inode 本身 + pub fn lookup_name( + &mut self, + parent_index: usize, + parent_inode: &Inode, + name: &OsStr, + ) -> Result<(u32, u32, Inode), c_int> { + self.load_direntry_map(parent_index, parent_inode)?; + if let Some(dir_entry_map) = self.dir_entry_map.get(&parent_index) { + if let Some((entry_index, _, dir_entry)) = dir_entry_map.get_full(name) { + let inode_index = dir_entry.inode; + let inode = self.get_inode(inode_index as usize).unwrap().clone(); + Ok((inode_index, entry_index as u32, inode)) + } else { + Err(ENOENT) + } + } else { + let mut entry_index = 0; + while entry_index < parent_inode.size { + if let Ok(entry) = self.get_direntry(parent_index, parent_inode, entry_index) { + if entry.name() == name { + let inode = self.get_inode(entry.inode as usize).unwrap().clone(); + return Ok((entry.inode, entry_index, inode)); + } + } + entry_index += 1; + } + Err(ENOENT) + } + } +} -- cgit v1.2.3-70-g09d2