Modify try_to_unmap to produce swap migration entries If we are trying to unmap an entry and do not have an associated swapcache entry but are doing migration then create a special swap pte of type SWP_TYPE_MIGRATION pointing to the pfn. Signed-off-by: Christoph Lameter Index: linux-2.6.17-rc1/mm/rmap.c =================================================================== --- linux-2.6.17-rc1.orig/mm/rmap.c 2006-04-06 10:47:24.000000000 -0700 +++ linux-2.6.17-rc1/mm/rmap.c 2006-04-06 11:09:14.000000000 -0700 @@ -595,14 +595,18 @@ static int try_to_unmap_one(struct page if (!pte) goto out; + if (migration) { + ptep_disable(pte); + goto out_unmap; + } + /* * If the page is mlock()d, we cannot swap it out. * If it's recently referenced (perhaps page_referenced * skipped over this mm) then we should reactivate it. */ if ((vma->vm_flags & VM_LOCKED) || - (ptep_clear_flush_young(vma, address, pte) - && !migration)) { + (ptep_clear_flush_young(vma, address, pte))) { ret = SWAP_FAIL; goto out_unmap; } @@ -638,6 +642,7 @@ static int try_to_unmap_one(struct page } else dec_mm_counter(mm, file_rss); +finish: page_remove_rmap(page); page_cache_release(page); Index: linux-2.6.17-rc1/mm/memory.c =================================================================== --- linux-2.6.17-rc1.orig/mm/memory.c 2006-04-06 10:47:11.000000000 -0700 +++ linux-2.6.17-rc1/mm/memory.c 2006-04-06 11:29:16.000000000 -0700 @@ -2202,6 +2202,7 @@ static inline int handle_pte_fault(struc pte_t entry; pte_t old_entry; spinlock_t *ptl; + struct page *page; old_entry = entry = *pte; if (!pte_present(entry)) { @@ -2218,11 +2219,12 @@ static inline int handle_pte_fault(struc return do_swap_page(mm, vma, address, pte, pmd, write_access, entry); } - ptl = pte_lockptr(mm, pmd); spin_lock(ptl); if (unlikely(!pte_same(*pte, entry))) goto unlock; + if (unlikely(pte_disabled(entry))) + goto disabled_pte; if (write_access) { if (!pte_write(entry)) return do_wp_page(mm, vma, address, @@ -2247,6 +2249,22 @@ static inline int handle_pte_fault(struc unlock: pte_unmap_unlock(pte, ptl); return VM_FAULT_MINOR; + +disabled_pte: + /* + * Pte is valid but temporarily disabled. + * This is typically done by page migration while + * migrating a page. In order to reenable the pte + * we need to get the page lock. + */ + page = vm_normal_page(vma, address, entry); + get_page(page); + pte_unmap_unlock(pte, ptl); + lock_page(page); + pte_enable(pte); + unlock_lock(page); + put_page(page); + return VM_FAULT_MINOR; } /*