Create new SFS from blank disk

master
WangRunji 7 years ago
parent 5f244d4538
commit 37839f316f

@ -16,6 +16,14 @@ impl<T> Dirty<T> {
} }
} }
/// Create a new Dirty with dirty set
pub fn new_dirty(val: T) -> Dirty<T> {
Dirty {
value: val,
dirty: true,
}
}
/// Returns true if dirty, false otherwise /// Returns true if dirty, false otherwise
#[allow(dead_code)] #[allow(dead_code)]
pub fn dirty(&self) -> bool { pub fn dirty(&self) -> bool {

@ -104,7 +104,7 @@ impl vfs::INode for INode {
for BlockRange { block, begin, end } in iter { for BlockRange { block, begin, end } in iter {
if let Some(disk_block_id) = self.disk_block_id(block) { if let Some(disk_block_id) = self.disk_block_id(block) {
let len = end - begin; 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; buf_offset += len;
} else { } else {
// Failed this time // Failed this time
@ -126,7 +126,7 @@ impl vfs::INode for INode {
for BlockRange { block, begin, end } in iter { for BlockRange { block, begin, end } in iter {
if let Some(disk_block_id) = self.disk_block_id(block) { if let Some(disk_block_id) = self.disk_block_id(block) {
let len = end - begin; 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; buf_offset += len;
} else { } else {
// Failed this time // Failed this time
@ -192,7 +192,7 @@ pub struct SimpleFileSystem {
/// on-disk superblock /// on-disk superblock
super_block: Dirty<SuperBlock>, super_block: Dirty<SuperBlock>,
/// blocks in use are mared 0 /// blocks in use are mared 0
free_map: BitSet, free_map: Dirty<BitSet>,
/// inode list /// inode list
inodes: BTreeMap<INodeId, Ptr<INode>>, inodes: BTreeMap<INodeId, Ptr<INode>>,
/// device /// device
@ -202,23 +202,51 @@ pub struct SimpleFileSystem {
} }
impl SimpleFileSystem { impl SimpleFileSystem {
/// Create a new SFS with device /// Load SFS from device
pub fn new(mut device: Box<Device>) -> Option<Ptr<Self>> { pub fn open(mut device: Box<Device>) -> Option<Ptr<Self>> {
let super_block = load_struct::<SuperBlock>(device.as_mut(), BLKN_SUPER); let super_block = load_struct::<SuperBlock>(device.as_mut(), BLKN_SUPER);
if super_block.check() == false { if super_block.check() == false {
return None; 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), super_block: Dirty::new(super_block),
free_map: BitSet::new(), free_map: Dirty::new(BitSet::from_bytes(&free_map)),
inodes: BTreeMap::<INodeId, Ptr<INode>>::new(), inodes: BTreeMap::<INodeId, Ptr<INode>>::new(),
device, device,
self_ptr: Weak::default(), self_ptr: Weak::default(),
})); }.wrap())
}
/// Create a new SFS on blank disk
pub fn create(mut device: Box<Device>, space: usize) -> Ptr<Self> {
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::<INodeId, Ptr<INode>>::new(),
device,
self_ptr: Weak::default(),
}.wrap()
}
/// Wrap pure SimpleFileSystem with Rc<RefCell<...>>
/// Used in constructors
fn wrap(self) -> Ptr<Self> {
let mut fs = Rc::new(RefCell::new(self));
fs.borrow_mut().self_ptr = Rc::downgrade(&fs); fs.borrow_mut().self_ptr = Rc::downgrade(&fs);
fs
Some(fs)
} }
/// Allocate a block, return block id /// Allocate a block, return block id
fn alloc_block(&mut self) -> Option<usize> { fn alloc_block(&mut self) -> Option<usize> {
@ -264,13 +292,18 @@ impl vfs::FileSystem for SimpleFileSystem {
let SimpleFileSystem { let SimpleFileSystem {
ref mut super_block, ref mut super_block,
ref mut device, ref mut device,
ref mut free_map,
.. ..
} = self; } = self;
if super_block.dirty() { 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(); super_block.sync();
} }
if free_map.dirty() {
device.write_at(BLKSIZE * BLKN_FREEMAP, free_map.as_buf()).unwrap();
free_map.sync();
}
Ok(()) 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 { trait BitsetAlloc {
fn alloc(&mut self) -> Option<usize>; fn alloc(&mut self) -> Option<usize>;
} }
@ -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)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

@ -72,6 +72,13 @@ impl Debug for Str32 {
write!(f, "{}", String::from_utf8_lossy(&self.0[0 .. len])) 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 { impl SuperBlock {
pub fn check(&self) -> bool { pub fn check(&self) -> bool {

@ -1,4 +1,4 @@
use std::fs::File; use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom}; use std::io::{Read, Write, Seek, SeekFrom};
use std::boxed::Box; use std::boxed::Box;
use super::sfs::*; use super::sfs::*;
@ -26,9 +26,9 @@ impl Device for File {
fn test() { fn test() {
let file = File::open("sfs.img") let file = File::open("sfs.img")
.expect("failed to 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"); .expect("failed to create SFS");
let mut root = sfs.borrow_mut().root_inode(); let root = sfs.borrow_mut().root_inode();
println!("{:?}", root); println!("{:?}", root);
use super::structs::{DiskEntry, AsBuf}; use super::structs::{DiskEntry, AsBuf};
@ -40,3 +40,13 @@ fn test() {
println!("{:?}", entry); 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);
}
Loading…
Cancel
Save