* Address space accounting code       <alan@lxorguk.ukuu.org.uk>
  */
 
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/backing-dev.h>
 #include <linux/mm.h>
        return 0;
 }
 
+static unsigned long count_vma_pages_range(struct mm_struct *mm,
+               unsigned long addr, unsigned long end)
+{
+       unsigned long nr_pages = 0;
+       struct vm_area_struct *vma;
+
+       /* Find first overlaping mapping */
+       vma = find_vma_intersection(mm, addr, end);
+       if (!vma)
+               return 0;
+
+       nr_pages = (min(end, vma->vm_end) -
+               max(addr, vma->vm_start)) >> PAGE_SHIFT;
+
+       /* Iterate over the rest of the overlaps */
+       for (vma = vma->vm_next; vma; vma = vma->vm_next) {
+               unsigned long overlap_len;
+
+               if (vma->vm_start > end)
+                       break;
+
+               overlap_len = min(end, vma->vm_end) - vma->vm_start;
+               nr_pages += overlap_len >> PAGE_SHIFT;
+       }
+
+       return nr_pages;
+}
+
 void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
                struct rb_node **rb_link, struct rb_node *rb_parent)
 {
        unsigned long charged = 0;
        struct inode *inode =  file ? file_inode(file) : NULL;
 
+       /* Check against address space limit. */
+       if (!may_expand_vm(mm, len >> PAGE_SHIFT)) {
+               unsigned long nr_pages;
+
+               /*
+                * MAP_FIXED may remove pages of mappings that intersects with
+                * requested mapping. Account for the pages it would unmap.
+                */
+               if (!(vm_flags & MAP_FIXED))
+                       return -ENOMEM;
+
+               nr_pages = count_vma_pages_range(mm, addr, addr + len);
+
+               if (!may_expand_vm(mm, (len >> PAGE_SHIFT) - nr_pages))
+                       return -ENOMEM;
+       }
+
        /* Clear old maps */
        error = -ENOMEM;
 munmap_back:
                goto munmap_back;
        }
 
-       /* Check against address space limit. */
-       if (!may_expand_vm(mm, len >> PAGE_SHIFT))
-               return -ENOMEM;
-
        /*
         * Private writable mapping: check memory availability
         */