diff --git a/src/lib.rs b/src/lib.rs
index 0f1dba46e849984178f3ecc2e52fd733eeab8a72..20c6c98294c184bc8547850f18dcfa23cf1c5a41 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,7 @@
 #![crate_name="redoxfs"]
 #![crate_type="lib"]
 
-#![deny(warnings)]
+//#![deny(warnings)]
 
 extern crate syscall;
 extern crate uuid;
diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs
index 7d812bcce3532629c947c72d9aa5ae22c28197c9..50c3d2cd786c60b30eb8accef3aa6d262f3fb590 100644
--- a/src/mount/redox/resource.rs
+++ b/src/mount/redox/resource.rs
@@ -2,12 +2,13 @@ use std::cmp::{min, max};
 use std::time::{SystemTime, UNIX_EPOCH};
 
 use syscall::data::TimeSpec;
-use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, EPERM};
+use syscall::error::{Error, Result, EBADF, EBUSY, EINVAL, EISDIR, EPERM};
 use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM};
 use syscall::{Stat, 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,12 +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, offset: usize, size: usize, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>;
+    fn funmap(&mut self, maps: &mut Fmaps, 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) -> Result<usize>;
+    fn sync(&mut self, maps: &mut Fmaps, 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>;
 }
@@ -87,6 +90,13 @@ impl<D: Disk> Resource<D> for DirResource {
         Ok(self.seek)
     }
 
+    fn fmap(&mut self, _offset: usize, _size: usize, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> {
+        Err(Error::new(EBADF))
+    }
+    fn funmap(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> {
+        Err(Error::new(EBADF))
+    }
+
     fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
         let mut node = fs.node(self.block)?;
 
@@ -158,7 +168,7 @@ impl<D: Disk> Resource<D> for DirResource {
         Ok(0)
     }
 
-    fn sync(&mut self) -> Result<usize> {
+    fn sync(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> {
         Err(Error::new(EBADF))
     }
 
@@ -177,6 +187,7 @@ pub struct FileResource {
     flags: usize,
     seek: u64,
     uid: u32,
+    fmap: Option<(usize, FmapKey)>
 }
 
 impl FileResource {
@@ -187,8 +198,31 @@ impl FileResource {
             flags: flags,
             seek: seek,
             uid: uid,
+            fmap: None
         }
     }
+
+    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 (_, value) = maps.index(*i).as_mut().expect("mapping dropped while still referenced");
+            // Minimum out of our size and the original file size
+            let actual_size = value.actual_size.min(key_exact.size);
+
+            let mut count = 0;
+            while count < actual_size {
+                let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+                match fs.write_node(self.block, key_exact.offset as u64 + count as u64, &value.buffer[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 {
@@ -203,6 +237,7 @@ impl<D: Disk> Resource<D> for FileResource {
             flags: self.flags,
             seek: self.seek,
             uid: self.uid,
+            fmap: None
         }))
     }
 
@@ -240,6 +275,71 @@ impl<D: Disk> Resource<D> for FileResource {
         Ok(self.seek as usize)
     }
 
+    fn fmap(&mut self, offset: usize, size: usize, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> {
+        if self.flags & O_ACCMODE == O_RDWR {
+            let key_exact = FmapKey {
+                block: self.block,
+                offset,
+                size
+            };
+
+            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..])? {
+                    0 => break,
+                    n => count += n
+                }
+            }
+
+            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))
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+    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)
+    }
+
     fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
         let mut node = fs.node(self.block)?;
 
@@ -318,7 +418,8 @@ impl<D: Disk> Resource<D> for FileResource {
         Ok(0)
     }
 
-    fn sync(&mut self) -> Result<usize> {
+    fn sync(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> {
+        self.sync_fmap(maps, fs)?;
         Ok(0)
     }
 
diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs
index 966b56501a68b6d0b5198fe2270a62728809d9d8..a5ce3be516ae36613e5c3f7249401793a2f2ca52 100644
--- a/src/mount/redox/scheme.rs
+++ b/src/mount/redox/scheme.rs
@@ -1,5 +1,6 @@
 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};
@@ -17,11 +18,81 @@ 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>>>>
+    files: Mutex<BTreeMap<usize, Box<Resource<D>>>>,
+    fmaps: Mutex<Fmaps>
 }
 
 impl<D: Disk> FileScheme<D> {
@@ -30,7 +101,8 @@ impl<D: Disk> FileScheme<D> {
             name: name,
             fs: RefCell::new(fs),
             next_id: AtomicUsize::new(1),
-            files: Mutex::new(BTreeMap::new())
+            files: Mutex::new(BTreeMap::new()),
+            fmaps: Mutex::new(Fmaps::default())
         }
     }
 
@@ -651,7 +723,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
         // println!("Fsync {}", id);
         let mut files = self.files.lock();
         if let Some(file) = files.get_mut(&id) {
-            file.sync()
+            file.sync(&mut self.fmaps.lock(), &mut self.fs.borrow_mut())
         } else {
             Err(Error::new(EBADF))
         }
@@ -677,10 +749,21 @@ impl<D: Disk> Scheme for FileScheme<D> {
         }
     }
 
+    fn fmap(&self, id: usize, offset: usize, size: usize) -> Result<usize> {
+        // println!("Fmap {}, {}, {}", id, offset, size);
+        let mut files = self.files.lock();
+        if let Some(file) = files.get_mut(&id) {
+            file.fmap(offset, size, &mut self.fmaps.lock(), &mut self.fs.borrow_mut())
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
     fn close(&self, id: usize) -> Result<usize> {
         // println!("Close {}", id);
         let mut files = self.files.lock();
-        if files.remove(&id).is_some() {
+        if let Some(mut file) = files.remove(&id) {
+            let _ = file.funmap(&mut self.fmaps.lock(), &mut self.fs.borrow_mut());
             Ok(0)
         } else {
             Err(Error::new(EBADF))