improve Device trait. fix some warnings.

master
WangRunji 6 years ago
parent 6f282baf2f
commit 09382c21b8

@ -5,7 +5,6 @@ use rcore_fs::vfs::FsError;
#[cfg(any(test, feature = "std"))]
pub use self::std_impl::*;
pub mod sgx_impl;
pub mod std_impl;
/// A file stores a normal file or directory.

@ -1,115 +0,0 @@
#![cfg(feature = "sgx")]
use std::boxed::Box;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::sgxfs::{remove, OpenOptions, SgxFile as File};
use std::sync::SgxMutex as Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
use std::untrusted::time::SystemTimeEx; // FIXME: use trusted ime
use rcore_fs::dev::TimeProvider;
use rcore_fs::vfs::Timespec;
use super::{DevResult, DeviceError};
pub struct SgxStorage {
path: PathBuf,
}
impl SgxStorage {
pub fn new(path: impl AsRef<Path>) -> Self {
// assert!(path.as_ref().is_dir());
SgxStorage {
path: path.as_ref().to_path_buf(),
}
}
}
impl super::Storage for SgxStorage {
fn open(&self, file_id: usize) -> DevResult<Box<super::File>> {
let mut path = self.path.to_path_buf();
path.push(format!("{}", file_id));
// TODO: key
let key = [0u8; 16];
let file = OpenOptions::new()
.read(true)
.update(true)
.open_ex(path, &key)?;
Ok(Box::new(LockedFile(Mutex::new(file))))
}
fn create(&self, file_id: usize) -> DevResult<Box<super::File>> {
let mut path = self.path.to_path_buf();
path.push(format!("{}", file_id));
// TODO: key
let key = [0u8; 16];
let file = OpenOptions::new()
.write(true)
.update(true)
.open_ex(path, &key)?;
Ok(Box::new(LockedFile(Mutex::new(file))))
}
fn remove(&self, file_id: usize) -> DevResult<()> {
let mut path = self.path.to_path_buf();
path.push(format!("{}", file_id));
remove(path)?;
Ok(())
}
}
impl From<std::io::Error> for DeviceError {
fn from(e: std::io::Error) -> Self {
println!("{:?}", e);
panic!("{:?}", e);
DeviceError
}
}
pub struct LockedFile(Mutex<File>);
// `sgx_tstd::sgxfs::SgxFile` not impl Send ...
unsafe impl Send for LockedFile {}
unsafe impl Sync for LockedFile {}
impl super::File for LockedFile {
fn read_at(&self, buf: &mut [u8], offset: usize) -> DevResult<usize> {
let mut file = self.0.lock().unwrap();
let offset = offset as u64;
file.seek(SeekFrom::Start(offset))?;
let len = file.read(buf)?;
Ok(len)
}
fn write_at(&self, buf: &[u8], offset: usize) -> DevResult<usize> {
let mut file = self.0.lock().unwrap();
let offset = offset as u64;
file.seek(SeekFrom::Start(offset))?;
let len = file.write(buf)?;
Ok(len)
}
fn set_len(&self, len: usize) -> DevResult<()> {
// NOTE: do nothing ??
Ok(())
}
fn flush(&self) -> DevResult<()> {
let mut file = self.0.lock().unwrap();
file.flush()?;
Ok(())
}
}
pub struct SgxTimeProvider;
impl TimeProvider for SgxTimeProvider {
fn current_time(&self) -> Timespec {
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
Timespec {
sec: duration.as_secs() as i64,
nsec: duration.subsec_nanos() as i32,
}
}
}

@ -77,13 +77,13 @@ impl super::File for Mutex<File> {
}
fn set_len(&self, len: usize) -> DevResult<()> {
let mut file = self.lock();
let file = self.lock();
file.set_len(len as u64)?;
Ok(())
}
fn flush(&self) -> DevResult<()> {
let mut file = self.lock();
let file = self.lock();
file.sync_all()?;
Ok(())
}

@ -113,8 +113,6 @@ pub const MAGIC: u32 = 0x2f8dbe2a;
pub const BLKSIZE: usize = 1usize << BLKSIZE_LOG2;
/// log2( size of block )
pub const BLKSIZE_LOG2: u8 = 7;
/// max length of information
pub const MAX_INFO_LEN: usize = 31;
/// max length of filename
pub const MAX_FNAME_LEN: usize = 255;
/// block the superblock lives in
@ -125,10 +123,6 @@ pub const BLKN_ROOT: BlockId = 2;
pub const BLKN_FREEMAP: BlockId = 1;
/// number of bits in a block
pub const BLKBITS: usize = BLKSIZE * 8;
/// size of one entry
pub const ENTRY_SIZE: usize = 4;
/// number of entries in a block
pub const BLK_NENTRY: usize = BLKSIZE / ENTRY_SIZE;
/// size of a dirent used in the size field
pub const DIRENT_SIZE: usize = 260;

@ -35,14 +35,14 @@ trait DeviceExt: Device {
fn read_block(&self, id: BlockId, offset: usize, buf: &mut [u8]) -> vfs::Result<()> {
debug_assert!(offset + buf.len() <= BLKSIZE);
match self.read_at(id * BLKSIZE + offset, buf) {
Some(len) if len == buf.len() => Ok(()),
Ok(len) if len == buf.len() => Ok(()),
_ => panic!("cannot read block {} offset {} from device", id, offset),
}
}
fn write_block(&self, id: BlockId, offset: usize, buf: &[u8]) -> vfs::Result<()> {
debug_assert!(offset + buf.len() <= BLKSIZE);
match self.write_at(id * BLKSIZE + offset, buf) {
Some(len) if len == buf.len() => Ok(()),
Ok(len) if len == buf.len() => Ok(()),
_ => panic!("cannot write block {} offset {} to device", id, offset),
}
}
@ -213,7 +213,7 @@ impl INodeImpl {
if blocks > MAX_NBLOCK_DOUBLE_INDIRECT as u32 {
return Err(FsError::InvalidParam);
}
use core::cmp::{Ord, Ordering};
use core::cmp::Ordering;
let old_blocks = self.disk_inode.read().blocks;
match blocks.cmp(&old_blocks) {
Ordering::Equal => {} // Do nothing

@ -9,30 +9,40 @@ pub trait TimeProvider: Send + Sync {
}
/// Interface for FS to read & write
/// TODO: use std::io::{Read, Write}
pub trait Device: Send + Sync {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Option<usize>;
fn write_at(&self, offset: usize, buf: &[u8]) -> Option<usize>;
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize>;
fn sync(&self) -> Result<()>;
}
/// Device which can only R/W in blocks
pub trait BlockDevice: Send + Sync {
const BLOCK_SIZE_LOG2: u8;
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> bool;
fn write_at(&self, block_id: usize, buf: &[u8]) -> bool;
fn read_at(&self, block_id: BlockId, buf: &mut [u8]) -> Result<()>;
fn write_at(&self, block_id: BlockId, buf: &[u8]) -> Result<()>;
fn sync(&self) -> Result<()>;
}
/// The error type for device.
#[derive(Debug, PartialEq, Eq)]
pub struct DevError;
/// A specialized `Result` type for device.
pub type Result<T> = core::result::Result<T, DevError>;
pub type BlockId = usize;
macro_rules! try0 {
($len:expr, $res:expr) => {
if !$res {
return Some($len);
if $res.is_err() {
return Ok($len);
}
};
}
/// Helper functions to R/W BlockDevice in bytes
impl<T: BlockDevice> Device for T {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Option<usize> {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
let iter = BlockIter {
begin: offset,
end: offset + buf.len(),
@ -48,18 +58,18 @@ impl<T: BlockDevice> Device for T {
try0!(len, BlockDevice::read_at(self, range.block, buf));
} else {
use core::mem::uninitialized;
let mut block_buf: [u8; 4096] = unsafe { uninitialized() };
assert!(Self::BLOCK_SIZE_LOG2 <= 12);
let mut block_buf: [u8; 1 << 10] = unsafe { uninitialized() };
assert!(Self::BLOCK_SIZE_LOG2 <= 10);
// Read to local buf first
try0!(len, BlockDevice::read_at(self, range.block, &mut block_buf));
// Copy to target buf then
buf.copy_from_slice(&mut block_buf[range.begin..range.end]);
}
}
Some(buf.len())
Ok(buf.len())
}
fn write_at(&self, offset: usize, buf: &[u8]) -> Option<usize> {
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
let iter = BlockIter {
begin: offset,
end: offset + buf.len(),
@ -75,8 +85,8 @@ impl<T: BlockDevice> Device for T {
try0!(len, BlockDevice::write_at(self, range.block, buf));
} else {
use core::mem::uninitialized;
let mut block_buf: [u8; 4096] = unsafe { uninitialized() };
assert!(Self::BLOCK_SIZE_LOG2 <= 12);
let mut block_buf: [u8; 1 << 10] = unsafe { uninitialized() };
assert!(Self::BLOCK_SIZE_LOG2 <= 10);
// Read to local buf first
try0!(len, BlockDevice::read_at(self, range.block, &mut block_buf));
// Write to local buf
@ -85,7 +95,11 @@ impl<T: BlockDevice> Device for T {
try0!(len, BlockDevice::write_at(self, range.block, &block_buf));
}
}
Some(buf.len())
Ok(buf.len())
}
fn sync(&self) -> Result<()> {
BlockDevice::sync(self)
}
}
@ -96,21 +110,24 @@ mod test {
impl BlockDevice for Mutex<[u8; 16]> {
const BLOCK_SIZE_LOG2: u8 = 2;
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> bool {
fn read_at(&self, block_id: BlockId, buf: &mut [u8]) -> Result<()> {
if block_id >= 4 {
return false;
return Err(DevError);
}
let begin = block_id << 2;
buf[..4].copy_from_slice(&mut self.lock().unwrap()[begin..begin + 4]);
true
Ok(())
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> bool {
fn write_at(&self, block_id: BlockId, buf: &[u8]) -> Result<()> {
if block_id >= 4 {
return false;
return Err(DevError);
}
let begin = block_id << 2;
self.lock().unwrap()[begin..begin + 4].copy_from_slice(&buf[..4]);
true
Ok(())
}
fn sync(&self) -> Result<()> {
Ok(())
}
}
@ -122,17 +139,17 @@ mod test {
// all inside
let ret = Device::read_at(&buf, 3, &mut res);
assert_eq!(ret, Some(6));
assert_eq!(ret, Ok(6));
assert_eq!(res, [3, 4, 5, 6, 7, 8]);
// partly inside
let ret = Device::read_at(&buf, 11, &mut res);
assert_eq!(ret, Some(5));
assert_eq!(ret, Ok(5));
assert_eq!(res, [11, 12, 13, 14, 15, 8]);
// all outside
let ret = Device::read_at(&buf, 16, &mut res);
assert_eq!(ret, Some(0));
assert_eq!(ret, Ok(0));
assert_eq!(res, [11, 12, 13, 14, 15, 8]);
}
@ -143,7 +160,7 @@ mod test {
// all inside
let ret = Device::write_at(&buf, 3, &res);
assert_eq!(ret, Some(6));
assert_eq!(ret, Ok(6));
assert_eq!(
*buf.lock().unwrap(),
[0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0]
@ -151,7 +168,7 @@ mod test {
// partly inside
let ret = Device::write_at(&buf, 11, &res);
assert_eq!(ret, Some(5));
assert_eq!(ret, Ok(5));
assert_eq!(
*buf.lock().unwrap(),
[0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 3, 4, 5, 6, 7]
@ -159,7 +176,7 @@ mod test {
// all outside
let ret = Device::write_at(&buf, 16, &res);
assert_eq!(ret, Some(0));
assert_eq!(ret, Ok(0));
assert_eq!(
*buf.lock().unwrap(),
[0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 3, 4, 5, 6, 7]

@ -1,29 +1,33 @@
#![cfg(any(test, feature = "std"))]
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::io::{Read, Seek, SeekFrom, Write, Error};
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
use super::*;
impl Device for Mutex<File> {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Option<usize> {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
let offset = offset as u64;
let mut file = self.lock().unwrap();
match file.seek(SeekFrom::Start(offset)) {
Ok(real_offset) if real_offset == offset => file.read(buf).ok(),
_ => None,
}
file.seek(SeekFrom::Start(offset))?;
let len = file.read(buf)?;
Ok(len)
}
fn write_at(&self, offset: usize, buf: &[u8]) -> Option<usize> {
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
let offset = offset as u64;
let mut file = self.lock().unwrap();
match file.seek(SeekFrom::Start(offset)) {
Ok(real_offset) if real_offset == offset => file.write(buf).ok(),
_ => None,
file.seek(SeekFrom::Start(offset))?;
let len = file.write(buf)?;
Ok(len)
}
fn sync(&self) -> Result<()> {
let file = self.lock().unwrap();
file.sync_all()?;
Ok(())
}
}
@ -38,3 +42,9 @@ impl TimeProvider for StdTimeProvider {
}
}
}
impl From<Error> for DevError {
fn from(e: Error) -> Self {
DevError
}
}

Loading…
Cancel
Save