From ff0106b212f6d67b30cf24fbf940f3a5a7b61ecd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 3 Mar 2016 15:01:36 -0700 Subject: [PATCH] Support for less-than-sector block allocations --- create.sh | 2 + scheme/scheme.rs | 4 +- src/collection.rs | 30 ---------- src/extent.rs | 29 +++++++++ src/filesystem.rs | 147 ++++++++++++++++++++++++++-------------------- src/lib.rs | 2 - src/node.rs | 16 ++--- 7 files changed, 121 insertions(+), 109 deletions(-) delete mode 100644 src/collection.rs diff --git a/create.sh b/create.sh index 7aee4f3ebd..e6136d19d9 100755 --- a/create.sh +++ b/create.sh @@ -19,6 +19,8 @@ C FILE cat c_file +ls + exit EOF diff --git a/scheme/scheme.rs b/scheme/scheme.rs index f20be65687..a393f056e2 100644 --- a/scheme/scheme.rs +++ b/scheme/scheme.rs @@ -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(§or); } }, diff --git a/src/collection.rs b/src/collection.rs deleted file mode 100644 index aa7f7e0517..0000000000 --- a/src/collection.rs +++ /dev/null @@ -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 { - 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, - }) - } -} diff --git a/src/extent.rs b/src/extent.rs index 7a0010b51f..64baf58739 100644 --- a/src/extent.rs +++ b/src/extent.rs @@ -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 { + 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 + } + } } diff --git a/src/filesystem.rs b/src/filesystem.rs index 5c5c7c0141..b61845586f 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -36,11 +36,11 @@ impl FileSystem { /// Create a file system on a disk pub fn create(mut disk: Box) -> Result { - 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) -> Result<()> { + fn node_extents(&mut self, block: u64, mut offset: u64, mut len: usize, extents: &mut Vec) -> 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 { + pub fn read_node(&mut self, block: u64, offset: u64, buf: &mut [u8]) -> Result { 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 { + pub fn write_node(&mut self, block: u64, offset: u64, buf: &[u8]) -> Result { 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, §or)); + + byte_offset = 0; } - - try!(self.disk.write_at(block, §or)); - - byte_offset = 0; } Ok(i) diff --git a/src/lib.rs b/src/lib.rs index 9e3d93401b..03b5667f04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/node.rs b/src/node.rs index bf50220c3a..5856945320 100644 --- a/src/node.rs +++ b/src/node.rs @@ -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)