Skip to content

Commit

Permalink
mm: bootmem: try harder to free pages in bulk
Browse files Browse the repository at this point in the history
The loop that frees pages to the page allocator while bootstrapping tries
to free higher-order blocks only when the starting address is aligned to
that block size.  Otherwise it will free all pages on that node
one-by-one.

Change it to free individual pages up to the first aligned block and then
try higher-order frees from there.

Signed-off-by: Johannes Weiner <[email protected]>
Cc: Uwe Kleine-König <[email protected]>
Cc: Tejun Heo <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
hnaz authored and torvalds committed Jan 11, 2012
1 parent 560a036 commit 799f933
Showing 1 changed file with 10 additions and 12 deletions.
22 changes: 10 additions & 12 deletions mm/bootmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)

static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
{
int aligned;
struct page *page;
unsigned long start, end, pages, count = 0;

Expand All @@ -181,27 +180,26 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
start = bdata->node_min_pfn;
end = bdata->node_low_pfn;

/*
* If the start is aligned to the machines wordsize, we might
* be able to free pages in bulks of that order.
*/
aligned = !(start & (BITS_PER_LONG - 1));

bdebug("nid=%td start=%lx end=%lx aligned=%d\n",
bdata - bootmem_node_data, start, end, aligned);
bdebug("nid=%td start=%lx end=%lx\n",
bdata - bootmem_node_data, start, end);

while (start < end) {
unsigned long *map, idx, vec;

map = bdata->node_bootmem_map;
idx = start - bdata->node_min_pfn;
vec = ~map[idx / BITS_PER_LONG];

if (aligned && vec == ~0UL) {
/*
* If we have a properly aligned and fully unreserved
* BITS_PER_LONG block of pages in front of us, free
* it in one go.
*/
if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) {
int order = ilog2(BITS_PER_LONG);

__free_pages_bootmem(pfn_to_page(start), order);
count += BITS_PER_LONG;
start += BITS_PER_LONG;
} else {
unsigned long off = 0;

Expand All @@ -214,8 +212,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
vec >>= 1;
off++;
}
start = ALIGN(start + 1, BITS_PER_LONG);
}
start += BITS_PER_LONG;
}

page = virt_to_page(bdata->node_bootmem_map);
Expand Down

0 comments on commit 799f933

Please sign in to comment.