summaryrefslogtreecommitdiff
path: root/src/memory
diff options
context:
space:
mode:
Diffstat (limited to 'src/memory')
-rw-r--r--src/memory/cached_block.rs85
-rw-r--r--src/memory/cached_inode.rs71
-rw-r--r--src/memory/inode_iter.rs233
-rw-r--r--src/memory/mod.rs1
4 files changed, 310 insertions, 80 deletions
diff --git a/src/memory/cached_block.rs b/src/memory/cached_block.rs
index eb59a4b..77cdf61 100644
--- a/src/memory/cached_block.rs
+++ b/src/memory/cached_block.rs
@@ -1,5 +1,6 @@
use crate::block_device::{BlockDevice, BLOCK_SIZE};
use crate::disk::block::Block;
+use crate::disk::inode::Inode;
use crate::AyaFS;
use and_then_some::BoolExt;
use log::debug;
@@ -70,17 +71,18 @@ impl<T: Block> BlockCache<T> {
/// 从 LRU cache 里获取一个 block 的引用, 如果没有在 cache 中会加载.
pub(crate) fn get_block<U: Block>(&mut self, index: usize) -> Option<&CachedBlock<U>> {
- self.load_block(index)
- .and_then(|| self.cache.get(&index).map(convert::<T, U>))
+ if !self.cache.contains(&index) {
+ self.load_block(index);
+ }
+ self.cache.get(&index).map(convert::<T,U>)
}
/// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载.
pub(crate) fn get_block_mut<U: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<U>> {
- debug!("Blockcache get block mut");
- self.load_block(index).and_then(|| {
- debug!("block loaded");
- self.cache.get_mut(&index).map(convert_mut::<T, U>)
- })
+ if !self.cache.contains(&index) {
+ self.load_block(index);
+ }
+ self.cache.get_mut(&index).map(convert_mut::<T, U>)
}
/// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载.
@@ -145,73 +147,4 @@ impl AyaFS {
pub(crate) fn update_block<T: Block>(&mut self, block: CachedBlock<T>) -> bool {
self.cached_blocks.update_block(block)
}
-
- // pub(crate) fn update_block<T: Block>(&mut self, block: CachedBlock<T>) -> bool {
- // if self.cached_blocks.contains(&block.index) {
- // let data_block = convert::<T, DataBlock>(&block).clone();
- // self.cached_blocks.push(block.index, data_block);
- // true
- // } else {
- // false
- // }
- // }
- //
- // /// 从 LRU cache 里获取一个 block 的引用, 如果没有在 cache 中会加载.
- // pub(crate) fn get_block<T: Block>(&mut self, index: usize) -> Option<&CachedBlock<T>> {
- // self.load_block(index)
- // .and_then(|| self.cached_blocks.get(&index).map(convert::<DataBlock, T>))
- // }
- //
- // /// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载.
- // pub(crate) fn get_block_mut<T: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<T>> {
- // self.load_block(index).and_then(|| {
- // self.cached_blocks
- // .get_mut(&index)
- // .map(convert_mut::<DataBlock, T>)
- // })
- // }
- //
- // /// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载.
- // pub(crate) fn peek_block<T: Block>(&self, index: usize) -> Option<&CachedBlock<T>> {
- // self.cached_blocks.peek(&index).map(convert::<DataBlock, T>)
- // }
- //
- // /// 从 LRU cache 中读取一个 block 的可变引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载.
- // pub(crate) fn peek_block_mut<T: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<T>> {
- // self.cached_blocks.peek_mut(&index).map(convert_mut::<DataBlock, T>)
- // }
- //
- // pub(crate) fn load_block(&mut self, index: usize) -> bool {
- // // 先看这个 block 是不是 valid, 不 valid 直接返回 false.
- // if !self.data_bitmap.query(index) {
- // self.cached_blocks.pop(&index);
- // // deallocate 时只更新 bitmap 没有动 cache, lazy 地驱逐 cache 中的无效 entry.
- // return false;
- // }
- //
- // // 接下来这个 block 一定 valid. 如果 cache 里没有这个 block 就把它 load 到 cache 里
- // if self.cached_blocks.contains(&index) == false {
- // let block = DataBlock::default();
- // let buffer = unsafe {
- // std::slice::from_raw_parts_mut(&block as *const DataBlock as *mut u8, BLOCK_SIZE)
- // };
- // self.device.read(index, buffer);
- // let cached_block = CachedBlock {
- // block,
- // index,
- // dirty: false,
- // };
- // if let Some((old_index, old_block)) = self.cached_blocks.push(index, cached_block) {
- // assert_ne!(old_index, index); // 只有 block 不在 cache 里的时候才会插入
- // if old_block.dirty {
- // let old_block_ptr = &old_block.block as *const DataBlock as *mut u8;
- // let old_block_buffer =
- // unsafe { std::slice::from_raw_parts(old_block_ptr, BLOCK_SIZE) };
- // self.device.write(old_index, old_block_buffer);
- // }
- // }
- // }
- //
- // true
- // }
}
diff --git a/src/memory/cached_inode.rs b/src/memory/cached_inode.rs
index dd5e5c3..be87850 100644
--- a/src/memory/cached_inode.rs
+++ b/src/memory/cached_inode.rs
@@ -1,10 +1,76 @@
-use crate::disk::block::InodeBlock;
+use crate::disk::block::{DirectoryBlock, DirectoryEntry, InodeBlock};
use crate::disk::inode::{Inode, InodeMode, INODE_SIZE};
+use crate::utils::from_filetype;
use crate::{utils, AyaFS};
use and_then_some::BoolExt;
+use fuser::FileType;
use log::debug;
impl AyaFS {
+ pub(crate) fn create_file(
+ &mut self,
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ flags: u32,
+ ) -> Option<(usize, &Inode)> {
+ self.inode_bitmap.allocate().map(|inode_index| {
+ self.get_inode_mut(inode_index).map(|inode| {
+ *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ });
+ (inode_index, self.get_inode(inode_index).unwrap())
+ })
+ }
+
+ pub(crate) fn create_directory(
+ &mut self,
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ flags: u32,
+ ) -> Option<(usize, &Inode)> {
+ self.inode_bitmap.allocate().map(|inode_index| {
+ // 创建 Inode
+ let mut new_inode =
+ Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ // 分配第一个 direct block
+ new_inode.direct[0] = self.allocate_block_for(&mut new_inode).unwrap();
+ new_inode.size = 2;
+ // 在 direct block 里分配 . 和 ..
+ if let Some(directory_block) =
+ self.get_block_mut::<DirectoryBlock>(new_inode.direct[0] as usize)
+ {
+ let dot = '.'.to_ascii_lowercase() as u8;
+ // add dot entry
+ directory_block.block.entries[0] = DirectoryEntry {
+ inode: inode_index as u32,
+ record_len: 264,
+ name_len: 1,
+ file_type: 0x2,
+ name: [0; 256],
+ };
+ directory_block.block.entries[0].name[0] = dot;
+
+ // add dot dot entry
+ directory_block.block.entries[1] = DirectoryEntry {
+ inode: 0, // TODO set this as parent inode number
+ record_len: 264,
+ name_len: 2,
+ file_type: 0x2,
+ name: [0; 256],
+ };
+ directory_block.block.entries[1].name[0] = dot;
+ directory_block.block.entries[1].name[1] = dot;
+ }
+ // 把 inode 放到指定位置
+ self.get_inode_mut(inode_index).map(|inode| {
+ *inode = new_inode;
+ });
+
+ (inode_index, self.get_inode(inode_index).unwrap())
+ })
+ }
+
pub(crate) fn create_inode(
&mut self,
permissions: u16,
@@ -13,9 +79,7 @@ impl AyaFS {
gid: u32,
flags: u32,
) -> Option<usize> {
- debug!("create inode");
self.inode_bitmap.allocate().map(|inode_index| {
- debug!("creating inode");
self.get_inode_mut(inode_index).map(|inode| {
*inode = Inode::make_inode(
permissions,
@@ -29,7 +93,6 @@ impl AyaFS {
0,
);
});
- debug!("inode created");
inode_index
})
}
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<T: Block>(&mut self, inode: &Inode, mut block_index_within_inode: usize) -> Option<&CachedBlock<T>> {
+ // direct block
+ if block_index_within_inode < DIRECT_NUMBER {
+ let block_index = inode.direct[block_index_within_inode] as usize;
+ return self.get_block::<T>(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::<IndirectBlock>(inode.single_indirect as usize)
+ {
+ let block_index = indirect_block.block.entries[block_index_within_inode] as usize;
+ self.get_block::<T>(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::<DoubleIndirectBlock>(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::<IndirectBlock>(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::<T>(block_index);
+ }
+ }
+ return None;
+ } else {
+ block_index_within_inode -= double_indirect_number;
+ }
+
+ // triple indirect block
+ if let Some(triple_indirect_block) =
+ self.get_block::<TripleIndirectBlock>(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::<DoubleIndirectBlock>(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::<IndirectBlock>(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::<T>(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<u32, c_int> {
+ 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<DirectoryEntry> {
+ let block_index_within_inode = (entry_index / 15) as usize;
+ let entry_index_within_block = (entry_index % 15) as usize;
+
+ self.access_block::<DirectoryBlock>(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<DirectoryEntry> {
+ // // 每个 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::<DirectoryBlock>(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::<IndirectBlock>(inode.single_indirect as usize)
+ // {
+ // let block_index = indirect_block.block.entries[block_index_within_inode] as usize;
+ // self.get_block::<DirectoryBlock>(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::<DoubleIndirectBlock>(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::<IndirectBlock>(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::<DirectoryBlock>(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::<TripleIndirectBlock>(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::<DoubleIndirectBlock>(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::<IndirectBlock>(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::<DirectoryBlock>(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)
+ }
+}
diff --git a/src/memory/mod.rs b/src/memory/mod.rs
index 3380d0f..dce7c42 100644
--- a/src/memory/mod.rs
+++ b/src/memory/mod.rs
@@ -2,3 +2,4 @@
/// This is where the crucial block and inode methods presented to upper calls implemented.
pub mod cached_block;
pub mod cached_inode;
+mod inode_iter;