Index: linux-2.6.15-rc5-mm3/mm/rmap.c =================================================================== --- linux-2.6.15-rc5-mm3.orig/mm/rmap.c 2005-12-15 13:30:50.000000000 -0800 +++ linux-2.6.15-rc5-mm3/mm/rmap.c 2005-12-15 19:28:53.000000000 -0800 @@ -208,14 +208,17 @@ out: #ifdef CONFIG_MIGRATION /* * Remove an anonymous page from swap replacing the swap pte's - * through real pte's pointing to valid pages. + * through real pte's pointing to valid pages and then releasing + * the page from the swap cache. + * + * Must hold page lock on page. */ void remove_from_swap(struct page *page) { struct anon_vma *anon_vma; struct vm_area_struct *vma; - if (!PageAnon(page)) + if (!PageSwapCache(page)) return; anon_vma = page_lock_anon_vma(page); @@ -224,6 +227,10 @@ void remove_from_swap(struct page *page) list_for_each_entry(vma, &anon_vma->head, anon_vma_node) remove_vma_swap(vma, page); + + spin_unlock(&anon_vma->lock); + + delete_from_swap_cache(page); } #endif Index: linux-2.6.15-rc5-mm3/mm/vmscan.c =================================================================== --- linux-2.6.15-rc5-mm3.orig/mm/vmscan.c 2005-12-15 13:34:09.000000000 -0800 +++ linux-2.6.15-rc5-mm3/mm/vmscan.c 2005-12-15 21:45:09.000000000 -0800 @@ -661,6 +661,8 @@ unlock_retry: retry: return -EAGAIN; } +EXPORT_SYMBOL(swap_page); + /* * Page migration was first developed in the context of the memory hotplug * project. The main authors of the migration code are: @@ -761,7 +763,6 @@ int migrate_page_remove_references(struc return 0; } -EXPORT_SYMBOL(swap_page); EXPORT_SYMBOL(migrate_page_remove_references); /* @@ -819,6 +820,15 @@ int migrate_page(struct page *newpage, s migrate_page_copy(newpage, page); + /* + * Remove auxiliary swap entries and replace + * them with real ptes. + * + * This will allow processes that are not waiting on + * the page lock to discover the new page via + * the page tables before the page is unlocked. + */ + remove_from_swap(newpage); return 0; } EXPORT_SYMBOL(migrate_page); @@ -980,11 +990,10 @@ next: list_move(&page->lru, failed); nr_failed++; } else { - if (newpage) { + if (newpage) /* Successful migration. Return new page to LRU */ - remove_from_swap(newpage); move_to_lru(newpage); - } + list_move(&page->lru, moved); } }