From 37839f316f62d5e174072058b8aeb882ab5f83e7 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 2 May 2018 00:07:55 +0800 Subject: [PATCH] Create new SFS from blank disk --- src/dirty.rs | 8 ++++++ src/sfs.rs | 76 ++++++++++++++++++++++++++++++++++++++++++-------- src/structs.rs | 7 +++++ src/tests.rs | 16 +++++++++-- 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/src/dirty.rs b/src/dirty.rs index 8e7eab9..6dea50e 100644 --- a/src/dirty.rs +++ b/src/dirty.rs @@ -16,6 +16,14 @@ impl Dirty { } } + /// Create a new Dirty with dirty set + pub fn new_dirty(val: T) -> Dirty { + Dirty { + value: val, + dirty: true, + } + } + /// Returns true if dirty, false otherwise #[allow(dead_code)] pub fn dirty(&self) -> bool { diff --git a/src/sfs.rs b/src/sfs.rs index 62ff7b4..85b45de 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -104,7 +104,7 @@ impl vfs::INode for INode { for BlockRange { block, begin, end } in iter { if let Some(disk_block_id) = self.disk_block_id(block) { let len = end - begin; - fs.borrow_mut().device.read_block(disk_block_id, begin, &mut buf[buf_offset..buf_offset + len]); + fs.borrow_mut().device.read_block(disk_block_id, begin, &mut buf[buf_offset..buf_offset + len]).unwrap(); buf_offset += len; } else { // Failed this time @@ -126,7 +126,7 @@ impl vfs::INode for INode { for BlockRange { block, begin, end } in iter { if let Some(disk_block_id) = self.disk_block_id(block) { let len = end - begin; - fs.borrow_mut().device.write_block(disk_block_id, begin, &buf[buf_offset..buf_offset + len]); + fs.borrow_mut().device.write_block(disk_block_id, begin, &buf[buf_offset..buf_offset + len]).unwrap(); buf_offset += len; } else { // Failed this time @@ -192,7 +192,7 @@ pub struct SimpleFileSystem { /// on-disk superblock super_block: Dirty, /// blocks in use are mared 0 - free_map: BitSet, + free_map: Dirty, /// inode list inodes: BTreeMap>, /// device @@ -202,23 +202,51 @@ pub struct SimpleFileSystem { } impl SimpleFileSystem { - /// Create a new SFS with device - pub fn new(mut device: Box) -> Option> { + /// Load SFS from device + pub fn open(mut device: Box) -> Option> { let super_block = load_struct::(device.as_mut(), BLKN_SUPER); if super_block.check() == false { return None; } + let free_map = load_struct::<[u8; BLKSIZE]>(device.as_mut(), BLKN_FREEMAP); - let mut fs = Rc::new(RefCell::new(SimpleFileSystem { + Some(SimpleFileSystem { super_block: Dirty::new(super_block), - free_map: BitSet::new(), + free_map: Dirty::new(BitSet::from_bytes(&free_map)), inodes: BTreeMap::>::new(), device, self_ptr: Weak::default(), - })); + }.wrap()) + } + /// Create a new SFS on blank disk + pub fn create(mut device: Box, space: usize) -> Ptr { + let blocks = (space / BLKSIZE).min(BLKBITS); + assert!(blocks >= 16, "space too small"); + + let super_block = SuperBlock { + magic: MAGIC, + blocks: blocks as u32, + unused_blocks: blocks as u32 - 3, + info: Str32::from_slice(b"simple file system"), + }; + let mut free_map = BitSet::with_capacity(BLKBITS); + for i in 3 .. blocks { + free_map.insert(i); + } + SimpleFileSystem { + super_block: Dirty::new_dirty(super_block), + free_map: Dirty::new_dirty(free_map), + inodes: BTreeMap::>::new(), + device, + self_ptr: Weak::default(), + }.wrap() + } + /// Wrap pure SimpleFileSystem with Rc> + /// Used in constructors + fn wrap(self) -> Ptr { + let mut fs = Rc::new(RefCell::new(self)); fs.borrow_mut().self_ptr = Rc::downgrade(&fs); - - Some(fs) + fs } /// Allocate a block, return block id fn alloc_block(&mut self) -> Option { @@ -264,13 +292,18 @@ impl vfs::FileSystem for SimpleFileSystem { let SimpleFileSystem { ref mut super_block, ref mut device, + ref mut free_map, .. } = self; if super_block.dirty() { - device.write_at(0, super_block.as_buf()); + device.write_at(BLKSIZE * BLKN_SUPER, super_block.as_buf()).unwrap(); super_block.sync(); } + if free_map.dirty() { + device.write_at(BLKSIZE * BLKN_FREEMAP, free_map.as_buf()).unwrap(); + free_map.sync(); + } Ok(()) } @@ -287,6 +320,14 @@ impl vfs::FileSystem for SimpleFileSystem { } } +impl Drop for SimpleFileSystem { + /// Auto sync when drop + fn drop(&mut self) { + use vfs::FileSystem; + self.sync().expect("failed to sync"); + } +} + trait BitsetAlloc { fn alloc(&mut self) -> Option; } @@ -302,6 +343,19 @@ impl BitsetAlloc for BitSet { } } +impl AsBuf for BitSet { + fn as_buf(&self) -> &[u8] { + let slice = self.get_ref().storage(); + unsafe{ slice::from_raw_parts(slice as *const _ as *const u8, slice.len() * 4) } + } + fn as_buf_mut(&mut self) -> &mut [u8] { + let slice = self.get_ref().storage(); + unsafe{ slice::from_raw_parts_mut(slice as *const _ as *mut u8, slice.len() * 4) } + } +} + +impl AsBuf for [u8; BLKSIZE] {} + #[cfg(test)] mod test { use super::*; diff --git a/src/structs.rs b/src/structs.rs index b0e101d..11df346 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -72,6 +72,13 @@ impl Debug for Str32 { write!(f, "{}", String::from_utf8_lossy(&self.0[0 .. len])) } } +impl Str32 { + pub fn from_slice(s: &[u8]) -> Self { + let mut ret = [0u8; 32]; + ret[0..s.len()].copy_from_slice(s); + Str32(ret) + } +} impl SuperBlock { pub fn check(&self) -> bool { diff --git a/src/tests.rs b/src/tests.rs index 6190d03..3c04e49 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,4 +1,4 @@ -use std::fs::File; +use std::fs::{File, OpenOptions}; use std::io::{Read, Write, Seek, SeekFrom}; use std::boxed::Box; use super::sfs::*; @@ -26,9 +26,9 @@ impl Device for File { fn test() { let file = File::open("sfs.img") .expect("failed to open sfs.img"); - let sfs = SimpleFileSystem::new(Box::new(file)) + let sfs = SimpleFileSystem::open(Box::new(file)) .expect("failed to create SFS"); - let mut root = sfs.borrow_mut().root_inode(); + let root = sfs.borrow_mut().root_inode(); println!("{:?}", root); use super::structs::{DiskEntry, AsBuf}; @@ -39,4 +39,14 @@ fn test() { root.borrow_mut().read_at(i * 4096, entry.as_buf_mut()); println!("{:?}", entry); } +} + +#[test] +fn create() { + let file = OpenOptions::new() + .read(true).write(true).create(true).open("test.img") + .expect("failed to create file"); + let sfs = SimpleFileSystem::create(Box::new(file), 16 * 4096); + + } \ No newline at end of file