Support for less-than-sector block allocations

This commit is contained in:
Jeremy Soller
2016-03-03 15:01:36 -07:00
parent 51e037150c
commit ff0106b212
7 changed files with 121 additions and 109 deletions
+2
View File
@@ -19,6 +19,8 @@ C FILE
cat c_file
ls
exit
EOF
+2 -2
View File
@@ -63,9 +63,9 @@ impl Scheme for FileScheme {
}
}
} else {
for i in 0..try!(self.fs.node_len(node.0)) {
for i in 0..(try!(self.fs.node_len(node.0)) + 511)/512 {
let mut sector = [0; 512];
try!(self.fs.read_node(node.0, i as usize * 512, &mut sector));
try!(self.fs.read_node(node.0, i as u64 * 512, &mut sector));
data.extend_from_slice(&sector);
}
},
-30
View File
@@ -1,30 +0,0 @@
use collections::Vec;
use system::error::Result;
use super::{ExNode, FileSystem, Node};
/// A collection of a Node and its associated ExNodes
pub struct Collection {
pub node: (u64, Node),
pub ex_nodes: Vec<(u64, ExNode)>
}
impl Collection {
pub fn load(fs: &mut FileSystem, block: u64) -> Result<Collection> {
let node = try!(fs.node(block));
let mut next = node.1.next;
let mut ex_nodes = Vec::new();
while next > 0 {
let ex_node = try!(fs.ex_node(next));
next = ex_node.1.next;
ex_nodes.push(ex_node);
}
Ok(Collection {
node: node,
ex_nodes: ex_nodes,
})
}
}
+29
View File
@@ -1,3 +1,24 @@
use core::cmp::min;
pub struct BlockIter {
block: u64,
length: u64,
i: u64
}
impl Iterator<> for BlockIter {
type Item = (u64, usize);
fn next(&mut self) -> Option<Self::Item> {
if self.i < (self.length + 511)/512 {
let ret = Some((self.block + self.i, min(512, self.length - self.i * 512) as usize));
self.i += 1;
ret
} else {
None
}
}
}
/// A disk extent
#[derive(Copy, Clone, Debug, Default)]
#[repr(packed)]
@@ -20,4 +41,12 @@ impl Extent {
length: length
}
}
pub fn blocks(&self) -> BlockIter {
BlockIter {
block: self.block,
length: self.length,
i: 0
}
}
}
+82 -65
View File
@@ -36,11 +36,11 @@ impl FileSystem {
/// Create a file system on a disk
pub fn create(mut disk: Box<Disk>) -> Result<Self> {
let size = try!(disk.size())/512;
let size = try!(disk.size());
if size >= 4 {
if size >= 4 * 512 {
let mut free = (3, Node::new(Node::MODE_FILE, "free", 0));
free.1.extents[0] = Extent::new(4, size - 4);
free.1.extents[0] = Extent::new(4, size - 4 * 512);
try!(disk.write_at(free.0, &free.1));
let root = (2, Node::new(Node::MODE_DIR, "root", 0));
@@ -64,9 +64,9 @@ impl FileSystem {
let mut free = try!(self.node(free_block));
let mut block_option = None;
for mut extent in free.1.extents.iter_mut() {
if extent.length >= length {
if extent.length/512 >= length {
block_option = Some(extent.block);
extent.length -= length;
extent.length -= length * 512;
extent.block += length;
break;
}
@@ -103,8 +103,10 @@ impl FileSystem {
let parent = try!(self.node(parent_block));
for extent in parent.1.extents.iter() {
for i in 0 .. extent.length {
children.push(try!(self.node(extent.block + i)));
for (block, size) in extent.blocks() {
if size >= 512 {
children.push(try!(self.node(block)));
}
}
}
@@ -118,18 +120,20 @@ impl FileSystem {
let parent = try!(self.node(parent_block));
for extent in parent.1.extents.iter() {
for i in 0 .. extent.length {
let child = try!(self.node(extent.block + i));
for (block, size) in extent.blocks() {
if size >= 512 {
let child = try!(self.node(block));
let mut matches = false;
if let Ok(child_name) = child.1.name() {
if child_name == name {
matches = true;
let mut matches = false;
if let Ok(child_name) = child.1.name() {
if child_name == name {
matches = true;
}
}
}
if matches {
return Ok(child);
if matches {
return Ok(child);
}
}
}
}
@@ -151,13 +155,13 @@ impl FileSystem {
extent.block = block;
extent.length = length;
break;
} else if extent.block == block + length {
} else if length % 512 == 0 && extent.block == block + length/512 {
//At beginning
inserted = true;
extent.block = block;
extent.length += length;
break;
} else if extent.block + extent.length == block {
} else if extent.length % 512 == 0 && extent.block + extent.length/512 == block {
//At end
inserted = true;
extent.length += length;
@@ -186,7 +190,7 @@ impl FileSystem {
let node = (try!(self.allocate(1)), Node::new(mode, name, parent_block));
try!(self.disk.write_at(node.0, &node.1));
try!(self.insert_blocks(node.0, 1, parent_block));
try!(self.insert_blocks(node.0, 512, parent_block));
Ok(node)
}
@@ -201,12 +205,12 @@ impl FileSystem {
let mut replace_option = None;
let mut parent = try!(self.node(parent_block));
for mut extent in parent.1.extents.iter_mut() {
if block >= extent.block && block + length <= extent.block + extent.length {
if block >= extent.block && block + length <= extent.block + length/512 {
//Inside
removed = true;
let left = Extent::new(extent.block, block - extent.block);
let right = Extent::new(block + length, (extent.block + extent.length) - (block + length));
let left = Extent::new(extent.block, (block - extent.block) * 512);
let right = Extent::new(block + length, ((extent.block + extent.length/512) - (block + length)) * 512);
if left.length > 0 {
*extent = left;
@@ -228,13 +232,10 @@ impl FileSystem {
try!(self.disk.write_at(parent.0, &parent.1));
if let Some(replace) = replace_option {
for i in 0..replace.length {
let block = replace.block + i;
try!(self.insert_blocks(block, 1, parent_block));
}
try!(self.insert_blocks(replace.block, replace.length, parent_block));
}
try!(self.deallocate(block, 1));
try!(self.deallocate(block, 512));
Ok(())
} else {
@@ -283,7 +284,7 @@ impl FileSystem {
if node.1.next > 0 {
self.node_ensure_len(node.1.next, length)
} else {
let new_block = try!(self.allocate(length));
let new_block = try!(self.allocate((length + 511)/512));
try!(self.insert_blocks(new_block, length, block));
Ok(())
}
@@ -292,80 +293,96 @@ impl FileSystem {
}
}
fn node_blocks(&mut self, block: u64, mut offset: usize, mut len: usize, blocks: &mut Vec<u64>) -> Result<()> {
fn node_extents(&mut self, block: u64, mut offset: u64, mut len: usize, extents: &mut Vec<Extent>) -> Result<()> {
if block == 0 {
return Err(Error::new(ENOENT));
return Ok(());
}
let node = try!(self.node(block));
for extent in node.1.extents.iter() {
for i in 0 .. extent.length {
let mut push_extent = Extent::default();
for (block, size) in extent.blocks() {
if offset == 0 {
if len > 0 {
blocks.push(extent.block + i);
len -= 1;
if push_extent.block == 0 {
push_extent.block = block;
}
if len >= size {
push_extent.length += size as u64;
len -= size;
} else if len > 0 {
push_extent.length += len as u64;
len = 0;
break;
} else {
return Ok(())
break;
}
} else {
offset -= 1;
}
}
if push_extent.length > 0 {
extents.push(push_extent);
}
if len == 0 {
break;
}
}
if offset > 0 || len > 0 {
self.node_blocks(node.1.next, offset, len, blocks)
if len > 0 {
self.node_extents(node.1.next, offset, len, extents)
} else {
Ok(())
}
}
pub fn read_node(&mut self, block: u64, offset: usize, buf: &mut [u8]) -> Result<usize> {
pub fn read_node(&mut self, block: u64, offset: u64, buf: &mut [u8]) -> Result<usize> {
let block_offset = offset / 512;
let mut byte_offset = offset % 512;
let block_len = (buf.len() + byte_offset + 511)/512;
let mut byte_offset = (offset % 512) as usize;
let mut blocks = Vec::new();
try!(self.node_blocks(block, block_offset, block_len, &mut blocks));
let mut extents = Vec::new();
try!(self.node_extents(block, block_offset, byte_offset + buf.len(), &mut extents));
let mut i = 0;
for &block in blocks.iter() {
let mut sector = [0; 512];
try!(self.disk.read_at(block, &mut sector));
for extent in extents.iter() {
for (block, size) in extent.blocks() {
let mut sector = [0; 512];
try!(self.disk.read_at(block, &mut sector));
for (s_b, mut b) in sector.iter().skip(byte_offset).zip((&mut buf[i..]).iter_mut()) {
*b = *s_b;
i += 1;
for (s_b, mut b) in sector[byte_offset..size].iter().zip(buf[i..].iter_mut()) {
*b = *s_b;
i += 1;
}
byte_offset = 0;
}
byte_offset = 0;
}
Ok(i)
}
pub fn write_node(&mut self, block: u64, offset: usize, buf: &[u8]) -> Result<usize> {
pub fn write_node(&mut self, block: u64, offset: u64, buf: &[u8]) -> Result<usize> {
let block_offset = offset / 512;
let mut byte_offset = offset % 512;
let block_len = (buf.len() + byte_offset + 511)/512;
let mut byte_offset = (offset % 512) as usize;
try!(self.node_ensure_len(block, (block_offset + block_len) as u64));
try!(self.node_ensure_len(block, block_offset as u64 * 512 + (byte_offset + buf.len()) as u64));
let mut blocks = Vec::new();
try!(self.node_blocks(block, block_offset, block_len, &mut blocks));
let mut extents = Vec::new();
try!(self.node_extents(block, block_offset, byte_offset + buf.len(), &mut extents));
let mut i = 0;
for &block in blocks.iter() {
let mut sector = [0; 512];
for extent in extents.iter() {
for (block, size) in extent.blocks() {
let mut sector = [0; 512];
for (mut s_b, b) in sector.iter_mut().skip(byte_offset).zip(buf[i..].iter()) {
*s_b = *b;
i += 1;
for (mut s_b, b) in sector[byte_offset..size].iter_mut().zip(buf[i..].iter()) {
*s_b = *b;
i += 1;
}
try!(self.disk.write_at(block, &sector));
byte_offset = 0;
}
try!(self.disk.write_at(block, &sector));
byte_offset = 0;
}
Ok(i)
-2
View File
@@ -15,7 +15,6 @@ extern crate collections;
extern crate system;
pub use self::collection::Collection;
pub use self::disk::Disk;
pub use self::ex_node::ExNode;
pub use self::extent::Extent;
@@ -23,7 +22,6 @@ pub use self::filesystem::FileSystem;
pub use self::header::Header;
pub use self::node::Node;
pub mod collection;
pub mod disk;
pub mod ex_node;
pub mod extent;
+6 -10
View File
@@ -10,11 +10,10 @@ pub struct Node {
pub mode: u16,
pub user: u16,
pub group: u16,
pub size: u64,
pub name: [u8; 258],
pub name: [u8; 250],
pub parent: u64,
pub next: u64,
pub extents: [Extent; 14],
pub extents: [Extent; 15],
}
impl Node {
@@ -29,16 +28,15 @@ impl Node {
mode: 0,
user: 0,
group: 0,
size: 0,
name: [0; 258],
name: [0; 250],
parent: 0,
next: 0,
extents: [Extent::default(); 14],
extents: [Extent::default(); 15],
}
}
pub fn new(mode: u16, name: &str, parent: u64) -> Node {
let mut bytes = [0; 258];
let mut bytes = [0; 250];
for (mut b, c) in bytes.iter_mut().zip(name.bytes()) {
*b = c;
}
@@ -47,11 +45,10 @@ impl Node {
mode: mode,
user: 0,
group: 0,
size: 0,
name: bytes,
parent: parent,
next: 0,
extents: [Extent::default(); 14],
extents: [Extent::default(); 15],
}
}
@@ -88,7 +85,6 @@ impl fmt::Debug for Node {
.field("mode", &self.mode)
.field("user", &self.user)
.field("group", &self.group)
.field("size", &self.size)
.field("name", &self.name())
.field("next", &self.next)
.field("extents", &extents)