sefs: impl block group and auto extend when allocating failed

master
WangRunji 6 years ago
parent 08518e5034
commit c1d047f503

@ -488,6 +488,7 @@ impl SEFS {
magic: MAGIC, magic: MAGIC,
blocks: blocks as u32, blocks: blocks as u32,
unused_blocks: blocks as u32 - 2, unused_blocks: blocks as u32 - 2,
groups: 1,
}; };
let free_map = { let free_map = {
let mut bitset = BitVec::with_capacity(BLKBITS); let mut bitset = BitVec::with_capacity(BLKBITS);
@ -538,15 +539,22 @@ impl SEFS {
/// Allocate a block, return block id /// Allocate a block, return block id
fn alloc_block(&self) -> Option<usize> { fn alloc_block(&self) -> Option<usize> {
let mut free_map = self.free_map.write(); let mut free_map = self.free_map.write();
let id = free_map.alloc();
if let Some(block_id) = id {
let mut super_block = self.super_block.write(); let mut super_block = self.super_block.write();
if super_block.unused_blocks == 0 { let id = free_map.alloc().or_else(|| {
free_map.set(block_id, true); // allocate a new group
return None; let new_group_id = super_block.groups as usize;
} super_block.groups += 1;
super_block.unused_blocks -= 1; // will not underflow super_block.blocks += BLKBITS as u32;
} super_block.unused_blocks += BLKBITS as u32 - 1;
self.meta_file.set_len(super_block.groups as usize * BLKBITS * BLKSIZE)
.expect("failed to extend meta file");
free_map.extend(core::iter::repeat(true).take(BLKBITS));
free_map.set(Self::get_freemap_block_id_of_group(new_group_id), false);
// allocate block again
free_map.alloc()
});
assert!(id.is_some(), "allocate block should always success");
super_block.unused_blocks -= 1;
id id
} }
/// Free a block /// Free a block
@ -621,23 +629,32 @@ impl SEFS {
inodes.remove(&id); inodes.remove(&id);
} }
} }
fn get_freemap_block_id_of_group(group_id: usize) -> usize {
BLKBITS * group_id + BLKN_FREEMAP
}
} }
impl vfs::FileSystem for SEFS { impl vfs::FileSystem for SEFS {
/// Write back super block if dirty /// Write back super block if dirty
fn sync(&self) -> vfs::Result<()> { fn sync(&self) -> vfs::Result<()> {
// sync super_block
let mut super_block = self.super_block.write(); let mut super_block = self.super_block.write();
if super_block.dirty() { if super_block.dirty() {
self.meta_file self.meta_file
.write_all_at(super_block.as_buf(), BLKSIZE * BLKN_SUPER)?; .write_all_at(super_block.as_buf(), BLKSIZE * BLKN_SUPER)?;
super_block.sync(); super_block.sync();
} }
// sync free_map
let mut free_map = self.free_map.write(); let mut free_map = self.free_map.write();
if free_map.dirty() { if free_map.dirty() {
for i in 0..super_block.groups as usize {
let slice = &free_map.as_ref()[BLKSIZE * i..BLKSIZE * (i+1)];
self.meta_file self.meta_file
.write_all_at(free_map.as_buf(), BLKSIZE * BLKN_FREEMAP)?; .write_all_at(slice, BLKSIZE * Self::get_freemap_block_id_of_group(i))?;
}
free_map.sync(); free_map.sync();
} }
// sync all INodes
self.flush_weak_inodes(); self.flush_weak_inodes();
for inode in self.inodes.read().values() { for inode in self.inodes.read().values() {
if let Some(inode) = inode.upgrade() { if let Some(inode) = inode.upgrade() {
@ -670,7 +687,7 @@ impl Drop for SEFS {
/// Auto sync when drop /// Auto sync when drop
fn drop(&mut self) { fn drop(&mut self) {
self.sync() self.sync()
.expect("Failed to sync when dropping the SimpleFileSystem"); .expect("Failed to sync when dropping the SEFS");
} }
} }

@ -16,6 +16,8 @@ pub struct SuperBlock {
pub blocks: u32, pub blocks: u32,
/// number of unused blocks in fs /// number of unused blocks in fs
pub unused_blocks: u32, pub unused_blocks: u32,
/// number of block groups
pub groups: u32,
} }
/// On-disk inode /// On-disk inode
@ -115,8 +117,6 @@ pub const BLKSIZE_LOG2: u8 = 7;
pub const MAX_INFO_LEN: usize = 31; pub const MAX_INFO_LEN: usize = 31;
/// max length of filename /// max length of filename
pub const MAX_FNAME_LEN: usize = 255; pub const MAX_FNAME_LEN: usize = 255;
/// max file size (128M)
pub const MAX_FILE_SIZE: usize = 1024 * 1024 * 128;
/// block the superblock lives in /// block the superblock lives in
pub const BLKN_SUPER: BlockId = 0; pub const BLKN_SUPER: BlockId = 0;
/// location of the root dir inode /// location of the root dir inode

Loading…
Cancel
Save