aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a44715e82058..d315e1127dc9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4477,3 +4477,50 @@ void unset_migratetype_isolate(struct page *page)
4477out: 4477out:
4478 spin_unlock_irqrestore(&zone->lock, flags); 4478 spin_unlock_irqrestore(&zone->lock, flags);
4479} 4479}
4480
4481#ifdef CONFIG_MEMORY_HOTREMOVE
4482/*
4483 * All pages in the range must be isolated before calling this.
4484 */
4485void
4486__offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
4487{
4488 struct page *page;
4489 struct zone *zone;
4490 int order, i;
4491 unsigned long pfn;
4492 unsigned long flags;
4493 /* find the first valid pfn */
4494 for (pfn = start_pfn; pfn < end_pfn; pfn++)
4495 if (pfn_valid(pfn))
4496 break;
4497 if (pfn == end_pfn)
4498 return;
4499 zone = page_zone(pfn_to_page(pfn));
4500 spin_lock_irqsave(&zone->lock, flags);
4501 pfn = start_pfn;
4502 while (pfn < end_pfn) {
4503 if (!pfn_valid(pfn)) {
4504 pfn++;
4505 continue;
4506 }
4507 page = pfn_to_page(pfn);
4508 BUG_ON(page_count(page));
4509 BUG_ON(!PageBuddy(page));
4510 order = page_order(page);
4511#ifdef CONFIG_DEBUG_VM
4512 printk(KERN_INFO "remove from free list %lx %d %lx\n",
4513 pfn, 1 << order, end_pfn);
4514#endif
4515 list_del(&page->lru);
4516 rmv_page_order(page);
4517 zone->free_area[order].nr_free--;
4518 __mod_zone_page_state(zone, NR_FREE_PAGES,
4519 - (1UL << order));
4520 for (i = 0; i < (1 << order); i++)
4521 SetPageReserved((page+i));
4522 pfn += (1 << order);
4523 }
4524 spin_unlock_irqrestore(&zone->lock, flags);
4525}
4526#endif