aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/hugetlbpage.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/hugetlbpage.c')
-rw-r--r--arch/x86/mm/hugetlbpage.c28
1 files changed, 11 insertions, 17 deletions
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 8ecbb4bba4b3..f6679a7fb8ca 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -308,10 +308,11 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
308{ 308{
309 struct hstate *h = hstate_file(file); 309 struct hstate *h = hstate_file(file);
310 struct mm_struct *mm = current->mm; 310 struct mm_struct *mm = current->mm;
311 struct vm_area_struct *vma, *prev_vma; 311 struct vm_area_struct *vma;
312 unsigned long base = mm->mmap_base, addr = addr0; 312 unsigned long base = mm->mmap_base;
313 unsigned long addr = addr0;
313 unsigned long largest_hole = mm->cached_hole_size; 314 unsigned long largest_hole = mm->cached_hole_size;
314 int first_time = 1; 315 unsigned long start_addr;
315 316
316 /* don't allow allocations above current base */ 317 /* don't allow allocations above current base */
317 if (mm->free_area_cache > base) 318 if (mm->free_area_cache > base)
@@ -322,6 +323,8 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
322 mm->free_area_cache = base; 323 mm->free_area_cache = base;
323 } 324 }
324try_again: 325try_again:
326 start_addr = mm->free_area_cache;
327
325 /* make sure it can fit in the remaining address space */ 328 /* make sure it can fit in the remaining address space */
326 if (mm->free_area_cache < len) 329 if (mm->free_area_cache < len)
327 goto fail; 330 goto fail;
@@ -337,22 +340,14 @@ try_again:
337 if (!vma) 340 if (!vma)
338 return addr; 341 return addr;
339 342
340 /* 343 if (addr + len <= vma->vm_start) {
341 * new region fits between prev_vma->vm_end and
342 * vma->vm_start, use it:
343 */
344 prev_vma = vma->vm_prev;
345 if (addr + len <= vma->vm_start &&
346 (!prev_vma || (addr >= prev_vma->vm_end))) {
347 /* remember the address as a hint for next time */ 344 /* remember the address as a hint for next time */
348 mm->cached_hole_size = largest_hole; 345 mm->cached_hole_size = largest_hole;
349 return (mm->free_area_cache = addr); 346 return (mm->free_area_cache = addr);
350 } else { 347 } else if (mm->free_area_cache == vma->vm_end) {
351 /* pull free_area_cache down to the first hole */ 348 /* pull free_area_cache down to the first hole */
352 if (mm->free_area_cache == vma->vm_end) { 349 mm->free_area_cache = vma->vm_start;
353 mm->free_area_cache = vma->vm_start; 350 mm->cached_hole_size = largest_hole;
354 mm->cached_hole_size = largest_hole;
355 }
356 } 351 }
357 352
358 /* remember the largest hole we saw so far */ 353 /* remember the largest hole we saw so far */
@@ -368,10 +363,9 @@ fail:
368 * if hint left us with no space for the requested 363 * if hint left us with no space for the requested
369 * mapping then try again: 364 * mapping then try again:
370 */ 365 */
371 if (first_time) { 366 if (start_addr != base) {
372 mm->free_area_cache = base; 367 mm->free_area_cache = base;
373 largest_hole = 0; 368 largest_hole = 0;
374 first_time = 0;
375 goto try_again; 369 goto try_again;
376 } 370 }
377 /* 371 /*