diff --git a/mkfs/main.rs b/mkfs/main.rs
index 738a07edf26410351c3a2fcd3eb806c2dafcf815..e0f6f00b04089b4bc069cadf175ccd5205da372c 100644
--- a/mkfs/main.rs
+++ b/mkfs/main.rs
@@ -3,7 +3,7 @@
 extern crate redoxfs;
 extern crate syscall;
 
-use std::{env, process, str};
+use std::{env, process, str, time};
 
 use redoxfs::FileSystem;
 
@@ -14,9 +14,11 @@ pub mod image;
 fn main() {
     let mut args = env::args();
     if let Some(path) = args.nth(1) {
+        let ctime = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
+
         //Open an existing image
         match Image::open(&path) {
-            Ok(disk) => match FileSystem::create(Box::new(disk)) {
+            Ok(disk) => match FileSystem::create(Box::new(disk), ctime.as_secs(), ctime.subsec_nanos()) {
                 Ok(filesystem) => {
                     println!("redoxfs-mkfs: created filesystem on {}, size {} MB", path, filesystem.header.1.size/1024/1024);
                 },
diff --git a/mount/fuse.rs b/mount/fuse.rs
index b51fe77cda0318863ff53e7c9ac6e1d68b8b3b1f..69cf53a1dca948b39dd59d616827438e07034510 100644
--- a/mount/fuse.rs
+++ b/mount/fuse.rs
@@ -4,6 +4,7 @@ extern crate time;
 use redoxfs;
 use std::path::Path;
 use std::os::unix::ffi::OsStrExt;
+use std::time::{SystemTime, UNIX_EPOCH};
 
 use self::fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyCreate, ReplyDirectory, ReplyEmpty, ReplyStatfs, ReplyWrite};
 use self::time::Timespec;
@@ -12,7 +13,7 @@ pub use self::fuse::mount;
 
 const TTL: Timespec = Timespec { sec: 1, nsec: 0 };                 // 1 second
 
-const CREATE_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
+const NULL_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
 
 pub struct Fuse {
     pub fs: redoxfs::FileSystem,
@@ -23,10 +24,16 @@ fn node_attr(node: &(u64, redoxfs::Node)) -> FileAttr {
         ino: node.0,
         size: node.1.extents[0].length,
         blocks: (node.1.extents[0].length + 511)/512,
-        atime: CREATE_TIME,
-        mtime: CREATE_TIME,
-        ctime: CREATE_TIME,
-        crtime: CREATE_TIME,
+        atime: NULL_TIME,
+        mtime: Timespec {
+            sec: node.1.mtime as i64,
+            nsec: node.1.mtime_nsec as i32,
+        },
+        ctime: Timespec {
+            sec: node.1.ctime as i64,
+            nsec: node.1.ctime_nsec as i32,
+        },
+        crtime: NULL_TIME,
         kind: if node.1.is_dir() {
             FileType::Directory
         } else if node.1.is_symlink() {
@@ -68,7 +75,7 @@ impl Filesystem for Fuse {
 
     fn setattr(&mut self, _req: &Request, block: u64, mode: Option<u32>,
                 uid: Option<u32>, gid: Option<u32>, size: Option<u64>,
-                _atime: Option<Timespec>, _mtime: Option<Timespec>, _fh: Option<u64>,
+                _atime: Option<Timespec>, mtime: Option<Timespec>, _fh: Option<u64>,
                 _crtime: Option<Timespec>, _chgtime: Option<Timespec>, _bkuptime: Option<Timespec>,
                 _flags: Option<u32>, reply: ReplyAttr) {
         if let Some(mode) = mode {
@@ -127,6 +134,23 @@ impl Filesystem for Fuse {
             }
         }
 
+        if let Some(mtime) = mtime {
+            match self.fs.node(block) {
+                Ok(mut node) => if mtime.sec as u64 > node.1.mtime || (mtime.sec as u64 == node.1.mtime && mtime.nsec as u32 > node.1.mtime_nsec) {
+                    node.1.mtime = mtime.sec as u64;
+                    node.1.mtime_nsec = mtime.nsec as u32;
+                    if let Err(err) = self.fs.write_at(node.0, &node.1) {
+                        reply.error(err.errno as i32);
+                        return;
+                    }
+                },
+                Err(err) => {
+                    reply.error(err.errno as i32);
+                    return;
+                }
+            }
+        }
+
         match self.fs.node(block) {
             Ok(node) => {
                 reply.attr(&TTL, &node_attr(&node));
@@ -150,7 +174,8 @@ impl Filesystem for Fuse {
     }
 
     fn write(&mut self, _req: &Request, block: u64, _fh: u64, offset: u64, data: &[u8], _flags: u32, reply: ReplyWrite) {
-        match self.fs.write_node(block, offset, &data) {
+        let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+        match self.fs.write_node(block, offset, &data, mtime.as_secs(), mtime.subsec_nanos()) {
             Ok(count) => {
                 reply.written(count as u32);
             },
@@ -196,7 +221,8 @@ impl Filesystem for Fuse {
     }
 
     fn create(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, flags: u32, reply: ReplyCreate) {
-        match self.fs.create_node(redoxfs::Node::MODE_FILE | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
+        let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+        match self.fs.create_node(redoxfs::Node::MODE_FILE | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block, ctime.as_secs(), ctime.subsec_nanos()) {
             Ok(node) => {
                 // println!("Create {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
                 reply.created(&TTL, &node_attr(&node), 0, 0, flags);
@@ -208,7 +234,8 @@ impl Filesystem for Fuse {
     }
 
     fn mkdir(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, reply: ReplyEntry) {
-        match self.fs.create_node(redoxfs::Node::MODE_DIR | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
+        let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+        match self.fs.create_node(redoxfs::Node::MODE_DIR | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block, ctime.as_secs(), ctime.subsec_nanos()) {
             Ok(node) => {
                 // println!("Mkdir {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
                 reply.entry(&TTL, &node_attr(&node), 0);
@@ -257,9 +284,11 @@ impl Filesystem for Fuse {
     }
 
     fn symlink(&mut self, _req: &Request, parent_block: u64, name: &Path, link: &Path, reply: ReplyEntry) {
-        match self.fs.create_node(redoxfs::Node::MODE_SYMLINK | 0o777, name.to_str().unwrap(), parent_block) {
+        let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+        match self.fs.create_node(redoxfs::Node::MODE_SYMLINK | 0o777, name.to_str().unwrap(), parent_block, ctime.as_secs(), ctime.subsec_nanos()) {
             Ok(node) => {
-                match self.fs.write_node(node.0, 0, link.as_os_str().as_bytes()) {
+                let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+                match self.fs.write_node(node.0, 0, link.as_os_str().as_bytes(), mtime.as_secs(), mtime.subsec_nanos()) {
                     Ok(_count) => {
                         reply.entry(&TTL, &node_attr(&node), 0);
                     },
diff --git a/src/filesystem.rs b/src/filesystem.rs
index c4ca2a7be365ded803d5699f51b93fe7e47063cb..38408f4df706471899d7b29f58ba10262e3a959c 100644
--- a/src/filesystem.rs
+++ b/src/filesystem.rs
@@ -37,15 +37,15 @@ impl FileSystem {
     }
 
     /// Create a file system on a disk
-    pub fn create(mut disk: Box<Disk>) -> Result<Self> {
+    pub fn create(mut disk: Box<Disk>, ctime: u64, ctime_nsec: u32) -> Result<Self> {
         let size = disk.size()?;
 
         if size >= 4 * 512 {
-            let mut free = (2, Node::new(Node::MODE_FILE, "free", 0));
+            let mut free = (2, Node::new(Node::MODE_FILE, "free", 0, ctime, ctime_nsec));
             free.1.extents[0] = Extent::new(4, size - 4 * 512);
             disk.write_at(free.0, &free.1)?;
 
-            let root = (1, Node::new(Node::MODE_DIR | 0o755, "root", 0));
+            let root = (1, Node::new(Node::MODE_DIR | 0o755, "root", 0, ctime, ctime_nsec));
             disk.write_at(root.0, &root.1)?;
 
             let header = (0, Header::new(size, root.0, free.0));
@@ -194,11 +194,11 @@ impl FileSystem {
         }
     }
 
-    pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result<(u64, Node)> {
+    pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64, ctime: u64, ctime_nsec: u32) -> Result<(u64, Node)> {
         if self.find_node(name, parent_block).is_ok() {
             Err(Error::new(EEXIST))
         } else {
-            let node = (self.allocate(1)?, Node::new(mode, name, parent_block));
+            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)?;
@@ -276,6 +276,7 @@ impl FileSystem {
         }
     }
 
+    // TODO: modification time
     fn node_ensure_len(&mut self, block: u64, mut length: u64) -> Result<()> {
         if block == 0 {
             return Err(Error::new(ENOENT));
@@ -319,6 +320,7 @@ impl FileSystem {
         }
     }
 
+    //TODO: modification time
     pub fn node_set_len(&mut self, block: u64, mut length: u64) -> Result<()> {
         if block == 0 {
             return Err(Error::new(ENOENT));
@@ -450,7 +452,7 @@ impl FileSystem {
         Ok(i)
     }
 
-    pub fn write_node(&mut self, block: u64, offset: u64, buf: &[u8]) -> Result<usize> {
+    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;
 
@@ -512,6 +514,15 @@ impl FileSystem {
             assert_eq!(block, extent.block + (extent.length + 511)/512);
         }
 
+        if i > 0 {
+            let mut node = self.node(block)?;
+            if mtime > node.1.mtime || (mtime == node.1.mtime && mtime_nsec > node.1.mtime_nsec) {
+                node.1.mtime = mtime;
+                node.1.mtime_nsec = mtime_nsec;
+                self.write_at(node.0, &node.1)?;
+            }
+        }
+
         Ok(i)
     }
 
diff --git a/src/header.rs b/src/header.rs
index 589339a00b02ff00635ca932c7e89a6c82eef6d8..82ce62f9b6ad1cd70613cd4b0d1a7ad31f836832 100644
--- a/src/header.rs
+++ b/src/header.rs
@@ -22,7 +22,7 @@ pub struct Header {
 
 impl Header {
     pub const SIGNATURE: &'static [u8; 8] = b"RedoxFS\0";
-    pub const VERSION: u64 = 1;
+    pub const VERSION: u64 = 2;
 
     pub fn default() -> Header {
         Header {
diff --git a/src/node.rs b/src/node.rs
index a6ecaf6caf69a5c72467821faa4a81a3372ff400..58e426d0898147328ce6a2646d83b9a946e0fec9 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -8,7 +8,11 @@ pub struct Node {
     pub mode: u16,
     pub uid: u32,
     pub gid: u32,
-    pub name: [u8; 246],
+    pub ctime: u64,
+    pub ctime_nsec: u32,
+    pub mtime: u64,
+    pub mtime_nsec: u32,
+    pub name: [u8; 222],
     pub parent: u64,
     pub next: u64,
     pub extents: [Extent; 15],
@@ -30,15 +34,19 @@ impl Node {
             mode: 0,
             uid: 0,
             gid: 0,
-            name: [0; 246],
+            ctime: 0,
+            ctime_nsec: 0,
+            mtime: 0,
+            mtime_nsec: 0,
+            name: [0; 222],
             parent: 0,
             next: 0,
             extents: [Extent::default(); 15],
         }
     }
 
-    pub fn new(mode: u16, name: &str, parent: u64) -> Node {
-        let mut bytes = [0; 246];
+    pub fn new(mode: u16, name: &str, parent: u64, ctime: u64, ctime_nsec: u32) -> Node {
+        let mut bytes = [0; 222];
         for (mut b, c) in bytes.iter_mut().zip(name.bytes()) {
             *b = c;
         }
@@ -47,6 +55,10 @@ impl Node {
             mode: mode,
             uid: 0,
             gid: 0,
+            ctime: ctime,
+            ctime_nsec: ctime_nsec,
+            mtime: ctime,
+            mtime_nsec: ctime_nsec,
             name: bytes,
             parent: parent,
             next: 0,
@@ -105,6 +117,10 @@ impl fmt::Debug for Node {
             .field("mode", &self.mode)
             .field("uid", &self.uid)
             .field("gid", &self.gid)
+            .field("ctime", &self.ctime)
+            .field("ctime_nsec", &self.ctime_nsec)
+            .field("mtime", &self.mtime)
+            .field("mtime_nsec", &self.mtime_nsec)
             .field("name", &self.name())
             .field("next", &self.next)
             .field("extents", &extents)