Implement multiple freemap blocks

master
Jiajie Chen 6 years ago
parent 807a5d3dac
commit 9c0aeb1e66

@ -65,7 +65,7 @@ fn main() {
.open(&opt.image)
.expect("failed to open image");
let device = Mutex::new(file);
const MAX_SPACE: usize = 0x1000 * 0x1000 * 8; // 128MB (4K bitmap)
const MAX_SPACE: usize = 0x1000 * 0x1000 * 1024; // 1G
match create {
true => sfs::SimpleFileSystem::create(Arc::new(device), MAX_SPACE),
false => sfs::SimpleFileSystem::open(Arc::new(device)).expect("failed to open sfs"),

@ -11,6 +11,7 @@ use alloc::{
string::String,
sync::{Arc, Weak},
vec::Vec,
vec,
};
use core::any::Any;
use core::fmt::{Debug, Error, Formatter};
@ -683,11 +684,14 @@ impl SimpleFileSystem {
if !super_block.check() {
return Err(FsError::WrongFs);
}
let free_map = device.load_struct::<[u8; BLKSIZE]>(BLKN_FREEMAP).unwrap();
let mut freemap_disk = vec![0u8; BLKSIZE * super_block.freemap_blocks as usize];
for i in 0..super_block.freemap_blocks as usize {
device.read_block(BLKN_FREEMAP + i, 0, &mut freemap_disk[i * BLKSIZE..(i+1) *BLKSIZE])?;
}
Ok(SimpleFileSystem {
super_block: RwLock::new(Dirty::new(super_block)),
free_map: RwLock::new(Dirty::new(BitVec::from(free_map.as_ref()))),
free_map: RwLock::new(Dirty::new(BitVec::from(freemap_disk.as_slice()))),
inodes: RwLock::new(BTreeMap::new()),
device,
self_ptr: Weak::default(),
@ -696,19 +700,21 @@ impl SimpleFileSystem {
}
/// Create a new SFS on blank disk
pub fn create(device: Arc<Device>, space: usize) -> Arc<Self> {
let blocks = (space / BLKSIZE).min(BLKBITS);
let blocks = (space + BLKSIZE - 1) / BLKSIZE;
let freemap_blocks = (space + BLKBITS * BLKSIZE - 1) / BLKBITS / BLKSIZE;
assert!(blocks >= 16, "space too small");
let super_block = SuperBlock {
magic: MAGIC,
blocks: blocks as u32,
unused_blocks: blocks as u32 - 3,
unused_blocks: (blocks - BLKN_FREEMAP - freemap_blocks) as u32,
info: Str32::from(DEFAULT_INFO),
freemap_blocks: freemap_blocks as u32,
};
let free_map = {
let mut bitset = BitVec::with_capacity(BLKBITS);
bitset.extend(core::iter::repeat(false).take(BLKBITS));
for i in 3..blocks {
let mut bitset = BitVec::with_capacity(freemap_blocks * BLKBITS);
bitset.extend(core::iter::repeat(false).take(freemap_blocks * BLKBITS));
for i in (BLKN_FREEMAP + freemap_blocks)..blocks {
bitset.set(i, true);
}
bitset
@ -753,11 +759,16 @@ impl SimpleFileSystem {
if let Some(block_id) = id {
let mut super_block = self.super_block.write();
if super_block.unused_blocks == 0 {
let super_block = self.super_block.read();
panic!("{:?}", super_block);
free_map.set(block_id, true);
return None;
}
super_block.unused_blocks -= 1; // will not underflow
trace!("alloc block {:#x}", block_id);
} else {
let super_block = self.super_block.read();
panic!("{:?}", super_block)
}
id
}
@ -841,9 +852,12 @@ impl vfs::FileSystem for SimpleFileSystem {
}
let mut free_map = self.free_map.write();
if free_map.dirty() {
let data = free_map.as_buf();
for i in 0..super_block.freemap_blocks as usize {
self.device
.write_at(BLKSIZE * BLKN_FREEMAP, free_map.as_buf())
.write_at(BLKSIZE * (BLKN_FREEMAP + i), &data[i * BLKSIZE..(i+1) * BLKSIZE])
.unwrap();
}
free_map.sync();
}
self.flush_weak_inodes();

@ -18,6 +18,8 @@ pub struct SuperBlock {
pub unused_blocks: u32,
/// information for sfs
pub info: Str32,
/// number of freemap blocks
pub freemap_blocks: u32,
}
/// inode (on disk)
@ -186,9 +188,8 @@ pub const DEFAULT_INFO: &str = "simple file system";
pub const MAX_INFO_LEN: usize = 31;
/// max length of filename
pub const MAX_FNAME_LEN: usize = 255;
/// max file size in theory (48KB + 4MB + 4GB), but freemap is not large enough
/// max file size (128M), 128M = 8 * 4096 * 4096
pub const MAX_FILE_SIZE: usize = 1024 * 1024 * 128;
/// max file size in theory (48KB + 4MB + 4GB)
pub const MAX_FILE_SIZE: usize = 48 * 1024 + 4 * 1024 * 1024 + 4 * 1024 * 1024 * 1024;
/// block the superblock lives in
pub const BLKN_SUPER: BlockId = 0;
/// location of the root dir inode

@ -43,7 +43,7 @@ fn create_file() -> Result<()> {
assert_eq!(
file1.metadata()?,
Metadata {
inode: 5,
inode: 8,
size: 0,
type_: FileType::File,
mode: 0o777,
@ -102,7 +102,7 @@ fn resize_too_large_should_panic() -> Result<()> {
let sfs = _create_new_sfs();
let root = sfs.root_inode();
let file1 = root.create("file1", FileType::File, 0o777)?;
assert!(file1.resize(1 << 28).is_err());
assert!(file1.resize(1 << 40).is_err());
sfs.sync()?;
Ok(())
@ -261,16 +261,18 @@ fn test_double_indirect_blocks() -> Result<()> {
file1.resize(MAX_NBLOCK_INDIRECT * BLKSIZE).unwrap();
// force usage of double indirect block
file1.resize((MAX_NBLOCK_INDIRECT + 1) * BLKSIZE).unwrap();
file1.resize(MAX_FILE_SIZE / 8).unwrap();
file1.resize((MAX_NBLOCK_INDIRECT + 2) * BLKSIZE).unwrap();
// resize up and down
file1.resize(0).unwrap();
file1.resize((MAX_NBLOCK_INDIRECT + 2) * BLKSIZE).unwrap();
file1.resize(MAX_NBLOCK_DIRECT * BLKSIZE).unwrap();
file1.resize((MAX_NBLOCK_DIRECT + 1) * BLKSIZE).unwrap();
file1.resize(MAX_NBLOCK_DIRECT * BLKSIZE).unwrap();
file1.resize(0).unwrap();
file1.resize((MAX_NBLOCK_INDIRECT + 1) * BLKSIZE).unwrap();
file1.resize(MAX_NBLOCK_DIRECT * BLKSIZE).unwrap();
file1.resize((MAX_NBLOCK_INDIRECT + 2) * BLKSIZE).unwrap();
file1.resize((MAX_NBLOCK_INDIRECT + 1) * BLKSIZE).unwrap();
file1.resize(0).unwrap();

Loading…
Cancel
Save