From 76ac602c3d79bb39c133c81a38425a77bc0b8b1f Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Sat, 25 Nov 2023 02:13:22 -0800 Subject: Some FUSE callbacks, some POSIX interface implementation --- src/memory/inode_iter.rs | 233 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 src/memory/inode_iter.rs (limited to 'src/memory/inode_iter.rs') diff --git a/src/memory/inode_iter.rs b/src/memory/inode_iter.rs new file mode 100644 index 0000000..d5909bc --- /dev/null +++ b/src/memory/inode_iter.rs @@ -0,0 +1,233 @@ +use std::ffi::OsStr; +use std::os::unix::ffi::OsStrExt; +use libc::{c_int, ENOENT, ENOSPC}; +use crate::disk::block::{Block, DirectoryBlock, DirectoryEntry, DoubleIndirectBlock, IndirectBlock, TripleIndirectBlock}; +use crate::disk::inode::{Inode, DIRECT_NUMBER}; +use crate::{AyaFS, INODE_PER_BLOCK}; +use crate::memory::cached_block::CachedBlock; + +impl AyaFS { + pub(crate) fn access_block(&mut self, inode: &Inode, mut block_index_within_inode: usize) -> Option<&CachedBlock> { + // direct block + if block_index_within_inode < DIRECT_NUMBER { + let block_index = inode.direct[block_index_within_inode] as usize; + return self.get_block::(block_index); + } else { + block_index_within_inode -= DIRECT_NUMBER; + } + + // indirect block + let indirect_number = INODE_PER_BLOCK; + if block_index_within_inode < indirect_number { + return if let Some(indirect_block) = + self.get_block::(inode.single_indirect as usize) + { + let block_index = indirect_block.block.entries[block_index_within_inode] as usize; + self.get_block::(block_index) + } else { + None + }; + } else { + block_index_within_inode -= indirect_number; + } + + // double indirect block + let double_indirect_number = INODE_PER_BLOCK * INODE_PER_BLOCK; + if block_index_within_inode < double_indirect_number { + if let Some(double_indirect_block) = + self.get_block::(inode.double_indirect as usize) + { + // 取出 double indirect block + let indirect_block_index = double_indirect_block.block.indirect + [block_index_within_inode / INODE_PER_BLOCK] + as usize; + // 要找的 entry 在 double indirect block 中的第几个 indirect block + if let Some(indirect_block) = self.get_block::(indirect_block_index) + { + let block_index = indirect_block.block.entries + [block_index_within_inode % INODE_PER_BLOCK] + as usize; + // 拿到 DirectoryBlock 的 index + return self.get_block::(block_index); + } + } + return None; + } else { + block_index_within_inode -= double_indirect_number; + } + + // triple indirect block + if let Some(triple_indirect_block) = + self.get_block::(inode.triple_indirect as usize) + { + // 取出 triple indirect block + let double_indirect_block_index = triple_indirect_block.block.double_indirect + [block_index_within_inode / (INODE_PER_BLOCK * INODE_PER_BLOCK)] + as usize; + // 要找的 entry 在 triple indirect block 中的第几个 double indirect block + if let Some(double_indirect_block) = + self.get_block::(double_indirect_block_index) + { + // 取出 double indirect block + let indirect_block_index = double_indirect_block.block.indirect + [block_index_within_inode % (INODE_PER_BLOCK * INODE_PER_BLOCK) + / INODE_PER_BLOCK] as usize; + // 要找的 entry 在 double indirect block 中的第几个 indirect block + if let Some(indirect_block) = self.get_block::(indirect_block_index) + { + let block_index = indirect_block.block.entries + [block_index_within_inode % INODE_PER_BLOCK] + as usize; + // DirectoryBlock 的 index + return self.get_block::(block_index); + } + } + } + + None + } + + pub(crate) fn add_direntry( + &mut self, + parent_inode: &mut Inode, + child_inode_index: u32, + child_inode_name: &OsStr, + child_inode: &Inode, + ) -> Result { + let entry_index = parent_inode.size; + let block_index_within_inode = (entry_index / 15) as usize; + let entry_index_within_block = (entry_index % 15) as usize; + + // TODO 如果 block 内 offset 是 0 (或者访问到 block_index_within_inode 无效?)则为 Inode 分配新的 block + + // TODO 把新的 entry 写到对应位置 + + Err(ENOSPC) + } + pub(crate) fn get_direntry( + &mut self, + inode: &Inode, + entry_index: u32 + ) -> Option { + let block_index_within_inode = (entry_index / 15) as usize; + let entry_index_within_block = (entry_index % 15) as usize; + + self.access_block::(inode, block_index_within_inode) + .map(|directory_block| { + directory_block.block.entries[entry_index_within_block].clone() + }) + } + + // pub(crate) fn get_direntry( + // &mut self, + // inode: &Inode, + // entry_index: u32, + // ) -> Option { + // // 每个 DirectoryBlock 里有 15 个 entry, 先确定 block 再确定 offset + // let mut block_index_within_inode = (entry_index / 15) as usize; + // let entry_index_within_block = (entry_index % 15) as usize; + // + // // direct block + // if block_index_within_inode < DIRECT_NUMBER { + // let block_index = inode.direct[block_index_within_inode] as usize; + // return self + // .get_block::(block_index) + // .map(|inode_block| inode_block.block.entries[entry_index_within_block].clone()); + // } else { + // block_index_within_inode -= DIRECT_NUMBER; + // } + // + // // indirect block + // let indirect_number = INODE_PER_BLOCK; + // if block_index_within_inode < indirect_number { + // return if let Some(indirect_block) = + // self.get_block::(inode.single_indirect as usize) + // { + // let block_index = indirect_block.block.entries[block_index_within_inode] as usize; + // self.get_block::(block_index) + // .map(|inode_block| inode_block.block.entries[entry_index_within_block].clone()) + // } else { + // None + // }; + // } else { + // block_index_within_inode -= indirect_number; + // } + // + // // double indirect block + // let double_indirect_number = INODE_PER_BLOCK * INODE_PER_BLOCK; + // if block_index_within_inode < double_indirect_number { + // if let Some(double_indirect_block) = + // self.get_block::(inode.double_indirect as usize) + // { + // // 取出 double indirect block + // let indirect_block_index = double_indirect_block.block.indirect + // [block_index_within_inode / INODE_PER_BLOCK] + // as usize; + // // 要找的 entry 在 double indirect block 中的第几个 indirect block + // if let Some(indirect_block) = self.get_block::(indirect_block_index) + // { + // let block_index = indirect_block.block.entries + // [block_index_within_inode % INODE_PER_BLOCK] + // as usize; + // // 拿到 DirectoryBlock 的 index + // return self + // .get_block::(block_index) + // .map(|inode_block| { + // inode_block.block.entries[entry_index_within_block].clone() + // }); + // } + // } + // return None; + // } else { + // block_index_within_inode -= double_indirect_number; + // } + // + // // triple indirect block + // if let Some(triple_indirect_block) = + // self.get_block::(inode.triple_indirect as usize) + // { + // // 取出 triple indirect block + // let double_indirect_block_index = triple_indirect_block.block.double_indirect + // [block_index_within_inode / (INODE_PER_BLOCK * INODE_PER_BLOCK)] + // as usize; + // // 要找的 entry 在 triple indirect block 中的第几个 double indirect block + // if let Some(double_indirect_block) = + // self.get_block::(double_indirect_block_index) + // { + // // 取出 double indirect block + // let indirect_block_index = double_indirect_block.block.indirect + // [block_index_within_inode % (INODE_PER_BLOCK * INODE_PER_BLOCK) + // / INODE_PER_BLOCK] as usize; + // // 要找的 entry 在 double indirect block 中的第几个 indirect block + // if let Some(indirect_block) = self.get_block::(indirect_block_index) + // { + // let block_index = indirect_block.block.entries + // [block_index_within_inode % INODE_PER_BLOCK] + // as usize; + // // DirectoryBlock 的 index + // return self + // .get_block::(block_index) + // .map(|inode_block| { + // inode_block.block.entries[entry_index_within_block].clone() + // }); + // } + // } + // } + // None + // } + + // TODO 实现一个带 cache 的版本 + pub fn lookup_name(&mut self, parent_inode: &Inode, name: &OsStr) -> Result<(u32, Inode), c_int> { + let mut entry_index = 0; + while entry_index < parent_inode.size { + if let Some(entry) = self.get_direntry(parent_inode, entry_index) { + if entry.name() == name { + let inode = self.get_inode(entry.inode as usize).unwrap().clone(); + return Ok((entry.inode, inode)) + } + } + entry_index += 1; + } + Err(ENOENT) + } +} -- cgit v1.2.3-70-g09d2