diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 22 | 
1 files changed, 16 insertions, 6 deletions
| diff --git a/mm/page_alloc.c b/mm/page_alloc.c index af982f7cdb2a..27b8681139fd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -268,13 +268,14 @@ void prep_compound_page(struct page *page, unsigned long order)  {  	int i;  	int nr_pages = 1 << order; +	struct page *p = page + 1;  	set_compound_page_dtor(page, free_compound_page);  	set_compound_order(page, order);  	__SetPageHead(page); -	for (i = 1; i < nr_pages; i++) { -		struct page *p = page + i; - +	for (i = 1; i < nr_pages; i++, p++) { +		if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) +			p = pfn_to_page(page_to_pfn(page) + i);  		__SetPageTail(p);  		p->first_page = page;  	} @@ -284,6 +285,7 @@ static void destroy_compound_page(struct page *page, unsigned long order)  {  	int i;  	int nr_pages = 1 << order; +	struct page *p = page + 1;  	if (unlikely(compound_order(page) != order))  		bad_page(page); @@ -291,8 +293,9 @@ static void destroy_compound_page(struct page *page, unsigned long order)  	if (unlikely(!PageHead(page)))  			bad_page(page);  	__ClearPageHead(page); -	for (i = 1; i < nr_pages; i++) { -		struct page *p = page + i; +	for (i = 1; i < nr_pages; i++, p++) { +		if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) +			p = pfn_to_page(page_to_pfn(page) + i);  		if (unlikely(!PageTail(p) |  				(p->first_page != page))) @@ -694,6 +697,9 @@ static int move_freepages(struct zone *zone,  #endif  	for (page = start_page; page <= end_page;) { +		/* Make sure we are not inadvertently changing nodes */ +		VM_BUG_ON(page_to_nid(page) != zone_to_nid(zone)); +  		if (!pfn_valid_within(page_to_pfn(page))) {  			page++;  			continue; @@ -2516,6 +2522,10 @@ static void setup_zone_migrate_reserve(struct zone *zone)  			continue;  		page = pfn_to_page(pfn); +		/* Watch out for overlapping nodes */ +		if (page_to_nid(page) != zone_to_nid(zone)) +			continue; +  		/* Blocks with reserved pages will never free, skip them. */  		if (PageReserved(page))  			continue; @@ -4064,7 +4074,7 @@ void __init set_dma_reserve(unsigned long new_dma_reserve)  }  #ifndef CONFIG_NEED_MULTIPLE_NODES -struct pglist_data contig_page_data = { .bdata = &bootmem_node_data[0] }; +struct pglist_data __refdata contig_page_data = { .bdata = &bootmem_node_data[0] };  EXPORT_SYMBOL(contig_page_data);  #endif | 
