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
#[allow(dead_code)]
pub fn dirty(&self) -> bool {

@ -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<SuperBlock>,
/// blocks in use are mared 0
free_map: BitSet,
free_map: Dirty<BitSet>,
/// inode list
inodes: BTreeMap<INodeId, Ptr<INode>>,
/// device
@ -202,23 +202,51 @@ pub struct SimpleFileSystem {
}
impl SimpleFileSystem {
/// Create a new SFS with device
pub fn new(mut device: Box<Device>) -> Option<Ptr<Self>> {
/// Load SFS from device
pub fn open(mut device: Box<Device>) -> Option<Ptr<Self>> {
let super_block = load_struct::<SuperBlock>(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::<INodeId, Ptr<INode>>::new(),
device,
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);
Some(fs)
fs
}
/// Allocate a block, return block id
fn alloc_block(&mut self) -> Option<usize> {
@ -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<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)]
mod test {
use super::*;

@ -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 {

@ -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);
}
Loading…
Cancel
Save