diff --git a/src/ex_node.rs b/src/ex_node.rs new file mode 100644 index 0000000000000000000000000000000000000000..85010c62a08ffc311305a026d656add438494528 --- /dev/null +++ b/src/ex_node.rs @@ -0,0 +1,60 @@ +use collections::Vec; + +use core::{fmt, mem, ops, slice}; + +use super::Extent; + +/// An extra node +#[repr(packed)] +pub struct ExNode { + pub prev: u64, + pub next: u64, + pub extents: [Extent; 31], +} + +impl ExNode { + pub fn default() -> ExNode { + ExNode { + prev: 0, + next: 0, + extents: [Extent::default(); 31], + } + } + + pub fn size(&self) -> u64 { + self.extents.iter().fold(0, |size, extent| size + extent.length) + } +} + +impl fmt::Debug for ExNode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let extents: Vec<&Extent> = self.extents.iter().filter(|extent| -> bool { extent.length > 0 }).collect(); + f.debug_struct("ExNode") + .field("prev", &self.prev) + .field("next", &self.next) + .field("extents", &extents) + .finish() + } +} + +impl ops::Deref for ExNode { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const ExNode as *const u8, mem::size_of::<ExNode>()) as &[u8] + } + } +} + +impl ops::DerefMut for ExNode { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut ExNode as *mut u8, mem::size_of::<ExNode>()) as &mut [u8] + } + } +} + +#[test] +fn ex_node_size_test(){ + assert!(mem::size_of::<ExNode>() <= 512); +} diff --git a/src/filesystem.rs b/src/filesystem.rs index 22008949e4b825106fc56dbdf4ef9ef5c7c663b2..3812a7b7dbef64539661ff2e285782dd40363918 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -88,21 +88,49 @@ impl<E> FileSystem<E> { try!(self.disk.write_at(node.0, &node.1)); let mut inserted = false; - for mut extent in self.root.1.extents.iter_mut() { - if extent.length == 0 { - inserted = true; - extent.length = 512; - extent.block = block; - break; + let mut last_node = (0, Node::default()); + let mut next_node = (self.header.1.root, Node::default()); + while ! inserted { + if next_node.0 > 0 { + try!(self.disk.read_at(next_node.0, &mut next_node.1)); + }else{ + if let Some(block) = try!(self.allocate()) { + next_node.0 = block; + if last_node.0 > 0 { + last_node.1.next = block; + if last_node.0 == self.root.0 { + self.root.1.next = last_node.1.next; + } + try!(self.disk.write_at(last_node.0, &last_node.1)); + } else { + panic!("last_node was 0"); + } + } else { + return Ok(None); + } + } + + for mut extent in next_node.1.extents.iter_mut() { + if extent.length == 0 { + inserted = true; + extent.length = 512; + extent.block = block; + break; + } } - } - if inserted { - try!(self.disk.write_at(self.root.0, &self.root.1)); - Ok(Some(node)) - } else { - Ok(None) + if inserted { + if next_node.0 == self.root.0 { + self.root.1.extents = next_node.1.extents; + } + try!(self.disk.write_at(next_node.0, &next_node.1)); + } else { + last_node = next_node; + next_node = (last_node.1.next, Node::default()); + } } + + Ok(Some(node)) } else { Ok(None) } diff --git a/src/lib.rs b/src/lib.rs index 32f1493aae5c6d76e0dede833bb7d107b1681171..aea8f9ff920b095ae73093ad8f19b98a30d36105 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,12 +14,14 @@ extern crate alloc; extern crate collections; pub use self::disk::Disk; +pub use self::ex_node::ExNode; pub use self::extent::Extent; pub use self::filesystem::FileSystem; pub use self::header::Header; pub use self::node::Node; pub mod disk; +pub mod ex_node; pub mod extent; pub mod filesystem; pub mod header;