diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2007-10-16 04:26:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:02 -0400 |
commit | 0c0e6195896535481173df98935ad8db174f4d45 (patch) | |
tree | 2b35d3b81ba54b5d38e691d2a2019f4bcdfd1dce /mm/page_alloc.c | |
parent | a5d76b54a3f3a40385d7f76069a2feac9f1bad63 (diff) |
memory unplug: page offline
Logic.
- set all pages in [start,end) as isolated migration-type.
by this, all free pages in the range will be not-for-use.
- Migrate all LRU pages in the range.
- Test all pages in the range's refcnt is zero or not.
Todo:
- allocate migration destination page from better area.
- confirm page_count(page)== 0 && PageReserved(page) page is safe to be freed..
(I don't like this kind of page but..
- Find out pages which cannot be migrated.
- more running tests.
- Use reclaim for unplugging other memory type area.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 47 |
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) | |||
4477 | out: | 4477 | out: |
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 | */ | ||
4485 | void | ||
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 | ||