diff options
author | Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> | 2012-03-21 19:33:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 20:54:56 -0400 |
commit | b716ad953a2bc4a543143c1d9836b7007a4b182f (patch) | |
tree | 99791c6c857b1ff7b922eaa0163ec3c912549009 | |
parent | f44d21985eb6af7361d3785e26923355172147bd (diff) |
mm: search from free_area_cache for the bigger size
If the required size is bigger than cached_hole_size it is better to
search from free_area_cache - it is easier to get a free region,
specifically for the 64 bit process whose address space is large enough
Do it just as hugetlb_get_unmapped_area_topdown() in arch/x86/mm/hugetlbpage.c
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Hillf Danton <dhillf@gmail.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Rik van Riel <riel@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/x86/kernel/sys_x86_64.c | 34 | ||||
-rw-r--r-- | mm/mmap.c | 36 |
2 files changed, 38 insertions, 32 deletions
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 051489082d59..ef59642ff1bf 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c | |||
@@ -195,7 +195,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
195 | { | 195 | { |
196 | struct vm_area_struct *vma; | 196 | struct vm_area_struct *vma; |
197 | struct mm_struct *mm = current->mm; | 197 | struct mm_struct *mm = current->mm; |
198 | unsigned long addr = addr0; | 198 | unsigned long addr = addr0, start_addr; |
199 | 199 | ||
200 | /* requested length too big for entire address space */ | 200 | /* requested length too big for entire address space */ |
201 | if (len > TASK_SIZE) | 201 | if (len > TASK_SIZE) |
@@ -223,25 +223,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
223 | mm->free_area_cache = mm->mmap_base; | 223 | mm->free_area_cache = mm->mmap_base; |
224 | } | 224 | } |
225 | 225 | ||
226 | try_again: | ||
226 | /* either no address requested or can't fit in requested address hole */ | 227 | /* either no address requested or can't fit in requested address hole */ |
227 | addr = mm->free_area_cache; | 228 | start_addr = addr = mm->free_area_cache; |
228 | |||
229 | /* make sure it can fit in the remaining address space */ | ||
230 | if (addr > len) { | ||
231 | unsigned long tmp_addr = align_addr(addr - len, filp, | ||
232 | ALIGN_TOPDOWN); | ||
233 | |||
234 | vma = find_vma(mm, tmp_addr); | ||
235 | if (!vma || tmp_addr + len <= vma->vm_start) | ||
236 | /* remember the address as a hint for next time */ | ||
237 | return mm->free_area_cache = tmp_addr; | ||
238 | } | ||
239 | |||
240 | if (mm->mmap_base < len) | ||
241 | goto bottomup; | ||
242 | 229 | ||
243 | addr = mm->mmap_base-len; | 230 | if (addr < len) |
231 | goto fail; | ||
244 | 232 | ||
233 | addr -= len; | ||
245 | do { | 234 | do { |
246 | addr = align_addr(addr, filp, ALIGN_TOPDOWN); | 235 | addr = align_addr(addr, filp, ALIGN_TOPDOWN); |
247 | 236 | ||
@@ -263,6 +252,17 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
263 | addr = vma->vm_start-len; | 252 | addr = vma->vm_start-len; |
264 | } while (len < vma->vm_start); | 253 | } while (len < vma->vm_start); |
265 | 254 | ||
255 | fail: | ||
256 | /* | ||
257 | * if hint left us with no space for the requested | ||
258 | * mapping then try again: | ||
259 | */ | ||
260 | if (start_addr != mm->mmap_base) { | ||
261 | mm->free_area_cache = mm->mmap_base; | ||
262 | mm->cached_hole_size = 0; | ||
263 | goto try_again; | ||
264 | } | ||
265 | |||
266 | bottomup: | 266 | bottomup: |
267 | /* | 267 | /* |
268 | * A failed mmap() very likely causes application failure, | 268 | * A failed mmap() very likely causes application failure, |
@@ -1442,7 +1442,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
1442 | { | 1442 | { |
1443 | struct vm_area_struct *vma; | 1443 | struct vm_area_struct *vma; |
1444 | struct mm_struct *mm = current->mm; | 1444 | struct mm_struct *mm = current->mm; |
1445 | unsigned long addr = addr0; | 1445 | unsigned long addr = addr0, start_addr; |
1446 | 1446 | ||
1447 | /* requested length too big for entire address space */ | 1447 | /* requested length too big for entire address space */ |
1448 | if (len > TASK_SIZE) | 1448 | if (len > TASK_SIZE) |
@@ -1466,22 +1466,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
1466 | mm->free_area_cache = mm->mmap_base; | 1466 | mm->free_area_cache = mm->mmap_base; |
1467 | } | 1467 | } |
1468 | 1468 | ||
1469 | try_again: | ||
1469 | /* either no address requested or can't fit in requested address hole */ | 1470 | /* either no address requested or can't fit in requested address hole */ |
1470 | addr = mm->free_area_cache; | 1471 | start_addr = addr = mm->free_area_cache; |
1471 | 1472 | ||
1472 | /* make sure it can fit in the remaining address space */ | 1473 | if (addr < len) |
1473 | if (addr > len) { | 1474 | goto fail; |
1474 | vma = find_vma(mm, addr-len); | ||
1475 | if (!vma || addr <= vma->vm_start) | ||
1476 | /* remember the address as a hint for next time */ | ||
1477 | return (mm->free_area_cache = addr-len); | ||
1478 | } | ||
1479 | |||
1480 | if (mm->mmap_base < len) | ||
1481 | goto bottomup; | ||
1482 | |||
1483 | addr = mm->mmap_base-len; | ||
1484 | 1475 | ||
1476 | addr -= len; | ||
1485 | do { | 1477 | do { |
1486 | /* | 1478 | /* |
1487 | * Lookup failure means no vma is above this address, | 1479 | * Lookup failure means no vma is above this address, |
@@ -1501,7 +1493,21 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
1501 | addr = vma->vm_start-len; | 1493 | addr = vma->vm_start-len; |
1502 | } while (len < vma->vm_start); | 1494 | } while (len < vma->vm_start); |
1503 | 1495 | ||
1504 | bottomup: | 1496 | fail: |
1497 | /* | ||
1498 | * if hint left us with no space for the requested | ||
1499 | * mapping then try again: | ||
1500 | * | ||
1501 | * Note: this is different with the case of bottomup | ||
1502 | * which does the fully line-search, but we use find_vma | ||
1503 | * here that causes some holes skipped. | ||
1504 | */ | ||
1505 | if (start_addr != mm->mmap_base) { | ||
1506 | mm->free_area_cache = mm->mmap_base; | ||
1507 | mm->cached_hole_size = 0; | ||
1508 | goto try_again; | ||
1509 | } | ||
1510 | |||
1505 | /* | 1511 | /* |
1506 | * A failed mmap() very likely causes application failure, | 1512 | * A failed mmap() very likely causes application failure, |
1507 | * so fall back to the bottom-up function here. This scenario | 1513 | * so fall back to the bottom-up function here. This scenario |