From 08518e503499520f6fca5b3827a772d24cc7399c Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 10 Apr 2019 16:26:03 +0800 Subject: [PATCH 1/4] sefs: fix SGX memory allocation fail, clear cache and retry --- sefs-fuse/enclave/src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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. From c1d047f5034204bba694c76141ffca67037c56c8 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 10 Apr 2019 19:32:36 +0800 Subject: [PATCH 2/4] sefs: impl block group and auto extend when allocating failed --- rcore-fs-sefs/src/lib.rs | 41 +++++++++++++++++++++++++----------- rcore-fs-sefs/src/structs.rs | 4 ++-- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/rcore-fs-sefs/src/lib.rs b/rcore-fs-sefs/src/lib.rs index 4f03118..6b0a812 100644 --- a/rcore-fs-sefs/src/lib.rs +++ b/rcore-fs-sefs/src/lib.rs @@ -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 { 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"); } } diff --git a/rcore-fs-sefs/src/structs.rs b/rcore-fs-sefs/src/structs.rs index 59b14a4..caa08fd 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 From 6537e7dc82e00f274e8bb9607f29f8d527f65dc1 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 10 Apr 2019 19:52:14 +0800 Subject: [PATCH 3/4] sefs: impl symlink --- rcore-fs-sefs/src/lib.rs | 13 +++++++++---- rcore-fs-sefs/src/structs.rs | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/rcore-fs-sefs/src/lib.rs b/rcore-fs-sefs/src/lib.rs index 6b0a812..003e26a 100644 --- a/rcore-fs-sefs/src/lib.rs +++ b/rcore-fs-sefs/src/lib.rs @@ -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()?; @@ -722,6 +726,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 caa08fd..14e1f55 100644 --- a/rcore-fs-sefs/src/structs.rs +++ b/rcore-fs-sefs/src/structs.rs @@ -139,7 +139,7 @@ pub enum FileType { Invalid = 0, File = 1, Dir = 2, - Link = 3, + SymLink = 3, } const_assert!(o1; size_of::() <= BLKSIZE); From 2865c419b3d36a8b0e7ef843b115cb1ecb3176f8 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Thu, 11 Apr 2019 22:21:53 +0800 Subject: [PATCH 4/4] sefs: fix load freemap --- rcore-fs-sefs/src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/rcore-fs-sefs/src/lib.rs b/rcore-fs-sefs/src/lib.rs index 003e26a..ef21220 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::*; @@ -468,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, @@ -665,6 +672,7 @@ impl vfs::FileSystem for SEFS { inode.sync_all()?; } } + self.meta_file.flush()?; Ok(()) }