diff options
Diffstat (limited to 'arch/x86/mm/hugetlbpage.c')
-rw-r--r-- | arch/x86/mm/hugetlbpage.c | 28 |
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 | } |
324 | try_again: | 325 | try_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 | /* |