summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChuyan Zhang <me@zcy.moe>2023-11-17 11:40:33 -0800
committerChuyan Zhang <me@zcy.moe>2023-11-17 11:40:33 -0800
commit95d8d84eef645b52d92fd3fb8fdea7aed1f6d474 (patch)
treeab65714726edeec94fd35f424e21a1f77da71b3c /src
parent7a748cadbb2e2ce8c0e045cb8fbd77ccbd47459f (diff)
downloadmyfs-95d8d84eef645b52d92fd3fb8fdea7aed1f6d474.tar.gz
myfs-95d8d84eef645b52d92fd3fb8fdea7aed1f6d474.zip
Layer 1 incomplete
Diffstat (limited to 'src')
-rw-r--r--src/block_device/memory_disk.rs5
-rw-r--r--src/cached_inode.rs7
-rw-r--r--src/disk/bitmap.rs13
-rw-r--r--src/disk/data_block.rs94
-rw-r--r--src/disk/inode.rs184
-rw-r--r--src/disk/mod.rs4
-rw-r--r--src/main.rs451
7 files changed, 614 insertions, 144 deletions
diff --git a/src/block_device/memory_disk.rs b/src/block_device/memory_disk.rs
index 4cffaf2..3876736 100644
--- a/src/block_device/memory_disk.rs
+++ b/src/block_device/memory_disk.rs
@@ -1,5 +1,5 @@
+use crate::block_device::{BlockDevice, BLOCK_SIZE};
use std::cell::RefCell;
-use crate::block_device::{BLOCK_SIZE, BlockDevice};
#[repr(C)]
pub struct MemoryDisk {
@@ -14,7 +14,6 @@ impl MemoryDisk {
arena: RefCell::new(vec![0u8; BLOCK_SIZE * 16384]),
}
}
-
}
impl BlockDevice for MemoryDisk {
@@ -31,4 +30,4 @@ impl BlockDevice for MemoryDisk {
let mut arena = self.arena.borrow_mut();
arena[block_front..block_back].copy_from_slice(buffer);
}
-} \ No newline at end of file
+}
diff --git a/src/cached_inode.rs b/src/cached_inode.rs
new file mode 100644
index 0000000..814c1aa
--- /dev/null
+++ b/src/cached_inode.rs
@@ -0,0 +1,7 @@
+use crate::disk::inode::Inode;
+
+pub struct CachedInode {
+ pub inode: Inode,
+ pub index: usize,
+ pub dirty: bool,
+}
diff --git a/src/disk/bitmap.rs b/src/disk/bitmap.rs
index a5a9cc4..d5a8fe9 100644
--- a/src/disk/bitmap.rs
+++ b/src/disk/bitmap.rs
@@ -19,20 +19,25 @@ impl Bitmap {
dirty_blocks: Vec::new(),
}
}
- pub fn allocate(&mut self) -> usize {
+ pub fn allocate(&mut self) -> Option<usize> {
for (i, byte) in self.data.iter_mut().enumerate() {
let leading_ones = byte.leading_ones();
if leading_ones != 8 {
*byte |= (1 << (7 - leading_ones)) as u8;
self.dirty_blocks.push(i / BLOCK_SIZE);
- return i * 8 + leading_ones as usize;
+ return Some(i * 8 + leading_ones as usize);
}
}
- panic!("No more space for allocation!")
+ None
+ // panic!("No more space for allocation!")
}
pub fn query(&self, index: usize) -> bool {
- self.data[index / 8] & ((1 << (7 - index % 8)) as u8) != 0
+ if index == 0 {
+ false
+ } else {
+ self.data[index / 8] & ((1 << (7 - index % 8)) as u8) != 0
+ }
}
fn write_back(&mut self) {
diff --git a/src/disk/data_block.rs b/src/disk/data_block.rs
new file mode 100644
index 0000000..2160b91
--- /dev/null
+++ b/src/disk/data_block.rs
@@ -0,0 +1,94 @@
+pub trait Block: Default {}
+
+#[derive(Default)]
+pub struct DataBlock([u8; 4096]);
+impl Block for DataBlock {}
+
+const FULL_MAP: u32 = 0b111_111_111_111_111;
+
+#[derive(Default)]
+pub struct DirectoryBlock {
+ entries: [[u8; 256]; 15],
+ inode_ids: [usize; 15],
+ occupancy_map: u32,
+ reserved: [u8; 132],
+}
+
+impl Block for DirectoryBlock {}
+
+impl DirectoryBlock {
+ fn vacant(&self) -> bool {
+ self.occupancy_map & FULL_MAP != FULL_MAP
+ }
+
+ fn first_free(&self) -> Option<usize> {
+ todo!()
+ }
+
+ fn mark_busy(&mut self, entry_id: usize) {
+ todo!()
+ }
+
+ /// 需要判断 entry_name.len() <= 255
+ pub fn write_entry(&mut self, entry_name: &[u8], entry_inode_id: usize) -> Option<usize> {
+ if let Some(entry_id) = self.first_free() {
+ self.mark_busy(entry_id);
+ self.entries[entry_id].copy_from_slice(entry_name);
+ self.inode_ids[entry_id] = entry_inode_id;
+ Some(entry_id)
+ } else {
+ None
+ }
+ }
+}
+
+#[derive(Default)]
+pub struct IndirectBlock {
+ pub entries: [u32; 1024],
+}
+
+impl Block for IndirectBlock {}
+
+impl IndirectBlock {
+ pub fn full(&self) -> bool {
+ todo!()
+ }
+
+ pub fn allocate(&mut self) -> Option<usize> {
+ todo!()
+ }
+}
+
+#[derive(Default)]
+pub struct DoubleIndirectBlock {
+ pub indirect: [u32; 1024],
+}
+
+impl Block for DoubleIndirectBlock {}
+
+impl DoubleIndirectBlock {
+ pub fn full(&self) -> bool {
+ todo!()
+ }
+
+ pub fn allocate(&mut self) -> Option<usize> {
+ todo!()
+ }
+}
+
+#[derive(Default)]
+pub struct TripleIndirectBlock {
+ pub double_indirect: [u32; 1024],
+}
+
+impl Block for TripleIndirectBlock {}
+
+impl TripleIndirectBlock {
+ pub fn full(&self) -> bool {
+ todo!()
+ }
+
+ pub fn allocate(&mut self) -> Option<usize> {
+ todo!()
+ }
+}
diff --git a/src/disk/inode.rs b/src/disk/inode.rs
index f38508a..6adc75d 100644
--- a/src/disk/inode.rs
+++ b/src/disk/inode.rs
@@ -42,111 +42,125 @@ pub struct Inode {
mode: InodeMode,
uid: u32,
size: u32,
- atime: u32, // time in seconds
- ctime: u32,
- mtime: u32,
- dtime: u32,
+ atime: u32, // access time, in seconds
+ ctime: u32, // change time, in seconds
+ mtime: u32, // modify time, in seconds
+ crtime: u32, // create time, in seconds
gid: u32,
- n_links: u16,
- n_blocks: u32,
+ pub n_links: u16,
+ pub n_blocks: u32,
flags: u32, // TODO: do we actually need this? maybe just return 0
- direct: [u32; DIRECT_NUMBER],
- single_indirect: u32,
- double_indirect: u32,
- triple_indirect: u32,
+ pub direct: [u32; DIRECT_NUMBER],
+ pub single_indirect: u32,
+ pub double_indirect: u32,
+ pub triple_indirect: u32,
generation: u32,
file_acl: u32,
dir_acl: u32, // TODO do we have to implement ACL......?
}
impl Inode {
- pub fn directory() -> Self {
+ fn new(
+ mode: InodeMode,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
Self {
- mode: InodeMode::IFDIR
- | InodeMode::IRUSR
- | InodeMode::IWUSR
- | InodeMode::IXUSR
- | InodeMode::IRGRP
- | InodeMode::IXGRP
- | InodeMode::IROTH
- | InodeMode::IXOTH,
- // Directory, 755 permissions
- uid: 0,
+ mode,
+ uid,
size: 0,
- atime: 0,
- ctime: 0,
- mtime: 0,
- dtime: 0,
- gid: 0,
+ atime: time,
+ ctime: time,
+ mtime: time,
+ crtime: time,
+ gid,
n_links: 0,
n_blocks: 0,
- flags: 0,
+ flags,
direct: [0; DIRECT_NUMBER],
single_indirect: 0,
double_indirect: 0,
triple_indirect: 0,
- generation: 0,
- file_acl: 0,
- dir_acl: 0,
+ generation,
+ file_acl,
+ dir_acl,
}
}
- pub fn file() -> Self {
- Self {
- mode: InodeMode::IFREG
- | InodeMode::IRUSR
- | InodeMode::IWUSR
- | InodeMode::IXUSR
- | InodeMode::IRGRP
- | InodeMode::IXGRP
- | InodeMode::IROTH
- | InodeMode::IXOTH,
- // RegularFile, 755 permissions
- uid: 0,
- size: 0,
- atime: 0,
- ctime: 0,
- mtime: 0,
- dtime: 0,
- gid: 0,
- n_links: 0,
- n_blocks: 0,
- flags: 0,
- direct: [0; DIRECT_NUMBER],
- single_indirect: 0,
- double_indirect: 0,
- triple_indirect: 0,
- generation: 0,
- file_acl: 0,
- dir_acl: 0,
- }
+ pub fn make_inode(
+ permissions: u16,
+ mode: InodeMode,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | mode,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
}
-}
-//
-// #[repr(C)]
-// #[derive(Debug, Default)]
-// pub struct FileInode {
-// file_size: u32,
-// direct_blocks: [u32; DIRECT_NUMBER],
-// indirect_block: u32,
-// doubly_indirect_block: u32,
-// } // sizeof(FileInode) == 124 bytes
-//
-// #[repr(C)]
-// #[derive(Debug, Default)]
-// pub struct DirectoryInode {
-// child_number: u32,
-// direct_blocks: [u32; DIRECT_NUMBER],
-// indirect_block: u32,
-// doubly_indirect_block: u32,
-// } // sizeof(FileInode) == 124 bytes
-//
-// #[repr(C)]
-// #[derive(Debug)]
-// pub enum Inode {
-// File(FileInode),
-// Directory(DirectoryInode),
-// } // sizeof(Inode) == 128 bytes
+ pub fn directory(
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | InodeMode::IFDIR,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
+ }
+ pub fn file(
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | InodeMode::IFREG,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
+ }
+
+ pub fn empty() -> Self {
+ Self::new(InodeMode(0), 0, 0, 0, 0, 0, 0, 0)
+ }
+}
pub const INODE_SIZE: usize = std::mem::size_of::<Inode>();
diff --git a/src/disk/mod.rs b/src/disk/mod.rs
index e4e4216..404c6ab 100644
--- a/src/disk/mod.rs
+++ b/src/disk/mod.rs
@@ -1,2 +1,4 @@
-pub mod inode;
pub mod bitmap;
+pub mod inode;
+
+pub mod data_block;
diff --git a/src/main.rs b/src/main.rs
index 414baaf..0e799e4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,17 +1,26 @@
mod block_device;
+mod cached_inode;
mod disk;
+use std::collections::HashMap;
use clap::Parser;
-use fuser::{Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, Request};
+use fuser::{
+ Filesystem, KernelConfig, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty,
+ ReplyEntry, ReplyLseek, ReplyWrite, Request, TimeOrNow,
+};
+use log::debug;
use std::ffi::OsStr;
use std::sync::Arc;
-use std::time::Duration;
-use log::debug;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+use crate::cached_inode::CachedInode;
+use crate::disk::data_block::{Block, DoubleIndirectBlock, IndirectBlock, TripleIndirectBlock};
+use crate::disk::inode::InodeMode;
use block_device::{memory_disk::MemoryDisk, BlockDevice, BLOCK_SIZE};
use disk::bitmap::Bitmap;
use disk::inode::{Inode, INODE_SIZE};
-use libc::ENOENT;
+use libc::{c_int, ENOENT, ENOSPC, ENOSYS};
+use users::{get_current_gid, get_current_uid};
#[derive(Parser, Debug)]
#[command(author, version, about)]
@@ -53,6 +62,9 @@ struct MyFS {
inode_bitmap: Bitmap,
inode_start_block: usize,
data_start_block: usize,
+
+ cached_inode: HashMap<usize, CachedInode>,
+ cache: [[u8; 4096]; 8192],
}
impl MyFS {
@@ -71,14 +83,20 @@ impl MyFS {
// Thus we have x = floor(BLK_SIZE * C / (BLK_SIZE + 1))
let data_block_number = BLOCK_SIZE * blocks_remaining / (BLOCK_SIZE + 1);
let data_bitmap_block_number = blocks_remaining - data_block_number;
- debug!("dbbn: {}", data_bitmap_block_number);
- debug!("ibbn: {}", inode_bitmap_block_number);
- debug!("ibn: {}", inode_block_number);
- debug!("dbn: {}", data_block_number);
- debug!("sum: {}", 1 + data_bitmap_block_number + inode_bitmap_block_number + inode_block_number + data_block_number);
-
- let mut data_bitmap = Bitmap::new(1, data_bitmap_block_number, device.clone());
- let mut inode_bitmap = Bitmap::new(
+ debug!("data_bitmap_block_number: {}", data_bitmap_block_number);
+ debug!("inode_bitmap_block_number: {}", inode_bitmap_block_number);
+ debug!("inode_block_number: {}", inode_block_number);
+ debug!("data_block_number: {}", data_block_number);
+ debug!(
+ "sum: {}",
+ 1 + data_bitmap_block_number
+ + inode_bitmap_block_number
+ + inode_block_number
+ + data_block_number
+ );
+
+ let data_bitmap = Bitmap::new(1, data_bitmap_block_number, device.clone());
+ let inode_bitmap = Bitmap::new(
data_bitmap_block_number + 1,
inode_bitmap_block_number,
device.clone(),
@@ -92,51 +110,262 @@ impl MyFS {
+ inode_bitmap_block_number
+ inode_block_number
+ 1,
+ cached_inode: HashMap::new(),
+ cache: [[0; 4096]; 8192],
};
- let _ = fs.inode_bitmap.allocate(); // Inode starts from 1
- let root_inode_index = fs.inode_bitmap.allocate();
+ let _ = fs.data_bitmap.allocate().unwrap(); // data block 0 is not usable
+ let _ = fs.inode_bitmap.allocate().unwrap(); // inode block 0 is not usable
+ let root_inode_index = fs.inode_bitmap.allocate().unwrap(); // Inode starts from 1
assert_eq!(root_inode_index, 1);
let (root_inode_block, root_inode_offset) = fs.locate_inode(root_inode_index);
- fs.put_inode(root_inode_block, root_inode_offset, Inode::directory());
+ fs.put_inode(
+ root_inode_block,
+ root_inode_offset,
+ &Inode::directory(
+ 0o755,
+ get_current_uid(),
+ get_current_gid(),
+ Self::time_now(),
+ 0,
+ 0,
+ 0,
+ 0,
+ ),
+ );
fs
}
- // pub fn allocate_inode(&mut self) -> usize {
- // self.inode_bitmap.allocate()
- // }
+ fn time_now() -> u32 {
+ SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .expect("How can current time be earlier than UNIX_EPOCH?")
+ .as_secs() as u32
+ }
pub fn inode_active(&self, inode: usize) -> bool {
self.inode_bitmap.query(inode)
}
/// 输入 inode 编号, 返回它对应的 block number 和 block 内 offset
- pub fn locate_inode(&self, inode: usize) -> (usize, usize) {
+ pub fn locate_inode(&self, inode_index: usize) -> (usize, usize) {
let block_number =
- inode / INODE_PER_BLOCK + 1 + self.inode_bitmap.length + self.data_bitmap.length;
- let block_offset = inode % INODE_PER_BLOCK * INODE_SIZE;
+ inode_index / INODE_PER_BLOCK + 1 + self.inode_bitmap.length + self.data_bitmap.length;
+ let block_offset = inode_index % INODE_PER_BLOCK * INODE_SIZE;
(block_number, block_offset)
}
+ pub fn create_inode(
+ &mut self,
+ permissions: u16,
+ mode: InodeMode,
+ uid: u32,
+ gid: u32,
+ flags: u32,
+ ) -> Option<usize> {
+ self.inode_bitmap.allocate().map(|inode_index| {
+ let inode = CachedInode {
+ inode: Inode::make_inode(
+ permissions,
+ mode,
+ uid,
+ gid,
+ Self::time_now(),
+ flags,
+ 0,
+ 0,
+ 0,
+ ),
+ index: inode_index,
+ dirty: false,
+ };
+ self.cached_inode.insert(inode_index, inode);
+ inode_index
+ })
+ }
+
+ /// 得有一个 Inode Cache 数据结构!
+ pub fn read_inode(
+ &mut self,
+ index: usize,
+ ) -> bool {
+ if self.cached_inode.contains_key(&index) {
+ return true;
+ } // 已经在 Inode Cache 里了, 返回 true
+ if self.inode_bitmap.query(index) {
+ let (block, offset) = self.locate_inode(index);
+ let inode = CachedInode {
+ inode: self.fetch_inode(block, offset),
+ index,
+ dirty: false,
+ };
+ self.cached_inode.insert(index, inode);
+ return true;
+ } // 没有在 Inode Cache 里, 但是是有效 inode, 可以读到 Cache 里, 返回 true
+ false // 都没有, 返回 false.
+ }
+
+ pub fn write_back_inode(
+ &mut self,
+ index: usize,
+ ) -> bool {
+ if let Some(cached_inode) = self.cached_inode.get_mut(&index) {
+ if cached_inode.dirty {
+ let (block, offset) = self.locate_inode(cached_inode.index);
+ self.put_inode(block, offset, &cached_inode.inode);
+ cached_inode.dirty = false;
+ }
+ true // Inode 在 Cache 中, 如果 dirty 则写回, 如果不脏不用管, 都返回写回成功.
+ } else {
+ false // Inode 没有在 Cache 中, 返回失败.
+ }
+ }
+
// TODO: 实现一个 LRU 的 cache 机制, 不要每次都开 buffer
- pub fn put_inode(&mut self, block: usize, offset: usize, inode: Inode) {
+ fn put_inode(&mut self, block: usize, offset: usize, inode: &Inode) {
let mut buffer = vec![0u8; BLOCK_SIZE];
self.device.read(block, buffer.as_mut_slice());
- let inode_raw = &inode as *const Inode as *const u8;
+ let inode_raw = inode as *const Inode as *const u8;
let inode_slice = unsafe { std::slice::from_raw_parts(inode_raw, INODE_SIZE) };
buffer[offset..offset + INODE_SIZE].copy_from_slice(inode_slice);
self.device.write(block, buffer.as_slice());
}
+ pub fn write_inode(&mut self, inode_index: usize, inode: &Inode) -> bool {
+ if self.inode_active(inode_index) {
+ let (block, offset) = self.locate_inode(inode_index);
+ self.put_inode(block, offset, inode);
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn get_inode(&self, inode_index: usize) -> Option<Inode> {
+ if self.inode_active(inode_index) {
+ let (block, offset) = self.locate_inode(inode_index);
+ Some(self.fetch_inode(block, offset))
+ } else {
+ None
+ }
+ }
+
+ /// 为 Inode 分配新 block, 返回 block 的编号
+ pub fn allocate_block(&mut self, inode: &mut Inode) -> Option<u32> {
+ /// 从 direct block 里面尝试分配
+ for index in inode.direct.iter_mut() {
+ /// 如果这个位置没被分配, 分配一个 index 塞进去
+ if self.data_bitmap.query(*index as usize) == false {
+ let block_index = self.data_bitmap.allocate() as u32;
+ *index = block_index;
+ inode.n_blocks += 1;
+ // TODO 标记 inode 所在 block 为脏
+ return Some(block_index);
+ }
+ }
+
+ /// 如果这个 indirect block 还未分配, 分配一个
+ if self.data_bitmap.query(inode.single_indirect as usize) == false {
+ // TODO 标记 inode 所在 block 为脏
+ inode.single_indirect = self.data_bitmap.allocate() as u32;
+ }
+ if let Some(block_index) = self.allocate_in_indirect(inode.single_indirect) {
+ // TODO 标记 inode 所在 block 为脏
+ inode.n_blocks += 1;
+ return Some(block_index);
+ }
+
+ /// 如果 double indirect block 还未分配, 分配一个
+ if self.data_bitmap.query(inode.double_indirect as usize) == false {
+ // TODO 标记 inode 所在 block 为脏
+ inode.double_indirect = self.data_bitmap.allocate() as u32;
+ }
+ if let Some(block_index) = self.alloc_in_double_indirect(inode.double_indirect) {
+ // TODO 标记 inode 所在 block 为脏
+ inode.n_blocks += 1;
+ return Some(block_index);
+ }
+
+ /// 如果 triple indirect block 还未分配, 分配一个
+ if self.data_bitmap.query(inode.triple_indirect as usize) == false {
+ // TODO 标记 inode 所在 block 为脏
+ inode.triple_indirect = self.data_bitmap.allocate() as u32;
+ }
+ if let Some(block_index) = self.alloc_in_triple_indirect(inode.triple_indirect) {
+ // TODO 标记 inode 所在 block 为脏
+ inode.n_blocks += 1;
+ return Some(block_index);
+ }
+
+ /// 到这里说明真没空间了
+ None
+ }
+
+ fn allocate_in_indirect(&mut self, indirect_entry: u32) -> Option<u32> {
+ // 取出 single indirect block, 尝试在里面分配
+ let indirect = self.fetch_block::<IndirectBlock>(*indirect_entry);
+ for entry in indirect.entries.iter_mut() {
+ // 如果这个位置没被分配, 分配一个 index 塞进去
+ if self.data_bitmap.query(*entry as usize) == false {
+ let block_index = self.data_bitmap.allocate() as u32;
+ *entry = block_index;
+ // TODO 标记 single indirect 为脏
+ return Some(block_index);
+ }
+ }
+ None
+ }
+
+ fn alloc_in_double_indirect(&mut self, double_indirect_entry: u32) -> Option<u32> {
+ let double_indirect = self.fetch_block::<DoubleIndirectBlock>(double_indirect_entry);
+ for indirect_entry in double_indirect.indirect.iter_mut() {
+ if self.data_bitmap.query(*indirect_entry as usize) == false {
+ // TODO 标记 double indirect 为脏
+ *indirect_entry = self.data_bitmap.allocate() as u32;
+ }
+ if let Some(block_index) = self.allocate_in_indirect(*indirect_entry) {
+ return Some(block_index);
+ }
+ }
+ None
+ }
+
+ fn alloc_in_triple_indirect(&mut self, triple_indirect_entry: u32) -> Option<u32> {
+ let triple_indirect = self.fetch_block::<TripleIndirectBlock>(triple_indirect_entry);
+ for double_indirect_entry in triple_indirect.double_indirect.iter_mut() {
+ if self.data_bitmap.query(*double_indirect_entry as usize) == false {
+ // TODO 标记 triple indirect 为脏
+ *double_indirect_entry = self.data_bitmap.allocate() as u32;
+ }
+ if let Some(block_index) = self.alloc_in_double_indirect(*double_indirect_entry) {
+ return Some(block_index);
+ }
+ }
+ None
+ }
+
+ // TODO: 实现一个 LRU 的 cache 机制, 不要每次都开 buffer
+ fn fetch_block<T: Block>(&self, block_index: u32) -> T {
+ let mut buffer = vec![0u8; BLOCK_SIZE];
+ self.device
+ .read(block_index as usize, buffer.as_mut_slice());
+
+ let block = T::default();
+ let block_slice =
+ unsafe { std::slice::from_raw_parts_mut(&block as *const T as *mut u8, BLOCK_SIZE) };
+ block_slice.copy_from_slice(&buffer[..]);
+ block
+ }
+
// TODO: 实现一个 LRU 的 cache 机制, 不要每次都开 buffer
- pub fn get_inode(&self, block: usize, offset: usize) -> Inode {
+ fn fetch_inode(&self, block: usize, offset: usize) -> Inode {
let mut buffer = vec![0u8; BLOCK_SIZE];
self.device.read(block, buffer.as_mut_slice());
- let inode = Inode::file();
+ let inode = Inode::empty();
let inode_slice = unsafe {
std::slice::from_raw_parts_mut(&inode as *const Inode as *mut u8, INODE_SIZE)
};
@@ -146,29 +375,159 @@ impl MyFS {
}
impl Filesystem for MyFS {
- fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
+ fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> Result<(), c_int> {
+ debug!("Filesystem::init called.");
+ Ok(())
+ }
+
+ fn destroy(&mut self) {
+ debug!("Filesystem::destroy()");
+ }
+
+ fn access(&mut self, _req: &Request<'_>, ino: u64, mask: i32, reply: ReplyEmpty) {
+ debug!("Filesystem::getattr(ino: {}, mask: {})", ino, mask);
+ if let Some(inode) = self.get_inode(ino as usize) {
+ reply.ok()
+ } else {
+ reply.error(ENOENT)
+ }
+ }
+
+ fn mkdir(
+ &mut self,
+ _req: &Request<'_>,
+ parent: u64,
+ name: &OsStr,
+ mode: u32,
+ umask: u32,
+ reply: ReplyEntry,
+ ) {
debug!(
- "Filesystem::lookup called with parent {} name {}",
- parent,
- name.to_str().unwrap()
+ "Filesystem::mkdir(parent: {}, name: {:?}, mode: {}, umask: {})",
+ parent, name, mode, umask
);
- let parent = parent as usize;
- if self.inode_active(parent) {
- let (block, offset) = self.locate_inode(parent);
- let inode = self.get_inode(block, offset);
- debug!("{:?}", inode);
+ if let Some(inode) = self.get_inode(parent as usize) {
+ } else {
+ reply.error(ENOENT);
}
- reply.error(ENOENT);
+ // reply.error(ENOSPC);
+ }
+
+ fn mknod(
+ &mut self,
+ _req: &Request<'_>,
+ parent: u64,
+ name: &OsStr,
+ mode: u32,
+ umask: u32,
+ rdev: u32,
+ reply: ReplyEntry,
+ ) {
+ debug!(
+ "Filesystem::mknod(parent: {}, name: {:?}, mode: {}, umask: {}, rdev: {})",
+ parent, name, mode, umask, rdev
+ );
+ reply.error(ENOSPC);
+ }
+
+ fn forget(&mut self, _req: &Request<'_>, _ino: u64, _nlookup: u64) {
+ debug!("Filesystem::forget()");
+ todo!("This is a dumb implementation")
}
fn getattr(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyAttr) {
- debug!("Filesystem::getattr called with ino {}", ino);
+ debug!("Filesystem::getattr(ino: {})", ino);
let ino = ino as usize;
- if self.inode_active(ino) {
- let (block, offset) = self.locate_inode(ino);
- let inode = self.get_inode(block, offset);
- debug!("{:?}", inode);
+ if let Some(inode) = self.get_inode(ino) {
+ // debug!("{:?}", inode);
+ }
+ reply.error(ENOENT);
+ }
+
+ fn setattr(
+ &mut self,
+ _req: &Request<'_>,
+ ino: u64,
+ mode: Option<u32>,
+ uid: Option<u32>,
+ gid: Option<u32>,
+ size: Option<u64>,
+ _atime: Option<TimeOrNow>,
+ _mtime: Option<TimeOrNow>,
+ _ctime: Option<SystemTime>,
+ fh: Option<u64>,
+ _crtime: Option<SystemTime>,
+ _chgtime: Option<SystemTime>,
+ _bkuptime: Option<SystemTime>,
+ flags: Option<u32>,
+ reply: ReplyAttr,
+ ) {
+ debug!(
+ "Filesystem::setattr(ino: {:#x?}, mode: {:?}, uid: {:?}, \
+ gid: {:?}, size: {:?}, fh: {:?}, flags: {:?})",
+ ino, mode, uid, gid, size, fh, flags
+ );
+ reply.error(ENOSYS);
+ }
+
+ fn readlink(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyData) {
+ debug!("[Not Implemented] readlink(ino: {})", ino);
+ reply.error(ENOSYS);
+ }
+
+ fn lseek(
+ &mut self,
+ _req: &Request<'_>,
+ ino: u64,
+ fh: u64,
+ offset: i64,
+ whence: i32,
+ reply: ReplyLseek,
+ ) {
+ debug!(
+ "lseek(ino: {:#x?}, fh: {}, offset: {}, whence: {})",
+ ino, fh, offset, whence
+ );
+ reply.error(ENOSYS);
+ }
+
+ fn copy_file_range(
+ &mut self,
+ _req: &Request<'_>,
+ ino_in: u64,
+ fh_in: u64,
+ offset_in: i64,
+ ino_out: u64,
+ fh_out: u64,
+ offset_out: i64,
+ len: u64,
+ flags: u32,
+ reply: ReplyWrite,
+ ) {
+ debug!(
+ "copy_file_range(ino_in: {:#x?}, fh_in: {}, \
+ offset_in: {}, ino_out: {:#x?}, fh_out: {}, offset_out: {}, \
+ len: {}, flags: {})",
+ ino_in, fh_in, offset_in, ino_out, fh_out, offset_out, len, flags
+ );
+ reply.error(ENOSYS);
+ }
+
+ fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
+ debug!(
+ "Filesystem::lookup called with parent {} name {}",
+ parent,
+ name.to_str().unwrap()
+ );
+ let parent = parent as usize;
+ if let Some(inode) = self.get_inode(parent) {
+ // debug!("{:?}", inode);
}
+ // if self.inode_active(parent) {
+ // let (block, offset) = self.locate_inode(parent);
+ // let inode = self.get_inode(block, offset);
+ // debug!("{:?}", inode);
+ // }
reply.error(ENOENT);
}
@@ -202,18 +561,8 @@ fn main() {
env_logger::init();
let args = Args::parse();
let mount_point = args.mount_point.unwrap();
- // let mut options = vec![
- // MountOption::RO,
- // MountOption::FSName("hello".to_string()),
- // ];
- // if args.allow_root {
- // options.push(MountOption::AutoUnmount);
- // }
- // if args.allow_root {
- // options.push(MountOption::AllowRoot);
- // }
let options = vec![
- MountOption::RO,
+ // MountOption::RO,
MountOption::FSName("hello".to_string()),
MountOption::AutoUnmount,
MountOption::AllowRoot,