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,
blocks: blocks as u32,
unused_blocks: blocks as u32 - 2,
groups: 1,
};
let free_map = {
let mut bitset = BitVec::with_capacity(BLKBITS);
@ -538,15 +539,22 @@ impl SEFS {
/// Allocate a block, return block id
fn alloc_block(&self) -> Option<usize> {
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();
if super_block.unused_blocks == 0 {
free_map.set(block_id, true);
return None;
}
super_block.unused_blocks -= 1; // will not underflow
}
let mut super_block = self.super_block.write();
let id = free_map.alloc().or_else(|| {
// allocate a new group
let new_group_id = super_block.groups as usize;
super_block.groups += 1;
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
}
/// Free a block
@ -621,23 +629,32 @@ impl SEFS {
inodes.remove(&id);
}
}
fn get_freemap_block_id_of_group(group_id: usize) -> usize {
BLKBITS * group_id + BLKN_FREEMAP
}
}
impl vfs::FileSystem for SEFS {
/// Write back super block if dirty
fn sync(&self) -> vfs::Result<()> {
// sync super_block
let mut super_block = self.super_block.write();
if super_block.dirty() {
self.meta_file
.write_all_at(super_block.as_buf(), BLKSIZE * BLKN_SUPER)?;
super_block.sync();
}
// sync free_map
let mut free_map = self.free_map.write();
if free_map.dirty() {
self.meta_file
.write_all_at(free_map.as_buf(), BLKSIZE * BLKN_FREEMAP)?;
for i in 0..super_block.groups as usize {
let slice = &free_map.as_ref()[BLKSIZE * i..BLKSIZE * (i+1)];
self.meta_file
.write_all_at(slice, BLKSIZE * Self::get_freemap_block_id_of_group(i))?;
}
free_map.sync();
}
// sync all INodes
self.flush_weak_inodes();
for inode in self.inodes.read().values() {
if let Some(inode) = inode.upgrade() {
@ -670,7 +687,7 @@ impl Drop for SEFS {
/// Auto sync when drop
fn drop(&mut self) {
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,
/// number of unused blocks in fs
pub unused_blocks: u32,
/// number of block groups
pub groups: u32,
}
/// On-disk inode
@ -115,8 +117,6 @@ pub const BLKSIZE_LOG2: u8 = 7;
pub const MAX_INFO_LEN: usize = 31;
/// max length of filename
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
pub const BLKN_SUPER: BlockId = 0;
/// location of the root dir inode

Loading…
Cancel
Save