extern int ext4_writepage_trans_blocks(struct inode *);
 extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
                struct address_space *mapping, loff_t from);
+extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page);
 
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
 
        return ret;
 }
 
+static struct vm_operations_struct ext4_file_vm_ops = {
+       .fault          = filemap_fault,
+       .page_mkwrite   = ext4_page_mkwrite,
+};
+
+static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct address_space *mapping = file->f_mapping;
+
+       if (!mapping->a_ops->readpage)
+               return -ENOEXEC;
+       file_accessed(file);
+       vma->vm_ops = &ext4_file_vm_ops;
+       vma->vm_flags |= VM_CAN_NONLINEAR;
+       return 0;
+}
+
 const struct file_operations ext4_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ext4_compat_ioctl,
 #endif
-       .mmap           = generic_file_mmap,
+       .mmap           = ext4_file_mmap,
        .open           = generic_file_open,
        .release        = ext4_release_file,
        .fsync          = ext4_sync_file,
 
 
        return err;
 }
+
+static int ext4_bh_unmapped(handle_t *handle, struct buffer_head *bh)
+{
+       return !buffer_mapped(bh);
+}
+
+int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+       loff_t size;
+       unsigned long len;
+       int ret = -EINVAL;
+       struct file *file = vma->vm_file;
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct address_space *mapping = inode->i_mapping;
+
+       /*
+        * Get i_alloc_sem to stop truncates messing with the inode. We cannot
+        * get i_mutex because we are already holding mmap_sem.
+        */
+       down_read(&inode->i_alloc_sem);
+       size = i_size_read(inode);
+       if (page->mapping != mapping || size <= page_offset(page)
+           || !PageUptodate(page)) {
+               /* page got truncated from under us? */
+               goto out_unlock;
+       }
+       ret = 0;
+       if (PageMappedToDisk(page))
+               goto out_unlock;
+
+       if (page->index == size >> PAGE_CACHE_SHIFT)
+               len = size & ~PAGE_CACHE_MASK;
+       else
+               len = PAGE_CACHE_SIZE;
+
+       if (page_has_buffers(page)) {
+               /* return if we have all the buffers mapped */
+               if (!walk_page_buffers(NULL, page_buffers(page), 0, len, NULL,
+                                      ext4_bh_unmapped))
+                       goto out_unlock;
+       }
+       /*
+        * OK, we need to fill the hole... Do write_begin write_end
+        * to do block allocation/reservation.We are not holding
+        * inode.i__mutex here. That allow * parallel write_begin,
+        * write_end call. lock_page prevent this from happening
+        * on the same page though
+        */
+       ret = mapping->a_ops->write_begin(file, mapping, page_offset(page),
+                       len, AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
+       if (ret < 0)
+               goto out_unlock;
+       ret = mapping->a_ops->write_end(file, mapping, page_offset(page),
+                       len, len, page, NULL);
+       if (ret < 0)
+               goto out_unlock;
+       ret = 0;
+out_unlock:
+       up_read(&inode->i_alloc_sem);
+       return ret;
+}