With this patch, mlocked pages can be migrated. It works the following steps: 1. Unmap a target page from process spaces. 2. Replace the page with new one. 3. Map the new page to the process spaces where the old one have been mapped. Signed-off-by: Hirokazu Takahashi Signed-off-by: Dave Hansen --- memhotplug-dave/include/linux/mmigrate.h | 8 +++++--- memhotplug-dave/mm/mmigrate.c | 31 ++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff -puN include/linux/mmigrate.h~AA-PM-17-mlock-migrated-pages include/linux/mmigrate.h --- memhotplug/include/linux/mmigrate.h~AA-PM-17-mlock-migrated-pages 2005-09-30 12:38:48.000000000 -0700 +++ memhotplug-dave/include/linux/mmigrate.h 2005-09-30 12:38:48.000000000 -0700 @@ -7,9 +7,11 @@ #ifdef CONFIG_MEMORY_MIGRATE extern int generic_migrate_page(struct page *, struct page *, - int (*)(struct page *, struct page *)); -extern int migrate_page_common(struct page *, struct page *); -extern int page_migratable(struct page *, struct page *, int); + int (*)(struct page *, struct page *, struct list_head *)); +extern int migrate_page_common(struct page *, struct page *, + struct list_head *); +extern int page_migratable(struct page *, struct page *, int, + struct list_head *); extern struct page * migrate_onepage(struct page *); extern int try_to_migrate_pages(struct list_head *); diff -puN mm/mmigrate.c~AA-PM-17-mlock-migrated-pages mm/mmigrate.c --- memhotplug/mm/mmigrate.c~AA-PM-17-mlock-migrated-pages 2005-09-30 12:38:48.000000000 -0700 +++ memhotplug-dave/mm/mmigrate.c 2005-09-30 12:38:48.000000000 -0700 @@ -106,12 +106,12 @@ replace_pages(struct page *page, struct */ int page_migratable(struct page *page, struct page *newpage, - int freeable_page_count) + int freeable_page_count, struct list_head *vlist) { int truncated; if (page_mapped(page)) { - switch (try_to_unmap(page, NULL)) { + switch (try_to_unmap(page, vlist)) { case SWAP_FAIL: return -EBUSY; case SWAP_AGAIN: @@ -132,14 +132,15 @@ page_migratable(struct page *page, struc * against the page, and copy it. */ int -migrate_page_common(struct page *page, struct page *newpage) +migrate_page_common(struct page *page, struct page *newpage, + struct list_head *vlist) { long timeout = 5000; /* XXXX */ int ret; while (timeout > 0) { BUG_ON(page_count(page) == 0); - ret = page_migratable(page, newpage, 2); + ret = page_migratable(page, newpage, 2, vlist); switch (ret) { case 0: case -ENOENT: @@ -236,8 +237,9 @@ out: */ int generic_migrate_page(struct page *page, struct page *newpage, - int (*migrate_fn)(struct page *, struct page *)) + int (*migrate_fn)(struct page *, struct page *, struct list_head *)) { + LIST_HEAD(vlist); int ret; /* @@ -257,7 +259,7 @@ generic_migrate_page(struct page *page, * can be caught and blocked in a pagefault handler. */ if (page_mapped(page)) { - while ((ret = try_to_unmap(page, NULL)) == SWAP_AGAIN) + while ((ret = try_to_unmap(page, &vlist)) == SWAP_AGAIN) msleep(1); if (ret != SWAP_SUCCESS) { ret = -EBUSY; @@ -277,7 +279,7 @@ generic_migrate_page(struct page *page, } /* Wait for all operations against the page to finish. */ - ret = migrate_fn(page, newpage); + ret = migrate_fn(page, newpage, &vlist); switch (ret) { default: /* The page is busy. Try it later. */ @@ -320,6 +322,14 @@ generic_migrate_page(struct page *page, end_page_writeback(newpage); unlock_page(newpage); + /* map the newpage where the old page have been mapped. */ + touch_unmapped_address(&vlist); + if (PageSwapCache(newpage)) { + lock_page(newpage); + __remove_exclusive_swap_page(newpage, 1); + unlock_page(newpage); + } + page->mapping = NULL; unlock_page(page); page_cache_release(page); @@ -329,6 +339,13 @@ generic_migrate_page(struct page *page, out_busy: /* Roll back all operations. */ unwind_page(page, newpage); + touch_unmapped_address(&vlist); + if (PageSwapCache(page)) { + lock_page(page); + __remove_exclusive_swap_page(page, 1); + unlock_page(page); + } + return ret; out_removing: _