diff options
author | Chuyan Zhang <me@zcy.moe> | 2023-11-17 11:40:33 -0800 |
---|---|---|
committer | Chuyan Zhang <me@zcy.moe> | 2023-11-17 11:40:33 -0800 |
commit | 95d8d84eef645b52d92fd3fb8fdea7aed1f6d474 (patch) | |
tree | ab65714726edeec94fd35f424e21a1f77da71b3c /src | |
parent | 7a748cadbb2e2ce8c0e045cb8fbd77ccbd47459f (diff) | |
download | myfs-95d8d84eef645b52d92fd3fb8fdea7aed1f6d474.tar.gz myfs-95d8d84eef645b52d92fd3fb8fdea7aed1f6d474.zip |
Layer 1 incomplete
Diffstat (limited to 'src')
-rw-r--r-- | src/block_device/memory_disk.rs | 5 | ||||
-rw-r--r-- | src/cached_inode.rs | 7 | ||||
-rw-r--r-- | src/disk/bitmap.rs | 13 | ||||
-rw-r--r-- | src/disk/data_block.rs | 94 | ||||
-rw-r--r-- | src/disk/inode.rs | 184 | ||||
-rw-r--r-- | src/disk/mod.rs | 4 | ||||
-rw-r--r-- | src/main.rs | 451 |
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, |