diff options
author | Johannes Weiner <hannes@saeurebad.de> | 2008-07-24 00:26:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:14 -0400 |
commit | 6b312c0e6e2f44b020e12953d1dd37eed60e3609 (patch) | |
tree | 4f2a1177b0013b411bf4799fb3c776128f5fa6f9 /mm/bootmem.c | |
parent | b61bfa3c462671c48a51fb5c31af337c5a996a04 (diff) |
mm: fix free_all_bootmem_core alignment check
The check for node_boot_start is bogus because we start freeing at the
corresponding pfn. So check if the pfn is properly aligned instead in a more
readable way and adjust the documentation.
Also remove an unneeded accounting variable.
Signed-off-by: Johannes Weiner <hannes@saeurebad.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Yinghai Lu <yhlu.kernel@gmail.com>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r-- | mm/bootmem.c | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 35b3cb667036..319a79bce7cd 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -377,7 +377,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) | |||
377 | struct page *page; | 377 | struct page *page; |
378 | unsigned long pfn; | 378 | unsigned long pfn; |
379 | bootmem_data_t *bdata = pgdat->bdata; | 379 | bootmem_data_t *bdata = pgdat->bdata; |
380 | unsigned long i, count, total = 0; | 380 | unsigned long i, count; |
381 | unsigned long idx; | 381 | unsigned long idx; |
382 | unsigned long *map; | 382 | unsigned long *map; |
383 | int gofast = 0; | 383 | int gofast = 0; |
@@ -389,10 +389,13 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) | |||
389 | pfn = PFN_DOWN(bdata->node_boot_start); | 389 | pfn = PFN_DOWN(bdata->node_boot_start); |
390 | idx = bdata->node_low_pfn - pfn; | 390 | idx = bdata->node_low_pfn - pfn; |
391 | map = bdata->node_bootmem_map; | 391 | map = bdata->node_bootmem_map; |
392 | /* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */ | 392 | /* |
393 | if (bdata->node_boot_start == 0 || | 393 | * Check if we are aligned to BITS_PER_LONG pages. If so, we might |
394 | ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG)) | 394 | * be able to free page orders of that size at once. |
395 | */ | ||
396 | if (!(pfn & (BITS_PER_LONG-1))) | ||
395 | gofast = 1; | 397 | gofast = 1; |
398 | |||
396 | for (i = 0; i < idx; ) { | 399 | for (i = 0; i < idx; ) { |
397 | unsigned long v = ~map[i / BITS_PER_LONG]; | 400 | unsigned long v = ~map[i / BITS_PER_LONG]; |
398 | 401 | ||
@@ -420,23 +423,19 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) | |||
420 | } | 423 | } |
421 | pfn += BITS_PER_LONG; | 424 | pfn += BITS_PER_LONG; |
422 | } | 425 | } |
423 | total += count; | ||
424 | 426 | ||
425 | /* | 427 | /* |
426 | * Now free the allocator bitmap itself, it's not | 428 | * Now free the allocator bitmap itself, it's not |
427 | * needed anymore: | 429 | * needed anymore: |
428 | */ | 430 | */ |
429 | page = virt_to_page(bdata->node_bootmem_map); | 431 | page = virt_to_page(bdata->node_bootmem_map); |
430 | count = 0; | ||
431 | idx = (get_mapsize(bdata) + PAGE_SIZE-1) >> PAGE_SHIFT; | 432 | idx = (get_mapsize(bdata) + PAGE_SIZE-1) >> PAGE_SHIFT; |
432 | for (i = 0; i < idx; i++, page++) { | 433 | for (i = 0; i < idx; i++, page++) |
433 | __free_pages_bootmem(page, 0); | 434 | __free_pages_bootmem(page, 0); |
434 | count++; | 435 | count += i; |
435 | } | ||
436 | total += count; | ||
437 | bdata->node_bootmem_map = NULL; | 436 | bdata->node_bootmem_map = NULL; |
438 | 437 | ||
439 | return total; | 438 | return count; |
440 | } | 439 | } |
441 | 440 | ||
442 | unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn, | 441 | unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn, |