diff --git a/Cargo.lock b/Cargo.lock
index dabb6df6fddcbe13f8ea35bda811fb0218a44833..9b30a29d6e602ef0c2da519d354179d57ae19f8b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,25 +1,11 @@
-[[package]]
-name = "bitflags"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "cfg-if"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "fuchsia-zircon"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "fuchsia-zircon-sys"
-version = "0.3.3"
+name = "fuchsia-cprng"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -27,16 +13,16 @@ name = "fuse"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.45"
+version = "0.2.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -52,7 +38,7 @@ name = "log"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -62,27 +48,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rand"
-version = "0.3.22"
+version = "0.3.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand"
-version = "0.4.3"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rdrand"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.49"
+version = "0.1.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -90,18 +98,12 @@ name = "redoxfs"
 version = "0.3.2"
 dependencies = [
  "fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)",
- "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "spin"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "thread-scoped"
 version = "1.0.2"
@@ -109,12 +111,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "time"
-version = "0.1.41"
+version = "0.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -122,12 +124,12 @@ name = "uuid"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
-version = "0.3.6"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -145,22 +147,22 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
-"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
-"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
-"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
+"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
 "checksum fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e57070510966bfef93662a81cb8aa2b1c7db0964354fa9921434f04b9e8660"
-"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
+"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
 "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
-"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
-"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
-"checksum redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f22c50afdcf3f0a31ebb6b47697f6a7c5e5a24967e842858118bce0615f0afad"
-"checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f"
+"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
+"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
+"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
+"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+"checksum redox_syscall 0.1.53 (registry+https://github.com/rust-lang/crates.io-index)" = "53848511b7ee6eb9d5c3db48481aaa5779b38fc0131bc133c98cb4f2b2411928"
 "checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99"
-"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
 "checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22"
-"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
+"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 657aefd8ab468be0faa59ac331e24c7e766edb1c..80e0a89e6947a418811071631c1b956d8b9ba14c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,6 @@ path = "src/bin/mkfs.rs"
 doc = false
 
 [dependencies]
-spin = "0.4"
 redox_syscall = "0.1"
 uuid = { version = "0.5", features = ["v4"] }
 
diff --git a/src/disk/cache.rs b/src/disk/cache.rs
index e11dfcbba1c8214104fafff3914c5259fc3b423c..cf0f96a8f8483a9e0297d41c249e6e3949222710 100644
--- a/src/disk/cache.rs
+++ b/src/disk/cache.rs
@@ -81,6 +81,7 @@ impl<T: Disk> Disk for DiskCache<T> {
     }
 
     fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
+        //TODO: Write only blocks that have changed
         // println!("Cache write at {}", block);
 
         self.inner.write_at(block, buffer)?;
diff --git a/src/mount/redox/mod.rs b/src/mount/redox/mod.rs
index f4a8cb06a98ddc0a34f61ea97cdfe2dfd371eca8..139f6f39c2c84b86de1d76a5fe2c0e80ea8544ea 100644
--- a/src/mount/redox/mod.rs
+++ b/src/mount/redox/mod.rs
@@ -1,5 +1,3 @@
-extern crate spin;
-
 use syscall;
 use syscall::{Packet, Scheme};
 use std::fs::File;
diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs
index 664efe66550a0a024a96e832d1857eca91372493..b5e47bdc0832c771a5c713ec9ddff7fa5873810a 100644
--- a/src/mount/redox/resource.rs
+++ b/src/mount/redox/resource.rs
@@ -1,13 +1,14 @@
 use std::cmp::{min, max};
+use std::collections::BTreeMap;
+use std::slice;
 use std::time::{SystemTime, UNIX_EPOCH};
 
 use syscall::data::{Map, Stat, TimeSpec};
-use syscall::error::{Error, Result, EBADF, EBUSY, EINVAL, EISDIR, EPERM};
+use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, ENOMEM, EPERM};
 use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM, PROT_READ, PROT_WRITE, SEEK_SET, SEEK_CUR, SEEK_END};
 
 use disk::Disk;
 use filesystem::FileSystem;
-use super::scheme::{Fmaps, FmapKey, FmapValue};
 
 pub trait Resource<D: Disk> {
     fn block(&self) -> u64;
@@ -15,14 +16,14 @@ pub trait Resource<D: Disk> {
     fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem<D>) -> Result<usize>;
     fn write(&mut self, buf: &[u8], fs: &mut FileSystem<D>) -> Result<usize>;
     fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem<D>) -> Result<usize>;
-    fn fmap(&mut self, map: &Map, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>;
-    fn funmap(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>;
+    fn fmap(&mut self, map: &Map, fs: &mut FileSystem<D>) -> Result<usize>;
+    fn funmap(&mut self, address: usize, fs: &mut FileSystem<D>) -> Result<usize>;
     fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize>;
     fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize>;
     fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize>;
     fn path(&self, buf: &mut [u8]) -> Result<usize>;
     fn stat(&self, _stat: &mut Stat, fs: &mut FileSystem<D>) -> Result<usize>;
-    fn sync(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>;
+    fn sync(&mut self, fs: &mut FileSystem<D>) -> Result<usize>;
     fn truncate(&mut self, len: usize, fs: &mut FileSystem<D>) -> Result<usize>;
     fn utimens(&mut self, times: &[TimeSpec], fs: &mut FileSystem<D>) -> Result<usize>;
 }
@@ -89,10 +90,10 @@ impl<D: Disk> Resource<D> for DirResource {
         Ok(self.seek)
     }
 
-    fn fmap(&mut self, _map: &Map, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> {
+    fn fmap(&mut self, _map: &Map, _fs: &mut FileSystem<D>) -> Result<usize> {
         Err(Error::new(EBADF))
     }
-    fn funmap(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> {
+    fn funmap(&mut self, _address: usize, _fs: &mut FileSystem<D>) -> Result<usize> {
         Err(Error::new(EBADF))
     }
 
@@ -167,7 +168,7 @@ impl<D: Disk> Resource<D> for DirResource {
         Ok(0)
     }
 
-    fn sync(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> {
+    fn sync(&mut self, _fs: &mut FileSystem<D>) -> Result<usize> {
         Err(Error::new(EBADF))
     }
 
@@ -180,13 +181,78 @@ impl<D: Disk> Resource<D> for DirResource {
     }
 }
 
+pub struct Fmap {
+    block: u64,
+    offset: usize,
+    flags: usize,
+    data: &'static mut [u8],
+}
+
+impl Fmap {
+    pub unsafe fn new<D: Disk>(block: u64, map: &Map, fs: &mut FileSystem<D>) -> Result<Self> {
+        extern "C" {
+            fn memalign(align: usize, size: usize) -> *mut u8;
+            fn free(ptr: *mut u8);
+        }
+
+        // Memory provided to fmap must be page aligned and sized
+        let align = 4096;
+        let address = memalign(align, ((map.size + align - 1) / align) * align);
+        if address.is_null() {
+            return Err(Error::new(ENOMEM));
+        }
+
+        // Read buffer from disk
+        let buf = slice::from_raw_parts_mut(address, map.size);
+        let count = match fs.read_node(block, map.offset as u64, buf) {
+            Ok(ok) => ok,
+            Err(err) => {
+                free(address);
+                return Err(err);
+            }
+        };
+
+        // Make sure remaining data is zeroed
+        for i in count..buf.len() {
+            buf[i] = 0;
+        }
+
+        Ok(Self {
+            block,
+            offset: map.offset,
+            flags: map.flags,
+            data: &mut buf[..count],
+        })
+    }
+
+    pub fn sync<D: Disk>(&mut self, fs: &mut FileSystem<D>) -> Result<()> {
+        if self.flags & PROT_WRITE == PROT_WRITE {
+            let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+            fs.write_node(self.block, self.offset as u64, &self.data, mtime.as_secs(), mtime.subsec_nanos())?;
+        }
+        Ok(())
+    }
+}
+
+impl Drop for Fmap {
+    fn drop(&mut self) {
+        unsafe {
+            extern "C" {
+                fn free(ptr: *mut u8);
+            }
+
+            free(self.data.as_mut_ptr());
+        }
+    }
+}
+
 pub struct FileResource {
     path: String,
     block: u64,
     flags: usize,
     seek: u64,
     uid: u32,
-    fmap: Option<(usize, FmapKey)>
+    fmaps: BTreeMap<usize, Fmap>,
 }
 
 impl FileResource {
@@ -197,35 +263,9 @@ impl FileResource {
             flags: flags,
             seek: seek,
             uid: uid,
-            fmap: None
+            fmaps: BTreeMap::new(),
         }
     }
-
-    fn sync_fmap<D: Disk>(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<()> {
-        if let Some((i, key_exact)) = self.fmap.as_ref() {
-            let (key_round, value) = maps.index(*i).as_mut().expect("mapping dropped while still referenced");
-
-            let rel_offset = key_exact.offset - key_round.offset;
-            // Minimum out of our size and the original file size
-            let actual_size = (value.actual_size - rel_offset).min(key_exact.size);
-
-            let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
-
-            let mut count = 0;
-            while count < actual_size {
-                match fs.write_node(self.block, key_exact.offset as u64 + count as u64,
-                        &value.buffer[rel_offset..][count..actual_size],
-                        mtime.as_secs(), mtime.subsec_nanos())? {
-                    0 => {
-                        eprintln!("Fmap failed to write whole buffer, encountered EOF early.");
-                        break;
-                    }
-                    n => count += n,
-                }
-            }
-        }
-        Ok(())
-    }
 }
 
 impl<D: Disk> Resource<D> for FileResource {
@@ -240,7 +280,7 @@ impl<D: Disk> Resource<D> for FileResource {
             flags: self.flags,
             seek: self.seek,
             uid: self.uid,
-            fmap: None
+            fmaps: BTreeMap::new(),
         }))
     }
 
@@ -278,7 +318,7 @@ impl<D: Disk> Resource<D> for FileResource {
         Ok(self.seek as usize)
     }
 
-    fn fmap(&mut self, map: &Map, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> {
+    fn fmap(&mut self, map: &Map, fs: &mut FileSystem<D>) -> Result<usize> {
         let accmode = self.flags & O_ACCMODE;
         if map.flags & PROT_READ > 0 && ! (accmode == O_RDWR || accmode == O_RDONLY) {
             return Err(Error::new(EBADF));
@@ -288,66 +328,20 @@ impl<D: Disk> Resource<D> for FileResource {
         }
         //TODO: PROT_EXEC?
 
-        let key_exact = FmapKey {
-            block: self.block,
-            offset: map.offset,
-            size: map.size
-        };
+        let map = unsafe { Fmap::new(self.block, map, fs)? };
+        let address = map.data.as_ptr() as usize;
+        self.fmaps.insert(address, map);
+        Ok(address)
+    }
 
-        let i = match maps.find_compatible(&key_exact) {
-            Ok((i, (key_existing, value))) => {
-                value.refcount += 1;
-                self.fmap = Some((i, key_exact));
-                return Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_existing.offset))
-            },
-            Err(None) => {
-                // This is bad!
-                // We reached the limit of maps, and we can't reallocate
-                // because that would invalidate stuff.
-                // Sorry, nothing personal :(
-                return Err(Error::new(EBUSY))
-            },
-            Err(Some(i)) => {
-                // Can't do stuff in here because lifetime issues
-                i
-            }
-        };
-        let key_round = key_exact.round();
-
-        let mut content = vec![0; key_round.size];
-        let mut count = 0;
-        while count < key_round.size {
-            match fs.read_node(self.block, key_round.offset as u64 + count as u64,
-                    &mut content[count..key_round.size])? {
-                0 => break,
-                n => count += n
-            }
-        }
+    fn funmap(&mut self, address: usize, fs: &mut FileSystem<D>) -> Result<usize> {
+        if let Some(mut fmap) = self.fmaps.remove(&address) {
+            fmap.sync(fs)?;
 
-        let value = maps.insert(i, key_round, FmapValue {
-            buffer: content,
-            actual_size: count,
-            refcount: 1
-        });
-
-        self.fmap = Some((i, key_exact));
-        Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_round.offset))
-    }
-
-    fn funmap(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> {
-        self.sync_fmap(maps, fs)?;
-        if let Some((i, _)) = self.fmap.as_ref() {
-            let value = maps.index(*i);
-            let clear = {
-                let (_, value) = value.as_mut().expect("mapping dropped while still referenced");
-                value.refcount -= 1;
-                value.refcount == 0
-            };
-            if clear {
-                *value = None;
-            }
+            Ok(0)
+        } else {
+            Err(Error::new(EINVAL))
         }
-        Ok(0)
     }
 
     fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
@@ -428,8 +422,11 @@ impl<D: Disk> Resource<D> for FileResource {
         Ok(0)
     }
 
-    fn sync(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> {
-        self.sync_fmap(maps, fs)?;
+    fn sync(&mut self, fs: &mut FileSystem<D>) -> Result<usize> {
+        for fmap in self.fmaps.values_mut() {
+            fmap.sync(fs)?;
+        }
+
         Ok(0)
     }
 
@@ -462,3 +459,11 @@ impl<D: Disk> Resource<D> for FileResource {
         }
     }
 }
+
+impl Drop for FileResource {
+    fn drop(&mut self) {
+        if ! self.fmaps.is_empty() {
+            eprintln!("redoxfs: file {} still has {} fmaps!", self.path, self.fmaps.len());
+        }
+    }
+}
diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs
index 198085745a0d3d38a600c0a8d1489015fd57f4a3..8d5dc9fbc1bf0c65c6ede5c0dde1ae17967ff6bd 100644
--- a/src/mount/redox/scheme.rs
+++ b/src/mount/redox/scheme.rs
@@ -1,6 +1,5 @@
 use std::cell::RefCell;
 use std::collections::BTreeMap;
-use std::result::Result as StdResult;
 use std::str;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::time::{SystemTime, UNIX_EPOCH};
@@ -16,83 +15,13 @@ use filesystem::FileSystem;
 use node::Node;
 
 use super::resource::{Resource, DirResource, FileResource};
-use super::spin::Mutex;
-
-/// The size to round offset/len up to.
-/// This ensures more fmaps can share the same memory even with different parameters.
-const PAGE_SIZE: usize = 4096;
-/// The max amount of fmaps that can be held simultaneously.
-/// This restriction is here because we can under no circumstances reallocate,
-/// that would invalidate previous mappings.
-const FMAP_AMOUNT: usize = 1024;
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct FmapKey {
-    pub block: u64,
-    pub offset: usize,
-    pub size: usize
-}
-impl FmapKey {
-    pub fn round(&self) -> FmapKey {
-        let remainder = self.size % PAGE_SIZE;
-        FmapKey {
-            block: self.block,
-            offset: self.offset - self.offset % PAGE_SIZE,
-            size: if remainder == 0 { self.size } else { self.size - remainder + PAGE_SIZE }
-        }
-    }
-    pub fn is_compatible(&self, other: &FmapKey) -> bool {
-        self.block == other.block
-            && self.offset <= other.offset
-            && self.offset + self.size >= other.offset + other.size
-    }
-}
-#[derive(Clone)]
-pub struct FmapValue {
-    pub buffer: Vec<u8>,
-    /// The actual file length. Syncing only writes &buffer[..actual_size].
-    pub actual_size: usize,
-    pub refcount: usize
-}
-
-// NOTE: This can NOT reallocate. That would invalidate previous mappings.
-pub struct Fmaps(Vec<Option<(FmapKey, FmapValue)>>);
-impl Default for Fmaps {
-    fn default() -> Fmaps {
-        Fmaps(vec![None; FMAP_AMOUNT])
-    }
-}
-
-impl Fmaps {
-    pub fn find_compatible(&mut self, key: &FmapKey) -> StdResult<(usize, &mut (FmapKey, FmapValue)), Option<usize>> {
-        let mut first_empty = None;
-        for (i, entry) in self.0.iter_mut().enumerate() {
-            match entry {
-                None if first_empty.is_none() => first_empty = Some(i),
-                Some(entry) if entry.0.is_compatible(key) => return Ok((i, entry)),
-                _ => ()
-            }
-        }
-        Err(first_empty)
-    }
-    pub fn index(&mut self, index: usize) -> &mut Option<(FmapKey, FmapValue)> {
-        &mut self.0[index]
-    }
-    pub fn insert(&mut self, index: usize, key: FmapKey, value: FmapValue) -> &mut FmapValue {
-        let elem = &mut self.0[index];
-        assert!(elem.is_none());
-        *elem = Some((key, value));
-
-        &mut elem.as_mut().unwrap().1
-    }
-}
 
 pub struct FileScheme<D: Disk> {
     name: String,
     fs: RefCell<FileSystem<D>>,
     next_id: AtomicUsize,
-    files: Mutex<BTreeMap<usize, Box<Resource<D>>>>,
-    fmaps: Mutex<Fmaps>
+    files: RefCell<BTreeMap<usize, Box<Resource<D>>>>,
+    fmap: RefCell<BTreeMap<usize, usize>>,
 }
 
 impl<D: Disk> FileScheme<D> {
@@ -101,8 +30,8 @@ impl<D: Disk> FileScheme<D> {
             name: name,
             fs: RefCell::new(fs),
             next_id: AtomicUsize::new(1),
-            files: Mutex::new(BTreeMap::new()),
-            fmaps: Mutex::new(Fmaps::default())
+            files: RefCell::new(BTreeMap::new()),
+            fmap: RefCell::new(BTreeMap::new()),
         }
     }
 
@@ -381,7 +310,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
         };
 
         let id = self.next_id.fetch_add(1, Ordering::SeqCst);
-        self.files.lock().insert(id, resource);
+        self.files.borrow_mut().insert(id, resource);
 
         Ok(id)
     }
@@ -494,7 +423,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
             return Err(Error::new(EINVAL));
         }
 
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         let resource = if let Some(old_resource) = files.get(&old_id) {
             old_resource.dup()?
         } else {
@@ -510,7 +439,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
     #[allow(unused_variables)]
     fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
         // println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.read(buf, &mut self.fs.borrow_mut())
         } else {
@@ -520,7 +449,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
         // println!("Write {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.write(buf, &mut self.fs.borrow_mut())
         } else {
@@ -530,7 +459,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
         // println!("Seek {}, {} {}", id, pos, whence);
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.seek(pos, whence, &mut self.fs.borrow_mut())
         } else {
@@ -539,7 +468,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
     }
 
     fn fchmod(&self, id: usize, mode: u16) -> Result<usize> {
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.fchmod(mode, &mut self.fs.borrow_mut())
         } else {
@@ -548,7 +477,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
     }
 
     fn fchown(&self, id: usize, uid: u32, gid: u32) -> Result<usize> {
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.fchown(uid, gid, &mut self.fs.borrow_mut())
         } else {
@@ -557,7 +486,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
     }
 
     fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.fcntl(cmd, arg)
         } else {
@@ -567,7 +496,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
         // println!("Fpath {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
-        let files = self.files.lock();
+        let files = self.files.borrow_mut();
         if let Some(file) = files.get(&id) {
             let name = self.name.as_bytes();
 
@@ -596,7 +525,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
         // println!("Frename {}, {} from {}, {}", id, path, uid, gid);
 
-        let files = self.files.lock();
+        let files = self.files.borrow_mut();
         if let Some(file) = files.get(&id) {
             //TODO: Check for EINVAL
             // The new pathname contained a path prefix of the old, or, more generally,
@@ -692,7 +621,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
         // println!("Fstat {}, {:X}", id, stat as *mut Stat as usize);
-        let files = self.files.lock();
+        let files = self.files.borrow_mut();
         if let Some(file) = files.get(&id) {
             file.stat(stat, &mut self.fs.borrow_mut())
         } else {
@@ -701,7 +630,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
     }
 
     fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result<usize> {
-        let files = self.files.lock();
+        let files = self.files.borrow_mut();
         if let Some(_file) = files.get(&id) {
             let mut fs = self.fs.borrow_mut();
 
@@ -721,9 +650,9 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn fsync(&self, id: usize) -> Result<usize> {
         // println!("Fsync {}", id);
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
-            file.sync(&mut self.fmaps.lock(), &mut self.fs.borrow_mut())
+            file.sync(&mut self.fs.borrow_mut())
         } else {
             Err(Error::new(EBADF))
         }
@@ -731,7 +660,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn ftruncate(&self, id: usize, len: usize) -> Result<usize> {
         // println!("Ftruncate {}, {}", id, len);
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.truncate(len, &mut self.fs.borrow_mut())
         } else {
@@ -741,7 +670,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn futimens(&self, id: usize, times: &[TimeSpec]) -> Result<usize> {
         // println!("Futimens {}, {}", id, times.len());
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
             file.utimens(times, &mut self.fs.borrow_mut())
         } else {
@@ -751,19 +680,33 @@ impl<D: Disk> Scheme for FileScheme<D> {
 
     fn fmap(&self, id: usize, map: &Map) -> Result<usize> {
         // println!("Fmap {}, {:?}", id, map);
-        let mut files = self.files.lock();
+        let mut files = self.files.borrow_mut();
         if let Some(file) = files.get_mut(&id) {
-            file.fmap(map, &mut self.fmaps.lock(), &mut self.fs.borrow_mut())
+            let address = file.fmap(map, &mut self.fs.borrow_mut())?;
+            self.fmap.borrow_mut().insert(address, id);
+            Ok(address)
         } else {
             Err(Error::new(EBADF))
         }
     }
 
+    fn funmap(&self, address: usize) -> Result<usize> {
+        if let Some(id) = self.fmap.borrow_mut().remove(&address) {
+            let mut files = self.files.borrow_mut();
+            if let Some(file) = files.get_mut(&id) {
+                file.funmap(address, &mut self.fs.borrow_mut())
+            } else {
+                Err(Error::new(EINVAL))
+            }
+        } else {
+            Err(Error::new(EINVAL))
+        }
+    }
+
     fn close(&self, id: usize) -> Result<usize> {
         // println!("Close {}", id);
-        let mut files = self.files.lock();
-        if let Some(mut file) = files.remove(&id) {
-            let _ = file.funmap(&mut self.fmaps.lock(), &mut self.fs.borrow_mut());
+        let mut files = self.files.borrow_mut();
+        if files.remove(&id).is_some() {
             Ok(0)
         } else {
             Err(Error::new(EBADF))