Merge remote-tracking branch 'occlum/sefs'

master
WangRunji 6 years ago
commit 7a7eb4864a

@ -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<usize> {
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<usize> {
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<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 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() {
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(free_map.as_buf(), BLKSIZE * BLKN_FREEMAP)?;
.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<FileType> for vfs::FileType {
match t {
FileType::File => vfs::FileType::File,
FileType::Dir => vfs::FileType::Dir,
FileType::SymLink => vfs::FileType::SymLink,
_ => panic!("unknown file type"),
}
}

@ -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::<SuperBlock>() <= BLKSIZE);

@ -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);
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.

Loading…
Cancel
Save