Make INode -> SFS weak. Impl getting root inode.

master
WangRunji 7 years ago
parent 157ee1a1bc
commit caf5f8aea1

@ -7,6 +7,7 @@ use super::structs::*;
use super::vfs; use super::vfs;
use core::mem::{uninitialized, size_of}; use core::mem::{uninitialized, size_of};
use core::slice; use core::slice;
use core::fmt::{Debug, Formatter, Error};
/// Interface for SFS to read & write /// Interface for SFS to read & write
/// TODO: use std::io::{Read, Write} /// TODO: use std::io::{Read, Write}
@ -32,14 +33,28 @@ pub trait Device {
} }
} }
/// Load struct `T` from given block in device
/// Workaround: It should be inside the trait `Device`. But that would cause compile error.
fn load_struct<T: AsBuf>(device: &mut Device, id: BlockId) -> T {
let mut s: T = unsafe{ uninitialized() };
device.read_block(id, 0, s.as_buf_mut()).unwrap();
s
}
/// inode for sfs /// inode for sfs
pub struct INode { pub struct INode {
/// on-disk inode /// on-disk inode
disk_inode: Dirty<DiskINode>, disk_inode: Dirty<DiskINode>,
/// inode number /// inode number
id: INodeId, id: INodeId,
/// Reference to SFS, used by almost all operations /// Weak reference to SFS, used by almost all operations
fs: Rc<RefCell<SimpleFileSystem>>, fs: Weak<RefCell<SimpleFileSystem>>,
}
impl Debug for INode {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{:?}", *self.disk_inode)
}
} }
impl INode { impl INode {
@ -52,7 +67,8 @@ impl INode {
Some(self.disk_inode.direct[id] as BlockId), Some(self.disk_inode.direct[id] as BlockId),
id if id < NDIRECT + BLK_NENTRY => { id if id < NDIRECT + BLK_NENTRY => {
let mut disk_block_id: BlockId = 0; let mut disk_block_id: BlockId = 0;
self.fs.borrow_mut().device.read_block( let fs = self.fs.upgrade().unwrap();
fs.borrow_mut().device.read_block(
self.disk_inode.indirect as usize, self.disk_inode.indirect as usize,
ENTRY_SIZE * (id - NDIRECT), ENTRY_SIZE * (id - NDIRECT),
disk_block_id.as_buf_mut() disk_block_id.as_buf_mut()
@ -73,7 +89,8 @@ impl vfs::INode for INode {
self.sync() self.sync()
} }
fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option<usize> { fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option<usize> {
let mut fs = self.fs.borrow_mut(); let fs0 = self.fs.upgrade().unwrap();
let mut fs = fs0.borrow_mut();
let iter = BlockIter { let iter = BlockIter {
begin: offset, begin: offset,
@ -95,7 +112,8 @@ impl vfs::INode for INode {
Some(buf_offset) Some(buf_offset)
} }
fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option<usize> { fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option<usize> {
let mut fs = self.fs.borrow_mut(); let fs0 = self.fs.upgrade().unwrap();
let mut fs = fs0.borrow_mut();
let iter = BlockIter { let iter = BlockIter {
begin: offset, begin: offset,
@ -118,7 +136,8 @@ impl vfs::INode for INode {
} }
fn sync(&mut self) -> Result<(), ()> { fn sync(&mut self) -> Result<(), ()> {
if self.disk_inode.dirty() { if self.disk_inode.dirty() {
let mut fs = self.fs.borrow_mut(); let fs0 = self.fs.upgrade().unwrap();
let mut fs = fs0.borrow_mut();
fs.device.write_block(self.id, 0, self.disk_inode.as_buf())?; fs.device.write_block(self.id, 0, self.disk_inode.as_buf())?;
self.disk_inode.sync(); self.disk_inode.sync();
} }
@ -164,25 +183,28 @@ pub struct SimpleFileSystem {
inodes: BTreeMap<INodeId, Rc<INode>>, inodes: BTreeMap<INodeId, Rc<INode>>,
/// device /// device
device: Box<Device>, device: Box<Device>,
/// Pointer to self, used by INodes
self_ptr: Weak<RefCell<SimpleFileSystem>>,
} }
impl SimpleFileSystem { impl SimpleFileSystem {
/// Create a new SFS with device /// Create a new SFS with device
pub fn new(mut device: Box<Device>) -> Option<Self> { pub fn new(mut device: Box<Device>) -> Option<Rc<RefCell<Self>>> {
let mut super_block: SuperBlock = unsafe{ uninitialized() }; let super_block = load_struct::<SuperBlock>(device.as_mut(), BLKN_SUPER);
if device.read_at(BLKN_SUPER * BLKSIZE, super_block.as_buf_mut()).is_none() {
return None;
}
if super_block.check() == false { if super_block.check() == false {
return None; return None;
} }
Some(SimpleFileSystem { let mut fs = Rc::new(RefCell::new(SimpleFileSystem {
super_block: Dirty::new(super_block), super_block: Dirty::new(super_block),
free_map: BitSet::new(), free_map: BitSet::new(),
inodes: BTreeMap::<INodeId, Rc<INode>>::new(), inodes: BTreeMap::<INodeId, Rc<INode>>::new(),
device, device,
}) self_ptr: Weak::default(),
}));
fs.borrow_mut().self_ptr = Rc::downgrade(&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> {
@ -198,12 +220,33 @@ impl SimpleFileSystem {
self.free_map.insert(block_id); self.free_map.insert(block_id);
self.super_block.unused_blocks += 1; self.super_block.unused_blocks += 1;
} }
/// Get inode by id
fn get_inode(&self, id: INodeId) -> Option<Rc<INode>> { /// Get inode by id. Load if not in memory.
self.inodes.get(&id).map(|rc| rc.clone()) /// ** Must ensure it's a valid INode **
fn get_inode(&mut self, id: INodeId) -> Rc<INode> {
assert!(!self.free_map.contains(id));
// Load if not in memory.
if !self.inodes.contains_key(&id) {
let disk_inode = load_struct::<DiskINode>(self.device.as_mut(), id);
let inode = Rc::new(INode {
disk_inode: Dirty::new(disk_inode),
id,
fs: self.self_ptr.clone(),
});
self.inodes.insert(id, inode.clone());
inode
} else {
self.inodes.get(&id).unwrap().clone()
}
} }
}
impl vfs::FileSystem for SimpleFileSystem {
type INode = INode;
/// Write back super block if dirty /// Write back super block if dirty
fn sync(&mut self) { fn sync(&mut self) -> Result<(), ()> {
let SimpleFileSystem { let SimpleFileSystem {
ref mut super_block, ref mut super_block,
ref mut device, ref mut device,
@ -214,18 +257,11 @@ impl SimpleFileSystem {
device.write_at(0, super_block.as_buf()); device.write_at(0, super_block.as_buf());
super_block.sync(); super_block.sync();
} }
} Ok(())
}
impl vfs::FileSystem for SimpleFileSystem {
type INode = INode;
fn sync(&mut self) -> Result<(), ()> {
unimplemented!()
} }
fn root_inode(&mut self) -> Rc<INode> { fn root_inode(&mut self) -> Rc<INode> {
unimplemented!() self.get_inode(BLKN_ROOT)
} }
fn unmount(&mut self) -> Result<(), ()> { fn unmount(&mut self) -> Result<(), ()> {

@ -38,7 +38,7 @@ pub struct DiskINode {
#[repr(C, packed)] #[repr(C, packed)]
pub struct IndirectBlock { pub struct IndirectBlock {
pub entrys: [u32; BLK_NENTRY], pub entries: [u32; BLK_NENTRY],
} }
/// file entry (on disk) /// file entry (on disk)

@ -26,7 +26,8 @@ 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 mut sfs = SimpleFileSystem::new(Box::new(file)) let sfs = SimpleFileSystem::new(Box::new(file))
.expect("failed to create SFS"); .expect("failed to create SFS");
// let root = sfs.root_inode(); let root = sfs.borrow_mut().root_inode();
println!("{:?}", root);
} }
Loading…
Cancel
Save