diff --git a/rcore-fs-sefs/src/lib.rs b/rcore-fs-sefs/src/lib.rs index 604d7d2..1ec5b9d 100644 --- a/rcore-fs-sefs/src/lib.rs +++ b/rcore-fs-sefs/src/lib.rs @@ -18,7 +18,7 @@ use bitvec::BitVec; use rcore_fs::dev::TimeProvider; use rcore_fs::dirty::Dirty; use rcore_fs::vfs::{self, FileSystem, FsError, INode, Timespec}; -//use log::*; +use log::*; use spin::RwLock; use self::dev::*; @@ -143,14 +143,16 @@ impl INodeImpl { impl vfs::INode for INodeImpl { fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result { - if self.disk_inode.read().type_ != FileType::File { + let type_ = self.disk_inode.read().type_; + if type_ != FileType::File && type_ != FileType::SymLink { return Err(FsError::NotFile); } let len = self.file.read_at(buf, offset)?; Ok(len) } fn write_at(&self, offset: usize, buf: &[u8]) -> vfs::Result { - if self.disk_inode.read().type_ != FileType::File { + let type_ = self.disk_inode.read().type_; + if type_ != FileType::File && type_ != FileType::SymLink { return Err(FsError::NotFile); } let len = self.file.write_at(buf, offset)?; @@ -170,7 +172,7 @@ impl vfs::INode for INodeImpl { dev: 0, inode: self.id, size: match disk_inode.type_ { - FileType::File => disk_inode.size as usize, + FileType::File | FileType::SymLink => disk_inode.size as usize, FileType::Dir => disk_inode.blocks as usize, _ => panic!("Unknown file type"), }, @@ -221,7 +223,8 @@ impl vfs::INode for INodeImpl { Ok(()) } fn resize(&self, len: usize) -> vfs::Result<()> { - if self.disk_inode.read().type_ != FileType::File { + let type_ = self.disk_inode.read().type_; + if type_ != FileType::File && type_ != FileType::SymLink { return Err(FsError::NotFile); } self.file.set_len(len)?; @@ -232,6 +235,7 @@ impl vfs::INode for INodeImpl { let type_ = match type_ { vfs::FileType::File => FileType::File, vfs::FileType::Dir => FileType::Dir, + vfs::FileType::SymLink => FileType::SymLink, _ => return Err(vfs::FsError::InvalidParam), }; let info = self.metadata()?; @@ -464,11 +468,18 @@ impl SEFS { if !super_block.check() { return Err(FsError::WrongFs); } - let free_map = meta_file.load_struct::<[u8; BLKSIZE]>(BLKN_FREEMAP)?; + + // load free map + let mut free_map = BitVec::with_capacity(BLKBITS * super_block.groups as usize); + unsafe { free_map.set_len(BLKBITS * super_block.groups as usize); } + for i in 0..super_block.groups as usize { + let block_id = Self::get_freemap_block_id_of_group(i); + meta_file.read_block(block_id, &mut free_map.as_mut()[BLKSIZE * i..BLKSIZE * (i+1)])?; + } Ok(SEFS { 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(free_map)), inodes: RwLock::new(BTreeMap::new()), device, meta_file, @@ -488,6 +499,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 +550,22 @@ impl SEFS { /// Allocate a block, return block id fn alloc_block(&self) -> Option { 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,29 +640,39 @@ 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() { inode.sync_all()?; } } + self.meta_file.flush()?; Ok(()) } @@ -670,7 +699,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"); } } @@ -705,6 +734,7 @@ impl From for vfs::FileType { match t { FileType::File => vfs::FileType::File, FileType::Dir => vfs::FileType::Dir, + FileType::SymLink => vfs::FileType::SymLink, _ => panic!("unknown file type"), } } diff --git a/rcore-fs-sefs/src/structs.rs b/rcore-fs-sefs/src/structs.rs index 59b14a4..14e1f55 100644 --- a/rcore-fs-sefs/src/structs.rs +++ b/rcore-fs-sefs/src/structs.rs @@ -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 @@ -139,7 +139,7 @@ pub enum FileType { Invalid = 0, File = 1, Dir = 2, - Link = 3, + SymLink = 3, } const_assert!(o1; size_of::() <= BLKSIZE); diff --git a/sefs-fuse/enclave/src/lib.rs b/sefs-fuse/enclave/src/lib.rs index 976bc66..141414c 100644 --- a/sefs-fuse/enclave/src/lib.rs +++ b/sefs-fuse/enclave/src/lib.rs @@ -45,7 +45,6 @@ use std::io::{Read, Seek, SeekFrom, Write}; use std::path::PathBuf; use std::sgxfs::{OpenOptions, SgxFile}; use std::sync::{SgxMutex as Mutex, SgxRwLock as RwLock}; -use std::vec::Vec; use sgx_types::sgx_key_128bit_t; #[no_mangle] @@ -147,7 +146,16 @@ pub extern "C" fn ecall_file_set_len(fd: usize, len: usize) -> i32 { let mut rest_len = len - current_len; while rest_len != 0 { let l = rest_len.min(0x1000); - try_io!(file.write(&ZEROS[..l])); + let ret = file.write(&ZEROS[..l]); + if let Err(e) = ret { + if e.raw_os_error().unwrap() == 12 { + warn!("Error 12: \"Cannot allocate memory\". Clear cache and try again."); + try_io!(file.clear_cache()); + try_io!(file.write(&ZEROS[..l])); + } else { + try_io!(Err(e)); + } + } rest_len -= l; } // NOTE: Don't try to write a large slice at once.