summaryrefslogtreecommitdiff
path: root/src/memory
diff options
context:
space:
mode:
Diffstat (limited to 'src/memory')
-rw-r--r--src/memory/cached_block.rs53
-rw-r--r--src/memory/cached_inode.rs87
-rw-r--r--src/memory/dir_entry.rs40
3 files changed, 124 insertions, 56 deletions
diff --git a/src/memory/cached_block.rs b/src/memory/cached_block.rs
index 783e987..002a75b 100644
--- a/src/memory/cached_block.rs
+++ b/src/memory/cached_block.rs
@@ -75,7 +75,7 @@ impl<T: Block> BlockCache<T> {
if !self.cache.contains(&index) {
self.load_block(index);
}
- self.cache.get(&index).map(convert::<T,U>)
+ self.cache.get(&index).map(convert::<T, U>)
}
/// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载.
@@ -90,6 +90,24 @@ impl<T: Block> BlockCache<T> {
})
}
+ /// 向 LRU cache 中插入一个全新初始化的 block
+ /// 这个 block 全 0, 而且是 dirty 的, 即使被挤出去也会触发一次落盘
+ pub(crate) fn init_block(&mut self, index: usize) {
+ let allocated_block = CachedBlock {
+ block: T::default(),
+ index,
+ dirty: true,
+ };
+ if let Some((old_index, old_block)) = self.cache.push(index, allocated_block) {
+ if old_block.dirty {
+ let old_block_ptr = &old_block.block as *const T 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);
+ }
+ }
+ }
+
/// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载.
pub(crate) fn peek_block<U: Block>(&self, index: usize) -> Option<&CachedBlock<U>> {
self.cache.peek(&index).map(convert::<T, U>)
@@ -117,26 +135,33 @@ impl<T: Block> BlockCache<T> {
}
impl AyaFS {
- pub(crate) fn load_block(&mut self, index: usize) -> bool {
- if !self.data_bitmap.query(index) {
- self.cached_blocks.pop(&index);
- // deallocate 时只更新 bitmap 没有动 cache, lazy 地驱逐 cache 中的无效 entry.
- return false;
- }
- self.cached_blocks.load_block(index)
+ pub(crate) fn init_block(&mut self, index: usize) {
+ self.cached_blocks.init_block(index);
}
pub(crate) fn get_block<T: Block>(&mut self, index: usize) -> Option<&CachedBlock<T>> {
- self.data_bitmap
- .query(index)
- .then(|| self.cached_blocks.get_block::<T>(index).unwrap())
+ if self.data_bitmap.query(index) {
+ Some(self.cached_blocks.get_block::<T>(index).unwrap())
+ } else {
+ self.cached_blocks.pop(&index);
+ None
+ }
+ // self.data_bitmap
+ // .query(index)
+ // .then(|| self.cached_blocks.get_block::<T>(index).unwrap())
// 返回 None 当且仅当 data_bitmap 中这个 block 为 invalid
}
pub(crate) fn get_block_mut<T: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<T>> {
- self.data_bitmap
- .query(index)
- .then(|| self.cached_blocks.get_block_mut::<T>(index).unwrap())
+ if self.data_bitmap.query(index) {
+ Some(self.cached_blocks.get_block_mut::<T>(index).unwrap())
+ } else {
+ self.cached_blocks.pop(&index);
+ None
+ }
+ // self.data_bitmap
+ // .query(index)
+ // .then(|| self.cached_blocks.get_block_mut::<T>(index).unwrap())
// 返回 None 当且仅当 data_bitmap 中这个 block 为 invalid
}
diff --git a/src/memory/cached_inode.rs b/src/memory/cached_inode.rs
index b1be2de..aa4f5e3 100644
--- a/src/memory/cached_inode.rs
+++ b/src/memory/cached_inode.rs
@@ -1,10 +1,8 @@
use crate::disk::block::{DirectoryBlock, DirectoryEntry, InodeBlock};
-use crate::disk::inode::{Inode, InodeMode, INODE_SIZE};
-use crate::utils::from_filetype;
+use crate::disk::inode::{Inode, INODE_SIZE};
use crate::{utils, AyaFS};
use and_then_some::BoolExt;
-use fuser::FileType;
-use log::debug;
+use libc::{c_int, EISDIR, ENOENT, ENOTDIR};
impl AyaFS {
pub(crate) fn create_file(
@@ -22,12 +20,14 @@ impl AyaFS {
})
}
+ /// 根目录的 parent_inode_number 传入 None, 会直接以自己作为 .. 的 inode number
pub(crate) fn create_directory(
&mut self,
permissions: u16,
uid: u32,
gid: u32,
flags: u32,
+ parent_inode_number: Option<u32>,
) -> Option<(usize, &Inode)> {
self.inode_bitmap.allocate().map(|inode_index| {
// 创建 Inode
@@ -53,7 +53,7 @@ impl AyaFS {
// add dot dot entry
directory_block.block.entries[1] = DirectoryEntry {
- inode: 0, // TODO set this as parent inode number
+ inode: parent_inode_number.unwrap_or(inode_index as u32),
record_len: 264,
name_len: 2,
file_type: 0x2,
@@ -70,31 +70,60 @@ impl AyaFS {
(inode_index, self.get_inode(inode_index).unwrap())
})
}
+
+ pub(crate) fn remove_file(&mut self, inode_index: usize) -> Result<bool, c_int> {
+ if self.inode_bitmap.query(inode_index) {
+ self.inode_bitmap.deallocate(inode_index);
+ let (block_index, offset) = self.locate_inode(inode_index);
+ if let Some(cached_block) = self.cached_inodes.get_block::<InodeBlock>(block_index) {
+ let inode = cached_block.block.inodes[offset / INODE_SIZE].clone();
+ if !inode.is_file() {
+ return Err(EISDIR);
+ }
+ self.deallocate_all_blocks_for(&inode).unwrap();
+ }
+ Ok(true)
+ } else {
+ Err(ENOENT)
+ }
+ }
+
+ pub(crate) fn remove_dir(&mut self, inode_index: usize) -> Result<bool, c_int> {
+ if self.inode_bitmap.query(inode_index) {
+ self.inode_bitmap.deallocate(inode_index);
+ let (block_index, offset) = self.locate_inode(inode_index);
+ if let Some(cached_block) = self.cached_inodes.get_block::<InodeBlock>(block_index) {
+ let inode = cached_block.block.inodes[offset / INODE_SIZE].clone();
+ if !inode.is_dir() {
+ return Err(ENOTDIR);
+ }
+ // TODO 递归删除所有下面的 direntry 里的 inode, 注意排除 . 和 ..
+ }
+ Ok(true)
+ } else {
+ Err(ENOENT)
+ }
+ }
- pub(crate) fn create_inode(
- &mut self,
- permissions: u16,
- mode: InodeMode,
- uid: u32,
- gid: u32,
- flags: u32,
- ) -> Option<usize> {
- self.inode_bitmap.allocate().map(|inode_index| {
- self.get_inode_mut(inode_index).map(|inode| {
- *inode = Inode::make_inode(
- permissions,
- mode,
- uid,
- gid,
- utils::time_now(),
- flags,
- 0,
- 0,
- 0,
- );
- });
- inode_index
- })
+ pub(crate) fn remove_inode(&mut self, inode_index: usize) -> bool {
+ if self.inode_bitmap.query(inode_index) {
+ self.inode_bitmap.deallocate(inode_index);
+ let (block_index, offset) = self.locate_inode(inode_index);
+ if let Some(cached_block) = self.cached_inodes.get_block::<InodeBlock>(block_index) {
+ let inode = &cached_block.block.inodes[offset / INODE_SIZE].clone();
+
+ if inode.is_file() {
+ self.deallocate_all_blocks_for(inode).unwrap();
+ } else if inode.is_dir() {
+ // TODO 把 dir 下所有子目录 remove 掉
+ } else {
+ unimplemented!("only file and dir are implemented!");
+ }
+ }
+ true
+ } else {
+ false
+ }
}
pub(crate) fn update_inode(&mut self, inode_index: usize, inode: Inode) -> bool {
diff --git a/src/memory/dir_entry.rs b/src/memory/dir_entry.rs
index 0ade23f..2d961db 100644
--- a/src/memory/dir_entry.rs
+++ b/src/memory/dir_entry.rs
@@ -1,15 +1,21 @@
-use std::ffi::OsStr;
-use std::os::unix::ffi::OsStrExt;
-use libc::{c_int, ENOENT, ENOSPC};
use crate::disk::block::{DirectoryBlock, DirectoryEntry};
-use crate::disk::inode::{Inode};
+use crate::disk::inode::Inode;
use crate::AyaFS;
+use libc::{c_int, ENOENT, ENOSPC};
+use std::ffi::OsStr;
+use std::os::unix::ffi::OsStrExt;
impl AyaFS {
+ /// 删除所有的 dir entry, 递归
+ pub(crate) fn clear_direntry(&mut self, parent_inode: &mut Inode) -> Result<(), c_int> {
+ todo!()
+ }
+
+ /// 删除第 entry_index 个 dir entry
pub(crate) fn remove_direntry(
&mut self,
parent_inode: &mut Inode,
- entry_index: u32
+ entry_index: u32,
) -> Result<(), c_int> {
let block_index_within_inode = (entry_index / 15) as usize;
let entry_index_within_block = (entry_index % 15) as usize;
@@ -18,7 +24,8 @@ impl AyaFS {
Some(directory_block) => {
if directory_block.block.query(entry_index_within_block) {
directory_block.block.deallocate(entry_index_within_block);
- directory_block.block.entries[entry_index_within_block] = DirectoryEntry::default();
+ directory_block.block.entries[entry_index_within_block] =
+ DirectoryEntry::default();
Ok(())
} else {
Err(ENOENT)
@@ -31,7 +38,7 @@ impl AyaFS {
pub(crate) fn add_direntry(
&mut self,
parent_inode: &mut Inode,
- child_inode_index: u32,
+ child_inode_index: usize,
child_inode_name: &OsStr,
child_inode: &Inode,
) -> Result<u32, c_int> {
@@ -45,7 +52,9 @@ impl AyaFS {
}
}
// 寻找当前块里有没有空闲空间
- if let Some(directory_block) = self.access_block_mut::<DirectoryBlock>(parent_inode, block_index_within_inode) {
+ if let Some(directory_block) =
+ self.access_block_mut::<DirectoryBlock>(parent_inode, block_index_within_inode)
+ {
if let Some(entry_index_within_block) = directory_block.block.allocate() {
// 如果有空闲空间, 可以分配一个块
let name_len = child_inode_name.len() as u8;
@@ -54,7 +63,7 @@ impl AyaFS {
name.copy_from_slice(child_inode_name.as_bytes());
let dir_entry = DirectoryEntry {
- inode: child_inode_index,
+ inode: child_inode_index as u32,
record_len: 264,
name_len,
file_type,
@@ -66,12 +75,12 @@ impl AyaFS {
}
}
block_index_within_inode += 1;
- };
+ }
}
pub(crate) fn get_direntry(
&mut self,
parent_inode: &Inode,
- entry_index: u32
+ 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;
@@ -87,13 +96,18 @@ impl AyaFS {
}
// TODO 实现一个带 cache 的版本
- pub fn lookup_name(&mut self, parent_inode: &Inode, name: &OsStr) -> Result<(u32, u32, Inode), c_int> {
+ /// 返回 inode_index, inode 在 parent 里的 index, inode 本身
+ pub fn lookup_name(
+ &mut self,
+ parent_inode: &Inode,
+ name: &OsStr,
+ ) -> Result<(u32, 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, entry_index, inode))
+ return Ok((entry.inode, entry_index, inode));
}
}
entry_index += 1;