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::dev::TimeProvider;
use rcore_fs::dirty::Dirty; use rcore_fs::dirty::Dirty;
use rcore_fs::vfs::{self, FileSystem, FsError, INode, Timespec}; use rcore_fs::vfs::{self, FileSystem, FsError, INode, Timespec};
//use log::*; use log::*;
use spin::RwLock; use spin::RwLock;
use self::dev::*; use self::dev::*;
@ -143,14 +143,16 @@ impl INodeImpl {
impl vfs::INode for INodeImpl { impl vfs::INode for INodeImpl {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result<usize> { 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); return Err(FsError::NotFile);
} }
let len = self.file.read_at(buf, offset)?; let len = self.file.read_at(buf, offset)?;
Ok(len) Ok(len)
} }
fn write_at(&self, offset: usize, buf: &[u8]) -> vfs::Result<usize> { 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); return Err(FsError::NotFile);
} }
let len = self.file.write_at(buf, offset)?; let len = self.file.write_at(buf, offset)?;
@ -170,7 +172,7 @@ impl vfs::INode for INodeImpl {
dev: 0, dev: 0,
inode: self.id, inode: self.id,
size: match disk_inode.type_ { 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, FileType::Dir => disk_inode.blocks as usize,
_ => panic!("Unknown file type"), _ => panic!("Unknown file type"),
}, },
@ -221,7 +223,8 @@ impl vfs::INode for INodeImpl {
Ok(()) Ok(())
} }
fn resize(&self, len: usize) -> vfs::Result<()> { 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); return Err(FsError::NotFile);
} }
self.file.set_len(len)?; self.file.set_len(len)?;
@ -232,6 +235,7 @@ impl vfs::INode for INodeImpl {
let type_ = match type_ { let type_ = match type_ {
vfs::FileType::File => FileType::File, vfs::FileType::File => FileType::File,
vfs::FileType::Dir => FileType::Dir, vfs::FileType::Dir => FileType::Dir,
vfs::FileType::SymLink => FileType::SymLink,
_ => return Err(vfs::FsError::InvalidParam), _ => return Err(vfs::FsError::InvalidParam),
}; };
let info = self.metadata()?; let info = self.metadata()?;
@ -464,11 +468,18 @@ impl SEFS {
if !super_block.check() { if !super_block.check() {
return Err(FsError::WrongFs); 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 { Ok(SEFS {
super_block: RwLock::new(Dirty::new(super_block)), 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()), inodes: RwLock::new(BTreeMap::new()),
device, device,
meta_file, meta_file,
@ -488,6 +499,7 @@ impl SEFS {
magic: MAGIC, magic: MAGIC,
blocks: blocks as u32, blocks: blocks as u32,
unused_blocks: blocks as u32 - 2, unused_blocks: blocks as u32 - 2,
groups: 1,
}; };
let free_map = { let free_map = {
let mut bitset = BitVec::with_capacity(BLKBITS); let mut bitset = BitVec::with_capacity(BLKBITS);
@ -538,15 +550,22 @@ impl SEFS {
/// Allocate a block, return block id /// Allocate a block, return block id
fn alloc_block(&self) -> Option<usize> { fn alloc_block(&self) -> Option<usize> {
let mut free_map = self.free_map.write(); 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(); let mut super_block = self.super_block.write();
if super_block.unused_blocks == 0 { let id = free_map.alloc().or_else(|| {
free_map.set(block_id, true); // allocate a new group
return None; let new_group_id = super_block.groups as usize;
} super_block.groups += 1;
super_block.unused_blocks -= 1; // will not underflow 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 id
} }
/// Free a block /// Free a block
@ -621,29 +640,39 @@ impl SEFS {
inodes.remove(&id); inodes.remove(&id);
} }
} }
fn get_freemap_block_id_of_group(group_id: usize) -> usize {
BLKBITS * group_id + BLKN_FREEMAP
}
} }
impl vfs::FileSystem for SEFS { impl vfs::FileSystem for SEFS {
/// Write back super block if dirty /// Write back super block if dirty
fn sync(&self) -> vfs::Result<()> { fn sync(&self) -> vfs::Result<()> {
// sync super_block
let mut super_block = self.super_block.write(); let mut super_block = self.super_block.write();
if super_block.dirty() { if super_block.dirty() {
self.meta_file self.meta_file
.write_all_at(super_block.as_buf(), BLKSIZE * BLKN_SUPER)?; .write_all_at(super_block.as_buf(), BLKSIZE * BLKN_SUPER)?;
super_block.sync(); super_block.sync();
} }
// sync free_map
let mut free_map = self.free_map.write(); let mut free_map = self.free_map.write();
if free_map.dirty() { 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 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(); free_map.sync();
} }
// sync all INodes
self.flush_weak_inodes(); self.flush_weak_inodes();
for inode in self.inodes.read().values() { for inode in self.inodes.read().values() {
if let Some(inode) = inode.upgrade() { if let Some(inode) = inode.upgrade() {
inode.sync_all()?; inode.sync_all()?;
} }
} }
self.meta_file.flush()?;
Ok(()) Ok(())
} }
@ -670,7 +699,7 @@ impl Drop for SEFS {
/// Auto sync when drop /// Auto sync when drop
fn drop(&mut self) { fn drop(&mut self) {
self.sync() 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 { match t {
FileType::File => vfs::FileType::File, FileType::File => vfs::FileType::File,
FileType::Dir => vfs::FileType::Dir, FileType::Dir => vfs::FileType::Dir,
FileType::SymLink => vfs::FileType::SymLink,
_ => panic!("unknown file type"), _ => panic!("unknown file type"),
} }
} }

@ -16,6 +16,8 @@ pub struct SuperBlock {
pub blocks: u32, pub blocks: u32,
/// number of unused blocks in fs /// number of unused blocks in fs
pub unused_blocks: u32, pub unused_blocks: u32,
/// number of block groups
pub groups: u32,
} }
/// On-disk inode /// On-disk inode
@ -115,8 +117,6 @@ pub const BLKSIZE_LOG2: u8 = 7;
pub const MAX_INFO_LEN: usize = 31; pub const MAX_INFO_LEN: usize = 31;
/// max length of filename /// max length of filename
pub const MAX_FNAME_LEN: usize = 255; 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 /// block the superblock lives in
pub const BLKN_SUPER: BlockId = 0; pub const BLKN_SUPER: BlockId = 0;
/// location of the root dir inode /// location of the root dir inode
@ -139,7 +139,7 @@ pub enum FileType {
Invalid = 0, Invalid = 0,
File = 1, File = 1,
Dir = 2, Dir = 2,
Link = 3, SymLink = 3,
} }
const_assert!(o1; size_of::<SuperBlock>() <= BLKSIZE); const_assert!(o1; size_of::<SuperBlock>() <= BLKSIZE);

@ -45,7 +45,6 @@ use std::io::{Read, Seek, SeekFrom, Write};
use std::path::PathBuf; use std::path::PathBuf;
use std::sgxfs::{OpenOptions, SgxFile}; use std::sgxfs::{OpenOptions, SgxFile};
use std::sync::{SgxMutex as Mutex, SgxRwLock as RwLock}; use std::sync::{SgxMutex as Mutex, SgxRwLock as RwLock};
use std::vec::Vec;
use sgx_types::sgx_key_128bit_t; use sgx_types::sgx_key_128bit_t;
#[no_mangle] #[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; let mut rest_len = len - current_len;
while rest_len != 0 { while rest_len != 0 {
let l = rest_len.min(0x1000); 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])); try_io!(file.write(&ZEROS[..l]));
} else {
try_io!(Err(e));
}
}
rest_len -= l; rest_len -= l;
} }
// NOTE: Don't try to write a large slice at once. // NOTE: Don't try to write a large slice at once.

Loading…
Cancel
Save