

Pages in a specified memory section are migrated when the section
is removed.

Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 memhotplug-dave/mm/page_alloc.c |   45 +++++++++++++++++++++++++++++++++++++---
 1 files changed, 42 insertions(+), 3 deletions(-)

diff -puN mm/page_alloc.c~P23-memsection_migrate mm/page_alloc.c
--- memhotplug/mm/page_alloc.c~P23-memsection_migrate	2004-12-10 13:53:20.000000000 -0800
+++ memhotplug-dave/mm/page_alloc.c	2004-12-10 13:53:20.000000000 -0800
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/suspend.h>
 #include <linux/pagevec.h>
+#include <linux/mmigrate.h>
 #include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/notifier.h>
@@ -702,6 +703,30 @@ static inline void force_captured_to_ina
 	}
 }
 
+static int
+grab_capturing_pages(struct list_head *page_list, unsigned long start_pfn,
+							unsigned long nr_pages)
+{
+	struct page *page;
+	struct zone *zone;
+	int rest = 0;
+	int i;
+
+	for (i = 0; i < nr_pages; i++) {
+		page = pfn_to_page(start_pfn + i);
+		zone = page_zone(page);
+		spin_lock_irq(&zone->lru_lock);
+		if (page_under_capture(page)) {
+			if (PageLRU(page) && __steal_page_from_lru(zone, page))
+				list_add(&page->lru, page_list);
+			else
+				rest++;
+		}
+		spin_unlock_irq(&zone->lru_lock);
+	}
+	return rest;
+}
+
 /*
  * Flags a given order of pages to be removed from memory, then removes any
  * of those pages that are currently in cpu cache or free lists.  The page
@@ -715,6 +740,9 @@ int capture_page_range(unsigned long sta
 	struct page *page;
 	int i;
 	unsigned long nr_pages = 1<<order;
+	LIST_HEAD(page_list);
+	int rest;
+	int remains;
 
 	for (i = 0; i < nr_pages; i++) {
 		struct page *page = pfn_to_page(start_pfn + i);
@@ -726,7 +754,7 @@ int capture_page_range(unsigned long sta
 	 * make sure that all the other CPUs can see the capture bits
 	 */
 	smp_wmb();
-
+retry:
 	/*
 	 * This drains the per-cpu caches, and makes sure that each
 	 * CPU does see the capture bits.
@@ -735,14 +763,25 @@ int capture_page_range(unsigned long sta
 
 	page = pfn_to_page(start_pfn);
 	remove_page_freearea(page, order);
-	force_captured_to_inactive_list(page);
+
+	rest = grab_capturing_pages(&page_list, start_pfn, nr_pages);
+	remains = try_to_migrate_pages(&page_list);
+
+	if (rest || !list_empty(&page_list)) {
+		if (remains == -ENOSPC) {
+			/* Any swap devices should be added. */
+		} else if (printk_ratelimit())
+			printk(KERN_NOTICE "Removing memory: still under capture:%d pages, not migrated yet:%d pages.\n", rest, remains);
+		msleep(1000);
+		goto retry;
+	}
+
 	/*
 	 * storing the last result (fp) keeps up from having
 	 * to walk the entire range each time
 	 */
 	fup = start_pfn;
 	while((fup = first_uncaptured_page(fup, nr_pages - (fup - start_pfn))) >= 0) {
-		while (shrink_all_memory(10000));
 		msleep(1000);
 	}
 
_
