BlockedDevice

master
WangRunji 7 years ago
parent 4f58ba5716
commit 0d39ec0428

@ -0,0 +1,141 @@
use util::*;
use vfs::Device;
/// Device which can only R/W in blocks
pub trait BlockedDevice {
fn block_size_log2(&self) -> u8;
fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool;
fn write_at(&mut self, block_id: usize, buf: &[u8]) -> bool;
}
macro_rules! try0 {
($len:expr, $res:expr) => {
if(!$res) {return Some($len);}
};
}
/// Helper functions to R/W BlockedDevice in bytes
impl<T: BlockedDevice> Device for T {
fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option<usize> {
let iter = BlockIter {
begin: offset,
end: offset + buf.len(),
block_size_log2: self.block_size_log2(),
};
// For each block
for mut range in iter {
let len = range.origin_begin() - offset;
let buf = &mut buf[range.origin_begin() - offset..range.origin_end() - offset];
if range.is_full() {
// Read to target buf directly
try0!(len, BlockedDevice::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);
// Read to local buf first
try0!(len, BlockedDevice::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())
}
fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option<usize> {
let iter = BlockIter {
begin: offset,
end: offset + buf.len(),
block_size_log2: self.block_size_log2(),
};
// For each block
for mut range in iter {
let len = range.origin_begin() - offset;
let buf = &buf[range.origin_begin() - offset..range.origin_end() - offset];
if range.is_full() {
// Write to target buf directly
try0!(len, BlockedDevice::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);
// Read to local buf first
try0!(len, BlockedDevice::read_at(self, range.block, &mut block_buf));
// Write to local buf
block_buf[range.begin..range.end].copy_from_slice(buf);
// Write back to target buf
try0!(len, BlockedDevice::write_at(self, range.block, &block_buf));
}
}
Some(buf.len())
}
}
#[cfg(test)]
mod test {
use super::*;
impl BlockedDevice for [u8; 16] {
fn block_size_log2(&self) -> u8 { 2 }
fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool {
if block_id >= 4 {
return false;
}
let begin = block_id << 2;
buf[..4].copy_from_slice(&mut self[begin..begin + 4]);
true
}
fn write_at(&mut self, block_id: usize, buf: &[u8]) -> bool {
if block_id >= 4 {
return false;
}
let begin = block_id << 2;
self[begin..begin + 4].copy_from_slice(&buf[..4]);
true
}
}
#[test]
fn read() {
let mut buf: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
let mut res: [u8; 6] = [0; 6];
// all inside
let ret = Device::read_at(&mut buf, 3, &mut res);
assert_eq!(ret, Some(6));
assert_eq!(res, [3, 4, 5, 6, 7, 8]);
// partly inside
let ret = Device::read_at(&mut buf, 11, &mut res);
assert_eq!(ret, Some(5));
assert_eq!(res, [11, 12, 13, 14, 15, 8]);
// all outside
let ret = Device::read_at(&mut buf, 16, &mut res);
assert_eq!(ret, Some(0));
assert_eq!(res, [11, 12, 13, 14, 15, 8]);
}
#[test]
fn write() {
let mut buf: [u8; 16] = [0; 16];
let mut res: [u8; 6] = [3, 4, 5, 6, 7, 8];
// all inside
let ret = Device::write_at(&mut buf, 3, &res);
assert_eq!(ret, Some(6));
assert_eq!(buf, [0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0]);
// partly inside
let ret = Device::write_at(&mut buf, 11, &res);
assert_eq!(ret, Some(5));
assert_eq!(buf, [0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 3, 4, 5, 6, 7]);
// all outside
let ret = Device::write_at(&mut buf, 16, &res);
assert_eq!(ret, Some(0));
assert_eq!(buf, [0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 3, 4, 5, 6, 7]);
}
}

@ -24,6 +24,8 @@ macro_rules! eprintln {
}
mod dirty;
mod util;
mod blocked_device;
mod vfs;
mod sfs;
mod structs;
@ -34,6 +36,7 @@ mod tests;
pub use sfs::*;
pub use vfs::*;
pub use blocked_device::BlockedDevice;
#[cfg(feature = "ucore")]
#[global_allocator]

@ -2,12 +2,13 @@ use spin::Mutex;
use bit_set::BitSet;
use alloc::{boxed::Box, Vec, BTreeMap, rc::{Rc, Weak}, String};
use core::cell::{RefCell, RefMut};
use dirty::Dirty;
use super::structs::*;
use super::vfs::{self, Device};
use core::mem::{uninitialized, size_of};
use core::slice;
use core::fmt::{Debug, Formatter, Error};
use dirty::Dirty;
use structs::*;
use vfs::{self, Device};
use util::*;
trait DeviceExt: Device {
fn read_block(&mut self, id: BlockId, offset: usize, buf: &mut [u8]) -> vfs::Result<()> {
@ -180,6 +181,7 @@ impl INode {
let iter = BlockIter {
begin: size.min(begin),
end: size.min(end),
block_size_log2: BLKSIZE_LOG2,
};
// For each block
@ -319,40 +321,6 @@ impl Drop for INode {
}
}
/// Given a range and iterate sub-range for each block
struct BlockIter {
begin: usize,
end: usize,
}
#[derive(Debug, Eq, PartialEq)]
struct BlockRange {
block: BlockId,
begin: usize,
end: usize,
}
impl BlockRange {
fn len(&self) -> usize {
self.end - self.begin
}
}
impl Iterator for BlockIter {
type Item = BlockRange;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
if self.begin >= self.end {
return None;
}
let block = self.begin / BLKSIZE;
let begin = self.begin % BLKSIZE;
let end = if block == self.end / BLKSIZE { self.end % BLKSIZE } else { BLKSIZE };
self.begin += end - begin;
Some(BlockRange { block, begin, end })
}
}
/// filesystem for sfs
///
@ -576,17 +544,3 @@ impl From<FileType> for vfs::FileType {
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn block_iter() {
let mut iter = BlockIter { begin: 0x123, end: 0x2018 };
assert_eq!(iter.next(), Some(BlockRange { block: 0, begin: 0x123, end: 0x1000 }));
assert_eq!(iter.next(), Some(BlockRange { block: 1, begin: 0, end: 0x1000 }));
assert_eq!(iter.next(), Some(BlockRange { block: 2, begin: 0, end: 0x18 }));
assert_eq!(iter.next(), None);
}
}

@ -153,7 +153,9 @@ pub type INodeId = BlockId;
/// magic number for sfs
pub const MAGIC: u32 = 0x2f8dbe2a;
/// size of block
pub const BLKSIZE: usize = 4096;
pub const BLKSIZE: usize = 1usize << BLKSIZE_LOG2;
/// log2( size of block )
pub const BLKSIZE_LOG2: u8 = 12;
/// number of direct blocks in inode
pub const NDIRECT: usize = 12;
/// max length of infomation

@ -0,0 +1,60 @@
/// Given a range and iterate sub-range for each block
pub struct BlockIter {
pub begin: usize,
pub end: usize,
pub block_size_log2: u8,
}
#[derive(Debug, Eq, PartialEq)]
pub struct BlockRange {
pub block: usize,
pub begin: usize,
pub end: usize,
pub block_size_log2: u8,
}
impl BlockRange {
pub fn len(&self) -> usize {
self.end - self.begin
}
pub fn is_full(&self) -> bool {
self.len() == (1usize << self.block_size_log2)
}
pub fn origin_begin(&self) -> usize {
(self.block << self.block_size_log2) + self.begin
}
pub fn origin_end(&self) -> usize {
(self.block << self.block_size_log2) + self.end
}
}
impl Iterator for BlockIter {
type Item = BlockRange;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
if self.begin >= self.end {
return None;
}
let block_size_log2 = self.block_size_log2;
let block_size = 1usize << self.block_size_log2;
let block = self.begin / block_size;
let begin = self.begin % block_size;
let end = if block == self.end / block_size { self.end % block_size } else { block_size };
self.begin += end - begin;
Some(BlockRange { block, begin, end, block_size_log2 })
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn block_iter() {
let mut iter = BlockIter { begin: 0x123, end: 0x2018, block_size_log2: 12 };
assert_eq!(iter.next(), Some(BlockRange { block: 0, begin: 0x123, end: 0x1000, block_size_log2: 12 }));
assert_eq!(iter.next(), Some(BlockRange { block: 1, begin: 0, end: 0x1000, block_size_log2: 12 }));
assert_eq!(iter.next(), Some(BlockRange { block: 2, begin: 0, end: 0x18, block_size_log2: 12 }));
assert_eq!(iter.next(), None);
}
}
Loading…
Cancel
Save