diff options
Diffstat (limited to 'mm/compaction.c')
| -rw-r--r-- | mm/compaction.c | 22 | 
1 files changed, 12 insertions, 10 deletions
| diff --git a/mm/compaction.c b/mm/compaction.c index 37f976287068..627dc2e4320f 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -671,16 +671,20 @@ static void isolate_freepages(struct zone *zone,  				struct compact_control *cc)  {  	struct page *page; -	unsigned long high_pfn, low_pfn, pfn, z_end_pfn, end_pfn; +	unsigned long high_pfn, low_pfn, pfn, z_end_pfn;  	int nr_freepages = cc->nr_freepages;  	struct list_head *freelist = &cc->freepages;  	/*  	 * Initialise the free scanner. The starting point is where we last -	 * scanned from (or the end of the zone if starting). The low point -	 * is the end of the pageblock the migration scanner is using. +	 * successfully isolated from, zone-cached value, or the end of the +	 * zone when isolating for the first time. We need this aligned to +	 * the pageblock boundary, because we do pfn -= pageblock_nr_pages +	 * in the for loop. +	 * The low boundary is the end of the pageblock the migration scanner +	 * is using.  	 */ -	pfn = cc->free_pfn; +	pfn = cc->free_pfn & ~(pageblock_nr_pages-1);  	low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages);  	/* @@ -700,6 +704,7 @@ static void isolate_freepages(struct zone *zone,  	for (; pfn >= low_pfn && cc->nr_migratepages > nr_freepages;  					pfn -= pageblock_nr_pages) {  		unsigned long isolated; +		unsigned long end_pfn;  		/*  		 * This can iterate a massively long zone without finding any @@ -734,13 +739,10 @@ static void isolate_freepages(struct zone *zone,  		isolated = 0;  		/* -		 * As pfn may not start aligned, pfn+pageblock_nr_page -		 * may cross a MAX_ORDER_NR_PAGES boundary and miss -		 * a pfn_valid check. Ensure isolate_freepages_block() -		 * only scans within a pageblock +		 * Take care when isolating in last pageblock of a zone which +		 * ends in the middle of a pageblock.  		 */ -		end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); -		end_pfn = min(end_pfn, z_end_pfn); +		end_pfn = min(pfn + pageblock_nr_pages, z_end_pfn);  		isolated = isolate_freepages_block(cc, pfn, end_pfn,  						   freelist, false);  		nr_freepages += isolated; | 

