diff options
Diffstat (limited to 'mm/memory_hotplug.c')
| -rw-r--r-- | mm/memory_hotplug.c | 19 | 
1 files changed, 14 insertions, 5 deletions
| diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index f767582af4f8..0082d699be94 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1576,7 +1576,7 @@ static int __ref __offline_pages(unsigned long start_pfn,  {  	unsigned long pfn, nr_pages;  	long offlined_pages; -	int ret, node; +	int ret, node, nr_isolate_pageblock;  	unsigned long flags;  	unsigned long valid_start, valid_end;  	struct zone *zone; @@ -1602,10 +1602,11 @@ static int __ref __offline_pages(unsigned long start_pfn,  	ret = start_isolate_page_range(start_pfn, end_pfn,  				       MIGRATE_MOVABLE,  				       SKIP_HWPOISON | REPORT_FAILURE); -	if (ret) { +	if (ret < 0) {  		reason = "failure to isolate range";  		goto failed_removal;  	} +	nr_isolate_pageblock = ret;  	arg.start_pfn = start_pfn;  	arg.nr_pages = nr_pages; @@ -1657,8 +1658,16 @@ static int __ref __offline_pages(unsigned long start_pfn,  	/* Ok, all of our target is isolated.  	   We cannot do rollback at this point. */  	offline_isolated_pages(start_pfn, end_pfn); -	/* reset pagetype flags and makes migrate type to be MOVABLE */ -	undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); + +	/* +	 * Onlining will reset pagetype flags and makes migrate type +	 * MOVABLE, so just need to decrease the number of isolated +	 * pageblocks zone counter here. +	 */ +	spin_lock_irqsave(&zone->lock, flags); +	zone->nr_isolate_pageblock -= nr_isolate_pageblock; +	spin_unlock_irqrestore(&zone->lock, flags); +  	/* removal success */  	adjust_managed_page_count(pfn_to_page(start_pfn), -offlined_pages);  	zone->present_pages -= offlined_pages; @@ -1690,12 +1699,12 @@ static int __ref __offline_pages(unsigned long start_pfn,  failed_removal_isolated:  	undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); +	memory_notify(MEM_CANCEL_OFFLINE, &arg);  failed_removal:  	pr_debug("memory offlining [mem %#010llx-%#010llx] failed due to %s\n",  		 (unsigned long long) start_pfn << PAGE_SHIFT,  		 ((unsigned long long) end_pfn << PAGE_SHIFT) - 1,  		 reason); -	memory_notify(MEM_CANCEL_OFFLINE, &arg);  	/* pushback to free area */  	mem_hotplug_done();  	return ret; |