Merge branch 'x86-x32-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-flexiantxendom0-3.2.10.git] / arch / x86 / kernel / sys_x86_64.c
index f921df8..b4d3c39 100644 (file)
@@ -195,7 +195,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 {
        struct vm_area_struct *vma;
        struct mm_struct *mm = current->mm;
-       unsigned long addr = addr0;
+       unsigned long addr = addr0, start_addr;
 
        /* requested length too big for entire address space */
        if (len > TASK_SIZE)
@@ -223,25 +223,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                mm->free_area_cache = mm->mmap_base;
        }
 
+try_again:
        /* either no address requested or can't fit in requested address hole */
-       addr = mm->free_area_cache;
-
-       /* make sure it can fit in the remaining address space */
-       if (addr > len) {
-               unsigned long tmp_addr = align_addr(addr - len, filp,
-                                                   ALIGN_TOPDOWN);
-
-               vma = find_vma(mm, tmp_addr);
-               if (!vma || tmp_addr + len <= vma->vm_start)
-                       /* remember the address as a hint for next time */
-                       return mm->free_area_cache = tmp_addr;
-       }
-
-       if (mm->mmap_base < len)
-               goto bottomup;
+       start_addr = addr = mm->free_area_cache;
 
-       addr = mm->mmap_base-len;
+       if (addr < len)
+               goto fail;
 
+       addr -= len;
        do {
                addr = align_addr(addr, filp, ALIGN_TOPDOWN);
 
@@ -263,6 +252,17 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                addr = vma->vm_start-len;
        } while (len < vma->vm_start);
 
+fail:
+       /*
+        * if hint left us with no space for the requested
+        * mapping then try again:
+        */
+       if (start_addr != mm->mmap_base) {
+               mm->free_area_cache = mm->mmap_base;
+               mm->cached_hole_size = 0;
+               goto try_again;
+       }
+
 bottomup:
        /*
         * A failed mmap() very likely causes application failure,