New migration scheme Signed-off-by: Christoph Lameter Index: linux-2.6.16-mm2/mm/migrate.c =================================================================== --- linux-2.6.16-mm2.orig/mm/migrate.c 2006-03-31 09:29:32.000000000 -0800 +++ linux-2.6.16-mm2/mm/migrate.c 2006-03-31 09:38:29.000000000 -0800 @@ -139,8 +139,9 @@ int migrate_page_remove_references(struc * indicates that the page is in use or truncate has removed * the page. */ - if (!mapping || page_mapcount(page) + nr_refs != page_count(page)) - return -EAGAIN; + if (!page->mapping || + page_mapcount(page) + nr_refs + !!mapping != page_count(page)) + return -EAGAIN; /* * Establish swap ptes for anonymous pages or destroy pte @@ -171,13 +172,19 @@ int migrate_page_remove_references(struc if (page_mapcount(page)) return -EAGAIN; + if (!mapping) + return 0; /* Anonymous page without swap */ + + /* + * Page has a mapping that we need to change + */ write_lock_irq(&mapping->tree_lock); radix_pointer = (struct page **)radix_tree_lookup_slot( &mapping->page_tree, page_index(page)); - if (!page_mapping(page) || page_count(page) != nr_refs || + if (!page_mapping(page) || page_count(page) != nr_refs + 1 || *radix_pointer != page) { write_unlock_irq(&mapping->tree_lock); return -EAGAIN; @@ -259,10 +269,12 @@ int migrate_page(struct page *newpage, s BUG_ON(PageWriteback(page)); /* Writeback must be complete */ - rc = migrate_page_remove_references(newpage, page, 2); + rc = migrate_page_remove_references(newpage, page, 1); - if (rc) + if (rc) { + remove_migration_ptes(page, page); return rc; + } migrate_page_copy(newpage, page); @@ -274,7 +286,7 @@ int migrate_page(struct page *newpage, s * waiting on the page lock to use the new page via the page tables * before the new page is unlocked. */ - remove_from_swap(newpage); + remove_migration_ptes(page, newpage); return 0; } EXPORT_SYMBOL(migrate_page); @@ -356,9 +368,12 @@ redo: * Try to migrate the page. */ mapping = page_mapping(page); - if (!mapping) + if (!mapping) { + + rc = migrate_page(newpage, page); goto unlock_both; + } else if (mapping->a_ops->migratepage) { /* * Most pages have a mapping and most filesystems @@ -450,7 +465,7 @@ int buffer_migrate_page(struct page *new head = page_buffers(page); - rc = migrate_page_remove_references(newpage, page, 3); + rc = migrate_page_remove_references(newpage, page, 2); if (rc) return rc;