aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@saeurebad.de>2008-07-24 00:28:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:20 -0400
commit0f3caba211babef6e3fbde1ba76ddc79321bc92f (patch)
treea240561bc4288ab3e17f16c458377df9d043a177
parente2bf3cae515090fefe28329e71230dfe7ab873b1 (diff)
bootmem: respect goal more likely
The old node-agnostic code tried allocating on all nodes starting from the one with the lowest range. alloc_bootmem_core retried without the goal if it could not satisfy it and so the goal was only respected at all when it happened to be on the first (lowest page numbers) node (or theoretically if allocations failed on all nodes before to the one holding the goal). Introduce a non-panicking helper that starts allocating from the node holding the goal and falls back only after all thes tries failed, thus moving the goal fallback code out of alloc_bootmem_core. Make all other allocation functions benefit from this new helper. Signed-off-by: Johannes Weiner <hannes@saeurebad.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: Yinghai Lu <yhlu.kernel@gmail.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Yasunori Goto <y-goto@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/bootmem.c92
1 files changed, 54 insertions, 38 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c
index e5415a5414a5..89646f77b427 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -408,6 +408,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
408 unsigned long size, unsigned long align, 408 unsigned long size, unsigned long align,
409 unsigned long goal, unsigned long limit) 409 unsigned long goal, unsigned long limit)
410{ 410{
411 unsigned long fallback = 0;
411 unsigned long min, max, start, sidx, midx, step; 412 unsigned long min, max, start, sidx, midx, step;
412 413
413 BUG_ON(!size); 414 BUG_ON(!size);
@@ -443,8 +444,11 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
443 midx = max - PFN_DOWN(bdata->node_boot_start); 444 midx = max - PFN_DOWN(bdata->node_boot_start);
444 445
445 if (bdata->hint_idx > sidx) { 446 if (bdata->hint_idx > sidx) {
446 /* Make sure we retry on failure */ 447 /*
447 goal = 1; 448 * Handle the valid case of sidx being zero and still
449 * catch the fallback below.
450 */
451 fallback = sidx + 1;
448 sidx = ALIGN(bdata->hint_idx, step); 452 sidx = ALIGN(bdata->hint_idx, step);
449 } 453 }
450 454
@@ -492,10 +496,39 @@ find_block:
492 return region; 496 return region;
493 } 497 }
494 498
499 if (fallback) {
500 sidx = ALIGN(fallback - 1, step);
501 fallback = 0;
502 goto find_block;
503 }
504
505 return NULL;
506}
507
508static void * __init ___alloc_bootmem_nopanic(unsigned long size,
509 unsigned long align,
510 unsigned long goal,
511 unsigned long limit)
512{
513 bootmem_data_t *bdata;
514
515restart:
516 list_for_each_entry(bdata, &bdata_list, list) {
517 void *region;
518
519 if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
520 continue;
521 if (limit && bdata->node_boot_start >= limit)
522 break;
523
524 region = alloc_bootmem_core(bdata, size, align, goal, limit);
525 if (region)
526 return region;
527 }
528
495 if (goal) { 529 if (goal) {
496 goal = 0; 530 goal = 0;
497 sidx = 0; 531 goto restart;
498 goto find_block;
499 } 532 }
500 533
501 return NULL; 534 return NULL;
@@ -515,16 +548,23 @@ find_block:
515 * Returns NULL on failure. 548 * Returns NULL on failure.
516 */ 549 */
517void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, 550void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
518 unsigned long goal) 551 unsigned long goal)
519{ 552{
520 bootmem_data_t *bdata; 553 return ___alloc_bootmem_nopanic(size, align, goal, 0);
521 void *ptr; 554}
522 555
523 list_for_each_entry(bdata, &bdata_list, list) { 556static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
524 ptr = alloc_bootmem_core(bdata, size, align, goal, 0); 557 unsigned long goal, unsigned long limit)
525 if (ptr) 558{
526 return ptr; 559 void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit);
527 } 560
561 if (mem)
562 return mem;
563 /*
564 * Whoops, we cannot satisfy the allocation request.
565 */
566 printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
567 panic("Out of memory");
528 return NULL; 568 return NULL;
529} 569}
530 570
@@ -544,16 +584,7 @@ void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
544void * __init __alloc_bootmem(unsigned long size, unsigned long align, 584void * __init __alloc_bootmem(unsigned long size, unsigned long align,
545 unsigned long goal) 585 unsigned long goal)
546{ 586{
547 void *mem = __alloc_bootmem_nopanic(size,align,goal); 587 return ___alloc_bootmem(size, align, goal, 0);
548
549 if (mem)
550 return mem;
551 /*
552 * Whoops, we cannot satisfy the allocation request.
553 */
554 printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
555 panic("Out of memory");
556 return NULL;
557} 588}
558 589
559/** 590/**
@@ -653,22 +684,7 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
653void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, 684void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
654 unsigned long goal) 685 unsigned long goal)
655{ 686{
656 bootmem_data_t *bdata; 687 return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);
657 void *ptr;
658
659 list_for_each_entry(bdata, &bdata_list, list) {
660 ptr = alloc_bootmem_core(bdata, size, align, goal,
661 ARCH_LOW_ADDRESS_LIMIT);
662 if (ptr)
663 return ptr;
664 }
665
666 /*
667 * Whoops, we cannot satisfy the allocation request.
668 */
669 printk(KERN_ALERT "low bootmem alloc of %lu bytes failed!\n", size);
670 panic("Out of low memory");
671 return NULL;
672} 688}
673 689
674/** 690/**