From 513bfaf805b7161128737052be6c56d1cdf51abb Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Sun, 19 Nov 2017 16:15:01 -0700
Subject: [PATCH] Set block size programatically

---
 src/disk/cache/linked_hash_map.rs | 204 ------------------------------
 src/disk/cache/lru_cache.rs       | 164 ------------------------
 src/disk/cache/mod.rs             |  27 ++--
 src/disk/file.rs                  |   5 +-
 src/ex_node.rs                    |   9 +-
 src/extent.rs                     |   8 +-
 src/filesystem.rs                 |  82 ++++++------
 src/header.rs                     |  12 +-
 src/lib.rs                        |   2 +
 src/mount/fuse.rs                 |   5 +-
 src/mount/redox/scheme.rs         |   3 +-
 src/node.rs                       |   9 +-
 12 files changed, 87 insertions(+), 443 deletions(-)

diff --git a/src/disk/cache/linked_hash_map.rs b/src/disk/cache/linked_hash_map.rs
index 845db2f..cc8f620 100644
--- a/src/disk/cache/linked_hash_map.rs
+++ b/src/disk/cache/linked_hash_map.rs
@@ -9,23 +9,6 @@
 // except according to those terms.
 
 //! A HashMap wrapper that holds key-value pairs in insertion order.
-//!
-//! # Examples
-//!
-//! ```
-//! use linked_hash_map::LinkedHashMap;
-//!
-//! let mut map = LinkedHashMap::new();
-//! map.insert(2, 20);
-//! map.insert(1, 10);
-//! map.insert(3, 30);
-//! assert_eq!(map[&1], 10);
-//! assert_eq!(map[&2], 20);
-//! assert_eq!(map[&3], 30);
-//!
-//! let items: Vec<(i32, i32)> = map.iter().map(|t| (*t.0, *t.1)).collect();
-//! assert_eq!(items, [(2, 20), (1, 10), (3, 30)]);
-//! ```
 
 #![forbid(missing_docs)]
 #![cfg_attr(feature = "nightly", feature(hashmap_public_hasher))]
@@ -167,18 +150,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
 
     /// Inserts a key-value pair into the map. If the key already existed, the old value is
     /// returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    ///
-    /// map.insert(1, "a");
-    /// map.insert(2, "b");
-    /// assert_eq!(map[&1], "a");
-    /// assert_eq!(map[&2], "b");
-    /// ```
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         if self.head.is_null() {
             // allocate the guard node if not present
@@ -231,39 +202,11 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Returns the value corresponding to the key in the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    ///
-    /// map.insert(1, "a");
-    /// map.insert(2, "b");
-    /// map.insert(2, "c");
-    /// map.insert(3, "d");
-    ///
-    /// assert_eq!(map.get(&1), Some(&"a"));
-    /// assert_eq!(map.get(&2), Some(&"c"));
-    /// ```
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Eq + Hash {
         self.map.get(Qey::from_ref(k)).map(|e| &e.value)
     }
 
     /// Returns the mutable reference corresponding to the key in the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    ///
-    /// map.insert(1, "a");
-    /// map.insert(2, "b");
-    ///
-    /// *map.get_mut(&1).unwrap() = "c";
-    /// assert_eq!(map.get(&1), Some(&"c"));
-    /// ```
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Eq + Hash {
         self.map.get_mut(Qey::from_ref(k)).map(|e| &mut e.value)
     }
@@ -272,21 +215,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     ///
     /// If value is found, it is moved to the end of the list.
     /// This operation can be used in implemenation of LRU cache.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    ///
-    /// map.insert(1, "a");
-    /// map.insert(2, "b");
-    /// map.insert(3, "d");
-    ///
-    /// assert_eq!(map.get_refresh(&2), Some(&mut "b"));
-    ///
-    /// assert_eq!((&2, &"b"), map.iter().rev().next().unwrap());
-    /// ```
     pub fn get_refresh<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Eq + Hash {
         let (value, node_ptr_opt) = match self.map.get_mut(Qey::from_ref(k)) {
             None => (None, None),
@@ -303,20 +231,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Removes and returns the value corresponding to the key from the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    ///
-    /// map.insert(2, "a");
-    ///
-    /// assert_eq!(map.remove(&1), None);
-    /// assert_eq!(map.remove(&2), Some("a"));
-    /// assert_eq!(map.remove(&2), None);
-    /// assert_eq!(map.len(), 0);
-    /// ```
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Eq + Hash {
         let removed = self.map.remove(Qey::from_ref(k));
         removed.map(|mut node| {
@@ -335,14 +249,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Returns the maximum number of key-value pairs the map can hold without reallocating.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map: LinkedHashMap<i32, &str> = LinkedHashMap::new();
-    /// let capacity = map.capacity();
-    /// ```
     pub fn capacity(&self) -> usize {
         self.map.capacity()
     }
@@ -350,18 +256,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     /// Removes the first entry.
     ///
     /// Can be used in implementation of LRU cache.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert(1, 10);
-    /// map.insert(2, 20);
-    /// map.pop_front();
-    /// assert_eq!(map.get(&1), None);
-    /// assert_eq!(map.get(&2), Some(&20));
-    /// ```
     #[inline]
     pub fn pop_front(&mut self) -> Option<(K, V)> {
         if self.len() > 0 {
@@ -375,16 +269,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Gets the first entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert(1, 10);
-    /// map.insert(2, 20);
-    /// assert_eq!(map.front(), Some((&1, &10)));
-    /// ```
     #[inline]
     pub fn front(&self) -> Option<(&K, &V)> {
         if self.len() > 0 {
@@ -396,18 +280,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Removes the last entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert(1, 10);
-    /// map.insert(2, 20);
-    /// map.pop_back();
-    /// assert_eq!(map.get(&1), Some(&10));
-    /// assert_eq!(map.get(&2), None);
-    /// ```
     #[inline]
     pub fn pop_back(&mut self) -> Option<(K, V)> {
         if self.len() > 0 {
@@ -421,16 +293,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Gets the last entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert(1, 10);
-    /// map.insert(2, 20);
-    /// assert_eq!(map.back(), Some((&2, &20)));
-    /// ```
     #[inline]
     pub fn back(&mut self) -> Option<(&K, &V)> {
         if self.len() > 0 {
@@ -461,22 +323,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
 
     /// Returns a double-ended iterator visiting all key-value pairs in order of insertion.
     /// Iterator element type is `(&'a K, &'a V)`
-    ///
-    /// # Examples
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    ///
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert("a", 10);
-    /// map.insert("c", 30);
-    /// map.insert("b", 20);
-    ///
-    /// let mut iter = map.iter();
-    /// assert_eq!((&"a", &10), iter.next().unwrap());
-    /// assert_eq!((&"c", &30), iter.next().unwrap());
-    /// assert_eq!((&"b", &20), iter.next().unwrap());
-    /// assert_eq!(None, iter.next());
-    /// ```
     pub fn iter(&self) -> Iter<K, V> {
         let head = if ! self.head.is_null() {
             unsafe { (*self.head).prev }
@@ -493,24 +339,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
 
     /// Returns a double-ended iterator visiting all key-value pairs in order of insertion.
     /// Iterator element type is `(&'a K, &'a mut V)`
-    /// # Examples
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    ///
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert("a", 10);
-    /// map.insert("c", 30);
-    /// map.insert("b", 20);
-    ///
-    /// {
-    ///     let mut iter = map.iter_mut();
-    ///     let mut entry = iter.next().unwrap();
-    ///     assert_eq!(&"a", entry.0);
-    ///     *entry.1 = 17;
-    /// }
-    ///
-    /// assert_eq!(&17, map.get(&"a").unwrap());
-    /// ```
     pub fn iter_mut(&mut self) -> IterMut<K, V> {
         let head = if ! self.head.is_null() {
             unsafe { (*self.head).prev }
@@ -526,22 +354,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Returns a double-ended iterator visiting all key in order of insertion.
-    ///
-    /// # Examples
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    ///
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert('a', 10);
-    /// map.insert('c', 30);
-    /// map.insert('b', 20);
-    ///
-    /// let mut keys = map.keys();
-    /// assert_eq!(&'a', keys.next().unwrap());
-    /// assert_eq!(&'c', keys.next().unwrap());
-    /// assert_eq!(&'b', keys.next().unwrap());
-    /// assert_eq!(None, keys.next());
-    /// ```
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((&'a K, &'a V)) -> &'a K = first; // coerce to fn ptr
@@ -550,22 +362,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
     }
 
     /// Returns a double-ended iterator visiting all values in order of insertion.
-    ///
-    /// # Examples
-    /// ```
-    /// use linked_hash_map::LinkedHashMap;
-    ///
-    /// let mut map = LinkedHashMap::new();
-    /// map.insert('a', 10);
-    /// map.insert('c', 30);
-    /// map.insert('b', 20);
-    ///
-    /// let mut values = map.values();
-    /// assert_eq!(&10, values.next().unwrap());
-    /// assert_eq!(&30, values.next().unwrap());
-    /// assert_eq!(&20, values.next().unwrap());
-    /// assert_eq!(None, values.next());
-    /// ```
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((&'a K, &'a V)) -> &'a V = second; // coerce to fn ptr
diff --git a/src/disk/cache/lru_cache.rs b/src/disk/cache/lru_cache.rs
index 6cdb28d..b5ea5e9 100644
--- a/src/disk/cache/lru_cache.rs
+++ b/src/disk/cache/lru_cache.rs
@@ -12,30 +12,6 @@
 //! capacity of the cache is exceeded, the least-recently-used
 //! (where "used" means a look-up or putting the pair into the cache)
 //! pair is automatically removed.
-//!
-//! # Examples
-//!
-//! ```
-//! use lru_cache::LruCache;
-//!
-//! let mut cache = LruCache::new(2);
-//!
-//! cache.insert(1, 10);
-//! cache.insert(2, 20);
-//! cache.insert(3, 30);
-//! assert!(cache.get_mut(&1).is_none());
-//! assert_eq!(*cache.get_mut(&2).unwrap(), 20);
-//! assert_eq!(*cache.get_mut(&3).unwrap(), 30);
-//!
-//! cache.insert(2, 22);
-//! assert_eq!(*cache.get_mut(&2).unwrap(), 22);
-//!
-//! cache.insert(6, 60);
-//! assert!(cache.get_mut(&3).is_none());
-//!
-//! cache.set_capacity(1);
-//! assert!(cache.get_mut(&2).is_none());
-//! ```
 
 use std::collections::hash_map::RandomState;
 use std::fmt;
@@ -54,13 +30,6 @@ pub struct LruCache<K, V, S = RandomState> where K: Eq + Hash, S: BuildHasher {
 
 impl<K: Hash + Eq, V> LruCache<K, V> {
     /// Creates an empty cache that can hold at most `capacity` items.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    /// let mut cache: LruCache<i32, &str> = LruCache::new(10);
-    /// ```
     pub fn new(capacity: usize) -> LruCache<K, V> {
         LruCache {
             map: LinkedHashMap::new(),
@@ -76,17 +45,6 @@ impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher {
     }
 
     /// Checks if the map contains the given key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(1);
-    ///
-    /// cache.insert(1, "a");
-    /// assert_eq!(cache.contains_key(&1), true);
-    /// ```
     pub fn contains_key<Q: ?Sized>(&mut self, key: &Q) -> bool
         where K: Borrow<Q>,
               Q: Hash + Eq
@@ -96,19 +54,6 @@ impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher {
 
     /// Inserts a key-value pair into the cache. If the key already existed, the old value is
     /// returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1, "a");
-    /// cache.insert(2, "b");
-    /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
-    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
-    /// ```
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         let old_val = self.map.insert(k, v);
         if self.len() > self.capacity() {
@@ -119,22 +64,6 @@ impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher {
 
     /// Returns a mutable reference to the value corresponding to the given key in the cache, if
     /// any.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1, "a");
-    /// cache.insert(2, "b");
-    /// cache.insert(2, "c");
-    /// cache.insert(3, "d");
-    ///
-    /// assert_eq!(cache.get_mut(&1), None);
-    /// assert_eq!(cache.get_mut(&2), Some(&mut "c"));
-    /// ```
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
         where K: Borrow<Q>,
               Q: Hash + Eq
@@ -143,21 +72,6 @@ impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher {
     }
 
     /// Removes the given key from the cache and returns its corresponding value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(2, "a");
-    ///
-    /// assert_eq!(cache.remove(&1), None);
-    /// assert_eq!(cache.remove(&2), Some("a"));
-    /// assert_eq!(cache.remove(&2), None);
-    /// assert_eq!(cache.len(), 0);
-    /// ```
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
         where K: Borrow<Q>,
               Q: Hash + Eq
@@ -166,50 +80,12 @@ impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher {
     }
 
     /// Returns the maximum number of key-value pairs the cache can hold.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    /// let mut cache: LruCache<i32, &str> = LruCache::new(2);
-    /// assert_eq!(cache.capacity(), 2);
-    /// ```
     pub fn capacity(&self) -> usize {
         self.max_size
     }
 
     /// Sets the number of key-value pairs the cache can hold. Removes
     /// least-recently-used key-value pairs if necessary.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1, "a");
-    /// cache.insert(2, "b");
-    /// cache.insert(3, "c");
-    ///
-    /// assert_eq!(cache.get_mut(&1), None);
-    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
-    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
-    ///
-    /// cache.set_capacity(3);
-    /// cache.insert(1, "a");
-    /// cache.insert(2, "b");
-    ///
-    /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
-    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
-    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
-    ///
-    /// cache.set_capacity(1);
-    ///
-    /// assert_eq!(cache.get_mut(&1), None);
-    /// assert_eq!(cache.get_mut(&2), None);
-    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
-    /// ```
     pub fn set_capacity(&mut self, capacity: usize) {
         for _ in capacity..self.len() {
             self.remove_lru();
@@ -234,52 +110,12 @@ impl<K, V, S> LruCache<K, V, S> where K: Eq + Hash, S: BuildHasher {
     /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order.
     ///
     /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1, 10);
-    /// cache.insert(2, 20);
-    /// cache.insert(3, 30);
-    ///
-    /// let kvs: Vec<_> = cache.iter().collect();
-    /// assert_eq!(kvs, [(&2, &20), (&3, &30)]);
-    /// ```
     pub fn iter(&self) -> Iter<K, V> { Iter(self.map.iter()) }
 
     /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order,
     /// with mutable references to the values.
     ///
     /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use lru_cache::LruCache;
-    ///
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1, 10);
-    /// cache.insert(2, 20);
-    /// cache.insert(3, 30);
-    ///
-    /// let mut n = 2;
-    ///
-    /// for (k, v) in cache.iter_mut() {
-    ///     assert_eq!(*k, n);
-    ///     assert_eq!(*v, n * 10);
-    ///     *v *= 10;
-    ///     n += 1;
-    /// }
-    ///
-    /// assert_eq!(n, 4);
-    /// assert_eq!(cache.get_mut(&2), Some(&mut 200));
-    /// assert_eq!(cache.get_mut(&3), Some(&mut 300));
-    /// ```
     pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut(self.map.iter_mut()) }
 }
 
diff --git a/src/disk/cache/mod.rs b/src/disk/cache/mod.rs
index a6e5ebe..d20e5ff 100644
--- a/src/disk/cache/mod.rs
+++ b/src/disk/cache/mod.rs
@@ -1,6 +1,7 @@
 use std::{cmp, ptr};
 use syscall::error::Result;
 
+use BLOCK_SIZE;
 use disk::Disk;
 
 use self::lru_cache::LruCache;
@@ -16,14 +17,14 @@ fn copy_memory(src: &[u8], dest: &mut [u8]) -> usize {
 
 pub struct DiskCache<T> {
     inner: T,
-    cache: LruCache<u64, [u8; 512]>,
+    cache: LruCache<u64, [u8; BLOCK_SIZE as usize]>,
 }
 
 impl<T: Disk> DiskCache<T> {
     pub fn new(inner: T) -> Self {
         DiskCache {
             inner: inner,
-            cache: LruCache::new(65536) // 32 MB cache
+            cache: LruCache::new((256 * 1024 * 1024 / BLOCK_SIZE) as usize) // 256 MB cache
         }
     }
 }
@@ -34,11 +35,11 @@ impl<T: Disk> Disk for DiskCache<T> {
 
         let mut read = 0;
         let mut failed = false;
-        for i in 0..(buffer.len() + 511)/512 {
+        for i in 0..(buffer.len() + BLOCK_SIZE as usize - 1)/(BLOCK_SIZE as usize) {
             let block_i = block + i as u64;
 
-            let buffer_i = i * 512;
-            let buffer_j = cmp::min(buffer_i + 512, buffer.len());
+            let buffer_i = i * BLOCK_SIZE as usize;
+            let buffer_j = cmp::min(buffer_i + BLOCK_SIZE as usize, buffer.len());
             let buffer_slice = &mut buffer[buffer_i .. buffer_j];
 
             if let Some(cache_buf) = self.cache.get_mut(&block_i) {
@@ -53,14 +54,14 @@ impl<T: Disk> Disk for DiskCache<T> {
             self.inner.read_at(block, buffer)?;
 
             read = 0;
-            for i in 0..(buffer.len() + 511)/512 {
+            for i in 0..(buffer.len() + BLOCK_SIZE as usize - 1)/(BLOCK_SIZE as usize) {
                 let block_i = block + i as u64;
 
-                let buffer_i = i * 512;
-                let buffer_j = cmp::min(buffer_i + 512, buffer.len());
+                let buffer_i = i * BLOCK_SIZE as usize;
+                let buffer_j = cmp::min(buffer_i + BLOCK_SIZE as usize, buffer.len());
                 let buffer_slice = &buffer[buffer_i .. buffer_j];
 
-                let mut cache_buf = [0; 512];
+                let mut cache_buf = [0; BLOCK_SIZE as usize];
                 read += copy_memory(buffer_slice, &mut cache_buf);
                 self.cache.insert(block_i, cache_buf);
             }
@@ -75,14 +76,14 @@ impl<T: Disk> Disk for DiskCache<T> {
         self.inner.write_at(block, buffer)?;
 
         let mut written = 0;
-        for i in 0..(buffer.len() + 511)/512 {
+        for i in 0..(buffer.len() + BLOCK_SIZE as usize - 1)/(BLOCK_SIZE as usize) {
             let block_i = block + i as u64;
 
-            let buffer_i = i * 512;
-            let buffer_j = cmp::min(buffer_i + 512, buffer.len());
+            let buffer_i = i * BLOCK_SIZE as usize;
+            let buffer_j = cmp::min(buffer_i + BLOCK_SIZE as usize, buffer.len());
             let buffer_slice = &buffer[buffer_i .. buffer_j];
 
-            let mut cache_buf = [0; 512];
+            let mut cache_buf = [0; BLOCK_SIZE as usize];
             written += copy_memory(buffer_slice, &mut cache_buf);
             self.cache.insert(block_i, cache_buf);
         }
diff --git a/src/disk/file.rs b/src/disk/file.rs
index a74f64f..578194f 100644
--- a/src/disk/file.rs
+++ b/src/disk/file.rs
@@ -2,6 +2,7 @@ use std::fs::{File, OpenOptions};
 use std::io::{Read, Write, Seek, SeekFrom};
 use syscall::error::{Error, Result, EIO};
 
+use BLOCK_SIZE;
 use disk::Disk;
 
 macro_rules! try_disk {
@@ -37,13 +38,13 @@ impl DiskFile {
 
 impl Disk for DiskFile {
     fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
-        try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
+        try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE)));
         let count = try_disk!(self.file.read(buffer));
         Ok(count)
     }
 
     fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
-        try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
+        try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE)));
         let count = try_disk!(self.file.write(buffer));
         Ok(count)
     }
diff --git a/src/ex_node.rs b/src/ex_node.rs
index ee745e5..0377ee3 100644
--- a/src/ex_node.rs
+++ b/src/ex_node.rs
@@ -1,13 +1,14 @@
 use std::{fmt, mem, ops, slice};
 
-use super::Extent;
+use BLOCK_SIZE;
+use Extent;
 
 /// An extra node
 #[repr(packed)]
 pub struct ExNode {
     pub prev: u64,
     pub next: u64,
-    pub extents: [Extent; 31],
+    pub extents: [Extent; (BLOCK_SIZE as usize - 16)/16],
 }
 
 impl ExNode {
@@ -15,7 +16,7 @@ impl ExNode {
         ExNode {
             prev: 0,
             next: 0,
-            extents: [Extent::default(); 31],
+            extents: [Extent::default(); (BLOCK_SIZE as usize - 16)/16],
         }
     }
 
@@ -54,5 +55,5 @@ impl ops::DerefMut for ExNode {
 
 #[test]
 fn ex_node_size_test() {
-    assert_eq!(mem::size_of::<ExNode>(), 512);
+    assert_eq!(mem::size_of::<ExNode>(), BLOCK_SIZE as usize);
 }
diff --git a/src/extent.rs b/src/extent.rs
index ac4718e..773d7ac 100644
--- a/src/extent.rs
+++ b/src/extent.rs
@@ -1,5 +1,7 @@
 use std::cmp::min;
 
+use BLOCK_SIZE;
+
 pub struct BlockIter {
     block: u64,
     length: u64,
@@ -7,10 +9,10 @@ pub struct BlockIter {
 }
 
 impl Iterator<> for BlockIter {
-    type Item = (u64, usize);
+    type Item = (u64, u64);
     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));
+        if self.i < (self.length + BLOCK_SIZE - 1)/BLOCK_SIZE {
+            let ret = Some((self.block + self.i, min(BLOCK_SIZE, self.length - self.i * BLOCK_SIZE)));
             self.i += 1;
             ret
         } else {
diff --git a/src/filesystem.rs b/src/filesystem.rs
index 51b0e53..406fed5 100644
--- a/src/filesystem.rs
+++ b/src/filesystem.rs
@@ -2,7 +2,7 @@ use std::cmp::min;
 
 use syscall::error::{Result, Error, EEXIST, EISDIR, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY};
 
-use super::{Disk, ExNode, Extent, Header, Node};
+use {BLOCK_SIZE, Disk, ExNode, Extent, Header, Node};
 
 /// A file system
 pub struct FileSystem<D: Disk> {
@@ -45,11 +45,11 @@ impl<D: Disk> FileSystem<D> {
     /// Reserved data will be zero padded up to the nearest block
     pub fn create_reserved(mut disk: D, reserved: &[u8], ctime: u64, ctime_nsec: u32) -> Result<Self> {
         let size = disk.size()?;
-        let block_offset = (reserved.len() as u64 + 511)/512;
+        let block_offset = (reserved.len() as u64 + BLOCK_SIZE - 1)/BLOCK_SIZE;
 
-        if size >= (block_offset + 4) * 512 {
+        if size >= (block_offset + 4) * BLOCK_SIZE {
             let mut free = (2, Node::new(Node::MODE_FILE, "free", 0, ctime, ctime_nsec));
-            free.1.extents[0] = Extent::new(4, size - (block_offset + 4) * 512);
+            free.1.extents[0] = Extent::new(4, size - (block_offset + 4) * BLOCK_SIZE);
             disk.write_at(block_offset + free.0, &free.1)?;
 
             let root = (1, Node::new(Node::MODE_DIR | 0o755, "root", 0, ctime, ctime_nsec));
@@ -59,11 +59,11 @@ impl<D: Disk> FileSystem<D> {
             disk.write_at(block_offset + header.0, &header.1)?;
 
             for block in 0..block_offset as usize {
-                let mut data = [0; 512];
+                let mut data = [0; BLOCK_SIZE as usize];
 
                 let mut i = 0;
-                while i < data.len() && block * 512 + i < reserved.len() {
-                    data[i] = reserved[block * 512 + i];
+                while i < data.len() && block * BLOCK_SIZE as usize + i < reserved.len() {
+                    data[i] = reserved[block * BLOCK_SIZE as usize + i];
                     i += 1;
                 }
 
@@ -94,9 +94,9 @@ impl<D: Disk> FileSystem<D> {
         let mut free = self.node(free_block)?;
         let mut block_option = None;
         for extent in free.1.extents.iter_mut() {
-            if extent.length/512 >= length {
+            if extent.length/BLOCK_SIZE >= length {
                 block_option = Some(extent.block);
-                extent.length -= length * 512;
+                extent.length -= length * BLOCK_SIZE;
                 extent.block += length;
                 break;
             }
@@ -134,7 +134,7 @@ impl<D: Disk> FileSystem<D> {
         let parent = self.node(parent_block)?;
         for extent in parent.1.extents.iter() {
             for (block, size) in extent.blocks() {
-                if size >= 512 {
+                if size >= BLOCK_SIZE {
                     children.push(self.node(block)?);
                 }
             }
@@ -151,7 +151,7 @@ impl<D: Disk> FileSystem<D> {
         let parent = self.node(parent_block)?;
         for extent in parent.1.extents.iter() {
             for (block, size) in extent.blocks() {
-                if size >= 512 {
+                if size >= BLOCK_SIZE {
                     let child = self.node(block)?;
 
                     let mut matches = false;
@@ -185,13 +185,13 @@ impl<D: Disk> FileSystem<D> {
                 extent.block = block;
                 extent.length = length;
                 break;
-            } else if length % 512 == 0 && extent.block == block + length/512 {
+            } else if length % BLOCK_SIZE == 0 && extent.block == block + length/BLOCK_SIZE {
                 //At beginning
                 inserted = true;
                 extent.block = block;
                 extent.length += length;
                 break;
-            } else if extent.length % 512 == 0 && extent.block + extent.length/512 == block {
+            } else if extent.length % BLOCK_SIZE == 0 && extent.block + extent.length/BLOCK_SIZE == block {
                 //At end
                 inserted = true;
                 extent.length += length;
@@ -225,7 +225,7 @@ impl<D: Disk> FileSystem<D> {
             let node = (self.allocate(1)?, Node::new(mode, name, parent_block, ctime, ctime_nsec));
             self.write_at(node.0, &node.1)?;
 
-            self.insert_blocks(node.0, 512, parent_block)?;
+            self.insert_blocks(node.0, BLOCK_SIZE, parent_block)?;
 
             Ok(node)
         }
@@ -240,12 +240,12 @@ impl<D: Disk> FileSystem<D> {
         let mut replace_option = None;
         let mut parent = self.node(parent_block)?;
         for extent in parent.1.extents.iter_mut() {
-            if block >= extent.block && block + length <= extent.block + extent.length/512 {
+            if block >= extent.block && block + length <= extent.block + extent.length/BLOCK_SIZE {
                 //Inside
                 removed = true;
 
-                let left = Extent::new(extent.block, (block - extent.block) * 512);
-                let right = Extent::new(block + length, ((extent.block + extent.length/512) - (block + length)) * 512);
+                let left = Extent::new(extent.block, (block - extent.block) * BLOCK_SIZE);
+                let right = Extent::new(block + length, ((extent.block + extent.length/BLOCK_SIZE) - (block + length)) * BLOCK_SIZE);
 
                 if left.length > 0 {
                     *extent = left;
@@ -270,7 +270,7 @@ impl<D: Disk> FileSystem<D> {
                 self.insert_blocks(replace.block, replace.length, parent_block)?;
             }
 
-            self.deallocate(block, 512)?;
+            self.deallocate(block, BLOCK_SIZE)?;
 
             Ok(())
         } else {
@@ -316,7 +316,7 @@ impl<D: Disk> FileSystem<D> {
                 break;
             } else {
                 changed = true;
-                let allocated = ((extent.length + 511)/512) * 512;
+                let allocated = ((extent.length + BLOCK_SIZE - 1)/BLOCK_SIZE) * BLOCK_SIZE;
                 if allocated >= length {
                     extent.length = length;
                     length = 0;
@@ -336,7 +336,7 @@ impl<D: Disk> FileSystem<D> {
             if node.1.next > 0 {
                 self.node_ensure_len(node.1.next, length)
             } else {
-                let new_block = self.allocate((length + 511)/512)?;
+                let new_block = self.allocate((length + BLOCK_SIZE - 1)/BLOCK_SIZE)?;
                 self.insert_blocks(new_block, length, block)?;
                 Ok(())
             }
@@ -356,10 +356,10 @@ impl<D: Disk> FileSystem<D> {
         let mut node = self.node(block)?;
         for extent in node.1.extents.iter_mut() {
             if extent.length > length {
-                let start = (length + 511)/512;
-                let end = (extent.length + 511)/512;
+                let start = (length + BLOCK_SIZE - 1)/BLOCK_SIZE;
+                let end = (extent.length + BLOCK_SIZE - 1)/BLOCK_SIZE;
                 if end > start {
-                    self.deallocate(extent.block + start, (end - start) * 512)?;
+                    self.deallocate(extent.block + start, (end - start) * BLOCK_SIZE)?;
                 }
                 extent.length = length;
                 changed = true;
@@ -393,9 +393,9 @@ impl<D: Disk> FileSystem<D> {
                     if push_extent.block == 0 {
                         push_extent.block = block;
                     }
-                    if len >= size {
-                        push_extent.length += size as u64;
-                        len -= size;
+                    if len as u64 >= size {
+                        push_extent.length += size;
+                        len -= size as usize;
                     } else if len > 0 {
                         push_extent.length += len as u64;
                         len = 0;
@@ -423,8 +423,8 @@ impl<D: Disk> FileSystem<D> {
     }
 
     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) as usize;
+        let block_offset = offset / BLOCK_SIZE;
+        let mut byte_offset = (offset % BLOCK_SIZE) as usize;
 
         let mut extents = Vec::new();
         self.node_extents(block, block_offset, byte_offset + buf.len(), &mut extents)?;
@@ -435,7 +435,7 @@ impl<D: Disk> FileSystem<D> {
             let mut length = extent.length;
 
             if byte_offset > 0 && length > 0 {
-                let mut sector = [0; 512];
+                let mut sector = [0; BLOCK_SIZE as usize];
                 self.read_at(block, &mut sector)?;
 
                 let sector_size = min(sector.len() as u64, length) as usize;
@@ -450,18 +450,18 @@ impl<D: Disk> FileSystem<D> {
                 byte_offset = 0;
             }
 
-            let length_aligned = ((min(length, (buf.len() - i) as u64)/512) * 512) as usize;
+            let length_aligned = ((min(length, (buf.len() - i) as u64)/BLOCK_SIZE) * BLOCK_SIZE) as usize;
 
             if length_aligned > 0 {
                 let extent_buf = &mut buf[i..i + length_aligned];
                 self.read_at(block, extent_buf)?;
                 i += length_aligned;
-                block += (length_aligned as u64)/512;
+                block += (length_aligned as u64)/BLOCK_SIZE;
                 length -= length_aligned as u64;
             }
 
             if length > 0 {
-                let mut sector = [0; 512];
+                let mut sector = [0; BLOCK_SIZE as usize];
                 self.read_at(block, &mut sector)?;
 
                 let sector_size = min(sector.len() as u64, length) as usize;
@@ -475,17 +475,17 @@ impl<D: Disk> FileSystem<D> {
             }
 
             assert_eq!(length, 0);
-            assert_eq!(block, extent.block + (extent.length + 511)/512);
+            assert_eq!(block, extent.block + (extent.length + BLOCK_SIZE - 1)/BLOCK_SIZE);
         }
 
         Ok(i)
     }
 
     pub fn write_node(&mut self, block: u64, offset: u64, buf: &[u8], mtime: u64, mtime_nsec: u32) -> Result<usize> {
-        let block_offset = offset / 512;
-        let mut byte_offset = (offset % 512) as usize;
+        let block_offset = offset / BLOCK_SIZE;
+        let mut byte_offset = (offset % BLOCK_SIZE) as usize;
 
-        self.node_ensure_len(block, block_offset as u64 * 512 + (byte_offset + buf.len()) as u64)?;
+        self.node_ensure_len(block, block_offset as u64 * BLOCK_SIZE + (byte_offset + buf.len()) as u64)?;
 
         let mut extents = Vec::new();
         self.node_extents(block, block_offset, byte_offset + buf.len(), &mut extents)?;
@@ -496,7 +496,7 @@ impl<D: Disk> FileSystem<D> {
             let mut length = extent.length;
 
             if byte_offset > 0 && length > 0 {
-                let mut sector = [0; 512];
+                let mut sector = [0; BLOCK_SIZE as usize];
                 self.read_at(block, &mut sector)?;
 
                 let sector_size = min(sector.len() as u64, length) as usize;
@@ -513,18 +513,18 @@ impl<D: Disk> FileSystem<D> {
                 byte_offset = 0;
             }
 
-            let length_aligned = ((min(length, (buf.len() - i) as u64)/512) * 512) as usize;
+            let length_aligned = ((min(length, (buf.len() - i) as u64)/BLOCK_SIZE) * BLOCK_SIZE) as usize;
 
             if length_aligned > 0 {
                 let extent_buf = &buf[i..i + length_aligned];
                 self.write_at(block, extent_buf)?;
                 i += length_aligned;
-                block += (length_aligned as u64)/512;
+                block += (length_aligned as u64)/BLOCK_SIZE;
                 length -= length_aligned as u64;
             }
 
             if length > 0 {
-                let mut sector = [0; 512];
+                let mut sector = [0; BLOCK_SIZE as usize];
                 self.read_at(block, &mut sector)?;
 
                 let sector_size = min(sector.len() as u64, length) as usize;
@@ -540,7 +540,7 @@ impl<D: Disk> FileSystem<D> {
             }
 
             assert_eq!(length, 0);
-            assert_eq!(block, extent.block + (extent.length + 511)/512);
+            assert_eq!(block, extent.block + (extent.length + BLOCK_SIZE - 1)/BLOCK_SIZE);
         }
 
         if i > 0 {
diff --git a/src/header.rs b/src/header.rs
index be7b7bb..7d978c5 100644
--- a/src/header.rs
+++ b/src/header.rs
@@ -3,6 +3,8 @@ use std::ops::{Deref, DerefMut};
 
 use uuid::Uuid;
 
+use BLOCK_SIZE;
+
 /// The header of the filesystem
 #[repr(packed)]
 pub struct Header {
@@ -12,14 +14,14 @@ pub struct Header {
     pub version: u64,
     /// Disk ID, a 128-bit unique identifier
     pub uuid: [u8; 16],
-    /// Disk size, in 512-byte sectors
+    /// Disk size, in number of BLOCK_SIZE sectors
     pub size: u64,
     /// Block of root node
     pub root: u64,
     /// Block of free space node
     pub free: u64,
     /// Padding
-    pub padding: [u8; 456]
+    pub padding: [u8; BLOCK_SIZE as usize - 56]
 }
 
 impl Header {
@@ -34,7 +36,7 @@ impl Header {
             size: 0,
             root: 0,
             free: 0,
-            padding: [0; 456]
+            padding: [0; BLOCK_SIZE as usize - 56]
         }
     }
 
@@ -47,7 +49,7 @@ impl Header {
             size: size,
             root: root,
             free: free,
-            padding: [0; 456]
+            padding: [0; BLOCK_SIZE as usize - 56]
         }
     }
 
@@ -88,5 +90,5 @@ impl DerefMut for Header {
 
 #[test]
 fn header_size_test() {
-    assert_eq!(mem::size_of::<Header>(), 512);
+    assert_eq!(mem::size_of::<Header>(), BLOCK_SIZE as usize);
 }
diff --git a/src/lib.rs b/src/lib.rs
index 3cde771..47a0bb3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,6 +6,8 @@
 extern crate syscall;
 extern crate uuid;
 
+pub const BLOCK_SIZE: u64 = 512;
+
 pub use self::disk::{Disk, DiskCache, DiskFile};
 pub use self::ex_node::ExNode;
 pub use self::extent::Extent;
diff --git a/src/mount/fuse.rs b/src/mount/fuse.rs
index b7bbac1..bdfab5b 100644
--- a/src/mount/fuse.rs
+++ b/src/mount/fuse.rs
@@ -7,6 +7,7 @@ use std::os::unix::ffi::OsStrExt;
 use std::path::Path;
 use std::time::{SystemTime, UNIX_EPOCH};
 
+use BLOCK_SIZE;
 use disk::Disk;
 use filesystem;
 use node::Node;
@@ -36,7 +37,7 @@ fn node_attr(node: &(u64, Node)) -> FileAttr {
     FileAttr {
         ino: node.0,
         size: node.1.extents[0].length,
-        blocks: (node.1.extents[0].length + 511)/512,
+        blocks: (node.1.extents[0].length + BLOCK_SIZE - 1)/BLOCK_SIZE,
         atime: NULL_TIME,
         mtime: Timespec {
             sec: node.1.mtime as i64,
@@ -297,7 +298,7 @@ impl<D: Disk> Filesystem for Fuse<D> {
         let free = self.fs.header.1.free;
         match self.fs.node_len(free) {
             Ok(free_size) => {
-                let bsize = 512;
+                let bsize = BLOCK_SIZE;
                 let blocks = self.fs.header.1.size/bsize;
                 let bfree = free_size/bsize;
                 reply.statfs(blocks, bfree, bfree, 0, 0, bsize as u32, 256, 0);
diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs
index 2607547..1f4bdb4 100644
--- a/src/mount/redox/scheme.rs
+++ b/src/mount/redox/scheme.rs
@@ -9,6 +9,7 @@ use syscall::error::{Error, Result, EACCES, EEXIST, EISDIR, ENOTDIR, EPERM, ENOE
 use syscall::flag::{O_APPEND, O_CREAT, O_DIRECTORY, O_STAT, O_EXCL, O_TRUNC, O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, MODE_PERM, O_SYMLINK, O_NOFOLLOW};
 use syscall::scheme::Scheme;
 
+use BLOCK_SIZE;
 use disk::Disk;
 use filesystem::FileSystem;
 use node::Node;
@@ -518,7 +519,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
             let free = fs.header.1.free;
             let free_size = fs.node_len(free)?;
 
-            stat.f_bsize = 512;
+            stat.f_bsize = BLOCK_SIZE as u32;
             stat.f_blocks = fs.header.1.size/(stat.f_bsize as u64);
             stat.f_bfree = free_size/(stat.f_bsize as u64);
             stat.f_bavail = stat.f_bfree;
diff --git a/src/node.rs b/src/node.rs
index ce7cd1d..334344b 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -1,5 +1,6 @@
 use std::{fmt, mem, ops, slice, str};
 
+use BLOCK_SIZE;
 use super::Extent;
 
 /// A file/folder node
@@ -15,7 +16,7 @@ pub struct Node {
     pub name: [u8; 222],
     pub parent: u64,
     pub next: u64,
-    pub extents: [Extent; 15],
+    pub extents: [Extent; (BLOCK_SIZE as usize - 272)/16],
 }
 
 impl Node {
@@ -41,7 +42,7 @@ impl Node {
             name: [0; 222],
             parent: 0,
             next: 0,
-            extents: [Extent::default(); 15],
+            extents: [Extent::default(); (BLOCK_SIZE as usize - 272)/16],
         }
     }
 
@@ -62,7 +63,7 @@ impl Node {
             name: bytes,
             parent: parent,
             next: 0,
-            extents: [Extent::default(); 15],
+            extents: [Extent::default(); (BLOCK_SIZE as usize - 272)/16],
         }
     }
 
@@ -147,5 +148,5 @@ impl ops::DerefMut for Node {
 
 #[test]
 fn node_size_test() {
-    assert_eq!(mem::size_of::<Node>(), 512);
+    assert_eq!(mem::size_of::<Node>(), BLOCK_SIZE as usize);
 }
-- 
GitLab